mikit-framework
Version:
A web framework for professional developers and designers alike.
295 lines (251 loc) • 7.16 kB
JavaScript
/**
* @library Mikit Modal
* @author Mikit
*/
(function ($) {
$.modalcurrent = null;
$.modalwindow = function (options) {
var opts = $.extend({}, options, {
show: true
});
var $element = $('<span />');
$element.modal(opts);
};
})(jQuery);
(function (Mikit) {
Mikit.Modal = function (element, options) {
this.namespace = 'modal';
this.defaults = {
target: null,
show: false,
url: false,
header: false,
width: '600px', // string
height: false, // or string
maxHeight: false,
position: 'center', // top or center
overlay: true,
appendForms: false,
appendFields: false,
animationOpen: 'show',
animationClose: 'hide',
callbacks: ['open', 'opened', 'close', 'closed']
};
// Parent Constructor
Mikit.apply(this, arguments);
// Services
this.utils = new Mikit.Utils();
this.detect = new Mikit.Detect();
// Initialization
this.start();
};
// Functionality
Mikit.Modal.prototype = {
start: function () {
if (!this.hasTarget()) {
return;
}
if (this.opts.show) this.load();
else this.$element.on('click.' + this.namespace, $.proxy(this.load, this));
},
buildModal: function () {
this.$modal = this.$target.find('.mi-modal');
this.$header = this.$target.find('.mi-modal-header');
this.$close = this.$target.find('.mi-close');
this.$body = this.$target.find('.mi-modal-body');
},
buildOverlay: function () {
if (this.opts.overlay === false) {
return;
}
if ($('#mi-modal-overlay').length !== 0) {
this.$overlay = $('#mi-modal-overlay');
} else {
this.$overlay = $('<div id="mi-modal-overlay">').addClass('mi-hide');
$('body').prepend(this.$overlay);
}
this.$overlay.addClass('mi-overlay');
},
buildHeader: function () {
if (this.opts.header) this.$header.html(this.opts.header);
},
load: function (e) {
this.buildModal();
this.buildOverlay();
this.buildHeader();
if (this.opts.url) this.buildContent();
else this.open(e);
},
open: function (e) {
if (e) e.preventDefault();
if (this.isOpened()) {
return;
}
if (this.detect.isMobile()) this.opts.width = '96%';
if (this.opts.overlay) this.$overlay.removeClass('mi-hide');
this.$target.removeClass('mi-hide');
this.$modal.removeClass('mi-hide');
this.enableEvents();
this.findActions();
this.resize();
$(window).on('resize.' + this.namespace, $.proxy(this.resize, this));
if (this.detect.isDesktop()) this.utils.disableBodyScroll();
// enter
this.$modal.find('input[type=text],input[type=url],input[type=email]').on('keydown.' + this.namespace, $.proxy(this.handleEnter, this));
this.callback('open');
this.$modal.animation(this.opts.animationOpen, $.proxy(this.onOpened, this));
},
close: function (e) {
if (!this.$modal || !this.isOpened()) {
return;
}
if (e) {
if (this.shouldNotBeClosed(e.target)) {
return;
}
e.preventDefault();
}
this.callback('close');
this.disableEvents();
this.$modal.animation(this.opts.animationClose, $.proxy(this.onClosed, this));
if (this.opts.overlay) this.$overlay.animation(this.opts.animationClose);
},
onOpened: function () {
this.$modal.addClass('mi-open');
this.callback('opened');
$.modalcurrent = this;
},
onClosed: function () {
this.callback('closed');
this.$target.addClass('mi-hide');
this.$modal.removeClass('mi-open');
if (this.detect.isDesktop()) this.utils.enableBodyScroll();
this.$body.css('height', '');
$.modalcurrent = null;
},
isOpened: function () {
return (this.$modal.hasClass('mi-open'));
},
getData: function () {
var formdata = new Mikit.FormData(this);
formdata.set('');
return formdata.get();
},
buildContent: function () {
$.ajax({
url: this.opts.url + '?' + new Date().getTime(),
cache: false,
type: 'post',
data: this.getData(),
success: $.proxy(function (data) {
this.$body.html(data);
this.open();
}, this)
});
},
buildWidth: function () {
var width = this.opts.width;
var top = '2%';
var bottom = '2%';
var percent = width.match(/%$/);
if ((parseInt(this.opts.width) > $(window).width()) && !percent) {
width = '96%';
} else if (!percent) {
top = '16px';
bottom = '16px';
}
this.$modal.css({
'width': width,
'margin-top': top,
'margin-bottom': bottom
});
},
buildPosition: function () {
if (this.opts.position !== 'center') {
return;
}
var windowHeight = $(window).height();
var height = this.$modal.outerHeight();
var top = (windowHeight / 2 - height / 2) + 'px';
if (this.detect.isMobile()) top = '2%';
else if (height > windowHeight) top = '16px';
this.$modal.css('margin-top', top);
},
buildHeight: function () {
var windowHeight = $(window).height();
if (this.opts.maxHeight) {
var padding = parseInt(this.$body.css('padding-top')) + parseInt(this.$body.css('padding-bottom'));
var margin = parseInt(this.$modal.css('margin-top')) + parseInt(this.$modal.css('margin-bottom'));
var height = windowHeight - this.$header.innerHeight() - padding - margin;
this.$body.height(height);
} else if (this.opts.height !== false) {
this.$body.css('height', this.opts.height);
}
var modalHeight = this.$modal.outerHeight();
if (modalHeight > windowHeight) {
this.opts.animationOpen = 'show';
this.opts.animationClose = 'hide';
}
},
resize: function () {
this.buildWidth();
this.buildPosition();
this.buildHeight();
},
enableEvents: function () {
this.$close.on('click.' + this.namespace, $.proxy(this.close, this));
$(document).on('keyup.' + this.namespace, $.proxy(this.handleEscape, this));
this.$target.on('click.' + this.namespace, $.proxy(this.close, this));
},
disableEvents: function () {
this.$close.off('.' + this.namespace);
$(document).off('.' + this.namespace);
this.$target.off('.' + this.namespace);
$(window).off('.' + this.namespace);
},
findActions: function () {
this.$body.find('[data-action="modal-close"]').on('mousedown.' + this.namespace, $.proxy(this.close, this));
},
setHeader: function (header) {
this.$header.html(header);
},
setContent: function (content) {
this.$body.html(content);
},
setWidth: function (width) {
this.opts.width = width;
this.resize();
},
getModal: function () {
return this.$modal;
},
getBody: function () {
return this.$body;
},
getHeader: function () {
return this.$header;
},
handleEnter: function (e) {
if (e.which === 13) {
e.preventDefault();
this.close(false);
}
},
handleEscape: function (e) {
return (e.which === 27) ? this.close(false) : true;
},
shouldNotBeClosed: function (el) {
if ($(el).attr('data-action') === 'modal-close' || el === this.$close[0]) {
return false;
} else if ($(el).closest('.mi-modal').length === 0) {
return false;
}
return true;
}
};
// Inheritance
Mikit.Modal.inherits(Mikit);
// Plugin
Mikit.Plugin.create('Modal');
Mikit.Plugin.autoload('Modal');
}(Mikit));