Files
piratepoet/assets/js/src/modal.js
2017-10-23 16:01:28 +00:00

641 lines
19 KiB
JavaScript

define('modal', ['mailpoet', 'jquery'],
function (mp, jQuery) {
'use strict';
var MailPoet = mp;
/** *************************************************************************
MailPoet Modal:
version: 0.9
author: Jonathan Labreuille
company: Wysija
dependencies: jQuery
Usage:
// popup mode
MailPoet.Modal.popup(options);
// panel mode
MailPoet.Modal.panel(options);
// loading mode
MailPoet.Modal.loading(bool);
************************************************************************** */
MailPoet.Modal = {
version: 0.9,
// flags
initialized: false,
opened: false,
locked: false,
// previously focused element
prevFocus: null,
// sub panels
subpanels: [],
// default values
defaults: {
// title
title: null,
// type
type: null,
// positionning
position: 'right',
// data sources
data: {},
url: null,
method: 'get',
params: {},
// template
template: null,
body_template: null,
// dimensions
width: 'auto',
height: 'auto',
// display overlay
overlay: false,
// focus upon displaying
focus: true,
// highlighted elements
highlight: null,
// callbacks
onInit: null,
onSuccess: null,
onCancel: null
},
renderer: 'html',
options: {},
templates: {
overlay: '<div id="mailpoet_modal_overlay" style="display:none;"></div>',
popup: '<div id="mailpoet_popup" tabindex="-1">' +
'<div class="mailpoet_popup_wrapper">' +
'<a href="javascript:;" id="mailpoet_modal_close"></a>' +
'<div id="mailpoet_popup_title"><h2></h2></div>' +
'<div class="mailpoet_popup_body clearfix"></div>' +
'</div>' +
'</div>',
loading: '<div id="mailpoet_loading" style="display:none;">' +
'<div id="mailpoet_modal_loading_1" class="mailpoet_modal_loading"></div>' +
'<div id="mailpoet_modal_loading_2" class="mailpoet_modal_loading"></div>' +
'<div id="mailpoet_modal_loading_3" class="mailpoet_modal_loading"></div>' +
'</div>',
panel: '<div id="mailpoet_panel">' +
'<a href="javascript:;" id="mailpoet_modal_close"></a>' +
'<div class="mailpoet_panel_wrapper" tabindex="-1">' +
'<div class="mailpoet_panel_body clearfix"></div>' +
'</div>' +
'</div>',
subpanel: '<div class="mailpoet_panel_wrapper" tabindex="-1">' +
'<div class="mailpoet_panel_body clearfix"></div>' +
'</div>'
},
getContentContainer: function () {
return jQuery('.mailpoet_' + this.options.type + '_body');
},
setRenderer: function (renderer) {
this.renderer = renderer;
return this;
},
compileTemplate: function (template) {
if (this.renderer === 'html') {
return function () { return template; };
} else {
return window.Handlebars.compile(template);
}
},
init: function (options) {
var modal;
if (this.initialized === true) {
this.close();
}
// merge options
this.options = jQuery.extend({}, this.defaults, options);
// set renderer
this.setRenderer(this.options.renderer);
// init overlay
this.initOverlay();
// toggle overlay
this.toggleOverlay(this.options.overlay);
if (this.options.type !== null) {
// insert modal depending on its type
if (this.options.type === 'popup') {
modal = this.compileTemplate(
this.templates[this.options.type]
);
// create modal
jQuery('#mailpoet_modal_overlay')
.append(modal(this.options));
// set title
jQuery('#mailpoet_popup_title h2')
.html(this.options.title);
} else if (this.options.type === 'panel') {
// create panel
jQuery('#mailpoet_modal_overlay')
.after(this.templates[this.options.type]);
}
// add proper overlay class
jQuery('#mailpoet_modal_overlay')
.removeClass('mailpoet_popup_overlay mailpoet_panel_overlay')
.addClass('mailpoet_' + this.options.type + '_overlay');
}
// set "success" callback if specified
if (options.onSuccess !== undefined) {
this.options.onSuccess = options.onSuccess;
}
// set "cancel" callback if specified
if (options.onCancel !== undefined) {
this.options.onCancel = options.onCancel;
}
// compile template
this.options.body_template = this.compileTemplate(
this.options.template
);
// setup events
this.setupEvents();
// set popup as initialized
this.initialized = true;
return this;
},
initOverlay: function () {
if (jQuery('#mailpoet_modal_overlay').length === 0) {
// insert overlay into the DOM
jQuery('body').append(this.templates.overlay);
// insert loading indicator into overlay
jQuery('#mailpoet_modal_overlay').append(this.templates.loading);
}
return this;
},
toggleOverlay: function (toggle) {
if (toggle === true) {
jQuery('#mailpoet_modal_overlay')
.removeClass('mailpoet_overlay_hidden');
} else {
jQuery('#mailpoet_modal_overlay')
.addClass('mailpoet_overlay_hidden');
}
return this;
},
setupEvents: function () {
// close popup when user clicks on close button
jQuery('#mailpoet_modal_close').on('click', this.cancel.bind(this));
// close popup when user clicks on overlay
jQuery('#mailpoet_modal_overlay').on('click', function (e) {
// we need to make sure that we are actually clicking on the overlay
// because when clicking on the popup content, it will trigger
// the click event on the overlay
if (e.target.id === 'mailpoet_modal_overlay') { this.cancel(); }
}.bind(this));
// close popup when user presses ESC key
jQuery(document).on('keyup.mailpoet_modal', function (e) {
if (this.opened === false) { return false; }
if (e.keyCode === 27) { this.cancel(); }
}.bind(this));
// make sure the popup is repositioned when the window is resized
jQuery(window).on('resize.mailpoet_modal', function () {
this.setPosition();
}.bind(this));
return this;
},
removeEvents: function () {
jQuery(document).unbind('keyup.mailpoet_modal');
jQuery(window).unbind('resize.mailpoet_modal');
jQuery('#mailpoet_modal_close').off('click');
if (this.options.overlay === true) {
jQuery('#mailpoet_modal_overlay').off('click');
}
return this;
},
lock: function () {
this.locked = true;
return this;
},
unlock: function () {
this.locked = false;
return this;
},
isLocked: function () {
return this.locked;
},
loadTemplate: function () {
if (this.subpanels.length > 0) {
// hide panel
jQuery('.mailpoet_' + this.options.type + '_wrapper').hide();
// add sub panel wrapper
jQuery('#mailpoet_' + this.options.type)
.append(this.templates['subpanel']);
// add sub panel content
jQuery('.mailpoet_' + this.options.type + '_body').last()
.html(this.subpanels[(this.subpanels.length - 1)].element);
// focus on sub panel
if (this.options.focus) {
this.focus();
}
} else if (this.options.element) {
jQuery('.mailpoet_' + this.options.type + '_body').empty();
jQuery('.mailpoet_' + this.options.type + '_body')
.append(this.options.element);
} else {
jQuery('.mailpoet_' + this.options.type + '_body')
.html(
this.options.body_template(
this.options.data
)
);
}
return this;
},
loadUrl: function () {
if (this.options.method === 'get') {
// make ajax request
jQuery.getJSON(this.options.url,
function (data) {
this.options.data = jQuery.extend({}, this.options.data, data);
// load template using fetched data
this.loadTemplate();
// show modal window
this.showModal();
}.bind(this)
);
} else if (this.options.method === 'post') {
// make ajax request
jQuery.post(this.options.url, JSON.stringify(this.options.params),
function (data) {
this.options.data = jQuery.extend({}, this.options.data, data);
// load template using fetched data
this.loadTemplate();
// show modal window
this.showModal();
}.bind(this),
'json'
);
}
return this;
},
setDimensions: function () {
switch (this.options.type) {
case 'popup':
// set popup dimensions
jQuery('#mailpoet_popup').css({
width: this.options.width,
height: this.options.height
});
// set popup wrapper height
jQuery('#mailpoet_popup_wrapper').css({
height: this.options.height
});
break;
case 'panel':
// set dimensions
if (this.options.position === 'right') {
jQuery('#mailpoet_panel').css({
width: this.options.width,
right: 0,
marginRight: '-' + this.options.width,
left: 'auto'
});
} else if (this.options.position === 'left') {
jQuery('#mailpoet_panel').css({
width: this.options.width,
left: 0,
marginLeft: '-' + this.options.width,
right: 'auto'
});
}
jQuery('#mailpoet_panel').css({ minHeight: 'auto' });
break;
}
return this;
},
setPosition: function () {
var screenWidth;
var screenHeight;
var modalWidth;
var modalHeight;
switch (this.options.type) {
case 'popup':
screenWidth = jQuery(window).width();
screenHeight = jQuery(window).height();
modalWidth = jQuery('.mailpoet_'+ this.options.type +'_wrapper').width();
modalHeight = jQuery('.mailpoet_'+ this.options.type +'_wrapper').height();
// set position of popup depending on screen dimensions.
jQuery('#mailpoet_popup').css({
top: Math.max(48, parseInt((screenHeight / 2) - (modalHeight / 2))),
left: Math.max(0, parseInt((screenWidth / 2) - (modalWidth / 2)))
});
break;
case 'panel':
setTimeout(function () {
// set position of popup depending on screen dimensions.
if (this.options.position === 'right') {
jQuery('#mailpoet_panel').css({
marginRight: 0
});
} else if (this.options.position === 'left') {
jQuery('#mailpoet_panel').css({
marginLeft: 0
});
}
}.bind(this), 0);
break;
}
return this;
},
showModal: function () {
// set modal dimensions
this.setDimensions();
// remember the previously focused element
this.prevFocus = jQuery(':focus');
// show popup
jQuery('#mailpoet_' + this.options.type).show();
// display overlay
this.showOverlay();
// set modal position
this.setPosition();
// add class on highlighted elements
if (this.options.highlight !== null) {
if (this.options.highlight.length > 0) {
this.highlightOn(this.options.highlight);
}
}
if (this.options.focus) {
this.focus();
}
// set popup as opened
this.opened = true;
// trigger init event if specified
if (this.options.onInit !== null) {
this.options.onInit(this);
}
return this;
},
focus: function () {
if (this.options.type == 'popup') {
jQuery('#mailpoet_' + this.options.type).focus();
} else {
// panel and subpanel
jQuery('#mailpoet_' + this.options.type + ' .mailpoet_panel_wrapper')
.filter(':visible').focus();
}
return this;
},
highlightOn: function (element) {
jQuery(element).addClass('mailpoet_modal_highlight');
return this;
},
highlightOff: function () {
jQuery('.mailpoet_modal_highlight')
.removeClass('mailpoet_modal_highlight');
return this;
},
hideModal: function () {
// set modal as closed
this.opened = false;
// hide modal
jQuery('#mailpoet_' + this.options.type).hide();
// remove class on highlighted elements
this.highlightOff();
return this;
},
showOverlay: function () {
jQuery('#mailpoet_modal_overlay').show();
return this;
},
hideOverlay: function () {
jQuery('#mailpoet_modal_overlay').hide();
return this;
},
popup: function (opts) {
// get options
var options = opts || {};
// set modal type
options.type = 'popup';
// set overlay state
options.overlay = options.overlay || true;
// initialize modal
this.init(options);
// open modal
this.open();
return this;
},
panel: function (opts) {
// get options
var options = opts || {};
// reset subpanels
this.subpanels = [];
// set modal type
options.type = 'panel';
// set overlay state
options.overlay = options.overlay || false;
// set highlighted element
options.highlight = options.highlight || null;
// set modal dimensions
options.width = options.width || '40%';
options.height = options.height || 'auto';
// initialize modal
this.init(options);
// open modal
this.open();
return this;
},
subpanel: function (options) {
if (this.opened === false) {
// if no panel is already opened, let's create one instead
this.panel(options);
} else {
// if a panel is already opened, add a sub panel to it
this.subpanels.push(options);
this.loadTemplate();
}
return this;
},
loading: function (toggle) {
// make sure the overlay is initialized and that it's visible
this.initOverlay(true);
if (toggle === true) {
this.showLoading();
} else {
this.hideLoading();
}
return this;
},
showLoading: function () {
jQuery('#mailpoet_loading').show();
// add loading class to overlay
jQuery('#mailpoet_modal_overlay')
.addClass('mailpoet_overlay_loading');
return this;
},
hideLoading: function () {
jQuery('#mailpoet_loading').hide();
// remove loading class from overlay
jQuery('#mailpoet_modal_overlay')
.removeClass('mailpoet_overlay_loading');
return this;
},
open: function () {
// load template if specified
if (this.options.template !== null) {
// check if a url was specified to get extra data
if (this.options.url !== null) {
this.loadUrl();
} else {
// load template
this.loadTemplate();
// show modal window
this.showModal();
}
} else {
this.cancel();
}
return this;
},
success: function () {
if (this.subpanels.length > 0) {
if (this.subpanels[(this.subpanels.length - 1)].onSuccess !== undefined) {
this.subpanels[(this.subpanels.length - 1)].onSuccess(this.subpanels[(this.subpanels.length - 1)].data);
}
} else {
if (this.options.onSuccess !== null) {
this.options.onSuccess(this.options.data);
}
}
this.close();
return this;
},
cancel: function () {
if (this.subpanels.length > 0) {
if (this.subpanels[(this.subpanels.length - 1)].onCancel !== undefined) {
this.subpanels[(this.subpanels.length - 1)].onCancel(this.subpanels[(this.subpanels.length - 1)].data);
}
} else {
if (this.options.onCancel !== null) {
this.options.onCancel(this.options.data);
}
}
this.close();
return this;
},
destroy: function () {
this.hideOverlay();
// remove extra modal
if (jQuery('#mailpoet_' + this.options.type).length > 0) {
jQuery('#mailpoet_' + this.options.type).remove();
}
this.initialized = false;
return this;
},
close: function () {
if (this.isLocked() === true) { return this; }
if (this.subpanels.length > 0) {
// close subpanel
jQuery('.mailpoet_' + this.options.type + '_wrapper').last().remove();
// show previous panel
jQuery('.mailpoet_' + this.options.type + '_wrapper').last().show();
// remove last subpanels
this.subpanels.pop();
// focus on previous panel
if (this.options.focus) {
this.focus();
}
return this;
}
// remove event handlers
this.removeEvents();
// hide modal window
this.hideModal();
// destroy modal element
this.destroy();
// restore the previously focused element
if (this.prevFocus !== undefined) {
this.prevFocus.focus();
}
// reset options
this.options = {
onSuccess: null,
onCancel: null
};
return this;
}
};
}
);