/*================================================================================================== MailPoet Modal: version: 0.8 author: Jonathan Labreuille company: Wysija dependencies: jQuery Options: Mandatory: // Modal window's title (string) title: 'Modal title' // template (string) template: jQuery('#handlebars_template').html() or literal html Optional: // jQuery cached element object node to be displayed, // instead of creating a new one (object) element: jQuery(selector) // - data object that will be passed to the template when rendering (object) data: {}, // - data will be loaded via this url and passed to the template // when rendering // - if a "data" option was specified, it will be merged with the // ajax's response data (string) url: '/url.json' // ajax method (string) method: 'post' (default: 'get') // ajax post params (object) params: {} // - integers are expressed in pixels (mixed) width: '50%' | 100 | '100px' // - integers are expressed in pixels // - will be ignored when in "panel" mode (mixed) height: '50%' | 100 | '100px' // - only used for "panel" mode // - will be ignored in "popup" mode (string) position: 'left' | 'right' // display overlay or not (boolean) overlay: true | false // element(s) to be highlighted when the overlay is "on" (object) highlight: jQuery element // callbacks (function) onInit: called when the modal is displayed (function) onSuccess: called by calling MailPoet_Guide.success() (function) onCancel: called when closing the popup or by calling MailPoet_Guide.cancel() Usage: // popup mode MailPoet.Modal.popup(options); // panel mode MailPoet.Modal.panel(options); // loading states MailPoet.Modal.loading(true); // displays loading indicator MailPoet.Modal.loading(false); // hides loading indicator ==================================================================================================*/ (function() { "use strict"; MailPoet.Modal = { version: 0.8, // flags initialized: false, opened: false, locked: false, // 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, // highlighted elements highlight: null, // callbacks onInit: null, onSuccess: null, onCancel: null }, renderer: 'html', options: {}, templates: { overlay: '', popup: '
'+ '
'+ ''+ '

'+ '
'+ '
'+ '
', loading: '', panel: '
'+ ''+ '
'+ '
'+ '
'+ '
', subpanel: '
'+ '
'+ '
' }, setRenderer: function() { this.renderer = (typeof(Handlebars) === "undefined") ? 'html' : 'handlebars'; }, compileTemplate: function(template) { if(this.renderer === 'html') { return function() { return template; }; } else { return Handlebars.compile(template); } }, init: function(options) { if(this.initialized === true) { this.close(); } // merge options this.options = jQuery.extend({}, this.defaults, options); // set renderer this.setRenderer(); // 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') { var 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'); } // render template if specified if(this.options.template !== null) { // 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(toggle) { 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); } 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) { // merge returned data with existing data passed when calling the "open" method 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) { // merge returned data with existing data passed when calling the "open" method 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, minHeight: 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() { switch(this.options.type) { case 'popup': var screenWidth = jQuery(window).width(), screenHeight = jQuery(window).height(), modalWidth = jQuery('.mailpoet_'+ this.options.type +'_wrapper').width(), modalHeight = jQuery('.mailpoet_'+ this.options.type +'_wrapper').height(); var top = Math.max(48, parseInt((screenHeight / 2) - (modalHeight / 2))), left = Math.max(0, parseInt((screenWidth / 2) - (modalWidth / 2))); // set position of popup depending on screen dimensions. jQuery('#mailpoet_popup').css({ top: top, left: left }); 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(); // add a flag on the body so that we can prevent scrolling (setting overflow hidden) jQuery('body').addClass('mailpoet_modal_opened'); // 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); } } // set popup as opened this.opened = true; // trigger init event if specified if(this.options.onInit !== null) { this.options.onInit(); } 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(callback) { // set modal as closed this.opened = false; // hide modal jQuery('#mailpoet_'+this.options.type).hide(); // remove class on highlighted elements this.highlightOff(); // remove class from body to let it be scrollable jQuery('body').removeClass('mailpoet_modal_opened'); return this; }, showOverlay: function(force) { jQuery('#mailpoet_modal_overlay').show(); return this; }, hideOverlay: function() { jQuery('#mailpoet_modal_overlay').hide(); return this; }, popup: function(options) { // get options options = options || {}; // 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(options) { // get options options = options || {}; // 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(); return this; } // remove event handlers this.removeEvents(); // hide modal window this.hideModal(); // destroy modal element this.destroy(); // reset options this.options = { onSuccess: null, onCancel: null }; return this; } }; })(window.MailPoet = window.MailPoet || {}, jQuery);