/* * Ajax Popup plugin * * Documentation: ../docs/popup.md * * Require: * - bootstrap/modal */ +function ($) { "use strict"; // POPUP CLASS DEFINITION // ============================ var Popup = function(element, options) { var self = this this.options = options this.$el = $(element) this.$container = null this.$modal = null this.$backdrop = null this.isOpen = false this.firstDiv = null this.allowHide = true this.$container = this.createPopupContainer() this.$content = this.$container.find('.modal-content:first') this.$modal = this.$container.modal({ show: false, backdrop: false, keyboard: this.options.keyboard }) /* * Duplicate the popup reference on the .control-popup container */ this.$container.data('oc.popup', this) /* * Hook in to BS Modal events */ this.$modal.on('hide.bs.modal', function(){ self.triggerEvent('hide.oc.popup') self.isOpen = false self.setBackdrop(false) }) this.$modal.on('hidden.bs.modal', function(){ self.triggerEvent('hidden.oc.popup') self.$container.remove() self.$el.data('oc.popup', null) $(document.body).removeClass('modal-open') }) this.$modal.on('show.bs.modal', function(){ self.isOpen = true self.setBackdrop(true) $(document.body).addClass('modal-open') }) this.$modal.on('shown.bs.modal', function(){ self.triggerEvent('shown.oc.popup') }) this.$modal.on('close.oc.popup', function(){ self.hide() return false }) this.init() } Popup.DEFAULTS = { ajax: null, handler: null, keyboard: true, extraData: {}, content: null, size: null, adaptiveHeight: false, zIndex: null } Popup.prototype.init = function(){ var self = this /* * Do not allow the same popup to open twice */ if (self.isOpen) return /* * Show loading panel */ this.setBackdrop(true) if (!this.options.content) this.setLoading(true) /* * October AJAX */ if (this.options.handler) { this.$el.request(this.options.handler, { data: this.options.extraData, success: function(data, textStatus, jqXHR) { this.success(data, textStatus, jqXHR).done(function(){ self.setContent(data.result) $(window).trigger('ajaxUpdateComplete', [this, data, textStatus, jqXHR]) self.triggerEvent('popupComplete') // Deprecated self.triggerEvent('complete.oc.popup') }) }, error: function(jqXHR, textStatus, errorThrown) { this.error(jqXHR, textStatus, errorThrown).done(function(){ self.hide() self.triggerEvent('popupError') // Deprecated self.triggerEvent('error.oc.popup') }) } }) } /* * Regular AJAX */ else if (this.options.ajax) { $.ajax({ url: this.options.ajax, data: this.options.extraData, success: function(data) { self.setContent(data) }, cache: false }) } /* * Specified content */ else if (this.options.content) { var content = typeof this.options.content == 'function' ? this.options.content.call(this.$el[0], this) : this.options.content this.setContent(content) } } Popup.prototype.createPopupContainer = function() { var modal = $('
').prop({ class: 'control-popup modal fade', role: 'dialog', tabindex: -1 }), modalDialog = $('').addClass('modal-dialog'), modalContent = $('').addClass('modal-content') if (this.options.size) modalDialog.addClass('size-' + this.options.size) if (this.options.adaptiveHeight) modalDialog.addClass('adaptive-height') if (this.options.zIndex !== null) modal.css('z-index', this.options.zIndex + 20) return modal.append(modalDialog.append(modalContent)) } Popup.prototype.setContent = function(contents) { this.$content.html(contents) this.setLoading(false) this.show() // Duplicate the popup object reference on to the first div // inside the popup. Eg: $('#firstDiv').popup('hide') this.firstDiv = this.$content.find('>div:first') if (this.firstDiv.length > 0) this.firstDiv.data('oc.popup', this) var $defaultFocus = $('[default-focus]', this.$content) if ($defaultFocus.is(":visible")) { window.setTimeout(function() { $defaultFocus.focus() $defaultFocus = null }, 300) } } Popup.prototype.setBackdrop = function(val) { if (val && !this.$backdrop) { this.$backdrop = $('') if (this.options.zIndex !== null) this.$backdrop.css('z-index', this.options.zIndex) this.$backdrop.appendTo(document.body) this.$backdrop.addClass('in') this.$backdrop.append($('')) } else if (!val && this.$backdrop) { this.$backdrop.remove() this.$backdrop = null } } Popup.prototype.setLoading = function(val) { if (!this.$backdrop) return; var self = this if (val) { setTimeout(function(){ self.$backdrop.addClass('loading'); }, 100) } else { this.$backdrop.removeClass('loading'); } } Popup.prototype.hideLoading = function(val) { this.setLoading(false) // Wait for animations to complete var self = this setTimeout(function() { self.setBackdrop(false) }, 250) setTimeout(function() { self.hide() }, 500) } Popup.prototype.triggerEvent = function(eventName, params) { if (!params) params = [this.$el, this.$modal] var eventObject = jQuery.Event(eventName, { relatedTarget: this.$container.get(0) }) this.$el.trigger(eventObject, params) if (this.firstDiv) this.firstDiv.trigger(eventObject, params) } Popup.prototype.reload = function() { this.init() } Popup.prototype.show = function() { this.$modal.modal('show') this.$modal.on('click.dismiss.popup', '[data-dismiss="popup"]', $.proxy(this.hide, this)) this.triggerEvent('popupShow') // Deprecated this.triggerEvent('show.oc.popup') } Popup.prototype.hide = function() { this.triggerEvent('popupHide') // Deprecated this.triggerEvent('hide.oc.popup') if (this.allowHide) this.$modal.modal('hide') } /* * Hide the popup without destroying it, * you should call .hide() once finished */ Popup.prototype.visible = function(val) { if (val) this.$modal.addClass('in') else this.$modal.removeClass('in') this.setBackdrop(val) } Popup.prototype.toggle = function() { this.triggerEvent('popupToggle', [this.$modal]) // Deprecated this.triggerEvent('toggle.oc.popup', [this.$modal]) this.$modal.modal('toggle') } /* * Lock the popup from closing */ Popup.prototype.lock = function(val) { this.allowHide = !val } // POPUP PLUGIN DEFINITION // ============================ var old = $.fn.popup $.fn.popup = function (option) { var args = Array.prototype.slice.call(arguments, 1) return this.each(function () { var $this = $(this) var data = $this.data('oc.popup') var options = $.extend({}, Popup.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data) $this.data('oc.popup', (data = new Popup(this, options))) else if (typeof option == 'string') data[option].apply(data, args) else data.reload() }) } $.fn.popup.Constructor = Popup $.popup = function (option) { return $('').popup(option) } // POPUP NO CONFLICT // ================= $.fn.popup.noConflict = function () { $.fn.popup = old return this } // POPUP DATA-API // =============== $(document).on('click.oc.popup', '[data-control="popup"]', function() { $(this).popup() return false }); /* * Only use the popup loading indicator if the handlers are an exact match. */ $(document) .on('ajaxPromise', '[data-popup-load-indicator]', function(event, context) { if ($(this).data('request') != context.handler) return $(this).closest('.control-popup').removeClass('in').popup('setLoading', true) }) .on('ajaxFail', '[data-popup-load-indicator]', function(event, context) { if ($(this).data('request') != context.handler) return $(this).closest('.control-popup').addClass('in').popup('setLoading', false) }) .on('ajaxDone', '[data-popup-load-indicator]', function(event, context) { if ($(this).data('request') != context.handler) return $(this).closest('.control-popup').popup('hideLoading') }) }(window.jQuery);