/*! * jQuery DialogExtend 1.1.0 * * Copyright (c) 2013 Shum Ting Hin, Thomas von Deyen * * Licensed under MIT * http:// www.opensource.org/licenses/mit-license.php * * Project Home: * http:// code.google.com/p/jquery-dialogextend/ * * Depends: * jQuery 1.9.1 * jQuery UI Dialog 1.10.1 * */ (function($){ // default settings var defaults = { "close" : true, "maximize" : false, "minimize" : false, "dblclick" : false, "titlebar" : false, "icons" : { "close" : "ui-icon-closethick", "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) // do bunch of things... .dialogExtend("_verifySettings") .dialogExtend("_initEvents") .dialogExtend("_initStyles") .dialogExtend("_initButtons") .dialogExtend("_initTitleBar") // set default dialog state .dialogExtend("_setState", "normal") // trigger custom event when done .dialogExtend("_trigger", "load"); }); // maintain chainability return self; }, "state" : function(){ return $(this).data("dialog-extend-state"); }, "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") // modify dialog size (after hiding content) .dialog("option", { "resizable" : false, "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") // mark new state .dialogExtend("_setState", "collapsed") // trigger custom event .dialogExtend("_trigger", "collapse"); // maintain chainability return self; }, "maximize" : function(){ var self = this; // caculate new dimension var newHeight = $(window).height()+10; var newWidth = $(window).width()-4; // start! $(self) // trigger custom event .dialogExtend("_trigger", "beforeMaximize") // restore to normal state first (when necessary) .each(function(){ if ( $(this).dialogExtend("state") != "normal" ) { $(this).dialogExtend("_restoreWithoutTriggerEvent"); } }) // remember original state .dialogExtend("_saveSnapshot") // 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") .find(".ui-dialog-draggable-handle").css("cursor", "text").end() .find(".ui-dialog-content") // mark new state .dialogExtend("_setState", "maximized") // modify dialog buttons according to new state .dialogExtend("_toggleButtons") // trigger custom event .dialogExtend("_trigger", "maximize"); // maintain chainability return self; }, "minimize" : function(){ var self = this; // 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 ( $("#dialog-extend-fixed-container").length ) { var fixedContainer = $("#dialog-extend-fixed-container"); } else { var fixedContainer = $('
').appendTo("body"); } $(fixedContainer).css({ "position" : "fixed", "bottom" : 1, "left" : 1, "z-index" : 9999 }); // start! $(self) // trigger custom event .dialogExtend("_trigger", "beforeMinimize") // remember original state .dialogExtend("_saveSnapshot") // move dialog from body to container (at lower-left-hand corner) .dialog("widget") .css({ // float is essential for stacking dialog when there are many many minimized dialogs "float" : "left", "margin" : 1, "position" : "static" }) .appendTo(fixedContainer) .find(".ui-dialog-content") // modify dialog with new config .dialog("option", { "resizable" : false, //"draggable" : false, "height" : newHeight, "width" : newWidth }) // avoid title text overlap buttons .dialog("widget") .find(".ui-dialog-titlebar").each(function(){ var titlebar = this; var buttonPane = $(this).find(".ui-dialog-titlebar-buttonpane"); var titleText = $(this).find(".ui-dialog-title"); $(titleText).css({ 'overflow': 'hidden', 'width' : $(titlebar).width() - $(buttonPane).width() + 10 }); }).end() .find(".ui-dialog-content") // 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") // mark new state .dialogExtend("_setState", "minimized") // modify dialog button according to new state .dialogExtend("_toggleButtons") // trigger custom event .dialogExtend("_trigger", "minimize"); // maintain chainability return self; }, "restore" : function(){ var self = this; // start! $(self) // trigger custom event .dialogExtend("_trigger", "beforeRestore") // restore to normal .dialogExtend("_restoreWithoutTriggerEvent") // mark new state ===> must set state *AFTER* restore because '_restoreWithoutTriggerEvent' will check 'beforeState' .dialogExtend("_setState", "normal") // modify dialog buttons according to new state .dialogExtend("_toggleButtons") // 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"); // create container for buttons var buttonPane = $('
').appendTo(titlebar); $(buttonPane).css({ "position" : "absolute", "top" : "50%", "right" : "0.3em", "margin-top" : "-10px", "height" : "18px" }); // move 'close' button to button-pane $(titlebar) .find(".ui-dialog-titlebar-close") // override some unwanted jquery-ui styles .css({ "position" : "static", "top" : "auto", "right" : "auto", "margin" : 0 }) // change icon .find(".ui-icon").removeClass("ui-icon-closethick").addClass(settings.icons.close).end() // move to button-pane .appendTo(buttonPane) .end(); // append other buttons to button-pane $(buttonPane) .append('') .append('') .append('') // 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"); $(this).removeClass("ui-state-default"); }) .mouseout(function(){ $(this).removeClass("ui-state-hover"); $(this).addClass("ui-state-default"); }) .focus(function(){ $(this).addClass("ui-state-focus"); $(this).removeClass("ui-state-default"); }) .blur(function(){ $(this).removeClass("ui-state-focus"); $(this).addClass("ui-state-default"); }) .end() // default show buttons // set button positions // on-click-button .find(".ui-dialog-titlebar-close") .toggle(settings.close) .end() .find(".ui-dialog-titlebar-maximize") .toggle(settings.maximize) .click(function(e){ e.preventDefault(); $(self).dialogExtend("maximize"); }) .end() .find(".ui-dialog-titlebar-minimize") .toggle(settings.minimize) .click(function(e){ e.preventDefault(); $(self).dialogExtend("minimize"); }) .end() .find(".ui-dialog-titlebar-restore") .hide() .click(function(e){ e.preventDefault(); $(self).dialogExtend("restore"); }) .end(); // other titlebar behaviors $(titlebar) // on-dblclick-titlebar : maximize/minimize/collapse/restore .dblclick(function(evt){ if ( settings.dblclick && settings.dblclick.length ) { $(self).dialogExtend( $(self).dialogExtend("state") != "normal" ? "restore" : settings.dblclick ); } }) // avoid text-highlight when double-click .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 if ( !$(".dialog-extend-css").length ) { 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", { "resizable" : original.config.resizable, "height" : original.size.height, "maxHeight" : original.size.maxHeight }); // maintain chainability return self; }, "_restoreFromNormal" : function(){ // do nothing actually... // maintain chainability return this; }, "_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 .dialog("option", { "resizable" : original.config.resizable, "draggable" : original.config.draggable, "height" : original.size.height, "width" : original.size.width, "maxHeight" : original.size.maxHeight }) // restore position *AFTER* size restored .dialog("option", { "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"); // 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") // revert title text .dialog("widget") .find(".ui-dialog-title") .css({ "width" : "auto" }) .end() .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 .dialog("option", { "resizable" : original.config.resizable, "draggable" : original.config.draggable, "height" : original.size.height, "width" : original.size.width, "maxHeight" : original.size.maxHeight }) // restore position *AFTER* size restored .dialog("option", { "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; }, "_restoreWithoutTriggerEvent" : function(){ var self = this; var beforeState = $(self).dialogExtend("state"); $(self) // restore dialog according to previous state .dialogExtend( beforeState == "maximized" ? "_restoreFromMaximized" : beforeState == "minimized" ? "_restoreFromMinimized" : beforeState == "collapsed" ? "_restoreFromCollapsed" : beforeState == "normal" ? "_restoreFromNormal" : $.error( "jQuery.dialogExtend Error : Cannot restore dialog from unknown state '" + beforeState +"'" ) ); // maintain chainability return self; }, "_saveSnapshot" : function(){ var self = this; // remember all configs under normal state if ( $(self).dialogExtend("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()+14) .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; }, "_setState" : function(state){ var self = this; $(self) // toggle data state .data("dialog-extend-state", state) // toggle class .removeClass("ui-dialog-normal ui-dialog-maximized ui-dialog-minimized ui-dialog-collapsed") .addClass("ui-dialog-"+state); // 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).dialogExtend("state") != "maximized" && settings.maximize ) .end() .find(".ui-dialog-titlebar-minimize") .toggle( $(self).dialogExtend("state") != "minimized" && settings.minimize ) .end() .find(".ui-dialog-titlebar-restore") .toggle( $(self).dialogExtend("state") != "normal" && ( settings.maximize || settings.minimize ) ) .css({ "right" : $(self).dialogExtend("state") == "maximized" ? "1.4em" : $(self).dialogExtend("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));