metro4
Version:
The front-end framework for Build responsive, mobile-first projects on the web with the first front-end component library in Metro Style
816 lines (675 loc) • 25 kB
JavaScript
/* global Metro, Cake */
(function(Metro, $) {
'use strict';
var Utils = Metro.utils;
var WindowDefaultConfig = {
windowDeferred: 0,
hidden: false,
width: "auto",
height: "auto",
btnClose: true,
btnMin: true,
btnMax: true,
draggable: true,
dragElement: ".window-caption .icon, .window-caption .title",
dragArea: "parent",
shadow: false,
icon: "",
title: "Window",
content: null,
resizable: true,
overlay: false,
overlayColor: 'transparent',
overlayAlpha: .5,
modal: false,
position: "absolute",
checkEmbed: true,
top: "auto",
left: "auto",
place: "auto",
closeAction: Metro.actions.REMOVE,
customButtons: null,
clsCustomButton: "",
clsCaption: "",
clsContent: "",
clsWindow: "",
_runtime: false,
minWidth: 0,
minHeight: 0,
maxWidth: 0,
maxHeight: 0,
onDragStart: Metro.noop,
onDragStop: Metro.noop,
onDragMove: Metro.noop,
onCaptionDblClick: Metro.noop,
onCloseClick: Metro.noop,
onMaxClick: Metro.noop,
onMinClick: Metro.noop,
onResizeStart: Metro.noop,
onResizeStop: Metro.noop,
onResize: Metro.noop,
onWindowCreate: Metro.noop,
onShow: Metro.noop,
onWindowDestroy: Metro.noop,
onCanClose: Metro.noop_true,
onClose: Metro.noop
};
Metro.windowSetup = function (options) {
WindowDefaultConfig = $.extend({}, WindowDefaultConfig, options);
};
if (typeof window["metroWindowSetup"] !== undefined) {
Metro.windowSetup(window["metroWindowSetup"]);
}
Metro.Component('window', {
init: function( options, elem ) {
this._super(elem, options, WindowDefaultConfig, {
win: null,
overlay: null,
position: {
top: 0,
left: 0
},
hidden: false,
content: null
});
return this;
},
_create: function(){
var that = this, element = this.element, o = this.options;
var win, overlay;
var parent = o.dragArea === "parent" ? element.parent() : $(o.dragArea);
var _content;
if (o.modal === true) {
o.btnMax = false;
o.btnMin = false;
o.resizable = false;
}
if (Utils.isNull(o.content)) {
o.content = element;
} else {
if (Utils.isUrl(o.content) && Utils.isVideoUrl(o.content)) {
o.content = Utils.embedUrl(o.content);
element.css({
height: "100%"
});
} else
if (!Utils.isQ(o.content) && Utils.isFunc(o.content)) {
o.content = Utils.exec(o.content);
}
_content = $(o.content);
if (_content.length === 0) {
element.appendText(o.content);
} else {
element.append(_content);
}
o.content = element;
}
if (o._runtime === true) {
this._runtime(element, "window");
}
win = this._window(o);
win.addClass("no-visible");
parent.append(win);
if (o.overlay === true) {
overlay = this._overlay();
overlay.appendTo(win.parent());
this.overlay = overlay;
}
this.win = win;
this._fireEvent("window-create", {
win: this.win[0],
element: element
});
setTimeout(function(){
that._setPosition();
if (o.hidden !== true) {
that.win.removeClass("no-visible");
}
that._fireEvent("show", {
win: that.win[0],
element: element
});
}, 100);
},
_setPosition: function(){
var o = this.options;
var win = this.win;
var parent = o.dragArea === "parent" ? win.parent() : $(o.dragArea);
var top_center = parent.height() / 2 - win[0].offsetHeight / 2;
var left_center = parent.width() / 2 - win[0].offsetWidth / 2;
var top, left, right, bottom;
if (o.place !== 'auto') {
switch (o.place.toLowerCase()) {
case "top-left": top = 0; left = 0; right = "auto"; bottom = "auto"; break;
case "top-center": top = 0; left = left_center; right = "auto"; bottom = "auto"; break;
case "top-right": top = 0; right = 0; left = "auto"; bottom = "auto"; break;
case "right-center": top = top_center; right = 0; left = "auto"; bottom = "auto"; break;
case "bottom-right": bottom = 0; right = 0; left = "auto"; top = "auto"; break;
case "bottom-center": bottom = 0; left = left_center; right = "auto"; top = "auto"; break;
case "bottom-left": bottom = 0; left = 0; right = "auto"; top = "auto"; break;
case "left-center": top = top_center; left = 0; right = "auto"; bottom = "auto"; break;
default: top = top_center; left = left_center; bottom = "auto"; right = "auto";
}
win.css({
top: top,
left: left,
bottom: bottom,
right: right
});
}
},
_window: function(o){
var that = this;
var win, caption, content, icon, title, buttons, btnClose, btnMin, btnMax, resizer, status;
var width = o.width, height = o.height;
win = $("<div>").addClass("window");
if (o.modal === true) {
win.addClass("modal");
}
caption = $("<div>").addClass("window-caption");
content = $("<div>").addClass("window-content");
win.append(caption);
win.append(content);
if (o.status === true) {
status = $("<div>").addClass("window-status");
win.append(status);
}
if (o.shadow === true) {
win.addClass("win-shadow");
}
if (Utils.isValue(o.icon)) {
icon = $("<span>").addClass("icon").html(o.icon);
icon.appendTo(caption);
}
title = $("<span>").addClass("title").html(Utils.isValue(o.title) ? o.title : " ");
title.appendTo(caption);
if (!Utils.isNull(o.content)) {
if (Utils.isQ(o.content)) {
o.content.appendTo(content);
} else {
content.html(o.content);
}
}
buttons = $("<div>").addClass("buttons");
buttons.appendTo(caption);
if (o.btnMax === true) {
btnMax = $("<span>").addClass("button btn-max sys-button");
btnMax.appendTo(buttons);
}
if (o.btnMin === true) {
btnMin = $("<span>").addClass("button btn-min sys-button");
btnMin.appendTo(buttons);
}
if (o.btnClose === true) {
btnClose = $("<span>").addClass("button btn-close sys-button");
btnClose.appendTo(buttons);
}
if (Utils.isValue(o.customButtons)) {
var customButtons = [];
if (Utils.isObject(o.customButtons) !== false) {
o.customButtons = Utils.isObject(o.customButtons);
}
if (typeof o.customButtons === "string" && o.customButtons.indexOf("{") > -1) {
customButtons = JSON.parse(o.customButtons);
} else if (typeof o.customButtons === "object" && Utils.objectLength(o.customButtons) > 0) {
customButtons = o.customButtons;
} else {
console.warn("Unknown format for custom buttons");
}
$.each(customButtons, function(){
var item = this;
var customButton = $("<span>");
customButton
.addClass("button btn-custom")
.addClass(o.clsCustomButton)
.addClass(item.cls)
.attr("tabindex", -1)
.html(item.html);
if (item.attr && typeof item.attr === 'object') {
$.each(item.attr, function(k, v){
customButton.attr(Str.dashedName(k), v);
});
}
customButton.data("action", item.onclick);
buttons.prepend(customButton);
});
}
caption.on(Metro.events.stop, ".btn-custom", function(e){
if (Utils.isRightMouse(e)) return;
var button = $(this);
var action = button.data("action");
Utils.exec(action, [button], this);
});
win.attr("id", o.id === undefined ? Utils.elementId("window") : o.id);
win.on(Metro.events.dblclick, ".window-caption", function(e){
that.maximized(e);
});
caption.on(Metro.events.click, ".btn-max, .btn-min, .btn-close", function(e){
if (Utils.isRightMouse(e)) return;
var target = $(e.target);
if (target.hasClass("btn-max")) that.maximized(e);
if (target.hasClass("btn-min")) that.minimized(e);
if (target.hasClass("btn-close")) that.close(e);
});
if (o.draggable === true) {
Metro.makePlugin(win, "draggable", {
dragContext: win[0],
dragElement: o.dragElement,
dragArea: o.dragArea,
onDragStart: o.onDragStart,
onDragStop: o.onDragStop,
onDragMove: o.onDragMove
});
}
win.addClass(o.clsWindow);
caption.addClass(o.clsCaption);
content.addClass(o.clsContent);
if (o.minWidth === 0) {
o.minWidth = 34;
$.each(buttons.children(".btn-custom"), function(){
o.minWidth += Utils.hiddenElementSize(this).width;
});
if (o.btnMax) o.minWidth += 34;
if (o.btnMin) o.minWidth += 34;
if (o.btnClose) o.minWidth += 34;
}
if (o.minWidth > 0 && !isNaN(o.width) && o.width < o.minWidth) {
width = o.minWidth;
}
if (o.minHeight > 0 && !isNaN(o.height) && o.height > o.minHeight) {
height = o.minHeight;
}
if (o.resizable === true) {
resizer = $("<span>").addClass("resize-element");
resizer.appendTo(win);
win.addClass("resizable");
Metro.makePlugin(win, "resizable", {
minWidth: o.minWidth,
minHeight: o.minHeight,
maxWidth: o.maxWidth,
maxHeight: o.maxHeight,
resizeElement: ".resize-element",
onResizeStart: o.onResizeStart,
onResizeStop: o.onResizeStop,
onResize: o.onResize
});
}
win.css({
width: width,
height: height,
position: o.position,
top: o.top,
left: o.left
});
return win;
},
_overlay: function(){
var o = this.options;
var overlay = $("<div>");
overlay.addClass("overlay");
if (o.overlayColor === 'transparent') {
overlay.addClass("transparent");
} else {
overlay.css({
background: Metro.colors.toRGBA(o.overlayColor, o.overlayAlpha)
});
}
return overlay;
},
width: function(v){
var win = this.win;
if (!Utils.isValue(v)) {
return win.width();
}
win.css("width", parseInt(v));
return this;
},
height: function(v){
var win = this.win;
if (!Utils.isValue(v)) {
return win.height();
}
win.css("height", parseInt(v));
return this;
},
maximized: function(e){
var win = this.win, o = this.options;
var target = $(e.target);
if (o.btnMax) {
win.removeClass("minimized");
win.toggleClass("maximized");
}
if (target.hasClass && target.hasClass("title")) {
this._fireEvent("caption-dbl-click", {
win: win[0]
});
} else {
this._fireEvent("max-click", {
win: win[0]
});
}
},
minimized: function(){
var win = this.win, o = this.options;
if (o.btnMin) {
win.removeClass("maximized");
win.toggleClass("minimized");
}
this._fireEvent("min-click", {
win: win[0]
});
},
close: function(){
var that = this, win = this.win, o = this.options;
if (Utils.exec(o.onCanClose, [win]) === false) {
return false;
}
var timeout = 0;
if (o.onClose !== Metro.noop) {
timeout = 500;
}
this._fireEvent("close", {
win: win[0]
});
setTimeout(function(){
if (o.modal === true) {
win.siblings(".overlay").remove();
}
that._fireEvent("close-click", {
win: win[0]
});
if (o.closeAction === Metro.actions.REMOVE) {
that._fireEvent("window-destroy", {
win: win[0]
});
win.remove();
} else {
that.hide();
}
}, timeout);
},
hide: function(){
var win = this.win;
win.css({
display: "none"
});
this._fireEvent("hide", {
win: win[0]
});
},
show: function(){
var win = this.win;
win
.removeClass("no-visible")
.css({
display: "flex"
});
this._fireEvent("show", {
win: win[0]
});
},
toggle: function(){
if (this.win.css("display") === "none" || this.win.hasClass("no-visible")) {
this.show();
} else {
this.hide();
}
},
isOpen: function(){
return this.win.hasClass("no-visible");
},
min: function(a){
a ? this.win.addClass("minimized") : this.win.removeClass("minimized");
},
max: function(a){
a ? this.win.addClass("maximized") : this.win.removeClass("maximized");
},
changeClass: function(a){
var element = this.element, win = this.win, o = this.options;
if (a === "data-cls-window") {
win[0].className = "window " + (o.resizable ? " resizable " : " ") + element.attr("data-cls-window");
}
if (a === "data-cls-caption") {
win.find(".window-caption")[0].className = "window-caption " + element.attr("data-cls-caption");
}
if (a === "data-cls-content") {
win.find(".window-content")[0].className = "window-content " + element.attr("data-cls-content");
}
},
toggleShadow: function(){
var element = this.element, win = this.win;
var flag = JSON.parse(element.attr("data-shadow"));
if (flag === true) {
win.addClass("win-shadow");
} else {
win.removeClass("win-shadow");
}
},
setContent: function(c){
var element = this.element, win = this.win;
var content = Utils.isValue(c) ? c : element.attr("data-content");
var result;
if (!Utils.isQ(content) && Utils.isFunc(content)) {
result = Utils.exec(content);
} else if (Utils.isQ(content)) {
result = content.html();
} else {
result = content;
}
win.find(".window-content").html(result);
},
setTitle: function(t){
var element = this.element, win = this.win;
var title = Utils.isValue(t) ? t : element.attr("data-title");
win.find(".window-caption .title").html(title);
},
setIcon: function(i){
var element = this.element, win = this.win;
var icon = Utils.isValue(i) ? i : element.attr("data-icon");
win.find(".window-caption .icon").html(icon);
},
getIcon: function(){
return this.win.find(".window-caption .icon").html();
},
getTitle: function(){
return this.win.find(".window-caption .title").html();
},
toggleDraggable: function(f){
var win = this.win;
var flag = Utils.bool(f);
var drag = Metro.getPlugin(win, "draggable");
if (flag === true) {
drag.on();
} else {
drag.off();
}
},
toggleResizable: function(f){
var win = this.win;
var flag = Utils.bool(f);
var resize = Metro.getPlugin(win, "resizable");
if (flag === true) {
resize.on();
win.find(".resize-element").removeClass("resize-element-disabled");
} else {
resize.off();
win.find(".resize-element").addClass("resize-element-disabled");
}
},
changePlace: function (p) {
var element = this.element, win = this.win;
var place = Utils.isValue(p) ? p : element.attr("data-place");
win.addClass(place);
},
pos: function(top, left){
var win = this.win;
win.css({
top: top,
left: left
});
return this;
},
top: function(v){
this.win.css({
top: v
});
return this;
},
left: function(v){
this.win.css({
left: v
});
return this;
},
changeAttribute: function(attr, value){
var changePos = function(a, v){
var win = this.win;
var pos;
if (a === "data-top") {
pos = parseInt(v);
if (!isNaN(pos)) {
return ;
}
win.css("top", pos);
}
if (a === "data-left") {
pos = parseInt(v);
if (!isNaN(pos)) {
return ;
}
win.css("left", pos);
}
};
var toggleButtons = function(a, v) {
var win = this.win;
var btnClose = win.find(".btn-close");
var btnMin = win.find(".btn-min");
var btnMax = win.find(".btn-max");
var _v = Utils.bool(v);
var func = _v ? "show" : "hide";
switch (a) {
case "data-btn-close": btnClose[func](); break;
case "data-btn-min": btnMin[func](); break;
case "data-btn-max": btnMax[func](); break;
}
};
var changeSize = function(a, v){
var win = this.win;
if (a === "data-width") {
win.css("width", +v);
}
if (a === "data-height") {
win.css("height", +v);
}
};
switch (attr) {
case "data-btn-close":
case "data-btn-min":
case "data-btn-max": toggleButtons(attr, value); break;
case "data-width":
case "data-height": changeSize(attr, value); break;
case "data-cls-window":
case "data-cls-caption":
case "data-cls-content": this.changeClass(attr); break;
case "data-shadow": this.toggleShadow(); break;
case "data-icon": this.setIcon(); break;
case "data-title": this.setTitle(); break;
case "data-content": this.setContent(); break;
case "data-draggable": this.toggleDraggable(value); break;
case "data-resizable": this.toggleResizable(value); break;
case "data-top":
case "data-left": changePos(attr, value); break;
case "data-place": this.changePlace(); break;
}
},
destroy: function(){
return this.element;
}
});
Metro['window'] = {
isWindow: function(el){
return Utils.isMetroObject(el, "window");
},
min: function(el, a){
if (!this.isWindow(el)) {
return false;
}
Metro.getPlugin(el,"window").min(a);
},
max: function(el, a){
if (!this.isWindow(el)) {
return false;
}
Metro.getPlugin(el, "window").max(a);
},
show: function(el){
if (!this.isWindow(el)) {
return false;
}
Metro.getPlugin(el, "window").show();
},
hide: function(el){
if (!this.isWindow(el)) {
return false;
}
Metro.getPlugin(el, "window").hide();
},
toggle: function(el){
if (!this.isWindow(el)) {
return false;
}
Metro.getPlugin(el, "window").toggle();
},
isOpen: function(el){
if (!this.isWindow(el)) {
return false;
}
var win = Metro.getPlugin(el,"window");
return win.isOpen();
},
close: function(el){
if (!this.isWindow(el)) {
return false;
}
Metro.getPlugin(el, "window").close();
},
pos: function(el, top, left){
if (!this.isWindow(el)) {
return false;
}
Metro.getPlugin(el, "window").pos(top, left);
},
top: function(el, top){
if (!this.isWindow(el)) {
return false;
}
Metro.getPlugin(el, "window").top(top);
},
left: function(el, left){
if (!this.isWindow(el)) {
return false;
}
Metro.getPlugin(el, "window").left(left);
},
width: function(el, width){
if (!this.isWindow(el)) {
return false;
}
Metro.getPlugin(el, "window").width(width);
},
height: function(el, height){
if (!this.isWindow(el)) {
return false;
}
Metro.getPlugin(el, "window").height(height);
},
create: function(options, parent){
var w;
w = $("<div>").appendTo(parent ? $(parent) : $("body"));
var w_options = $.extend({
_runtime: true
}, (options ? options : {}));
return Metro.makePlugin(w, "window", w_options);
}
};
}(Metro, m4q));