| /* |
| A simple jQuery modal (http://github.com/kylefox/jquery-modal) |
| Version 0.9.1-patched |
| */ |
| |
| (function (factory) { |
| // Making your jQuery plugin work better with npm tools |
| // http://blog.npmjs.org/post/112712169830/making-your-jquery-plugin-work-better-with-npm |
| if(typeof module === "object" && typeof module.exports === "object") { |
| factory(require("jquery"), window, document); |
| } |
| else { |
| factory(jQuery, window, document); |
| } |
| }(function($, window, document, undefined) { |
| |
| var modals = [], |
| getCurrent = function() { |
| return modals.length ? modals[modals.length - 1] : null; |
| }, |
| selectCurrent = function() { |
| var i, |
| selected = false; |
| for (i=modals.length-1; i>=0; i--) { |
| if (modals[i].$blocker) { |
| modals[i].$blocker.toggleClass('current',!selected).toggleClass('behind',selected); |
| selected = true; |
| } |
| } |
| }; |
| |
| $.modal = function(el, options) { |
| var remove, target; |
| this.$body = $('body'); |
| this.options = $.extend({}, $.modal.defaults, options); |
| this.options.doFade = !isNaN(parseInt(this.options.fadeDuration, 10)); |
| this.$blocker = null; |
| if (this.options.closeExisting) |
| while ($.modal.isActive()) |
| $.modal.close(); // Close any open modals. |
| modals.push(this); |
| if (el.is('a')) { |
| target = el.attr('href'); |
| this.anchor = el; |
| //Select element by id from href |
| if (/^#/.test(target)) { |
| this.$elm = $(target); |
| if (this.$elm.length !== 1) return null; |
| this.$body.append(this.$elm); |
| this.open(); |
| //AJAX |
| } else { |
| this.$elm = $('<div>'); |
| this.$body.append(this.$elm); |
| remove = function(event, modal) { modal.elm.remove(); }; |
| this.showSpinner(); |
| el.trigger($.modal.AJAX_SEND); |
| $.get(target).done(function(html) { |
| if (!$.modal.isActive()) return; |
| el.trigger($.modal.AJAX_SUCCESS); |
| var current = getCurrent(); |
| if (window.trustedTypes && window.trustedTypes.createPolicy) { |
| const policy = self.trustedTypes.createPolicy('jquery-modal-fix', { |
| createHTML: function(_ignored) { return html } |
| }); |
| safeHtml = policy.createHTML('_ignored'); |
| } else { |
| safeHtml = html; |
| } |
| current.$elm[0].innerHTML = trustedTypes.emptyHTML; |
| current.$elm[0].innerHTML = safeHtml; |
| current.$elm.on($.modal.CLOSE, remove); |
| current.hideSpinner(); |
| current.open(); |
| el.trigger($.modal.AJAX_COMPLETE); |
| }).fail(function() { |
| el.trigger($.modal.AJAX_FAIL); |
| var current = getCurrent(); |
| current.hideSpinner(); |
| modals.pop(); // remove expected modal from the list |
| el.trigger($.modal.AJAX_COMPLETE); |
| }); |
| } |
| } else { |
| this.$elm = el; |
| this.anchor = el; |
| this.$body.append(this.$elm); |
| this.open(); |
| } |
| }; |
| |
| $.modal.prototype = { |
| constructor: $.modal, |
| |
| open: function() { |
| var m = this; |
| this.block(); |
| this.anchor.blur(); |
| if(this.options.doFade) { |
| setTimeout(function() { |
| m.show(); |
| }, this.options.fadeDuration * this.options.fadeDelay); |
| } else { |
| this.show(); |
| } |
| $(document).off('keydown.modal').on('keydown.modal', function(event) { |
| var current = getCurrent(); |
| if (event.which === 27 && current.options.escapeClose) current.close(); |
| }); |
| if (this.options.clickClose) |
| this.$blocker.click(function(e) { |
| if (e.target === this) |
| $.modal.close(); |
| }); |
| }, |
| |
| close: function() { |
| modals.pop(); |
| this.unblock(); |
| this.hide(); |
| if (!$.modal.isActive()) |
| $(document).off('keydown.modal'); |
| }, |
| |
| block: function() { |
| var div = document.createElement('div'); |
| div.setAttribute('class', this.options.blockerClass + ' blocker current'); |
| this.$elm.trigger($.modal.BEFORE_BLOCK, [this._ctx()]); |
| this.$body.css('overflow','hidden'); |
| this.$blocker = $(this.$body[0].appendChild(div)); |
| selectCurrent(); |
| if(this.options.doFade) { |
| this.$blocker.css('opacity',0).animate({opacity: 1}, this.options.fadeDuration); |
| } |
| this.$elm.trigger($.modal.BLOCK, [this._ctx()]); |
| }, |
| |
| unblock: function(now) { |
| if (!now && this.options.doFade) |
| this.$blocker.fadeOut(this.options.fadeDuration, this.unblock.bind(this,true)); |
| else { |
| this.$blocker.children().appendTo(this.$body); |
| this.$blocker.remove(); |
| this.$blocker = null; |
| selectCurrent(); |
| if (!$.modal.isActive()) |
| this.$body.css('overflow',''); |
| } |
| }, |
| |
| show: function() { |
| this.$elm.trigger($.modal.BEFORE_OPEN, [this._ctx()]); |
| if (this.options.showClose) { |
| var closeButton; |
| this.$elm.trigger($.modal.BEFORE_OPEN, [this._ctx()]), |
| closeButton = document.createElement('a'); |
| closeButton.setAttribute('href', '#close-modal'); |
| closeButton.setAttribute('rel', 'modal:close'); |
| closeButton.setAttribute('class', 'close-modal ' + this.options.closeClass); |
| txt = document.createTextNode(this.options.closeText); |
| closeButton.appendChild(txt); |
| this.$elm.append(this.closeButton); |
| } |
| this.$elm.addClass(this.options.modalClass).appendTo(this.$blocker); |
| if(this.options.doFade) { |
| this.$elm.css({opacity: 0, display: 'inline-block'}).animate({opacity: 1}, this.options.fadeDuration); |
| } else { |
| this.$elm.css('display', 'inline-block'); |
| } |
| this.$elm.trigger($.modal.OPEN, [this._ctx()]); |
| }, |
| |
| hide: function() { |
| this.$elm.trigger($.modal.BEFORE_CLOSE, [this._ctx()]); |
| if (this.closeButton) this.closeButton.remove(); |
| var _this = this; |
| if(this.options.doFade) { |
| this.$elm.fadeOut(this.options.fadeDuration, function () { |
| _this.$elm.trigger($.modal.AFTER_CLOSE, [_this._ctx()]); |
| }); |
| } else { |
| this.$elm.hide(0, function () { |
| _this.$elm.trigger($.modal.AFTER_CLOSE, [_this._ctx()]); |
| }); |
| } |
| this.$elm.trigger($.modal.CLOSE, [this._ctx()]); |
| }, |
| |
| showSpinner: function() { |
| if (!this.options.showSpinner) return; |
| var div = document.createElement('div'); |
| div.setAttribute('class', this.options.modalClass + '-spinner'); |
| |
| var divSpinner1 = document.createElement('div'); |
| divSpinner1.setAttribute('class','rect1'); |
| div.appendChild(divSpinner1); |
| |
| var divSpinner2 = document.createElement('div'); |
| divSpinner2.setAttribute('class','rect2'); |
| div.appendChild(divSpinner2); |
| |
| var divSpinner3 = document.createElement('div'); |
| divSpinner3.setAttribute('class','rect3'); |
| div.appendChild(divSpinner3); |
| |
| var divSpinner4 = document.createElement('div'); |
| divSpinner4.setAttribute('class','rect4'); |
| div.appendChild(divSpinner4); |
| |
| this.spinner = this.spinner || $(div); |
| this.$body.append(this.spinner); |
| this.spinner.show(); |
| }, |
| |
| hideSpinner: function() { |
| if (this.spinner) this.spinner.remove(); |
| }, |
| |
| //Return context for custom events |
| _ctx: function() { |
| return { elm: this.$elm, $elm: this.$elm, $blocker: this.$blocker, options: this.options }; |
| } |
| }; |
| |
| $.modal.close = function(event) { |
| if (!$.modal.isActive()) return; |
| if (event) event.preventDefault(); |
| var current = getCurrent(); |
| current.close(); |
| return current.$elm; |
| }; |
| |
| // Returns if there currently is an active modal |
| $.modal.isActive = function () { |
| return modals.length > 0; |
| }; |
| |
| $.modal.getCurrent = getCurrent; |
| |
| $.modal.defaults = { |
| closeExisting: true, |
| escapeClose: true, |
| clickClose: true, |
| closeText: 'Close', |
| closeClass: '', |
| modalClass: "modal", |
| blockerClass: "jquery-modal", |
| spinnerHtml: '<div class="rect1"></div><div class="rect2"></div><div class="rect3"></div><div class="rect4"></div>', |
| showSpinner: true, |
| showClose: true, |
| fadeDuration: null, // Number of milliseconds the fade animation takes. |
| fadeDelay: 1.0 // Point during the overlay's fade-in that the modal begins to fade in (.5 = 50%, 1.5 = 150%, etc.) |
| }; |
| |
| // Event constants |
| $.modal.BEFORE_BLOCK = 'modal:before-block'; |
| $.modal.BLOCK = 'modal:block'; |
| $.modal.BEFORE_OPEN = 'modal:before-open'; |
| $.modal.OPEN = 'modal:open'; |
| $.modal.BEFORE_CLOSE = 'modal:before-close'; |
| $.modal.CLOSE = 'modal:close'; |
| $.modal.AFTER_CLOSE = 'modal:after-close'; |
| $.modal.AJAX_SEND = 'modal:ajax:send'; |
| $.modal.AJAX_SUCCESS = 'modal:ajax:success'; |
| $.modal.AJAX_FAIL = 'modal:ajax:fail'; |
| $.modal.AJAX_COMPLETE = 'modal:ajax:complete'; |
| |
| $.fn.modal = function(options){ |
| if (this.length === 1) { |
| new $.modal(this, options); |
| } |
| return this; |
| }; |
| |
| // Automatically bind links with rel="modal:close" to, well, close the modal. |
| $(document).on('click.modal', 'a[rel~="modal:close"]', $.modal.close); |
| $(document).on('click.modal', 'a[rel~="modal:open"]', function(event) { |
| event.preventDefault(); |
| $(this).modal(); |
| }); |
| })); |