Browse Source

Added more compatible methods.

Dante 11 years ago
parent
commit
25d91d3524

+ 8 - 0
README.md

@@ -11,6 +11,14 @@ Thanks for [akinoniku](https://github.com/akinoniku)'s suggestions on dialog app
 
 ================
 
+## The newer, the better!
+
+We have been adding too much for making BootstrapDialog being compatible with older version of Bootstrap Modal, that's not cool. 
+
+We encourage you always choose the latest Bootstrap and BootstrapDialog.
+
+================
+
 ## Use Guidances from contributors
 
 <a href="https://gist.github.com/Genkilabs/bdcc5f62c5b46a8e0904">How to use bootstrap-dialog as Rails 4 confirm</a> - @[Genkilabs](https://github.com/Genkilabs)

+ 1 - 1
bower.json

@@ -1,7 +1,7 @@
 {
     "name": "bootstrap3-dialog",
     "description": "Make use of Bootstrap Modal more monkey-friendly. http://nakupanda.github.io/bootstrap3-dialog/",
-    "version": "1.34.0",
+    "version": "1.34.1",
     "keywords": [
         "css",
         "js",

+ 4 - 0
changelog.txt

@@ -2,6 +2,10 @@ LASTEST NOT RELEASED
 ------------------------------
 NONE
 
+V1.34.1
+------------------------------
+* Added more compatible methods to make BootstrapDialog works better with older version of Bootstrap Modal. *
+
 V1.34.0
 ------------------------------
 * FIXED #84 *

+ 182 - 40
dist/js/bootstrap-dialog.js

@@ -33,6 +33,134 @@
 
     "use strict";
 
+    /* ================================================
+     * Definition of BootstrapDialogModal.
+     * Extend Bootstrap Modal and override some functions.
+     * BootstrapDialogModal === Modified Modal.
+     * ================================================ */
+    var Modal = $.fn.modal.Constructor;
+    var BootstrapDialogModal = function(element, options) {
+        Modal.call(this, element, options);
+    };
+    BootstrapDialogModal.getModalVersion = function() {
+        var version = null;
+        if (typeof $.fn.modal.Constructor.VERSION === 'undefined') {
+            version = 'v3.1';
+        } else if (/3\.2\.\d+/.test($.fn.modal.Constructor.VERSION)) {
+            version = 'v3.2';
+        } else {
+            version = 'v3.3';  // v3.3+
+        }
+
+        return version;
+    };
+    BootstrapDialogModal.ORIGINAL_BODY_PADDING = $('body').css('padding-right') || 0;
+    BootstrapDialogModal.METHODS_TO_OVERRIDE = {};
+    BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.1'] = {};
+    BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.2'] = {
+        hide: function(e) {
+            if (e) {
+                e.preventDefault();
+            }
+            e = $.Event('hide.bs.modal');
+
+            this.$element.trigger(e);
+
+            if (!this.isShown || e.isDefaultPrevented()) {
+                return;
+            }
+
+            this.isShown = false;
+
+            // Remove css class 'modal-open' when the last opened dialog is closing.
+            var openedDialogs = this.getGlobalOpenedDialogs();
+            if (openedDialogs.length === 0) {
+                this.$body.removeClass('modal-open');
+            }
+
+            this.resetScrollbar();
+            this.escape();
+
+            $(document).off('focusin.bs.modal');
+
+            this.$element
+            .removeClass('in')
+            .attr('aria-hidden', true)
+            .off('click.dismiss.bs.modal');
+
+            $.support.transition && this.$element.hasClass('fade') ?
+            this.$element
+            .one('bsTransitionEnd', $.proxy(this.hideModal, this))
+            .emulateTransitionEnd(300) :
+            this.hideModal();
+        }
+    };
+    BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.3'] = {
+        /**
+         * Overrided.
+         * 
+         * @returns {undefined}
+         */
+        setScrollbar: function() {
+            var bodyPad = BootstrapDialogModal.ORIGINAL_BODY_PADDING;
+            if (this.bodyIsOverflowing) {
+                this.$body.css('padding-right', bodyPad + this.scrollbarWidth);
+            }
+        },
+        /**
+         * Overrided.
+         * 
+         * @returns {undefined}
+         */
+        resetScrollbar: function() {
+            var openedDialogs = this.getGlobalOpenedDialogs();
+            if (openedDialogs.length === 0) {
+                this.$body.css('padding-right', BootstrapDialogModal.ORIGINAL_BODY_PADDING);
+            }
+        },
+        /**
+         * Overrided.
+         * 
+         * @returns {undefined}
+         */
+        hideModal: function() {
+            this.$element.hide();
+            this.backdrop($.proxy(function() {
+                var openedDialogs = this.getGlobalOpenedDialogs();
+                if (openedDialogs.length === 0) {
+                    this.$body.removeClass('modal-open');
+                }
+                this.resetAdjustments();
+                this.resetScrollbar();
+                this.$element.trigger('hidden.bs.modal');
+            }, this));
+        }
+    };
+    BootstrapDialogModal.prototype = {
+        constructor: BootstrapDialogModal,
+        /**
+         * New function, to get the dialogs that opened by BootstrapDialog.
+         * 
+         * @returns {undefined}
+         */
+        getGlobalOpenedDialogs: function() {
+            var openedDialogs = [];
+            $.each(BootstrapDialog.dialogs, function(id, dialogInstance) {
+                if (dialogInstance.isRealized() && dialogInstance.isOpened()) {
+                    openedDialogs.push(dialogInstance);
+                }
+            });
+
+            return openedDialogs;
+        }
+    };
+
+    // Add compatible methods.
+    BootstrapDialogModal.prototype = $.extend(BootstrapDialogModal.prototype, Modal.prototype, BootstrapDialogModal.METHODS_TO_OVERRIDE[BootstrapDialogModal.getModalVersion()]);
+
+    /* ================================================
+     * Definition of BootstrapDialog.
+     * ================================================ */
     var BootstrapDialog = function(options) {
         this.defaultOptions = $.extend(true, {
             id: BootstrapDialog.newGuid(),
@@ -88,10 +216,6 @@
 
     BootstrapDialog.ICON_SPINNER = 'glyphicon glyphicon-asterisk';
 
-    // Will be removed in later version, after Bootstrap Modal >= 3.3.0, updating z-index is unnecessary.
-    BootstrapDialog.ZINDEX_BACKDROP = 1040;
-    BootstrapDialog.ZINDEX_MODAL = 1050;
-
     /**
      * Default options.
      */
@@ -147,17 +271,49 @@
         }
     };
 
-    /**
-     * Determin if current version of Bootstrap Modal is greater than 3.3.0
-     * 
-     * @returns boolean
-     */
-    BootstrapDialog.isModernModal = function() {
-        var modal = $.fn.modal.Constructor;
+    BootstrapDialog.METHODS_TO_OVERRIDE = {};
+    BootstrapDialog.METHODS_TO_OVERRIDE['v3.1'] = {
+        handleModalBackdropEvent: function() {
+            this.getModal().on('click', {dialog: this}, function(event) {
+                event.target === this && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
+            });
 
-        return typeof $.fn.modal.Constructor.VERSION !== 'undefined' && /3\.3\.\d+/.test($.fn.modal.Constructor.VERSION);
-    };
+            return this;
+        },
+        /**
+         * To make multiple opened dialogs look better.
+         * 
+         * Will be removed in later version, after Bootstrap Modal >= 3.3.0, updating z-index is unnecessary.
+         */
+        updateZIndex: function() {
+            var zIndexBackdrop = 1040;
+            var zIndexModal = 1050;
+            var dialogCount = 0;
+            $.each(BootstrapDialog.dialogs, function(dialogId, dialogInstance) {
+                dialogCount++;
+            });
+            var $modal = this.getModal();
+            var $backdrop = $modal.data('bs.modal').$backdrop;
+            $modal.css('z-index', zIndexModal + (dialogCount - 1) * 20);
+            $backdrop.css('z-index', zIndexBackdrop + (dialogCount - 1) * 20);
 
+            return this;
+        },
+        open: function() {
+            !this.isRealized() && this.realize();
+            this.getModal().modal('show');
+            this.updateZIndex();
+            this.setOpened(true);
+
+            return this;
+        }
+    };
+    BootstrapDialog.METHODS_TO_OVERRIDE['v3.2'] = {
+        handleModalBackdropEvent: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['handleModalBackdropEvent'],
+        updateZIndex: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['updateZIndex'],
+        open: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['open']
+    };
+    BootstrapDialog.METHODS_TO_OVERRIDE['v3.3'] = {};
     BootstrapDialog.prototype = {
         constructor: BootstrapDialog,
         initOptions: function(options) {
@@ -815,13 +971,7 @@
             });
 
             // Backdrop, I did't find a way to change bs3 backdrop option after the dialog is popped up, so here's a new wheel.
-            this.getModal().on('click', {dialog: this}, function(event) {
-                if (!BootstrapDialog.isModernModal()) {
-                    event.target === this && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
-                } else {
-                    $(event.target).hasClass('modal-backdrop') && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
-                }
-            });
+            this.handleModalBackdropEvent();
 
             // ESC key support
             this.getModal().on('keyup', {dialog: this}, function(event) {
@@ -839,6 +989,13 @@
 
             return this;
         },
+        handleModalBackdropEvent: function() {
+            this.getModal().on('click', {dialog: this}, function(event) {
+                $(event.target).hasClass('modal-backdrop') && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
+            });
+
+            return this;
+        },
         isModalEvent: function(event) {
             return typeof event.namespace !== 'undefined' && event.namespace === 'bs.modal';
         },
@@ -870,23 +1027,6 @@
 
             return this;
         },
-        /**
-         * To make multiple opened dialogs look better.
-         * 
-         * Will be removed in later version, after Bootstrap Modal >= 3.3.0, updating z-index is unnecessary.
-         */
-        updateZIndex: function() {
-            var dialogCount = 0;
-            $.each(BootstrapDialog.dialogs, function(dialogId, dialogInstance) {
-                dialogCount++;
-            });
-            var $modal = this.getModal();
-            var $backdrop = $modal.data('bs.modal').$backdrop;
-            $modal.css('z-index', BootstrapDialog.ZINDEX_MODAL + (dialogCount - 1) * 20);
-            $backdrop.css('z-index', BootstrapDialog.ZINDEX_BACKDROP + (dialogCount - 1) * 20);
-
-            return this;
-        },
         realize: function() {
             this.initModalStuff();
             this.getModal().addClass(BootstrapDialog.NAMESPACE)
@@ -898,11 +1038,11 @@
             this.getModalFooter().append(this.createFooterContent());
             this.getModalHeader().append(this.createHeaderContent());
             this.getModalBody().append(this.createBodyContent());
-            this.getModal().modal({
+            this.getModal().data('bs.modal', new BootstrapDialogModal(this.getModal(), {
                 backdrop: 'static',
                 keyboard: false,
                 show: false
-            });
+            }));
             this.makeModalDraggable();
             this.handleModalEvents();
             this.setRealized(true);
@@ -919,7 +1059,6 @@
         open: function() {
             !this.isRealized() && this.realize();
             this.getModal().modal('show');
-            !BootstrapDialog.isModernModal() && this.updateZIndex(); // Will be removed in later version.
             this.setOpened(true);
 
             return this;
@@ -935,6 +1074,9 @@
         }
     };
 
+    // Add compatible methods.
+    BootstrapDialog.prototype = $.extend(BootstrapDialog.prototype, BootstrapDialog.METHODS_TO_OVERRIDE[BootstrapDialogModal.getModalVersion()]);
+
     /**
      * RFC4122 version 4 compliant unique id creator.
      *

File diff suppressed because it is too large
+ 1 - 1
dist/js/bootstrap-dialog.min.js


+ 182 - 40
examples/assets/bootstrap-dialog/js/bootstrap-dialog.js

@@ -33,6 +33,134 @@
 
     "use strict";
 
+    /* ================================================
+     * Definition of BootstrapDialogModal.
+     * Extend Bootstrap Modal and override some functions.
+     * BootstrapDialogModal === Modified Modal.
+     * ================================================ */
+    var Modal = $.fn.modal.Constructor;
+    var BootstrapDialogModal = function(element, options) {
+        Modal.call(this, element, options);
+    };
+    BootstrapDialogModal.getModalVersion = function() {
+        var version = null;
+        if (typeof $.fn.modal.Constructor.VERSION === 'undefined') {
+            version = 'v3.1';
+        } else if (/3\.2\.\d+/.test($.fn.modal.Constructor.VERSION)) {
+            version = 'v3.2';
+        } else {
+            version = 'v3.3';  // v3.3+
+        }
+
+        return version;
+    };
+    BootstrapDialogModal.ORIGINAL_BODY_PADDING = $('body').css('padding-right') || 0;
+    BootstrapDialogModal.METHODS_TO_OVERRIDE = {};
+    BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.1'] = {};
+    BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.2'] = {
+        hide: function(e) {
+            if (e) {
+                e.preventDefault();
+            }
+            e = $.Event('hide.bs.modal');
+
+            this.$element.trigger(e);
+
+            if (!this.isShown || e.isDefaultPrevented()) {
+                return;
+            }
+
+            this.isShown = false;
+
+            // Remove css class 'modal-open' when the last opened dialog is closing.
+            var openedDialogs = this.getGlobalOpenedDialogs();
+            if (openedDialogs.length === 0) {
+                this.$body.removeClass('modal-open');
+            }
+
+            this.resetScrollbar();
+            this.escape();
+
+            $(document).off('focusin.bs.modal');
+
+            this.$element
+            .removeClass('in')
+            .attr('aria-hidden', true)
+            .off('click.dismiss.bs.modal');
+
+            $.support.transition && this.$element.hasClass('fade') ?
+            this.$element
+            .one('bsTransitionEnd', $.proxy(this.hideModal, this))
+            .emulateTransitionEnd(300) :
+            this.hideModal();
+        }
+    };
+    BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.3'] = {
+        /**
+         * Overrided.
+         * 
+         * @returns {undefined}
+         */
+        setScrollbar: function() {
+            var bodyPad = BootstrapDialogModal.ORIGINAL_BODY_PADDING;
+            if (this.bodyIsOverflowing) {
+                this.$body.css('padding-right', bodyPad + this.scrollbarWidth);
+            }
+        },
+        /**
+         * Overrided.
+         * 
+         * @returns {undefined}
+         */
+        resetScrollbar: function() {
+            var openedDialogs = this.getGlobalOpenedDialogs();
+            if (openedDialogs.length === 0) {
+                this.$body.css('padding-right', BootstrapDialogModal.ORIGINAL_BODY_PADDING);
+            }
+        },
+        /**
+         * Overrided.
+         * 
+         * @returns {undefined}
+         */
+        hideModal: function() {
+            this.$element.hide();
+            this.backdrop($.proxy(function() {
+                var openedDialogs = this.getGlobalOpenedDialogs();
+                if (openedDialogs.length === 0) {
+                    this.$body.removeClass('modal-open');
+                }
+                this.resetAdjustments();
+                this.resetScrollbar();
+                this.$element.trigger('hidden.bs.modal');
+            }, this));
+        }
+    };
+    BootstrapDialogModal.prototype = {
+        constructor: BootstrapDialogModal,
+        /**
+         * New function, to get the dialogs that opened by BootstrapDialog.
+         * 
+         * @returns {undefined}
+         */
+        getGlobalOpenedDialogs: function() {
+            var openedDialogs = [];
+            $.each(BootstrapDialog.dialogs, function(id, dialogInstance) {
+                if (dialogInstance.isRealized() && dialogInstance.isOpened()) {
+                    openedDialogs.push(dialogInstance);
+                }
+            });
+
+            return openedDialogs;
+        }
+    };
+
+    // Add compatible methods.
+    BootstrapDialogModal.prototype = $.extend(BootstrapDialogModal.prototype, Modal.prototype, BootstrapDialogModal.METHODS_TO_OVERRIDE[BootstrapDialogModal.getModalVersion()]);
+
+    /* ================================================
+     * Definition of BootstrapDialog.
+     * ================================================ */
     var BootstrapDialog = function(options) {
         this.defaultOptions = $.extend(true, {
             id: BootstrapDialog.newGuid(),
@@ -88,10 +216,6 @@
 
     BootstrapDialog.ICON_SPINNER = 'glyphicon glyphicon-asterisk';
 
-    // Will be removed in later version, after Bootstrap Modal >= 3.3.0, updating z-index is unnecessary.
-    BootstrapDialog.ZINDEX_BACKDROP = 1040;
-    BootstrapDialog.ZINDEX_MODAL = 1050;
-
     /**
      * Default options.
      */
@@ -147,17 +271,49 @@
         }
     };
 
-    /**
-     * Determin if current version of Bootstrap Modal is greater than 3.3.0
-     * 
-     * @returns boolean
-     */
-    BootstrapDialog.isModernModal = function() {
-        var modal = $.fn.modal.Constructor;
+    BootstrapDialog.METHODS_TO_OVERRIDE = {};
+    BootstrapDialog.METHODS_TO_OVERRIDE['v3.1'] = {
+        handleModalBackdropEvent: function() {
+            this.getModal().on('click', {dialog: this}, function(event) {
+                event.target === this && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
+            });
 
-        return typeof $.fn.modal.Constructor.VERSION !== 'undefined' && /3\.3\.\d+/.test($.fn.modal.Constructor.VERSION);
-    };
+            return this;
+        },
+        /**
+         * To make multiple opened dialogs look better.
+         * 
+         * Will be removed in later version, after Bootstrap Modal >= 3.3.0, updating z-index is unnecessary.
+         */
+        updateZIndex: function() {
+            var zIndexBackdrop = 1040;
+            var zIndexModal = 1050;
+            var dialogCount = 0;
+            $.each(BootstrapDialog.dialogs, function(dialogId, dialogInstance) {
+                dialogCount++;
+            });
+            var $modal = this.getModal();
+            var $backdrop = $modal.data('bs.modal').$backdrop;
+            $modal.css('z-index', zIndexModal + (dialogCount - 1) * 20);
+            $backdrop.css('z-index', zIndexBackdrop + (dialogCount - 1) * 20);
 
+            return this;
+        },
+        open: function() {
+            !this.isRealized() && this.realize();
+            this.getModal().modal('show');
+            this.updateZIndex();
+            this.setOpened(true);
+
+            return this;
+        }
+    };
+    BootstrapDialog.METHODS_TO_OVERRIDE['v3.2'] = {
+        handleModalBackdropEvent: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['handleModalBackdropEvent'],
+        updateZIndex: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['updateZIndex'],
+        open: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['open']
+    };
+    BootstrapDialog.METHODS_TO_OVERRIDE['v3.3'] = {};
     BootstrapDialog.prototype = {
         constructor: BootstrapDialog,
         initOptions: function(options) {
@@ -815,13 +971,7 @@
             });
 
             // Backdrop, I did't find a way to change bs3 backdrop option after the dialog is popped up, so here's a new wheel.
-            this.getModal().on('click', {dialog: this}, function(event) {
-                if (!BootstrapDialog.isModernModal()) {
-                    event.target === this && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
-                } else {
-                    $(event.target).hasClass('modal-backdrop') && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
-                }
-            });
+            this.handleModalBackdropEvent();
 
             // ESC key support
             this.getModal().on('keyup', {dialog: this}, function(event) {
@@ -839,6 +989,13 @@
 
             return this;
         },
+        handleModalBackdropEvent: function() {
+            this.getModal().on('click', {dialog: this}, function(event) {
+                $(event.target).hasClass('modal-backdrop') && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
+            });
+
+            return this;
+        },
         isModalEvent: function(event) {
             return typeof event.namespace !== 'undefined' && event.namespace === 'bs.modal';
         },
@@ -870,23 +1027,6 @@
 
             return this;
         },
-        /**
-         * To make multiple opened dialogs look better.
-         * 
-         * Will be removed in later version, after Bootstrap Modal >= 3.3.0, updating z-index is unnecessary.
-         */
-        updateZIndex: function() {
-            var dialogCount = 0;
-            $.each(BootstrapDialog.dialogs, function(dialogId, dialogInstance) {
-                dialogCount++;
-            });
-            var $modal = this.getModal();
-            var $backdrop = $modal.data('bs.modal').$backdrop;
-            $modal.css('z-index', BootstrapDialog.ZINDEX_MODAL + (dialogCount - 1) * 20);
-            $backdrop.css('z-index', BootstrapDialog.ZINDEX_BACKDROP + (dialogCount - 1) * 20);
-
-            return this;
-        },
         realize: function() {
             this.initModalStuff();
             this.getModal().addClass(BootstrapDialog.NAMESPACE)
@@ -898,11 +1038,11 @@
             this.getModalFooter().append(this.createFooterContent());
             this.getModalHeader().append(this.createHeaderContent());
             this.getModalBody().append(this.createBodyContent());
-            this.getModal().modal({
+            this.getModal().data('bs.modal', new BootstrapDialogModal(this.getModal(), {
                 backdrop: 'static',
                 keyboard: false,
                 show: false
-            });
+            }));
             this.makeModalDraggable();
             this.handleModalEvents();
             this.setRealized(true);
@@ -919,7 +1059,6 @@
         open: function() {
             !this.isRealized() && this.realize();
             this.getModal().modal('show');
-            !BootstrapDialog.isModernModal() && this.updateZIndex(); // Will be removed in later version.
             this.setOpened(true);
 
             return this;
@@ -935,6 +1074,9 @@
         }
     };
 
+    // Add compatible methods.
+    BootstrapDialog.prototype = $.extend(BootstrapDialog.prototype, BootstrapDialog.METHODS_TO_OVERRIDE[BootstrapDialogModal.getModalVersion()]);
+
     /**
      * RFC4122 version 4 compliant unique id creator.
      *

File diff suppressed because it is too large
+ 1 - 1
examples/assets/bootstrap-dialog/js/bootstrap-dialog.min.js


+ 31 - 0
examples/index.html

@@ -263,6 +263,37 @@
         -->
     </div>
 
+    <a name="opening-multiple-dialogs"></a>
+    <h3>Opening multiple dialogs</h3>
+    <p>A good looking stacked dialogs. Please also note the second and the third dialog are draggable.</p>
+    <div class="source-code runnable">
+        <!--
+        var shortContent = '<p>Something here.</p>';
+        var longContent = '';
+        for(var i = 1; i <= 200; i++) {
+            longContent += shortContent;
+        }
+        BootstrapDialog.show({
+            title: 'Another long dialog',
+            message: longContent
+        });
+        BootstrapDialog.show({
+            title: 'Another short dialog',
+            message: shortContent,
+            draggable: true
+        });
+        BootstrapDialog.show({
+            title: 'A long dialog',
+            message: longContent,
+            draggable: true
+        });
+        BootstrapDialog.show({
+            title: 'A short dialog',
+            message: shortContent
+        });
+        -->
+    </div>
+    
     <h3>Creating dialog instances</h3>
     <p>BootstrapDialog.show(...) is just a shortcut method, if you need dialog instances, use 'new'.</p>
     <div class="source-code runnable">

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "bootstrap3-dialog",
-  "version": "1.34.0",
+  "version": "1.34.1",
   "description": "Make use of Bootstrap Modal more monkey-friendly.",
   "private": true,
   "directories": {

+ 182 - 40
src/js/bootstrap-dialog.js

@@ -33,6 +33,134 @@
 
     "use strict";
 
+    /* ================================================
+     * Definition of BootstrapDialogModal.
+     * Extend Bootstrap Modal and override some functions.
+     * BootstrapDialogModal === Modified Modal.
+     * ================================================ */
+    var Modal = $.fn.modal.Constructor;
+    var BootstrapDialogModal = function(element, options) {
+        Modal.call(this, element, options);
+    };
+    BootstrapDialogModal.getModalVersion = function() {
+        var version = null;
+        if (typeof $.fn.modal.Constructor.VERSION === 'undefined') {
+            version = 'v3.1';
+        } else if (/3\.2\.\d+/.test($.fn.modal.Constructor.VERSION)) {
+            version = 'v3.2';
+        } else {
+            version = 'v3.3';  // v3.3+
+        }
+
+        return version;
+    };
+    BootstrapDialogModal.ORIGINAL_BODY_PADDING = $('body').css('padding-right') || 0;
+    BootstrapDialogModal.METHODS_TO_OVERRIDE = {};
+    BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.1'] = {};
+    BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.2'] = {
+        hide: function(e) {
+            if (e) {
+                e.preventDefault();
+            }
+            e = $.Event('hide.bs.modal');
+
+            this.$element.trigger(e);
+
+            if (!this.isShown || e.isDefaultPrevented()) {
+                return;
+            }
+
+            this.isShown = false;
+
+            // Remove css class 'modal-open' when the last opened dialog is closing.
+            var openedDialogs = this.getGlobalOpenedDialogs();
+            if (openedDialogs.length === 0) {
+                this.$body.removeClass('modal-open');
+            }
+
+            this.resetScrollbar();
+            this.escape();
+
+            $(document).off('focusin.bs.modal');
+
+            this.$element
+            .removeClass('in')
+            .attr('aria-hidden', true)
+            .off('click.dismiss.bs.modal');
+
+            $.support.transition && this.$element.hasClass('fade') ?
+            this.$element
+            .one('bsTransitionEnd', $.proxy(this.hideModal, this))
+            .emulateTransitionEnd(300) :
+            this.hideModal();
+        }
+    };
+    BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.3'] = {
+        /**
+         * Overrided.
+         * 
+         * @returns {undefined}
+         */
+        setScrollbar: function() {
+            var bodyPad = BootstrapDialogModal.ORIGINAL_BODY_PADDING;
+            if (this.bodyIsOverflowing) {
+                this.$body.css('padding-right', bodyPad + this.scrollbarWidth);
+            }
+        },
+        /**
+         * Overrided.
+         * 
+         * @returns {undefined}
+         */
+        resetScrollbar: function() {
+            var openedDialogs = this.getGlobalOpenedDialogs();
+            if (openedDialogs.length === 0) {
+                this.$body.css('padding-right', BootstrapDialogModal.ORIGINAL_BODY_PADDING);
+            }
+        },
+        /**
+         * Overrided.
+         * 
+         * @returns {undefined}
+         */
+        hideModal: function() {
+            this.$element.hide();
+            this.backdrop($.proxy(function() {
+                var openedDialogs = this.getGlobalOpenedDialogs();
+                if (openedDialogs.length === 0) {
+                    this.$body.removeClass('modal-open');
+                }
+                this.resetAdjustments();
+                this.resetScrollbar();
+                this.$element.trigger('hidden.bs.modal');
+            }, this));
+        }
+    };
+    BootstrapDialogModal.prototype = {
+        constructor: BootstrapDialogModal,
+        /**
+         * New function, to get the dialogs that opened by BootstrapDialog.
+         * 
+         * @returns {undefined}
+         */
+        getGlobalOpenedDialogs: function() {
+            var openedDialogs = [];
+            $.each(BootstrapDialog.dialogs, function(id, dialogInstance) {
+                if (dialogInstance.isRealized() && dialogInstance.isOpened()) {
+                    openedDialogs.push(dialogInstance);
+                }
+            });
+
+            return openedDialogs;
+        }
+    };
+
+    // Add compatible methods.
+    BootstrapDialogModal.prototype = $.extend(BootstrapDialogModal.prototype, Modal.prototype, BootstrapDialogModal.METHODS_TO_OVERRIDE[BootstrapDialogModal.getModalVersion()]);
+
+    /* ================================================
+     * Definition of BootstrapDialog.
+     * ================================================ */
     var BootstrapDialog = function(options) {
         this.defaultOptions = $.extend(true, {
             id: BootstrapDialog.newGuid(),
@@ -88,10 +216,6 @@
 
     BootstrapDialog.ICON_SPINNER = 'glyphicon glyphicon-asterisk';
 
-    // Will be removed in later version, after Bootstrap Modal >= 3.3.0, updating z-index is unnecessary.
-    BootstrapDialog.ZINDEX_BACKDROP = 1040;
-    BootstrapDialog.ZINDEX_MODAL = 1050;
-
     /**
      * Default options.
      */
@@ -147,17 +271,49 @@
         }
     };
 
-    /**
-     * Determin if current version of Bootstrap Modal is greater than 3.3.0
-     * 
-     * @returns boolean
-     */
-    BootstrapDialog.isModernModal = function() {
-        var modal = $.fn.modal.Constructor;
+    BootstrapDialog.METHODS_TO_OVERRIDE = {};
+    BootstrapDialog.METHODS_TO_OVERRIDE['v3.1'] = {
+        handleModalBackdropEvent: function() {
+            this.getModal().on('click', {dialog: this}, function(event) {
+                event.target === this && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
+            });
 
-        return typeof $.fn.modal.Constructor.VERSION !== 'undefined' && /3\.3\.\d+/.test($.fn.modal.Constructor.VERSION);
-    };
+            return this;
+        },
+        /**
+         * To make multiple opened dialogs look better.
+         * 
+         * Will be removed in later version, after Bootstrap Modal >= 3.3.0, updating z-index is unnecessary.
+         */
+        updateZIndex: function() {
+            var zIndexBackdrop = 1040;
+            var zIndexModal = 1050;
+            var dialogCount = 0;
+            $.each(BootstrapDialog.dialogs, function(dialogId, dialogInstance) {
+                dialogCount++;
+            });
+            var $modal = this.getModal();
+            var $backdrop = $modal.data('bs.modal').$backdrop;
+            $modal.css('z-index', zIndexModal + (dialogCount - 1) * 20);
+            $backdrop.css('z-index', zIndexBackdrop + (dialogCount - 1) * 20);
 
+            return this;
+        },
+        open: function() {
+            !this.isRealized() && this.realize();
+            this.getModal().modal('show');
+            this.updateZIndex();
+            this.setOpened(true);
+
+            return this;
+        }
+    };
+    BootstrapDialog.METHODS_TO_OVERRIDE['v3.2'] = {
+        handleModalBackdropEvent: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['handleModalBackdropEvent'],
+        updateZIndex: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['updateZIndex'],
+        open: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['open']
+    };
+    BootstrapDialog.METHODS_TO_OVERRIDE['v3.3'] = {};
     BootstrapDialog.prototype = {
         constructor: BootstrapDialog,
         initOptions: function(options) {
@@ -815,13 +971,7 @@
             });
 
             // Backdrop, I did't find a way to change bs3 backdrop option after the dialog is popped up, so here's a new wheel.
-            this.getModal().on('click', {dialog: this}, function(event) {
-                if (!BootstrapDialog.isModernModal()) {
-                    event.target === this && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
-                } else {
-                    $(event.target).hasClass('modal-backdrop') && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
-                }
-            });
+            this.handleModalBackdropEvent();
 
             // ESC key support
             this.getModal().on('keyup', {dialog: this}, function(event) {
@@ -839,6 +989,13 @@
 
             return this;
         },
+        handleModalBackdropEvent: function() {
+            this.getModal().on('click', {dialog: this}, function(event) {
+                $(event.target).hasClass('modal-backdrop') && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
+            });
+
+            return this;
+        },
         isModalEvent: function(event) {
             return typeof event.namespace !== 'undefined' && event.namespace === 'bs.modal';
         },
@@ -870,23 +1027,6 @@
 
             return this;
         },
-        /**
-         * To make multiple opened dialogs look better.
-         * 
-         * Will be removed in later version, after Bootstrap Modal >= 3.3.0, updating z-index is unnecessary.
-         */
-        updateZIndex: function() {
-            var dialogCount = 0;
-            $.each(BootstrapDialog.dialogs, function(dialogId, dialogInstance) {
-                dialogCount++;
-            });
-            var $modal = this.getModal();
-            var $backdrop = $modal.data('bs.modal').$backdrop;
-            $modal.css('z-index', BootstrapDialog.ZINDEX_MODAL + (dialogCount - 1) * 20);
-            $backdrop.css('z-index', BootstrapDialog.ZINDEX_BACKDROP + (dialogCount - 1) * 20);
-
-            return this;
-        },
         realize: function() {
             this.initModalStuff();
             this.getModal().addClass(BootstrapDialog.NAMESPACE)
@@ -898,11 +1038,11 @@
             this.getModalFooter().append(this.createFooterContent());
             this.getModalHeader().append(this.createHeaderContent());
             this.getModalBody().append(this.createBodyContent());
-            this.getModal().modal({
+            this.getModal().data('bs.modal', new BootstrapDialogModal(this.getModal(), {
                 backdrop: 'static',
                 keyboard: false,
                 show: false
-            });
+            }));
             this.makeModalDraggable();
             this.handleModalEvents();
             this.setRealized(true);
@@ -919,7 +1059,6 @@
         open: function() {
             !this.isRealized() && this.realize();
             this.getModal().modal('show');
-            !BootstrapDialog.isModernModal() && this.updateZIndex(); // Will be removed in later version.
             this.setOpened(true);
 
             return this;
@@ -935,6 +1074,9 @@
         }
     };
 
+    // Add compatible methods.
+    BootstrapDialog.prototype = $.extend(BootstrapDialog.prototype, BootstrapDialog.METHODS_TO_OVERRIDE[BootstrapDialogModal.getModalVersion()]);
+
     /**
      * RFC4122 version 4 compliant unique id creator.
      *