API Docs for:
Show:

File: ../src/dialog.js

(function(){
	/****************** DIALOG **********************/
	/**
	* Dialog
	*
	* @class Dialog
	* @param {Object} options useful options are { title, width, height, closable, on_close, scroll }
	* @constructor
	*/
	function Dialog( options, legacy )
	{
		if( legacy || (options && options.constructor === String) )
		{
			var id = options;
			options = legacy || {};
			options.id = id;
			console.warn("LiteGUI.Dialog legacy parameter, use options as first parameter instead of id.");
		}

		this._ctor( options );
	}

	Dialog.MINIMIZED_WIDTH = 200;
	Dialog.title_height = "20px";

	Dialog.getDialog = function( id )
	{
		var element = document.getElementById( id );		
		if(!element)
			return null;
		return element.dialog;
	}

	Dialog.prototype._ctor = function( options )
	{
		options = options || {};

		var that = this;
		this.width = options.width;
		this.height = options.height;
		this.minWidth = options.minWidth || 150;
		this.minHeight = options.minHeight || 100;
		this.content = options.content || "";

		var panel = document.createElement("div");
		if(options.id)
			panel.id = options.id;

		panel.className = "litedialog " + (options.className || "");
		panel.data = this;
		panel.dialog = this;

		var code = "";
		if(options.title)
		{
			code += "<div class='panel-header'>"+options.title+"</div><div class='buttons'>";
			if(options.minimize){
				code += "<button class='litebutton mini-button minimize-button'>-</button>";
				code += "<button class='litebutton mini-button maximize-button' style='display:none'></button>";
			}
			if(options.hide)
				code += "<button class='litebutton mini-button hide-button'></button>";
			if(options.detachable)
				code += "<button class='litebutton mini-button detach-button'></button>";
			
			if(options.close || options.closable)
				code += "<button class='litebutton mini-button close-button'>"+ LiteGUI.special_codes.close +"</button>";
			code += "</div>";
		}

		code += "<div class='content'>"+this.content+"</div>";
		code += "<div class='panel-footer'></div>";
		panel.innerHTML = code;

		this.root = panel;
		this.content = panel.querySelector(".content");
		this.footer = panel.querySelector(".panel-footer");

		if(options.fullcontent)
		{
			this.content.style.width = "100%";		
			this.content.style.height = options.title ? "calc( 100% - "+Dialog.title_height+" )" : "100%";
		}

		if(options.buttons)
		{
			for(var i in options.buttons)
				this.addButton(options.buttons[i].name, options.buttons[i]);
		}

		//if(options.scroll == false)	this.content.style.overflow = "hidden";
		if(options.scroll == true)
			this.content.style.overflow = "auto";

		//buttons *********************************
		var close_button = panel.querySelector(".close-button");
		if(close_button)
			close_button.addEventListener("click", this.close.bind(this) );

		var maximize_button = panel.querySelector(".maximize-button");
		if(maximize_button)
			maximize_button.addEventListener("click", this.maximize.bind(this) );

		var minimize_button = panel.querySelector(".minimize-button");
		if(minimize_button)
			minimize_button.addEventListener("click", this.minimize.bind(this) );

		var hide_button = panel.querySelector(".hide-button");
		if(hide_button)
			hide_button.addEventListener("click", this.hide.bind(this) );

		var detach_button = panel.querySelector(".detach-button");
		if(detach_button)
			detach_button.addEventListener("click", function() { that.detachWindow(); });

		//size, draggable, resizable, etc
		this.enableProperties(options);

		this.root.addEventListener("DOMNodeInsertedIntoDocument", function(){ 
			if( that.on_attached_to_DOM )
				that.on_attached_to_DOM();
			if( that.on_resize )
				that.on_resize();
		});
		this.root.addEventListener("DOMNodeRemovedFromDocument", function(){ 
			if( that.on_detached_from_DOM )
				that.on_detached_from_DOM();
		});


		//attach
		if(options.attach || options.parent)
		{
			var parent = null;
			if(options.parent)
				parent = typeof(options.parent) == "string" ? document.querySelector(options.parent) : options.parent;
			if(!parent)
				parent = LiteGUI.root;
			parent.appendChild( this.root );
			this.center();
		}

		//if(options.position) //not docked
		//	this.setPosition( options.position[0], options.position[1] );
	}

	/**
	* add widget or html to the content of the dialog
	* @method add
	*/
	Dialog.prototype.add = function( litegui_item )
	{
		this.content.appendChild( litegui_item.root || litegui_item );
	}

	//takes the info from the parent to 
	Dialog.prototype.enableProperties = function(options)
	{
		options = options || {};
		var that = this;

		var panel = this.root;
		panel.style.position = "absolute";
		//panel.style.display = "none";

		panel.style.minWidth = this.minWidth + "px";
		panel.style.minHeight = this.minHeight + "px";

		if(this.width)
			panel.style.width = this.width + "px";

		if(this.height)
		{
			if(typeof(this.height) == "number")
			{
				panel.style.height = this.height + "px";
			}
			else
			{
				if(this.height.indexOf("%") != -1)
					panel.style.height = this.height;
			}

			this.content.style.height = "calc( " + this.height + "px - 24px )";
		}

		panel.style.boxShadow = "0 0 3px black";

		if(options.draggable)
		{
			this.draggable = true;
			LiteGUI.draggable( panel, panel.querySelector(".panel-header"), function(){
				that.bringToFront();
			},null, function(){
				return !that.minimized;
			});
		}

		if(options.resizable)
			this.setResizable();
	}

	Dialog.prototype.setResizable = function()
	{
		if(this.resizable)
			return;

		var root = this.root;
		this.resizable = true;
		var footer = this.footer;
		footer.style.minHeight = "4px";
		footer.classList.add("resizable");

		var corner = document.createElement("div");
		corner.className = "resizable-corner";
		this.root.appendChild( corner );

		footer.addEventListener("mousedown", inner_mouse);
		corner.addEventListener("mousedown", inner_mouse, true);

		var mouse = [0,0];
		var that = this;

		var is_corner = false;

		function inner_mouse(e)
		{
			//console.log( getTime(), is_corner );

			if(e.type == "mousedown")
			{
				document.body.addEventListener("mousemove", inner_mouse);
				document.body.addEventListener("mouseup", inner_mouse);
				is_corner = this == corner;
				mouse[0] = e.pageX;
				mouse[1] = e.pageY;
			}
			else if(e.type == "mousemove")
			{
				var rect = LiteGUI.getRect( root );
				var w = rect.width;
				var neww = w - (mouse[0] - e.pageX);
	
				var h = rect.height;
				var newh = h - (mouse[1] - e.pageY);

				if(is_corner)
					root.style.width = neww + "px";
				root.style.height = newh + "px";

				mouse[0] = e.pageX;
				mouse[1] = e.pageY;
				that.content.style.height = "calc( 100% - 24px )";

				if(that.on_resize && (w != neww || h != newh) )
					that.on_resize(e,neww,newh);
			}
			else if(e.type == "mouseup")
			{
				document.body.removeEventListener("mousemove", inner_mouse);
				document.body.removeEventListener("mouseup", inner_mouse);
				is_corner = false;
			}
			e.preventDefault();
			e.stopPropagation();
			return false;
		}
	}

	Dialog.prototype.dockTo = function( parent, dock_type )
	{
		if(!parent) return;
		var panel = this.root;

		dock_type = dock_type || "full";
		parent = parent.content || parent;

		panel.style.top = 0;
		panel.style.left = 0;

		panel.style.boxShadow = "0 0 0";

		if(dock_type == "full")
		{
			panel.style.position = "relative";
			panel.style.width = "100%";
			panel.style.height = "100%";
			this.content.style.width = "100%";
			this.content.style.height = "calc(100% - "+ LiteGUI.Panel.title_height +")"; //title offset: 20px
			this.content.style.height = "-moz-calc(100% - "+ LiteGUI.Panel.title_height +")";
			this.content.style.height = "-webkit-calc(100% - "+ LiteGUI.Panel.title_height +")"; 
			this.content.style.overflow = "auto";
		}
		else if(dock_type == 'left' || dock_type == 'right')
		{
			panel.style.position = "absolute";
			panel.style.top = 0;
			panel.style[dock_type] = 0;

			panel.style.width = this.width + "px";
			panel.style.height = "100%";

			this.content.style.height = "-moz-calc(100% - "+ LiteGUI.Panel.title_height +")";
			this.content.style.height = "-webkit-calc(100% - "+ LiteGUI.Panel.title_height +")";
			this.content.style.height = "calc(100% - "+ LiteGUI.Panel.title_height +")";
			this.content.style.overflow = "auto";

			if(dock_type == 'right')
			{
				panel.style.left = "auto";
				panel.style.right = 0;
			}
		}
		else if(dock_type == 'bottom' || dock_type == 'top')
		{
			panel.style.width = "100%";
			panel.style.height = this.height + "px";
			if(dock_type == 'bottom')
			{
				panel.style.bottom = 0;
				panel.style.top = "auto";
			}
		}

		if(this.draggable)
		{
			//$(panel).draggable({disabled: true});
			LiteGUI.draggable(panel);
		}
		

		if(parent.content)
			parent.content.appendChild(panel);
		else if( typeof(parent) == "string")
		{
			parent = document.querySelector( parent );
			if(parent)
				parent.appendChild( panel )
		}
		else
			parent.appendChild( panel ); 
	}

	Dialog.prototype.addButton = function(name,options)
	{
		options = options || {};
		if( options.constructor === Function )
			options = { callback: options };

		var that = this;
		var button = document.createElement("button");
		button.className = "litebutton";

		button.innerHTML = name;
		if(options.className)
			button.className += " " + options.className;

		this.root.querySelector(".panel-footer").appendChild( button );

		button.addEventListener("click", function(e) { 
			if(options.callback)
				options.callback(this);

			if(options.close)
				that.close();
		});

		return button;
	}

	/**
	* destroys the dialog
	* @method close
	*/
	Dialog.prototype.close = function() {
		LiteGUI.remove( this.root );
		LiteGUI.trigger( this, "closed", this);
		if(this.on_close)
			this.on_close();
		if(this.onclose)
			console.warn("Dialog: Do not use onclose, use on_close instead");
		if(this.dialog_window)
		{
			this.dialog_window.close();
			this.dialog_window = null;
		}
	}

	Dialog.prototype.highlight = function(time)
	{
		time = time || 100;
		this.root.style.outline = "1px solid white";
		var doc = this.root.ownerDocument;
		var w = doc.defaultView || doc.parentWindow;
		w.focus();
		setTimeout( (function(){
			this.root.style.outline = null;
		}).bind(this), time );
	}

	Dialog.minimized = [];

	Dialog.prototype.minimize = function() {
		if(this.minimized)
			return;

		this.minimized = true;
		this.old_box = this.root.getBoundingClientRect();

		this.root.querySelector(".content").style.display = "none";
		
		var minimize_button = this.root.querySelector(".minimize-button");
		if(minimize_button)	
			minimize_button.style.display = "none";

		var maximize_button = this.root.querySelector(".maximize-button");
		if(maximize_button)
			maximize_button.style.display = "";

		this.root.style.width = LiteGUI.Dialog.MINIMIZED_WIDTH + "px";

		LiteGUI.bind( this, "closed", function() {
			LiteGUI.Dialog.minimized.splice( LiteGUI.Dialog.minimized.indexOf( this ), 1);
			LiteGUI.Dialog.arrangeMinimized();
		});

		LiteGUI.Dialog.minimized.push( this );
		LiteGUI.Dialog.arrangeMinimized();

		LiteGUI.trigger( this,"minimizing" );
	}

	Dialog.arrangeMinimized = function()
	{
		for(var i in LiteGUI.Dialog.minimized)
		{
			var dialog = LiteGUI.Dialog.minimized[i];
			var parent = dialog.root.parentNode;
			var pos = parent.getBoundingClientRect().height - 20;
			//$(dialog.root).animate({ left: LiteGUI.Dialog.MINIMIZED_WIDTH * i, top: pos + "px" },100);
			dialog.root.style.left = LiteGUI.Dialog.MINIMIZED_WIDTH * i;
			dialog.root.style.top = pos + "px";
		}
	}

	Dialog.prototype.maximize = function() {
		if(!this.minimized)
			return;
		this.minimized = false;

		this.root.querySelector(".content").style.display = "";
		LiteGUI.draggable(this.root);
		this.root.style.left = this.old_box.left+"px";
		this.root.style.top = this.old_box.top + "px";
		this.root.style.width = this.old_box.width + "px";
		this.root.style.height = this.old_box.height + "px";

		var minimize_button = this.root.querySelector(".minimize-button");
		if(minimize_button)
			minimize_button.style.display = "";

		var maximize_button = this.root.querySelector(".maximize-button");
		if(maximize_button)
			maximize_button.style.display = "none";

		LiteGUI.Dialog.minimized.splice( LiteGUI.Dialog.minimized.indexOf( this ), 1);
		LiteGUI.Dialog.arrangeMinimized();
		LiteGUI.trigger( this, "maximizing" );
	}

	Dialog.prototype.makeModal = function()
	{
		LiteGUI.showModalBackground(true);
		LiteGUI.modalbg_div.appendChild( this.root ); //add panel
		this.show();
		this.center();

		LiteGUI.bind( this, "closed", inner );

		function inner(e)
		{
			LiteGUI.showModalBackground(false);
		}
	}

	Dialog.prototype.bringToFront = function()
	{
		var parent = this.root.parentNode;
		parent.removeChild(this.root);
		parent.appendChild(this.root);
	}

	/**
	* shows a hidden dialog
	* @method show
	*/
	Dialog.prototype.show = function( v, reference_element )
	{
		if(!this.root.parentNode)
		{
			if(!reference_element)
				LiteGUI.add( this );
			else
			{
				var doc = reference_element.ownerDocument;
				var parent = doc.querySelector(".litegui-wrap") || doc.body;
				parent.appendChild( this.root );
				var w = doc.defaultView || doc.parentWindow;
				w.focus();
			}
			this.center();
		}

		//$(this.root).show(v,null,100,callback);
		if(!this.detach_window)
		{
			this.root.style.display = "";
			LiteGUI.trigger( this, "shown" );
		}
	}

	/**
	* hides the dialog
	* @method hide
	*/
	Dialog.prototype.hide = function( v )
	{
		this.root.style.display = "none";
		LiteGUI.trigger(this, "hidden");
	}

	Dialog.prototype.fadeIn = function(time)
	{
		time = time || 1000;
		this.root.style.display = "";
		this.root.style.opacity = 0;
		var that = this;
		setTimeout(function(){
			that.root.style.transition = "opacity "+time+"ms";
			that.root.style.opacity = 1;
		},100);
	}

	Dialog.prototype.setPosition = function(x,y)
	{
		if(!this.root.parentNode)
			console.warn("LiteGUI.Dialog: Cannot set position of dialog if it is not in the DOM");
		this.root.position = "absolute";
		this.root.style.left = x + "px";
		this.root.style.top = y + "px";
	}

	Dialog.prototype.setSize = function( w, h )
	{
		this.root.style.width = typeof(w) == "number" ? w + "px" : w;
		this.root.style.height = typeof(h) == "number" ? h + "px" : h;
	}

	Dialog.prototype.setTitle = function(text)
	{
		if(!this.header)
			return;
		this.header.innerHTML = text;
	}

	Dialog.prototype.center = function()
	{
		if(!this.root.parentNode)
			return;

		this.root.position = "absolute";
		var width = this.root.offsetWidth;
		var height = this.root.offsetHeight;
		var parent_width = this.root.parentNode.offsetWidth;
		var parent_height = this.root.parentNode.offsetHeight;
		this.root.style.left = Math.floor(( parent_width - width ) * 0.5) + "px";
		this.root.style.top = Math.floor(( parent_height - height ) * 0.5) + "px";
	}

	/**
	* Adjust the size of the dialog to the size of the content
	* @method adjustSize
	* @param {number} margin
	*/
	Dialog.prototype.adjustSize = function( margin, skip_timeout )
	{
		margin = margin || 0;
		this.content.style.height = "auto";

		if(this.content.offsetHeight == 0 && !skip_timeout) //happens sometimes if the dialog is not yet visible
		{
			var that = this;
			setTimeout( function(){ that.adjustSize( margin, true ); }, 1 );
			return;
		}

		var extra = 0;
		var footer = this.root.querySelector(".panel-footer");
		if(footer)
			extra += footer.offsetHeight;

		var width = this.content.offsetWidth;
		var height = this.content.offsetHeight + 20 + margin + extra;

		this.setSize( width, height );
	}

	Dialog.prototype.clear = function()
	{
		this.content.innerHTML = "";
	}

	Dialog.prototype.detachWindow = function( on_complete, on_close )
	{
		if(this.dialog_window)
			return;

		//create window
		var rect = this.root.getClientRects()[0];
		var w = rect.width;
		var h = rect.height;
		var title = "Window";
		var header = this.root.querySelector(".panel-header");
		if(header)
			title = header.textContent;

		var dialog_window = window.open("","","width="+w+", height="+h+", location=no, status=no, menubar=no, titlebar=no, fullscreen=yes");
		dialog_window.document.write( "<head><title>"+title+"</title>" );
		this.dialog_window = dialog_window;

		//transfer style
		var styles = document.querySelectorAll("link[rel='stylesheet'],style");
		for(var i = 0; i < styles.length; i++)
			dialog_window.document.write( styles[i].outerHTML );
		dialog_window.document.write( "</head><body></body>" );
		dialog_window.document.close();

		var that = this;

		//closing event
		dialog_window.onbeforeunload = function(){
			var index = LiteGUI.windows.indexOf( dialog_window );
			if(index != -1)
				LiteGUI.windows.splice( index, 1 );
			if(on_close)
				on_close();
		}

		//move the content there
		dialog_window.document.body.appendChild( this.content );
		this.root.style.display = "none"; //hide
		this._old_height = this.content.style.height;
		this.content.style.height = "100%";

		LiteGUI.windows.push( dialog_window );

		if(on_complete)
			on_complete();

		return dialog_window;		
	}

	Dialog.prototype.reattachWindow = function( on_complete )
	{
		if(!this.dialog_window)
			return;

		this.root.appendChild( this.content );
		this.root.style.display = ""; //show
		this.content.style.height = this._old_height;
		delete this._old_height;
		this.dialog_window.close();
		var index = LiteGUI.windows.indexOf( this.dialog_window );
		if(index != -1)
			LiteGUI.windows.splice( index, 1 );
		this.dialog_window = null;
	}


	//*********************************************

	Dialog.showAll = function()
	{
		var dialogs = document.body.querySelectorAll("litedialog");
		for(var i = 0; i < dialogs.length; i++)
		{
			var dialog = dialogs[i];
			dialog.dialog.show();
		}
	}

	Dialog.hideAll = function()
	{
		var dialogs = document.body.querySelectorAll("litedialog");
		for(var i = 0; i < dialogs.length; i++)
		{
			var dialog = dialogs[i];
			dialog.dialog.hide();
		}
	}

	Dialog.closeAll = function()
	{
		var dialogs = document.body.querySelectorAll("litedialog");
		for(var i = 0; i < dialogs.length; i++)
		{
			var dialog = dialogs[i];
			dialog.dialog.close();
		}
	}

	LiteGUI.Dialog = Dialog;
})();