ax5ui-modal
Version:
A modal plugin that works with Bootstrap & jQuery
1,255 lines (1,137 loc) • 45.1 kB
JavaScript
/*
* Copyright (c) 2016. tom@axisj.com
* - github.com/thomasjang
* - www.axisj.com
*/
// ax5.ui.modal
(function() {
const UI = ax5.ui;
const U = ax5.util;
let MODAL;
UI.addClass(
{
className: "modal"
},
(function() {
/**
* @class ax5modal
* @alias ax5.ui.modal
* @author tom@axisj.com
*/
return function() {
let self = this,
cfg,
ENM = {
mousedown: ax5.info.supportTouch ? "touchstart" : "mousedown",
mousemove: ax5.info.supportTouch ? "touchmove" : "mousemove",
mouseup: ax5.info.supportTouch ? "touchend" : "mouseup"
},
getMousePosition = function(e) {
let mouseObj = e;
if ("changedTouches" in e && e.changedTouches) {
mouseObj = e.changedTouches[0];
}
return {
clientX: mouseObj.clientX,
clientY: mouseObj.clientY
};
};
this.instanceId = ax5.getGuid();
this.config = {
id: "ax5-modal-" + this.instanceId,
position: {
left: "center",
top: "middle",
margin: 10
},
minimizePosition: "bottom-right",
clickEventName:
"ontouchstart" in document.documentElement ? "touchstart" : "click",
theme: "default",
width: 300,
height: 400,
closeToEsc: true,
disableDrag: false,
disableResize: false,
animateTime: 250,
iframe: false
};
this.activeModal = null;
this.watingModal = false;
this.$ = {}; // UI inside of the jQuery object store
cfg = this.config; // extended config copy cfg
let onStateChanged = function(opts, that) {
var eventProcessor = {
resize: function(that) {
if (opts && opts.onResize) {
opts.onResize.call(that, that);
} else if (this.onResize) {
this.onResize.call(that, that);
}
},
move: function() {}
};
if (that.state in eventProcessor) {
eventProcessor[that.state].call(this, that);
}
if (opts && opts.onStateChanged) {
opts.onStateChanged.call(that, that);
} else if (this.onStateChanged) {
this.onStateChanged.call(that, that);
}
return true;
},
getContent = function(modalId, opts) {
let data = {
modalId: modalId,
theme: opts.theme,
header: opts.header,
fullScreen: opts.fullScreen ? "fullscreen" : "",
styles: "",
iframe: opts.iframe,
iframeLoadingMsg: opts.iframeLoadingMsg,
disableResize: opts.disableResize
};
if (opts.zIndex) {
data.styles += "z-index:" + opts.zIndex + ";";
}
if (opts.absolute) {
data.styles += "position:absolute;";
}
if (data.iframe && typeof data.iframe.param === "string") {
data.iframe.param = ax5.util.param(data.iframe.param);
}
return MODAL.tmpl.get.call(this, "content", data, {});
},
open = function(opts, callback) {
let that;
jQuery(document.body).append(getContent.call(this, opts.id, opts));
this.activeModal = jQuery("#" + opts.id);
// 파트수집
this.$ = {
root: this.activeModal,
header: this.activeModal.find('[data-modal-els="header"]'),
body: this.activeModal.find('[data-modal-els="body"]')
};
if (opts.iframe) {
this.$["iframe-wrap"] = this.activeModal.find(
'[data-modal-els="iframe-wrap"]'
);
this.$["iframe"] = this.activeModal.find(
'[data-modal-els="iframe"]'
);
this.$["iframe-form"] = this.activeModal.find(
'[data-modal-els="iframe-form"]'
);
this.$["iframe-loading"] = this.activeModal.find(
'[data-modal-els="iframe-loading"]'
);
} else {
this.$["body-frame"] = this.activeModal.find(
'[data-modal-els="body-frame"]'
);
}
//- position 정렬
this.align();
that = {
self: this,
id: opts.id,
theme: opts.theme,
width: opts.width,
height: opts.height,
state: "open",
$: this.$
};
if (opts.iframe) {
this.$["iframe-wrap"].css({ height: opts.height });
this.$["iframe"].css({ height: opts.height });
// iframe content load
this.$["iframe-form"].attr({ method: opts.iframe.method });
this.$["iframe-form"].attr({ target: opts.id + "-frame" });
this.$["iframe-form"].attr({ action: opts.iframe.url });
this.$["iframe"].on(
"load",
function() {
that.state = "load";
if (opts.iframeLoadingMsg) {
this.$["iframe-loading"].hide();
}
onStateChanged.call(this, opts, that);
}.bind(this)
);
if (!opts.iframeLoadingMsg) {
this.$["iframe"].show();
}
this.$["iframe-form"].submit();
}
if (callback) callback.call(that, that);
if (!this.watingModal) {
onStateChanged.call(this, opts, that);
}
// bind key event
if (opts.closeToEsc) {
jQuery(window).bind(
"keydown.ax-modal",
function(e) {
onkeyup.call(this, e || window.event);
}.bind(this)
);
}
jQuery(window).bind(
"resize.ax-modal",
function(e) {
this.align(null, e || window.event);
}.bind(this)
);
this.$.header
.off(ENM["mousedown"])
.off("dragstart")
.on(ENM["mousedown"], function(e) {
/// 이벤트 필터링 추가 : 버튼엘리먼트로 부터 발생된 이벤트이면 moveModal 시작하지 않도록 필터링
let isButton = U.findParentNode(e.target, function(_target) {
if (_target.getAttribute("data-modal-header-btn")) {
return true;
}
});
if (
!opts.isFullScreen &&
!isButton &&
opts.disableDrag != true
) {
self.mousePosition = getMousePosition(e);
moveModal.on.call(self);
}
if (isButton) {
btnOnClick.call(self, e || window.event, opts);
}
})
.on("dragstart", function(e) {
U.stopEvent(e.originalEvent);
return false;
});
this.activeModal
.off(ENM["mousedown"])
.off("dragstart")
.on(ENM["mousedown"], "[data-ax5modal-resizer]", function(e) {
if (opts.disableDrag || opts.isFullScreen) return false;
self.mousePosition = getMousePosition(e);
resizeModal.on.call(
self,
this.getAttribute("data-ax5modal-resizer")
);
})
.on("dragstart", function(e) {
U.stopEvent(e.originalEvent);
return false;
});
},
btnOnClick = function(e, opts, callback, target, k) {
let that;
if (e.srcElement) e.target = e.srcElement;
target = U.findParentNode(e.target, function(target) {
if (target.getAttribute("data-modal-header-btn")) {
return true;
}
});
if (target) {
k = target.getAttribute("data-modal-header-btn");
that = {
self: this,
key: k,
value: opts.header.btns[k],
dialogId: opts.id,
btnTarget: target
};
if (opts.header.btns[k].onClick) {
opts.header.btns[k].onClick.call(that, k);
}
}
that = null;
opts = null;
callback = null;
target = null;
k = null;
},
onkeyup = function(e) {
if (e.keyCode == ax5.info.eventKeys.ESC) {
this.close();
}
},
alignProcessor = {
"top-left": function() {
this.align({ left: "left", top: "top" });
},
"top-right": function() {
this.align({ left: "right", top: "top" });
},
"bottom-left": function() {
this.align({ left: "left", top: "bottom" });
},
"bottom-right": function() {
this.align({ left: "right", top: "bottom" });
},
"center-middle": function() {
this.align({ left: "center", top: "middle" });
}
},
moveModal = {
on: function() {
let modalZIndex = this.activeModal.css("z-index"),
modalOffset = this.activeModal.offset(),
modalBox = {
width: this.activeModal.outerWidth(),
height: this.activeModal.outerHeight()
},
windowBox = {
width: jQuery(window).width(),
height: jQuery(window).height(),
scrollLeft: jQuery(document).scrollLeft(),
scrollTop: jQuery(document).scrollTop()
},
getResizerPosition = function(e) {
self.__dx = e.clientX - self.mousePosition.clientX;
self.__dy = e.clientY - self.mousePosition.clientY;
/*
if (minX > modalOffset.left + self.__dx) {
self.__dx = -modalOffset.left;
} else if (maxX < modalOffset.left + self.__dx) {
self.__dx = maxX - modalOffset.left;
}
if (minY > modalOffset.top + self.__dy) {
self.__dy = -modalOffset.top;
} else if (maxY < modalOffset.top + self.__dy) {
self.__dy = maxY - modalOffset.top;
}
*/
return {
left: modalOffset.left + self.__dx,
top: modalOffset.top + self.__dy
};
};
let minX = 0,
maxX = windowBox.width - modalBox.width,
minY = 0,
maxY = windowBox.height - modalBox.height;
self.__dx = 0; // 변화량 X
self.__dy = 0; // 변화량 Y
// self.resizerBg : body 가 window보다 작을 때 문제 해결을 위한 DIV
self.resizerBg = jQuery(
'<div class="ax5modal-resizer-background" ondragstart="return false;"></div>'
);
self.resizer = jQuery(
'<div class="ax5modal-resizer" ondragstart="return false;"></div>'
);
self.resizerBg.css({ zIndex: modalZIndex });
self.resizer.css({
left: modalOffset.left,
top: modalOffset.top,
width: modalBox.width,
height: modalBox.height,
zIndex: modalZIndex + 1
});
jQuery(document.body)
.append(self.resizerBg)
.append(self.resizer);
self.activeModal.addClass("draged");
jQuery(document.body)
.on(
ENM["mousemove"] + ".ax5modal-move-" + this.instanceId,
function(e) {
self.resizer.css(getResizerPosition(e));
}
)
.on(
ENM["mouseup"] + ".ax5modal-move-" + this.instanceId,
function(e) {
moveModal.off.call(self);
}
)
.on("mouseleave.ax5modal-move-" + this.instanceId, function(e) {
moveModal.off.call(self);
});
jQuery(document.body)
.attr("unselectable", "on")
.css("user-select", "none")
.on("selectstart", false);
},
off: function() {
let setModalPosition = function() {
let box = this.resizer.offset();
if (!this.modalConfig.absolute) {
box.left -= jQuery(document).scrollLeft();
box.top -= jQuery(document).scrollTop();
}
this.activeModal.css(box);
this.modalConfig.left = box.left;
this.modalConfig.top = box.top;
box = null;
};
this.activeModal.removeClass("draged");
setModalPosition.call(this);
this.resizer.remove();
this.resizer = null;
this.resizerBg.remove();
this.resizerBg = null;
//this.align();
jQuery(document.body)
.off(ENM["mousemove"] + ".ax5modal-move-" + this.instanceId)
.off(ENM["mouseup"] + ".ax5modal-move-" + this.instanceId)
.off("mouseleave.ax5modal-move-" + this.instanceId);
jQuery(document.body)
.removeAttr("unselectable")
.css("user-select", "auto")
.off("selectstart");
onStateChanged.call(this, self.modalConfig, {
self: this,
state: "move"
});
}
},
resizeModal = {
on: function(resizerType) {
let modalZIndex = this.activeModal.css("z-index"),
modalOffset = this.activeModal.offset(),
modalBox = {
width: this.activeModal.outerWidth(),
height: this.activeModal.outerHeight()
},
windowBox = {
width: jQuery(window).width(),
height: jQuery(window).height(),
scrollLeft: jQuery(document).scrollLeft(),
scrollTop: jQuery(document).scrollTop()
},
resizerProcessor = {
top: function(e) {
if (minHeight > modalBox.height - self.__dy) {
self.__dy = modalBox.height - minHeight;
}
if (e.shiftKey) {
if (minHeight > modalBox.height - self.__dy * 2) {
self.__dy = (modalBox.height - minHeight) / 2;
}
return {
left: modalOffset.left,
top: modalOffset.top + self.__dy,
width: modalBox.width,
height: modalBox.height - self.__dy * 2
};
} else if (e.altKey) {
if (minHeight > modalBox.height - self.__dy * 2) {
self.__dy = (modalBox.height - minHeight) / 2;
}
return {
left: modalOffset.left + self.__dy,
top: modalOffset.top + self.__dy,
width: modalBox.width - self.__dy * 2,
height: modalBox.height - self.__dy * 2
};
} else {
return {
left: modalOffset.left,
top: modalOffset.top + self.__dy,
width: modalBox.width,
height: modalBox.height - self.__dy
};
}
},
bottom: function(e) {
if (minHeight > modalBox.height + self.__dy) {
self.__dy = -modalBox.height + minHeight;
}
if (e.shiftKey) {
if (minHeight > modalBox.height + self.__dy * 2) {
self.__dy = (-modalBox.height + minHeight) / 2;
}
return {
left: modalOffset.left,
top: modalOffset.top - self.__dy,
width: modalBox.width,
height: modalBox.height + self.__dy * 2
};
} else if (e.altKey) {
if (minHeight > modalBox.height + self.__dy * 2) {
self.__dy = (-modalBox.height + minHeight) / 2;
}
return {
left: modalOffset.left - self.__dy,
top: modalOffset.top - self.__dy,
width: modalBox.width + self.__dy * 2,
height: modalBox.height + self.__dy * 2
};
} else {
return {
left: modalOffset.left,
top: modalOffset.top,
width: modalBox.width,
height: modalBox.height + self.__dy
};
}
},
left: function(e) {
if (minWidth > modalBox.width - self.__dx) {
self.__dx = modalBox.width - minWidth;
}
if (e.shiftKey) {
if (minWidth > modalBox.width - self.__dx * 2) {
self.__dx = (modalBox.width - minWidth) / 2;
}
return {
left: modalOffset.left + self.__dx,
top: modalOffset.top,
width: modalBox.width - self.__dx * 2,
height: modalBox.height
};
} else if (e.altKey) {
if (minWidth > modalBox.width - self.__dx * 2) {
self.__dx = (modalBox.width - minWidth) / 2;
}
return {
left: modalOffset.left + self.__dx,
top: modalOffset.top + self.__dx,
width: modalBox.width - self.__dx * 2,
height: modalBox.height - self.__dx * 2
};
} else {
return {
left: modalOffset.left + self.__dx,
top: modalOffset.top,
width: modalBox.width - self.__dx,
height: modalBox.height
};
}
},
right: function(e) {
if (minWidth > modalBox.width + self.__dx) {
self.__dx = -modalBox.width + minWidth;
}
if (e.shiftKey) {
if (minWidth > modalBox.width + self.__dx * 2) {
self.__dx = (-modalBox.width + minWidth) / 2;
}
return {
left: modalOffset.left - self.__dx,
top: modalOffset.top,
width: modalBox.width + self.__dx * 2,
height: modalBox.height
};
} else if (e.altKey) {
if (minWidth > modalBox.width + self.__dx * 2) {
self.__dx = (-modalBox.width + minWidth) / 2;
}
return {
left: modalOffset.left - self.__dx,
top: modalOffset.top - self.__dx,
width: modalBox.width + self.__dx * 2,
height: modalBox.height + self.__dx * 2
};
} else {
return {
left: modalOffset.left,
top: modalOffset.top,
width: modalBox.width + self.__dx,
height: modalBox.height
};
}
},
"top-left": function(e) {
if (minWidth > modalBox.width - self.__dx) {
self.__dx = modalBox.width - minWidth;
}
if (minHeight > modalBox.height - self.__dy) {
self.__dy = modalBox.height - minHeight;
}
if (e.shiftKey || e.altKey) {
if (minHeight > modalBox.height - self.__dy * 2) {
self.__dy = (modalBox.height - minHeight) / 2;
}
if (minWidth > modalBox.width - self.__dx * 2) {
self.__dx = (modalBox.width - minWidth) / 2;
}
return {
left: modalOffset.left + self.__dx,
top: modalOffset.top + self.__dy,
width: modalBox.width - self.__dx * 2,
height: modalBox.height - self.__dy * 2
};
} else {
if (minHeight > modalBox.height - self.__dy * 2) {
self.__dy = (modalBox.height - minHeight) / 2;
}
if (minWidth > modalBox.width - self.__dx * 2) {
self.__dx = (modalBox.width - minWidth) / 2;
}
return {
left: modalOffset.left + self.__dx,
top: modalOffset.top + self.__dy,
width: modalBox.width - self.__dx,
height: modalBox.height - self.__dy
};
}
},
"top-right": function(e) {
if (minWidth > modalBox.width + self.__dx) {
self.__dx = -modalBox.width + minWidth;
}
if (minHeight > modalBox.height - self.__dy) {
self.__dy = modalBox.height - minHeight;
}
if (e.shiftKey || e.altKey) {
if (minHeight > modalBox.height - self.__dy * 2) {
self.__dy = (modalBox.height - minHeight) / 2;
}
if (minWidth > modalBox.width + self.__dx * 2) {
self.__dx = (-modalBox.width + minWidth) / 2;
}
return {
left: modalOffset.left - self.__dx,
top: modalOffset.top + self.__dy,
width: modalBox.width + self.__dx * 2,
height: modalBox.height - self.__dy * 2
};
} else {
return {
left: modalOffset.left,
top: modalOffset.top + self.__dy,
width: modalBox.width + self.__dx,
height: modalBox.height - self.__dy
};
}
},
"bottom-left": function(e) {
if (minWidth > modalBox.width - self.__dx) {
self.__dx = modalBox.width - minWidth;
}
if (minHeight > modalBox.height + self.__dy) {
self.__dy = -modalBox.height + minHeight;
}
if (e.shiftKey || e.altKey) {
if (minWidth > modalBox.width - self.__dx * 2) {
self.__dx = (modalBox.width - minWidth) / 2;
}
if (minHeight > modalBox.height + self.__dy * 2) {
self.__dy = (-modalBox.height + minHeight) / 2;
}
return {
left: modalOffset.left + self.__dx,
top: modalOffset.top - self.__dy,
width: modalBox.width - self.__dx * 2,
height: modalBox.height + self.__dy * 2
};
} else {
return {
left: modalOffset.left + self.__dx,
top: modalOffset.top,
width: modalBox.width - self.__dx,
height: modalBox.height + self.__dy
};
}
},
"bottom-right": function(e) {
if (minWidth > modalBox.width + self.__dx) {
self.__dx = -modalBox.width + minWidth;
}
if (minHeight > modalBox.height + self.__dy) {
self.__dy = -modalBox.height + minHeight;
}
if (e.shiftKey || e.altKey) {
if (minWidth > modalBox.width + self.__dx * 2) {
self.__dx = (-modalBox.width + minWidth) / 2;
}
if (minHeight > modalBox.height + self.__dy * 2) {
self.__dy = (-modalBox.height + minHeight) / 2;
}
return {
left: modalOffset.left - self.__dx,
top: modalOffset.top - self.__dy,
width: modalBox.width + self.__dx * 2,
height: modalBox.height + self.__dy * 2
};
} else {
return {
left: modalOffset.left,
top: modalOffset.top,
width: modalBox.width + self.__dx,
height: modalBox.height + self.__dy
};
}
}
},
getResizerPosition = function(e) {
self.__dx = e.clientX - self.mousePosition.clientX;
self.__dy = e.clientY - self.mousePosition.clientY;
return resizerProcessor[resizerType](e);
};
let minWidth = 100,
minHeight = 100;
let cursorType = {
top: "row-resize",
bottom: "row-resize",
left: "col-resize",
right: "col-resize",
"top-left": "nwse-resize",
"top-right": "nesw-resize",
"bottom-left": "nesw-resize",
"bottom-right": "nwse-resize"
};
self.__dx = 0; // 변화량 X
self.__dy = 0; // 변화량 Y
// self.resizerBg : body 가 window보다 작을 때 문제 해결을 위한 DIV
self.resizerBg = jQuery(
'<div class="ax5modal-resizer-background" ondragstart="return false;"></div>'
);
self.resizer = jQuery(
'<div class="ax5modal-resizer" ondragstart="return false;"></div>'
);
self.resizerBg.css({
zIndex: modalZIndex,
cursor: cursorType[resizerType]
});
self.resizer.css({
left: modalOffset.left,
top: modalOffset.top,
width: modalBox.width,
height: modalBox.height,
zIndex: modalZIndex + 1,
cursor: cursorType[resizerType]
});
jQuery(document.body)
.append(self.resizerBg)
.append(self.resizer);
self.activeModal.addClass("draged");
jQuery(document.body)
.bind(
ENM["mousemove"] + ".ax5modal-resize-" + this.instanceId,
function(e) {
self.resizer.css(getResizerPosition(e));
}
)
.bind(
ENM["mouseup"] + ".ax5modal-resize-" + this.instanceId,
function(e) {
resizeModal.off.call(self);
}
)
.bind("mouseleave.ax5modal-resize-" + this.instanceId, function(
e
) {
resizeModal.off.call(self);
});
jQuery(document.body)
.attr("unselectable", "on")
.css("user-select", "none")
.bind("selectstart", false);
},
off: function() {
let setModalPosition = function() {
let box = this.resizer.offset();
jQuery.extend(box, {
width: this.resizer.width(),
height: this.resizer.height()
});
if (!this.modalConfig.absolute) {
box.left -= jQuery(document).scrollLeft();
box.top -= jQuery(document).scrollTop();
}
this.activeModal.css(box);
this.modalConfig.left = box.left;
this.modalConfig.top = box.top;
this.modalConfig.width = box.width;
this.modalConfig.height = box.height;
this.$["body"].css({
height: box.height - this.modalConfig.headerHeight
});
if (this.modalConfig.iframe) {
this.$["iframe-wrap"].css({
height: box.height - this.modalConfig.headerHeight
});
this.$["iframe"].css({
height: box.height - this.modalConfig.headerHeight
});
}
box = null;
};
this.activeModal.removeClass("draged");
setModalPosition.call(this);
this.resizer.remove();
this.resizer = null;
this.resizerBg.remove();
this.resizerBg = null;
onStateChanged.call(this, self.modalConfig, {
self: this,
state: "resize"
});
jQuery(document.body)
.unbind(
ENM["mousemove"] + ".ax5modal-resize-" + this.instanceId
)
.unbind(ENM["mouseup"] + ".ax5modal-resize-" + this.instanceId)
.unbind("mouseleave.ax5modal-resize-" + this.instanceId);
jQuery(document.body)
.removeAttr("unselectable")
.css("user-select", "auto")
.unbind("selectstart");
}
};
/// private end
/**
* Preferences of modal UI
* @method ax5modal.setConfig
* @param {Object} config - 클래스 속성값
* @param {Number} [config.zIndex]
* @param {Object} [config.position]
* @param {String} [config.position.left="center"]
* @param {String} [config.position.top="middle"]
* @param {Number} [config.position.margin=10]
* @param {String} [config.minimizePosition="bottom-right"]
* @param {Number} [config.width=300]
* @param {Number} [config.height=400]
* @param {Boolean} [config.closeToEsc=true]
* @param {Boolean} [config.absolute=false]
* @param {Boolean} [config.disableDrag=false]
* @param {Boolean} [config.disableResize=false]
* @param {Number} [config.animateTime=250]
* @param {Function} [config.fullScreen]
* @param {Function} [config.onStateChanged] - `onStateChanged` function can be defined in setConfig method or new ax5.ui.modal initialization method. However, you can us to define an event function after initialization, if necessary
* @param {Function} [config.onResize]
* @returns {ax5modal}
* @example
* ```js
* var modal = new ax5.ui.modal({
* iframeLoadingMsg: '<i class="fa fa-spinner fa-5x fa-spin" aria-hidden="true"></i>',
* header: {
* title: "MODAL TITLE",
* btns: {
* minimize: {
* label: '<i class="fa fa-minus-circle" aria-hidden="true"></i>', onClick: function () {
* modal.minimize();
* }
* },
* maximize: {
* label: '<i class="fa fa-plus-circle" aria-hidden="true"></i>', onClick: function () {
* modal.maximize();
* }
* },
* close: {
* label: '<i class="fa fa-times-circle" aria-hidden="true"></i>', onClick: function () {
* modal.close();
* }
* }
* }
* }
* });
*
* modal.open({
* width: 800,
* height: 600,
* fullScreen: function(){
* return ($(window).width() < 600);
* },
* iframe: {
* method: "get",
* url: "http://chequer-app:2017/html/login.html",
* param: "callback=modalCallback"
* },
* onStateChanged: function(){
* console.log(this);
* },
* onResize: function(){
* console.log(this);
* }
* });
* ```
*/
//== class body start
this.init = function() {
this.onStateChanged = cfg.onStateChanged;
this.onResize = cfg.onResize;
};
/**
* open the modal
* @method ax5modal.open
* @returns {ax5modal}
* @example
* ```
* modal.open();
* modal.open({
* width: 500,
* height: 500
* });
* moaal.open({}, function(){
* console.log(this);
* });
* ```
*/
this.open = function(opts, callback, tryCount) {
if (typeof tryCount === "undefined") tryCount = 0;
if (!this.activeModal) {
opts = self.modalConfig = jQuery.extend(true, {}, cfg, opts);
open.call(this, opts, callback);
this.watingModal = false;
} else if (tryCount < 3) {
// 3번까지 재 시도
this.watingModal = true;
setTimeout(
function() {
this.open(opts, callback, tryCount + 1);
}.bind(this),
cfg.animateTime
);
} else {
// 열기 시도 종료
this.watingModal = false;
}
return this;
};
/**
* close the modal
* @method ax5modal.close
* @param _option
* @returns {ax5modal}
* @example
* ```
* my_modal.close();
* my_modal.close({callback: function(){
* // on close event
* });
* // close 함수에 callback을 전달하면 정확한 close 타이밍을 캐치할 수 있습니다
* ```
*/
this.close = function(_option) {
let opts, that;
if (this.activeModal) {
opts = self.modalConfig;
this.activeModal.addClass("destroy");
jQuery(window).unbind("keydown.ax-modal");
jQuery(window).unbind("resize.ax-modal");
setTimeout(
function() {
// 프레임 제거
if (opts.iframe) {
var $iframe = this.$["iframe"]; // iframe jQuery Object
if ($iframe) {
var iframeObject = $iframe.get(0),
idoc = iframeObject.contentDocument
? iframeObject.contentDocument
: iframeObject.contentWindow.document;
try {
$(idoc.body)
.children()
.each(function() {
$(this).remove();
});
} catch (e) {}
idoc.innerHTML = "";
$iframe.attr("src", "about:blank").remove();
// force garbarge collection for IE only
window.CollectGarbage && window.CollectGarbage();
}
}
this.activeModal.remove();
this.activeModal = null;
// 모달 오픈 대기중이면 닫기 상태 전달 안함.
if (!this.watingModal) {
onStateChanged.call(this, opts, {
self: this,
state: "close"
});
}
if (_option && U.isFunction(_option.callback)) {
that = {
self: this,
id: opts.id,
theme: opts.theme,
width: opts.width,
height: opts.height,
state: "close",
$: this.$
};
_option.callback.call(that, that);
}
}.bind(this),
cfg.animateTime
);
}
this.minimized = false; // hoksi
return this;
};
/**
* @method ax5modal.minimize
* @returns {ax5modal}
*/
this.minimize = (function() {
return function(minimizePosition) {
if (this.minimized !== true) {
var opts = self.modalConfig;
if (typeof minimizePosition === "undefined")
minimizePosition = cfg.minimizePosition;
this.minimized = true;
this.$.body.hide();
self.modalConfig.originalHeight = opts.height;
self.modalConfig.height = 0;
alignProcessor[minimizePosition].call(this);
onStateChanged.call(this, opts, {
self: this,
state: "minimize"
});
}
return this;
};
})();
/**
* @method ax5modal.restore
* @returns {ax5modal}
*/
this.restore = function() {
var opts = self.modalConfig;
if (this.minimized) {
this.minimized = false;
this.$.body.show();
self.modalConfig.height = self.modalConfig.originalHeight;
self.modalConfig.originalHeight = undefined;
this.align({ left: "center", top: "middle" });
onStateChanged.call(this, opts, {
self: this,
state: "restore"
});
}
return this;
};
/**
* setCSS
* @method ax5modal.css
* @param {Object} css -
* @returns {ax5modal}
*/
this.css = function(css) {
if (this.activeModal && !self.fullScreen) {
this.activeModal.css(css);
if (typeof css.width !== "undefined") {
self.modalConfig.width = css.width;
}
if (typeof css.height !== "undefined") {
self.modalConfig.height = css.height;
}
this.align();
}
return this;
};
/**
* @method ax5modal.setModalConfig
* @param _config
* @returns {ax5.ui.ax5modal}
*/
this.setModalConfig = function(_config) {
self.modalConfig = jQuery.extend({}, self.modalConfig, _config);
this.align();
return this;
};
/**
* @method ax5modal.align
* @param position
* @param e
* @returns {ax5modal}
* @example
* ```js
* modal.align({left:"center", top:"middle"});
* modal.align({left:"left", top:"top", margin: 20});
* ```
*/
this.align = (function() {
return function(position, e) {
if (!this.activeModal) return this;
var opts = self.modalConfig,
box = {
width: opts.width,
height: opts.height
};
var fullScreen = (opts.isFullScreen = (function(_fullScreen) {
if (typeof _fullScreen === "undefined") {
return false;
} else if (U.isFunction(_fullScreen)) {
return _fullScreen();
}
})(opts.fullScreen));
if (fullScreen) {
if (opts.header) this.$.header.show();
if (opts.header) {
opts.headerHeight = this.$.header.outerHeight();
box.height += opts.headerHeight;
} else {
opts.headerHeight = 0;
}
box.width = jQuery(window).width();
box.height = opts.height;
box.left = 0;
box.top = 0;
} else {
if (opts.header) this.$.header.show();
if (position) {
jQuery.extend(true, opts.position, position);
}
if (opts.header) {
opts.headerHeight = this.$.header.outerHeight();
box.height += opts.headerHeight;
} else {
opts.headerHeight = 0;
}
//- position 정렬
if (opts.position.left == "left") {
box.left = opts.position.margin || 0;
} else if (opts.position.left == "right") {
// window.innerWidth;
box.left =
jQuery(window).width() -
box.width -
(opts.position.margin || 0);
} else if (opts.position.left == "center") {
box.left = jQuery(window).width() / 2 - box.width / 2;
} else {
box.left = opts.position.left || 0;
}
if (opts.position.top == "top") {
box.top = opts.position.margin || 0;
} else if (opts.position.top == "bottom") {
box.top =
jQuery(window).height() -
box.height -
(opts.position.margin || 0);
} else if (opts.position.top == "middle") {
box.top = jQuery(window).height() / 2 - box.height / 2;
} else {
box.top = opts.position.top || 0;
}
if (box.left < 0) box.left = 0;
if (box.top < 0) box.top = 0;
if (opts.absolute) {
box.top += jQuery(window).scrollTop();
box.left += jQuery(window).scrollLeft();
}
}
this.activeModal.css(box);
this.$["body"].css({
height: box.height - (opts.headerHeight || 0)
});
if (opts.iframe) {
this.$["iframe-wrap"].css({
height: box.height - opts.headerHeight
});
this.$["iframe"].css({ height: box.height - opts.headerHeight });
} else {
}
return this;
};
})();
// 클래스 생성자
this.main = function() {
UI.modal_instance = UI.modal_instance || [];
UI.modal_instance.push(this);
if (arguments && U.isObject(arguments[0])) {
this.setConfig(arguments[0]);
}
}.apply(this, arguments);
};
})()
);
MODAL = ax5.ui.modal;
})();