/* * Ajax Popup plugin * * Options: * - content: content HTML string or callback * * Data attributes: * - data-control="popup" - enables the ajax popup plugin * - data-ajax="popup-content.htm" - ajax content to load * - data-handler="widget:pluginName" - October ajax request name * - data-keyboard="false" - Allow popup to be closed with the keyboard * - data-request-data="file_id: 1" - October ajax request data * * JavaScript API: * $('a#someLink').popup({ ajax: 'popup-content.htm' }) * $('a#someLink').popup({ handler: 'onOpenPopupForm' }) * * Dependences: * - Bootstrap Modal (modal.js) */ +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.isOpen = false self.setBackdrop(false) }) this.$modal.on('hidden.bs.modal', function(){ self.$container.remove() self.$el.data('oc.popup', null) }) this.$modal.on('show.bs.modal', function(){ self.isOpen = true self.setBackdrop(true) }) 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 } 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') 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) } Popup.prototype.setBackdrop = function(val) { if (val && !this.$backdrop) { 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 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 }); $(document) .on('ajaxPromise', '[data-popup-load-indicator]', function() { $(this).closest('.control-popup').removeClass('in').popup('setLoading', true) }) .on('ajaxFail', '[data-popup-load-indicator]', function() { $(this).closest('.control-popup').addClass('in').popup('setLoading', false) }) .on('ajaxDone', '[data-popup-load-indicator]', function() { $(this).closest('.control-popup').popup('hideLoading') }) }(window.jQuery);