API Docs for:
Show:

File: ../src/area.js

//enclose in a scope
(function(){

	
	/****************** AREA **************/
	/** An Area is am streched container.
	* Areas can be split several times horizontally or vertically to fit different colums or rows
	*
	* @class Area
	* @constructor
	* @param {Object} options
	*/
	function Area( options, legacy )
	{
		//for legacy code
		if( (options && options.constructor === String) || legacy )
		{
			var id = options;
			options = legacy || {};
			options.id = id;
			console.warn("LiteGUI.Area legacy parameter, use options as first parameter instead of id.");
		}

		options = options || {};
		/* the root element containing all sections */
		var root = document.createElement("div");
		root.className = "litearea";
		if(options.id)
			root.id = options.id;
		if(options.className)
			root.className +=  " " + options.className;

		this.root = root;
		this.root.litearea = this; //dbl link

		var width = options.width || "100%";
		var height = options.height || "100%";

		if( width < 0 )
			width = 'calc( 100% - '+Math.abs(width)+'px)';
		if( height < 0 )
			height = 'calc( 100% - '+ Math.abs(height)+'px)';

		root.style.width = width;
		root.style.height = height;

		this.options = options;

		var that = this;
		//window.addEventListener("resize",function(e) { that.onResize(e); });
		//$(this).bind("resize",function(e) { that.resize(e); });

		//this._computed_size = [ $(this.root).width(), $(this.root).height() ];
		this._computed_size = [ this.root.offsetWidth, this.root.offserHeight ];

		var content = document.createElement("div");
		if(options.content_id)
			content.id = options.content_id;
		content.className = "liteareacontent";
		content.style.width = "100%";
		content.style.height = "100%";
		this.root.appendChild( content );
		this.content = content;

		this.split_direction = "none";
		this.sections = [];

		if(options.autoresize)
			LiteGUI.bind( LiteGUI, "resized", function() { 
				that.onResize(); 
			});
	}

	Area.VERTICAL = "vertical";
	Area.HORIZONTAL = "horizontal";

	Area.splitbar_size = 4;

	/* get container of the section */
	Area.prototype.getSection = function(num)
	{
		num = num || 0;
		if(this.sections.length > num)
			return this.sections[num];
		return null;
	}

	Area.prototype.onResize = function(e)
	{
		//this._computed_size = [ $(this.root).width(), $(this.root).height() ];
		var computed_size = [ this.root.offsetWidth, this.root.offsetHeight ];
		if( e && this._computed_size && computed_size[0] == this._computed_size[0] && computed_size[1] == this._computed_size[1])
			return;

		this.sendResizeEvent(e);
	}

	//sends the resize event to all the sections
	Area.prototype.sendResizeEvent = function(e)
	{
		if(this.sections.length)
			for(var i in this.sections)
			{
				var section = this.sections[i];
				section.onResize(e);
				//$(section).trigger("resize"); //it is a LiteArea
				//$(section.root).trigger("resize");
				/*
				for (var j = 0; j < section.root.childNodes.length; j++)
					$(section.root.childNodes[j]).trigger("resize");
				*/
			}
		else //send it to the children
		{
			for (var j = 0; j < this.root.childNodes.length; j++)
			{
				var element = this.root.childNodes[j];
				if(element.litearea)
					element.litearea.onResize();
				else
					LiteGUI.trigger( element, "resize" );
			}
		}

		//inner callback
		if( this.onresize )
			this.onresize();
	}

	Area.prototype.getWidth = function()
	{
		return this.root.offsetWidth;
	}

	Area.prototype.getHeight = function()
	{
		return this.root.offsetHeight;
	}

	Area.prototype.isVisible = function()
	{
		return this.root.style.display != "none";	
	}

	Area.prototype.adjustHeight = function()
	{
		if(!this.root.parentNode)
		{
			console.error("Cannot adjust height of LiteGUI.Area without parent");
			return;
		}

		//check parent height
		var h = this.root.parentNode.offsetHeight;

		//check position
		var y = this.root.getClientRects()[0].top;

		//adjust height
		this.root.style.height = "calc( 100% - " + y + "px )";
	}

	Area.prototype.split = function( direction, sizes, editable )
	{
		if( !direction || direction.constructor !== String )
			throw ("First parameter must be a string: 'vertical' or 'horizontal'");

		if( !sizes )
			sizes = ["50%",null];

		if( direction != "vertical" && direction != "horizontal" )
			throw ("First parameter must be a string: 'vertical' or 'horizontal'");

		if(this.sections.length)
			throw "cannot split twice";

		//create areas
		var area1 = new LiteGUI.Area({ content_id: this.content.id });
		area1.root.style.display = "inline-block";
		var area2 = new LiteGUI.Area();
		area2.root.style.display = "inline-block";

		var splitinfo = "";
		var splitbar = null;
		var dynamic_section = null;
		if(editable)
		{
			splitinfo = " - " + (Area.splitbar_size + 2) +"px"; //2 px margin �?
			splitbar = document.createElement("div");
			splitbar.className = "litesplitbar " + direction;
			if(direction == "vertical")
				splitbar.style.height = Area.splitbar_size + "px";
			else
				splitbar.style.width = Area.splitbar_size + "px";
			this.splitbar = splitbar;
			splitbar.addEventListener("mousedown", inner_mousedown);
		}

		sizes = sizes || ["50%",null];

		if(direction == "vertical")
		{
			area1.root.style.width = "100%";
			area2.root.style.width = "100%";

			if(sizes[0] == null)
			{
				var h = sizes[1];
				if(typeof(h) == "number")
					h = sizes[1] + "px";

				area1.root.style.height = "-moz-calc( 100% - " + h + splitinfo + " )";
				area1.root.style.height = "-webkit-calc( 100% - " + h + splitinfo + " )";
				area1.root.style.height = "calc( 100% - " + h + splitinfo + " )";
				area2.root.style.height = h;
				area2.size = h;
				dynamic_section = area1;
			}
			else if(sizes[1] == null)
			{
				var h = sizes[0];
				if(typeof(h) == "number")
					h = sizes[0] + "px";

				area1.root.style.height = h;
				area1.size = h;
				area2.root.style.height = "-moz-calc( 100% - " + h + splitinfo + " )";
				area2.root.style.height = "-webkit-calc( 100% - " + h + splitinfo + " )";
				area2.root.style.height = "calc( 100% - " + h + splitinfo + " )";
				dynamic_section = area2;
			}
			else
			{
				var h1 = sizes[0];
				if(typeof(h1) == "number")
					h1 = sizes[0] + "px";
				var h2 = sizes[1];
				if(typeof(h2) == "number")
					h2 = sizes[1] + "px";
				area1.root.style.height = h1;
				area1.size = h1;
				area2.root.style.height = h2;
				area2.size = h2;
			}
		}
		else //horizontal
		{
			area1.root.style.height = "100%";
			area2.root.style.height = "100%";

			if(sizes[0] == null)
			{
				var w = sizes[1];
				if(typeof(w) == "number")
					w = sizes[1] + "px";
				area1.root.style.width = "-moz-calc( 100% - " + w + splitinfo + " )";
				area1.root.style.width = "-webkit-calc( 100% - " + w + splitinfo + " )";
				area1.root.style.width = "calc( 100% - " + w + splitinfo + " )";
				area2.root.style.width = w;
				area2.size = sizes[1];
				dynamic_section = area1;
			}
			else if(sizes[1] == null)
			{
				var w = sizes[0];
				if(typeof(w) == "number")
					w = sizes[0] + "px";

				area1.root.style.width = w;
				area1.size = w;
				area2.root.style.width = "-moz-calc( 100% - " + w + splitinfo + " )";
				area2.root.style.width = "-webkit-calc( 100% - " + w + splitinfo + " )";
				area2.root.style.width = "calc( 100% - " + w + splitinfo + " )";
				dynamic_section = area2;
			}
			else
			{
				var w1 = sizes[0];
				if(typeof(w1) == "number")
					w1 = sizes[0] + "px";
				var w2 = sizes[1];
				if(typeof(w2) == "number")
					w2 = sizes[1] + "px";

				area1.root.style.width = w1;
				area1.size = w1;
				area2.root.style.width = w2;
				area2.size = w2;
			}
		}

		area1.root.removeChild( area1.content );
		area1.root.appendChild( this.content );
		area1.content = this.content;

		this.root.appendChild( area1.root );
		if(splitbar)
			this.root.appendChild( splitbar );
		this.root.appendChild( area2.root );

		this.sections = [area1, area2];
		this.dynamic_section = dynamic_section;
		this.direction = direction;

		//SPLITTER DRAGGER INTERACTION
		var that = this;
		var last_pos = [0,0];
		function inner_mousedown(e)
		{
			var doc = that.root.ownerDocument;
			doc.addEventListener("mousemove",inner_mousemove);
			doc.addEventListener("mouseup",inner_mouseup);
			last_pos[0] = e.pageX;
			last_pos[1] = e.pageY;
			e.stopPropagation();
			e.preventDefault();
		}

		function inner_mousemove(e)
		{
			if(direction == "horizontal")
			{
				if (last_pos[0] != e.pageX)
					that.moveSplit(last_pos[0] - e.pageX);
			}
			else if(direction == "vertical")
			{
				if (last_pos[1] != e.pageY)
					that.moveSplit(e.pageY - last_pos[1]);
			}

			last_pos[0] = e.pageX;
			last_pos[1] = e.pageY;
			e.stopPropagation();
			e.preventDefault();
			if(that.options.immediateResize || that.options.inmediateResize) //inmediate is for legacy...
				that.onResize();
		}

		function inner_mouseup(e)
		{
			var doc = that.root.ownerDocument;
			doc.removeEventListener("mousemove",inner_mousemove);
			doc.removeEventListener("mouseup",inner_mouseup);
			that.onResize();
		}
	}

	Area.prototype.hide = function()
	{
		this.root.style.display = "none";
	}

	Area.prototype.show = function()
	{
		this.root.style.display = "block";
	}

	Area.prototype.showSection = function(num)
	{
		var section = this.sections[num];
		var size = 0;

		if( section && section.root.style.display != "none" )
			return; //already visible
		
		if(this.direction == "horizontal")
			size = section.root.style.width;
		else
			size = section.root.style.height;

		if(size.indexOf("calc") != -1)
			size = "50%";

		for(var i in this.sections)
		{
			var section = this.sections[i];

			if(i == num)
				section.root.style.display = "inline-block";
			else
			{
				if(this.direction == "horizontal")
					section.root.style.width = "calc( 100% - " + size + " - 5px)";
				else
					section.root.style.height = "calc( 100% - " + size + " - 5px)";
			}
		}

		if(this.splitbar)
			this.splitbar.style.display = "inline-block";

		this.sendResizeEvent();
	}

	Area.prototype.hideSection = function(num)
	{
		for(var i in this.sections)
		{
			var section = this.sections[i];

			if(i == num)
				section.root.style.display = "none";
			else
			{
				if(this.direction == "horizontal")
					section.root.style.width = "100%";
				else
					section.root.style.height = "100%";
			}
		}

		if(this.splitbar)
			this.splitbar.style.display = "none";

		this.sendResizeEvent();
	}

	Area.prototype.moveSplit = function(delta)
	{
		if(!this.sections) return;

		var area1 = this.sections[0];
		var area2 = this.sections[1];
		var splitinfo = " - "+ Area.splitbar_size +"px";

		var min_size = this.options.minSplitSize || 10;

		if(this.direction == "horizontal")
		{

			if (this.dynamic_section == area1)
			{
				//var size = ($(area2.root).width() + delta) + "px";
				var size = (area2.root.offsetWidth + delta);
				if(size < min_size)
					size = min_size;
				area1.root.style.width = "-moz-calc( 100% - " + size + "px " + splitinfo + " )";
				area1.root.style.width = "-webkit-calc( 100% - " + size + "px " + splitinfo + " )";
				area1.root.style.width = "calc( 100% - " + size + "px " + splitinfo + " )";
				area2.root.style.width = size + "px"; //other split
			}
			else
			{
				//var size = ($(area1.root).width() - delta) + "px";
				var size = (area1.root.offsetWidth - delta);
				if(size < min_size)
					size = min_size;
				area2.root.style.width = "-moz-calc( 100% - " + size + "px " + splitinfo + " )";
				area2.root.style.width = "-webkit-calc( 100% - " + size + "px " + splitinfo + " )";
				area2.root.style.width = "calc( 100% - " + size + "px " + splitinfo + " )";
				area1.root.style.width = size + "px"; //other split
			}
		}
		else if(this.direction == "vertical")
		{
			if (this.dynamic_section == area1)
			{
				//var size = ($(area2.root).height() - delta) + "px";
				var size = (area2.root.offsetHeight - delta);
				if(size < min_size)
					size = min_size;
				area1.root.style.height = "-moz-calc( 100% - " + size + "px " + splitinfo + " )";
				area1.root.style.height = "-webkit-calc( 100% - " + size + "px " + splitinfo + " )";
				area1.root.style.height = "calc( 100% - " + size + "px " + splitinfo + " )";
				area2.root.style.height = size + "px"; //other split
			}
			else
			{
				//var size = ($(area1.root).height() + delta) + "px";
				var size = (area1.root.offsetHeight + delta);
				if(size < min_size)
					size = min_size;
				area2.root.style.height = "-moz-calc( 100% - " + size + "px " + splitinfo + " )";
				area2.root.style.height = "-webkit-calc( 100% - " + size + "px " + splitinfo + " )";
				area2.root.style.height = "calc( 100% - " + size + "px " + splitinfo + " )";
				area1.root.style.height = size + "px"; //other split
			}
		}

		LiteGUI.trigger( this.root, "split_moved");
		//trigger split_moved event in all areas inside this area
		var areas = this.root.querySelectorAll(".litearea");
		for(var i = 0; i < areas.length; ++i)
			LiteGUI.trigger( areas[i], "split_moved" );
	}

	Area.prototype.addEventListener = function(a,b,c,d)
	{
		return this.root.addEventListener(a,b,c,d);
	}

	Area.prototype.setAreaSize = function(area,size)
	{
		var element = this.sections[1];

		var splitinfo = " - "+Area.splitbar_size+"px";
		element.root.style.width = "-moz-calc( 100% - " + size + splitinfo + " )";
		element.root.style.width = "-webkit-calc( 100% - " + size + splitinfo + " )";
		element.root.style.width = "calc( 100% - " + size + splitinfo + " )";
	}

	Area.prototype.merge = function(main_section)
	{
		if(this.sections.length == 0) throw "not splitted";

		var main = this.sections[main_section || 0];

		this.root.appendChild( main.content );
		this.content = main.content;

		this.root.removeChild( this.sections[0].root );
		this.root.removeChild( this.sections[1].root );

		/*
		while(main.childNodes.length > 0)
		{
			var e = main.childNodes[0];
			this.root.appendChild(e);
		}

		this.root.removeChild( this.sections[0].root );
		this.root.removeChild( this.sections[1].root );
		*/

		this.sections = [];
		this._computed_size = null;
		this.onResize();
	}

	Area.prototype.add = function(v)
	{
		if(typeof(v) == "string")
		{
			var element = document.createElement("div");
			element.innerHTML = v;
			v = element;
		}

		this.content.appendChild( v.root || v );
	}

	Area.prototype.query = function(v)
	{
		return this.root.querySelector(v);
	}

	LiteGUI.Area = Area;

	/***************** SPLIT ******************/

	/**
	* Split 
	*
	* @class Split
	* @constructor
	*/
	function Split(id, sections, options)
	{
		options = options || {};

		var root = document.createElement("div");
		this.root = root;
		root.id = id;
		root.className = "litesplit " + (options.vertical ? "vsplit" : "hsplit");
		this.sections = [];

		for(var i in sections)
		{
			var section = document.createElement("div");

			section.className = "split-section split" + i;
			if(typeof(sections[i]) == "number")
			{
				if(options.vertical)
					section.style.height = sections[i].toFixed(1) + "%";
				else
					section.style.width = sections[i].toFixed(1) + "%";
			}
			else if(typeof(sections[i]) == "string")
			{
				if(options.vertical)
					section.style.height = sections[i];
				else
					section.style.width = sections[i];
			}
			else
			{
				if(sections[i].id) section.id = sections[i].id;
				if(options.vertical)
					section.style.height = (typeof(sections[i].height) == "Number" ? sections[i].height.toFixed(1) + "%" : sections[i].height);
				else
					section.style.width = (typeof(sections[i].width) == "Number" ? sections[i].width.toFixed(1) + "%" : sections[i].width);
			}

			section.add = function(element) {
				this.appendChild( element.root || element );
			}

			this.sections.push(section);
			root.appendChild(section);
		}

		if(options.parent)
		{
			if(options.parent.root)
				options.parent.root.appendChild(root);
			else
				options.parent.appendChild(root);
		}

		this.getSection = function(n)
		{
			return this.sections[n];
		}
	}

	LiteGUI.Split = Split;

})();