/* =========================================================== * ModalDialogForm.js v0.0.1 * =========================================================== * Copyright 2016 Prevu * ========================================================== */ (function ($) { "use strict"; /* ModalDialogForm CLASS DEFINITION * ====================== */ var C_CHANGABLE_CONTROLS_SELECTOR = 'input[type=checkbox],input[type=radio],input[type=text],select,textarea'; var ModalDialogForm = function (element, options) { this.init(element, options); }; ModalDialogForm.prototype = { constructor: ModalDialogForm, init: function (element, options) { var plugin = this; this.options = options; this.$container = $(element); this.$data = { formDataChanged: false, formCloseEventHandler: null }; this.validateIncomingParams(); if (this.options.initCallback && (typeof this.options.initCallback === 'function')) { this.options.initCallback(this); } }, validateIncomingParams: function () { // Add validation of incoming params here, if needed. Throw exception, if something is wrong }, getContainerId: function () { if (!this.$container) return; return $(this.$container).attr('id'); }, attachToFormEvents: function () { var plugin = this; var containerId = this.getContainerId(); if (!containerId) { throw "Unable to sign to modal form 'on close' event: container has no 'id' attribute"; } if (!this.$data) { this.$data = {}; } var containerSelector = '#' + containerId; this.$data.formCloseEventHandler = function (e) { return plugin.onFormClosingQuery(e, plugin); } $(document).on('hide.bs.modal', containerSelector, this.$data.formCloseEventHandler); }, detachFromFormEvents: function () { if (this.$data && this.$data.formCloseEventHandler && (typeof this.$data.formCloseEventHandler === 'function')) { var containerId = this.getContainerId(); if (!containerId) { throw "Unable to unasign from modal form 'on close' event: container has no 'id' attribute"; } var containerSelector = '#' + containerId; $(document).off('hide.bs.modal', containerSelector, this.$data.formCloseEventHandler); this.$data.formCloseEventHandler = null; } }, startTrackingControlChanges: function () { var plugin = this; $(this.$container).find(C_CHANGABLE_CONTROLS_SELECTOR).on("change.modalDialogForm", function () { plugin.setDataChanged(true); }); }, finishTrackingControlChanges: function () { $(this.$container).find(C_CHANGABLE_CONTROLS_SELECTOR).off("change.modalDialogForm"); }, onFormClosingQuery: function (e, plugin) { var containerId = plugin.getContainerId(); if ($(e.target).attr('id') != containerId) { plugin.$container.focus(); return true; // close modal form } if (plugin.isDataChanged()) { bootbox.confirm(plugin.options.confirmMessage, function (result) { if (result) { plugin.resetDataChanges(); plugin.detachFromFormEvents(); plugin.finishTrackingControlChanges(); plugin.$container.modal('hide'); } }); plugin.$container.focus(); return false; // DO NOT close modal form } plugin.$container.focus(); plugin.detachFromFormEvents(); plugin.finishTrackingControlChanges(); return true; // close modal form }, setDataChanged: function (isChanged) { if (!this.$data) { this.$data = {}; } this.$data.formDataChanged = isChanged; }, resetDataChanges: function () { if (!this.$data) { this.$data = {}; } this.$data.formDataChanged = false; }, isDataChanged: function () { return this.$data ? this.$data.formDataChanged : false; }, show: function () { this.startTrackingControlChanges(); this.attachToFormEvents(); this.resetDataChanges(); this.$container.modal('show'); if (this.options.parseValidators) $.validator.unobtrusive.parseDynamicContent(this.$container.find('form')); }, hide: function () { this.resetDataChanges(); this.$container.modal('hide'); }, setData: function (data) { if (data) { this.$data = data; } else { this.$data = null; } }, destroy: function () { console.log('Modal form destroy'); var e = $.Event('destroy'); this.$container.trigger(e); if (e.isDefaultPrevented()) return; this.detachFromFormEvents(); this.$container.removeData('modalDialogForm'); } }; /* MODAL DIALOG FORM PLUGIN DEFINITION * ======================= */ $.fn.modalDialogForm = function (option, args) { return this.each(function () { var $this = $(this), data = $this.data('modalDialogForm'), options = $.extend({}, $.fn.modalDialogForm.defaults, $this.data(), typeof option == 'object' && option); if (!data) $this.data('modalDialogForm', (data = new ModalDialogForm(this, options))); if (typeof option == 'string') data[option].apply(data, [].concat(args)); }); }; $.fn.modalDialogForm.defaults = { confirmMessage: "Form contains data changes, do you really want to close the form?", initCallback: null, parseValidators: false }; $.fn.modalDialogForm.Constructor = ModalDialogForm; }(jQuery));