Files
2024-12-10 23:24:15 +01:00

460 lines
17 KiB
JavaScript

/*
* jQuery.dockmodal - jQuery dockable modal dialog widget
*
* Copyright 2014, uxMine
* Dual licensed under the MIT or GPL Version 2 licenses.
* Date: 2/11/2014
* @author Tarafder Ashek E Elahi
* @version 1.1
* Depends:
* jquery.js
*
*/
;
(function ($) {
var defaults = {
width: 400,
height: "65%",
minimizedWidth: 200,
gutter: 10,
poppedOutDistance: "6%",
title: function() {
return "";
},
dialogClass: "",
buttons: [], /* id, html, buttonClass, click */
animationSpeed: 400,
opacity: 1,
initialState: 'modal', /* "modal", "docked", "minimized" */
showClose: true,
showPopout: true,
showMinimize: true,
create: undefined,
open: undefined,
beforeClose: undefined,
close: undefined,
beforeMinimize: undefined,
minimize: undefined,
beforeRestore: undefined,
restore: undefined,
beforePopout: undefined,
popout: undefined
};
var dClass = "dockmodal";
var windowWidth = $(window).width();
function setAnimationCSS($this, $el) {
var aniSpeed = $this.options.animationSpeed / 1000;
$el.css({"transition": aniSpeed + "s right, " + aniSpeed + "s left, " + aniSpeed + "s top, " + aniSpeed + "s bottom, " + aniSpeed + "s height, " + aniSpeed + "s width"});
return true;
}
function removeAnimationCSS($el) {
$el.css({"transition": "none"});
return true;
}
var methods = {
init: function (options) {
return this.each(function () {
var $this = $(this);
var data = $this.data('dockmodal');
$this.options = $.extend({}, defaults, options);
// Check to see if title is a returned function
(function titleCheck() {
if (typeof $this.options.title == "function") {
$this.options.title = $this.options.title.call($this);
}
})();
// If the plugin hasn't been initialized yet
if (!data) {
$this.data('dockmodal', $this);
} else {
$("body").append($this.closest("." + dClass).show());
//methods.restore.apply($this);
methods.refreshLayout();
setTimeout(function () {
methods.restore.apply($this);
}, $this.options.animationSpeed);
return;
}
// create modal
var $body = $("body");
var $window = $(window);
var $dockModal = $('<div/>').addClass(dClass).addClass($this.options.dialogClass);
if ($this.options.initialState == "modal") {
$dockModal.addClass("popped-out");
} else if ($this.options.initialState == "minimized") {
$dockModal.addClass("minimized");
}
//$dockModal.width($this.options.width);
$dockModal.height(0);
setAnimationCSS($this, $dockModal);
// create title
var $dockHeader = $('<div></div>').addClass(dClass + "-header");
if ($this.options.showClose) {
$('<a href="#" class="header-action action-close" title="Close"><i class="icon-dockmodal-close"></i></a>').appendTo($dockHeader).click(function (e) {
methods.destroy.apply($this);
return false;
});
}
if ($this.options.showPopout) {
$('<a href="#" class="header-action action-popout" title="Pop out"><i class="icon-dockmodal-popout"></i></a>').appendTo($dockHeader).click(function (e) {
if ($dockModal.hasClass("popped-out")) {
methods.restore.apply($this);
} else {
methods.popout.apply($this);
}
return false;
});
}
if ($this.options.showMinimize) {
$('<a href="#" class="header-action action-minimize" title="Minimize"><i class="icon-dockmodal-minimize"></i></a>').appendTo($dockHeader).click(function (e) {
if ($dockModal.hasClass("minimized")) {
if ($dockModal.hasClass("popped-out")) {
methods.popout.apply($this);
} else {
methods.restore.apply($this);
}
} else {
methods.minimize.apply($this);
}
return false;
});
}
if ($this.options.showMinimize && $this.options.showPopout) {
$dockHeader.click(function () {
if ($dockModal.hasClass("minimized")) {
if ($dockModal.hasClass("popped-out")) {
methods.popout.apply($this);
} else {
methods.restore.apply($this);
}
} else {
methods.minimize.apply($this);
}
return false;
});
}
$dockHeader.append('<div class="title-text">' + ($this.options.title || $this.attr("title")) + '</div>');
$dockModal.append($dockHeader);
// create body section
var $placeholder = $('<div class="modal-placeholder"></div>').insertAfter($this);
$this.placeholder = $placeholder;
var $dockBody = $('<div></div>').addClass(dClass + "-body").append($this);
$dockModal.append($dockBody);
// create footer
if ($this.options.buttons.length) {
var $dockFooter = $('<div></div>').addClass(dClass + "-footer");
var $dockFooterButtonset = $('<div></div>').addClass(dClass + "-footer-buttonset");
$dockFooter.append($dockFooterButtonset);
$.each($this.options.buttons, function (indx, el) {
var $btn = $('<a href="#" class="btn"></a>');
$btn.attr({ "id": el.id, "class": el.buttonClass });
$btn.html(el.html);
$btn.click(function (e) {
el.click(e, $this);
return false;
});
$dockFooterButtonset.append($btn);
});
$dockModal.append($dockFooter);
} else {
$dockModal.addClass("no-footer");
}
// create overlay
var $overlay = $("." + dClass + "-overlay");
if (!$overlay.length) {
$overlay = $('<div/>').addClass(dClass + "-overlay");
}
// raise create event
if ($.isFunction($this.options.create)) {
$this.options.create($this);
}
$body.append($dockModal);
$dockModal.after($overlay);
$dockBody.focus();
// raise open event
if ($.isFunction($this.options.open)) {
setTimeout(function () {
$this.options.open($this);
}, $this.options.animationSpeed);
}
//methods.restore.apply($this);
if ($dockModal.hasClass("minimized")) {
$dockModal.find(".dockmodal-body, .dockmodal-footer").hide();
methods.minimize.apply($this);
} else {
if ($dockModal.hasClass("popped-out")) {
methods.popout.apply($this);
} else {
methods.restore.apply($this);
}
}
// attach resize event
// track width, set to window width
$body.data("windowWidth", $window.width());
$window.unbind("resize.dockmodal").bind("resize.dockmodal", function () {
// do nothing if the width is the same
// update new width value
if ($window.width() == $body.data("windowWidth")) {
return;
}
$body.data("windowWidth", $window.width());
methods.refreshLayout();
});
});
},
destroy: function () {
return this.each(function () {
var $this = $(this).data('dockmodal');
if (!$this)
return;
// raise beforeClose event
if ($.isFunction($this.options.beforeClose)) {
if ($this.options.beforeClose($this) === false) {
return;
}
}
try {
var $dockModal = $this.closest("." + dClass);
if ($dockModal.hasClass("popped-out") && !$dockModal.hasClass("minimized")) {
$dockModal.css({
"left": "50%",
"right": "50%",
"top": "50%",
"bottom": "50%"
});
} else {
$dockModal.css({
"width": "0",
"height": "0"
});
}
setTimeout(function () {
$this.removeData('dockmodal');
$this.placeholder.replaceWith($this);
$dockModal.remove();
$("." + dClass + "-overlay").hide();
methods.refreshLayout();
// raise close event
if ($.isFunction($this.options.close)) {
$this.options.close($this);
}
}, $this.options.animationSpeed);
}
catch (err) {
alert(err.message);
}
// other destroy routines
})
},
close: function () {
methods.destroy.apply(this);
},
minimize: function () {
return this.each(function () {
var $this = $(this).data('dockmodal');
if (!$this)
return;
// raise beforeMinimize event
if ($.isFunction($this.options.beforeMinimize)) {
if ($this.options.beforeMinimize($this) === false) {
return;
}
}
var $dockModal = $this.closest("." + dClass);
var headerHeight = $dockModal.find(".dockmodal-header").outerHeight();
$dockModal.addClass("minimized").css({
"width": $this.options.minimizedWidth + "px",
"height": headerHeight + "px",
"left": "auto",
"right": "auto",
"top": "auto",
"bottom": "0"
});
setTimeout(function () {
// for safty, hide the body and footer
$dockModal.find(".dockmodal-body, .dockmodal-footer").hide();
// raise minimize event
if ($.isFunction($this.options.minimize)) {
$this.options.minimize($this);
}
}, $this.options.animationSpeed);
$("." + dClass + "-overlay").hide();
$dockModal.find(".action-minimize").attr("title", "Restore");
methods.refreshLayout();
})
},
restore: function () {
return this.each(function () {
var $this = $(this).data('dockmodal');
if (!$this)
return;
// raise beforeRestore event
if ($.isFunction($this.options.beforeRestore)) {
if ($this.options.beforeRestore($this) === false) {
return;
}
}
var $dockModal = $this.closest("." + dClass);
$dockModal.removeClass("minimized popped-out");
$dockModal.find(".dockmodal-body, .dockmodal-footer").show();
$dockModal.css({
"width": $this.options.width + "px",
"height": $this.options.height,
"left": "auto",
"right": "auto",
"top": "auto",
"bottom": "0"
});
$("." + dClass + "-overlay").hide();
$dockModal.find(".action-minimize").attr("title", "Minimize");
$dockModal.find(".action-popout").attr("title", "Pop-out");
setTimeout(function () {
// raise restore event
if ($.isFunction($this.options.restore)) {
$this.options.restore($this);
}
}, $this.options.animationSpeed);
methods.refreshLayout();
})
},
popout: function () {
return this.each(function () {
var $this = $(this).data('dockmodal');
if (!$this)
return;
// raise beforePopout event
if ($.isFunction($this.options.beforePopout)) {
if ($this.options.beforePopout($this) === false) {
return;
}
}
var $dockModal = $this.closest("." + dClass);
$dockModal.find(".dockmodal-body, .dockmodal-footer").show();
// prepare element for animation
removeAnimationCSS($dockModal);
var offset = $dockModal.position();
var windowWidth = $(window).width();
$dockModal.css({
"width": "auto",
"height": "auto",
"left": offset.left + "px",
"right": (windowWidth - offset.left - $dockModal.outerWidth(true)) + "px",
"top": offset.top + "px",
"bottom": 0
});
setAnimationCSS($this, $dockModal);
setTimeout(function () {
$dockModal.removeClass("minimized").addClass("popped-out").css({
"width": "auto",
"height": "auto",
"left": $this.options.poppedOutDistance,
"right": $this.options.poppedOutDistance,
"top": $this.options.poppedOutDistance,
"bottom": $this.options.poppedOutDistance
});
$("." + dClass + "-overlay").show();
$dockModal.find(".action-popout").attr("title", "Pop-in");
methods.refreshLayout();
}, 10);
setTimeout(function () {
// raise popout event
if ($.isFunction($this.options.popout)) {
$this.options.popout($this);
}
}, $this.options.animationSpeed);
});
},
refreshLayout: function () {
var right = 0;
var windowWidth = $(window).width();
$.each($("." + dClass).toArray().reverse(), function (i, val) {
var $dockModal = $(this);
var $this = $dockModal.find("." + dClass + "-body > div").data("dockmodal");
if ($dockModal.hasClass("popped-out") && !$dockModal.hasClass("minimized")) {
return;
}
right += $this.options.gutter;
$dockModal.css({ "right": right + "px" });
if ($dockModal.hasClass("minimized")) {
right += $this.options.minimizedWidth;
} else {
right += $this.options.width;
}
if (right > windowWidth) {
$dockModal.hide();
} else {
setTimeout(function () {
$dockModal.show();
}, $this.options.animationSpeed);
}
});
}
};
$.fn.dockmodal = function (method) {
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('Method ' + method + ' does not exist on jQuery.dockmodal');
}
};
})(jQuery);