/*! * jQuery DialogExtend 1.0 * * Copyright (c) 2010 Shum Ting Hin * * Licensed under MIT * http://www.opensource.org/licenses/mit-license.php * * Project Home: * http://code.google.com/p/jquery-dialogextend/ * * Depends: * jQuery 1.4 * jQuery UI Dialog 1.8.0 * * History: * 0.9 / 2010-11-04 / hin / creation of plugin * 0.9.1 / 2010-11-16 / hin / fix bug of zero-config * 0.9.2 / 2010-12-16 / hin / fix bug of not firing event * apply as init option for defining event-callback * 1.0 / 2010-01-05 / hin / fix bug of button-pane in 'minimized' state * fix bug of title-bar word-wrap in 'minimized' state * apply as init option for enhancing title-bar feature * apply as init option for enhancing double-click feature * */ (function($){ //default settings var defaults = { "maximize" : false, "minimize" : false, "dblclick" : false, "titlebar" : false, "icons" : { "maximize" : "ui-icon-extlink", "minimize" : "ui-icon-minus", "restore" : "ui-icon-newwin" }, "events" : { "load" : null, "beforeCollapse" : null, "beforeMaximize" : null, "beforeMinimize" : null, "beforeRestore" : null, "collapse" : null, "maximize" : null, "minimize" : null, "restore" : null } }; //plugin settings (will be modified during init) var settings; //plubic methods var methods = { "init" : function( options ){ var self = this; //validation if ( !$(self).dialog ) { $.error( "jQuery.dialogExtend Error : Only jQuery UI Dialog element is accepted" ); } //merge defaults & options, without modifying the defaults options = options || {}; options.icons = options.icons || {}; options.events = options.events || {}; settings = $.extend({}, defaults, options); settings.icons = $.extend({}, defaults.icons, options.icons); settings.events = $.extend({}, defaults.events, options.events); //initiate plugin... $(self).each(function(){ $(this) //set default dialog state .data("dialog-state", "normal") //do bunch of things... .dialogExtend("_verifySettings") .dialogExtend("_initEvents") .dialogExtend("_initStyles") .dialogExtend("_initButtons") .dialogExtend("_initTitleBar") //trigger custom event when done .dialogExtend("_trigger", "load"); }); //maintain chainability return self; }, "collapse" : function(){ var self = this; //calculate new dimension var newHeight = $(this).dialog("widget").find(".ui-dialog-titlebar").height()+15; //start! $(self) //trigger custom event .dialogExtend("_trigger", "beforeCollapse") //remember original state .dialogExtend("_saveSnapshot") //mark new state .data("dialog-state", "collapsed") //modify dialog size (after hiding content) .dialog("option", { "height" : newHeight, "maxHeight" : newHeight }) //hide content //hide button-pane //make title-bar no-wrap .hide() .dialog("widget") .find(".ui-dialog-buttonpane:visible").hide().end() .find(".ui-dialog-titlebar").css("white-space", "nowrap").end() .find(".ui-dialog-content") //trigger custom event .dialogExtend("_trigger", "collapse"); //maintain chainability return self; }, "maximize" : function(){ var self = this; //caculate new dimension var newHeight = $(window).height()-11; var newWidth = $(window).width()-11; //start! $(self) //trigger custom event .dialogExtend("_trigger", "beforeMaximize") //remember original state .dialogExtend("_saveSnapshot") //mark new state .data("dialog-state", "maximized") //modify dialog button .dialogExtend("_toggleButtons") //fix dialog from scrolling .dialog("widget") .css("position", "fixed") .find(".ui-dialog-content") //show content //show button-pane (when minimized/collapsed) .show() .dialog("widget") .find(".ui-dialog-buttonpane").show().end() .find(".ui-dialog-content") //modify dialog with new config .dialog("option", { "resizable" : false, "draggable" : false, "height" : newHeight, "width" : newWidth, "position" : [1, 1] }) //disable draggable-handle (for only) .dialog("widget") // .draggable("option", "handle", null) .find(".ui-dialog-draggable-handle").css("cursor", "text").end() .find(".ui-dialog-content") //trigger custom event .dialogExtend("_trigger", "maximize"); //maintain chainability return self; }, "minimize" : function(){ var self = this; var container = "#minimized-dialog-container"; //caculate new dimension var newHeight = $(this).dialog("widget").find(".ui-dialog-titlebar").height()+15; var newWidth = 200; //create container for (multiple) minimized dialogs (when necessary) if ( !$(container).length ) { $("
") .attr("id", container.replace("#", "")) .css({ "left" : 1, "bottom" : 1, "position" : "fixed" }) .appendTo("body"); } //start! $(self) //trigger custom event .dialogExtend("_trigger", "beforeMinimize") //remember original state .dialogExtend("_saveSnapshot") //mark new state .data("dialog-state", "minimized") //modify dialog button .dialogExtend("_toggleButtons") //move dialog from body to container .dialog("widget") .css({ "float" : "left", //float is essential for stacking "margin" : 1, "position" : "static" }) .appendTo(container) .find(".ui-dialog-content") //modify dialog with new config .dialog("option", { "resizable" : false, "draggable" : false, "height" : newHeight, "width" : newWidth }) //hide content //hide button-pane //make title-bar no-wrap .hide() .dialog("widget") .find(".ui-dialog-buttonpane:visible").hide().end() .find(".ui-dialog-titlebar").css("white-space", "nowrap").end() .find(".ui-dialog-content") //disable draggable-handle (for only) .dialog("widget") .draggable("option", "handle", null) .find(".ui-dialog-draggable-handle").css("cursor", "text").end() .find(".ui-dialog-content") //trigger custom event .dialogExtend("_trigger", "minimize"); //maintain chainability return self; }, "restore" : function(){ var self = this; var beforeState = $(self).data("dialog-state"); //start! $(self) //trigger custom event .dialogExtend("_trigger", "beforeRestore") //mark new state .data("dialog-state", "normal") //restore dialog button .dialogExtend("_toggleButtons") //restore dialog according to previous state .dialogExtend( beforeState == "maximized" ? "_restoreFromMaximized" : beforeState == "minimized" ? "_restoreFromMinimized" : beforeState == "collapsed" ? "_restoreFromCollapsed" : $.error( "jQuery.dialogExtend Error : Cannot restore dialog from unknown state '" + beforeState +"'" ) ) //trigger custom event .dialogExtend("_trigger", "restore"); //maintain chainability return self; }, "_initButtons" : function(){ var self = this; //start operation on titlebar var titlebar = $(self).dialog("widget").find(".ui-dialog-titlebar"); $(titlebar) .append('maximize') .append('minimize') .append('restore') //add effect to buttons .find(".ui-dialog-titlebar-maximize,.ui-dialog-titlebar-minimize,.ui-dialog-titlebar-restore") .attr("role", "button") .mouseover(function(){ $(this).addClass("ui-state-hover"); }) .mouseout(function(){ $(this).removeClass("ui-state-hover"); }) .focus(function(){ $(this).addClass("ui-state-focus"); }) .blur(function(){ $(this).removeClass("ui-state-focus"); }) .end() //default show buttons //set button positions //on-click-button .find(".ui-dialog-titlebar-maximize") .toggle(settings.maximize) .css({ "right" : settings.maximize ? "1.4em" : "-9999em" }) .click(function(e){ e.preventDefault(); $(self).dialogExtend("maximize"); }) .end() .find(".ui-dialog-titlebar-minimize") .toggle(settings.minimize) .css({ "right" : settings.maximize ? "2.5em" : settings.minimize ? "1.4em" : "-9999em" }) .click(function(e){ e.preventDefault(); $(self).dialogExtend("minimize"); }) .end() .find(".ui-dialog-titlebar-restore") .hide() .css({ "right" : "-9999em" }) .click(function(e){ e.preventDefault(); $(self).dialogExtend("restore"); }) .end() //on-dblclick-titlebar : maximize/minimize/collapse/restore .dblclick(function(evt){ if ( settings.dblclick && settings.dblclick.length ) { $(self).dialogExtend( $(self).data("dialog-state") != "normal" ? "restore" : settings.dblclick ); } }) //avoid text-highlight when double-click .each(function(){ $(this) //.attr("unselectable", "on") //.css({ "-moz-user-select" : "none", "-khtml-user-select" : "none" }) .select(function(){ return false; }); }); //maintain chainability return self; }, "_initEvents" : function(){ var self = this; //bind event callbacks which specified at init $.each(settings.events, function(type){ if ( $.isFunction( settings.events[type] ) ) { $(self).bind(type+".dialogExtend", settings.events[type]); } }); //maintain chainability return self; }, "_initStyles" : function(){ var self = this; //append styles for this plugin to body var style = ''; style += ''; $(style).appendTo("body"); //maintain chainability return self; }, "_initTitleBar" : function(){ var self = this; //modify title bar switch ( settings.titlebar ) { case false: //do nothing break; case "none": //create new draggable-handle as substitute of title bar if ( $(self).dialog("option", "draggable") ) { var handle = $("
").addClass("ui-dialog-draggable-handle").css("cursor", "move").height(5); $(self).dialog("widget").prepend(handle).draggable("option", "handle", handle); } //remove title bar and keep it draggable $(self) .dialog("widget") .find(".ui-dialog-titlebar") //clear title text .find(".ui-dialog-title").html(" ").end() //keep buttons at upper-right-hand corner .css({ "background-color" : "transparent", "background-image" : "none", "border" : 0, "position" : "absolute", "right" : 0, "top" : 0, "z-index" : 9999 }) .end(); break; case "transparent": //remove title style $(self) .dialog("widget") .find(".ui-dialog-titlebar") .css({ "background-color" : "transparent", "background-image" : "none", "border" : 0 }); break; default: $.error( "jQuery.dialogExtend Error : Invalid value '" + settings.titlebar + "'" ); } //maintain chainability return self; }, "_loadSnapshot" : function(){ var self = this; return { "config" : { "resizable" : $(self).data("original-config-resizable"), "draggable" : $(self).data("original-config-draggable") }, "size" : { "height" : $(self).data("original-size-height"), "width" : $(self).data("original-size-width"), "maxHeight" : $(self).data("original-size-maxHeight") }, "position" : { "mode" : $(self).data("original-position-mode"), "left" : $(self).data("original-position-left"), "top" : $(self).data("original-position-top") }, "titlebar" : { "wrap" : $(self).data("original-titlebar-wrap") } }; }, "_restoreFromCollapsed" : function(){ var self = this; var original = $(this).dialogExtend("_loadSnapshot"); //restore dialog $(self) //show content //show button-pane //fix title-bar wrap .show() .dialog("widget") .find(".ui-dialog-buttonpane:hidden").show().end() .find(".ui-dialog-titlebar").css("white-space", original.titlebar.wrap).end() .find(".ui-dialog-content") //restore config & size .dialog("option", { "height" : original.size.height, "maxHeight" : original.size.maxHeight }); //maintain chainability return self; }, "_restoreFromMaximized" : function(){ var self = this; var original = $(this).dialogExtend("_loadSnapshot"); //restore dialog $(self) //free dialog from scrolling //fix title-bar wrap (if dialog was minimized/collapsed) .dialog("widget") .css("position", original.position.mode) .find(".ui-dialog-titlebar").css("white-space", original.titlebar.wrap).end() .find(".ui-dialog-content") //restore config & size & position .dialog("option", { "resizable" : original.config.resizable, "draggable" : original.config.draggable, "height" : original.size.height, "width" : original.size.width, "maxHeight" : original.size.maxHeight, "position" : [ original.position.left, original.position.top ] }) //restore draggable-handle (for only) .dialog("widget") .draggable("option", "handle", $(this).find(".ui-dialog-draggable-handle")) .find(".ui-dialog-draggable-handle") .css("cursor", "move"); //maintain chainability return self; }, "_restoreFromMinimized" : function(){ var self = this; var original = $(this).dialogExtend("_loadSnapshot"); var container = "#minimized-dialog-container"; //restore dialog $(self) //move dialog back from container to body .dialog("widget") .appendTo("body") .css({ "float" : "none", "margin" : 0, "position" : original.position.mode }) .find(".ui-dialog-content") //show content //show button-pane //fix title-bar wrap .show() .dialog("widget") .find(".ui-dialog-buttonpane:hidden").show().end() .find(".ui-dialog-titlebar").css("white-space", original.titlebar.wrap).end() .find(".ui-dialog-content") //restore config & size & position .dialog("option", { "resizable" : original.config.resizable, "draggable" : original.config.draggable, "height" : original.size.height, "width" : original.size.width, "maxHeight" : original.size.maxHeight, "position" : [ original.position.left, original.position.top ] }) //restore draggable-handle (for only) .dialog("widget") .draggable("option", "handle", $(this).find(".ui-dialog-draggable-handle")) .find(".ui-dialog-draggable-handle") .css("cursor", "move"); //maintain chainability return self; }, "_saveSnapshot" : function(){ var self = this; //remember all configs under normal state if ( $(self).data("dialog-state") == "normal" ) { $(self) .data("original-config-resizable", $(self).dialog("option", "resizable")) .data("original-config-draggable", $(self).dialog("option", "draggable")) .data("original-size-height", $(self).dialog("widget").height()) .data("original-size-width", $(self).dialog("option", "width")) .data("original-size-maxHeight", $(self).dialog("option", "maxHeight")) .data("original-position-mode", $(self).dialog("widget").css("position")) .data("original-position-left", $(self).dialog("widget").offset().left) .data("original-position-top", $(self).dialog("widget").offset().top) .data("original-titlebar-wrap", $(self).dialog("widget").find(".ui-dialog-titlebar").css("white-space")); } //maintain chainability return self; }, "_toggleButtons" : function(){ var self = this; //show or hide buttons & decide position $(self).dialog("widget") .find(".ui-dialog-titlebar-maximize") .toggle( $(self).data("dialog-state") != "maximized" && settings.maximize ) .end() .find(".ui-dialog-titlebar-minimize") .toggle( $(self).data("dialog-state") != "minimized" && settings.minimize ) .end() .find(".ui-dialog-titlebar-restore") .toggle( $(self).data("dialog-state") != "normal" && ( settings.maximize || settings.minimize ) ) .css({ "right" : $(self).data("dialog-state") == "maximized" ? "1.4em" : $(self).data("dialog-state") == "minimized" ? !settings.maximize ? "1.4em" : "2.5em" : "-9999em" }) .end(); //maintain chainability return self; }, "_trigger" : function( type ){ var self = this; //trigger event with namespace when user bind to it $(self).triggerHandler(type+".dialogExtend", this); //maintain chainability return self; }, "_verifySettings" : function(){ var self = this; //check option if ( !settings.dblclick ) { } else if ( settings.dblclick == "maximize" ) { } else if ( settings.dblclick == "minimize" ) { } else if ( settings.dblclick == "collapse" ) { } else { $.error( "jQuery.dialogExtend Error : Invalid value '" + settings.dblclick + "'" ); settings.dblclick = false; } //check option if ( !settings.titlebar ) { } else if ( settings.titlebar == "none" ) { } else if ( settings.titlebar == "transparent" ) { } else { $.error( "jQuery.dialogExtend Error : Invalid value '" + settings.titlebar + "'" ); settings.titlebar = false; } //maintain chainability return self; } }; //core method $.fn.dialogExtend = function( method ){ //method calling logic if ( methods[ method ] ) { return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ) ); } else if ( typeof method === "object" || ! method ) { return methods.init.apply( this, arguments ); } else { $.error( "jQuery.dialogExtend Error : Method <" + method + "> does not exist" ); } }; }(jQuery));