Improved DOMNodeInsertedHandler
authorAlexander Ebert <ebert@woltlab.com>
Mon, 27 May 2013 15:47:39 +0000 (17:47 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 27 May 2013 15:48:14 +0000 (17:48 +0200)
Attention developers! I've redesigned it's entire API, you must now manually call WCF.DOMNodeInsertedHandler.execute() if you manipulate the DOM. The only exception are success-callbacks for WCF.Action.Proxy, in this case that method call is automatically invoked.

wcfsetup/install/files/acp/js/WCF.ACP.js
wcfsetup/install/files/js/WCF.ACL.js
wcfsetup/install/files/js/WCF.Attachment.js
wcfsetup/install/files/js/WCF.Comment.js
wcfsetup/install/files/js/WCF.ImageViewer.js
wcfsetup/install/files/js/WCF.Like.js
wcfsetup/install/files/js/WCF.Message.js
wcfsetup/install/files/js/WCF.Poll.js
wcfsetup/install/files/js/WCF.User.js
wcfsetup/install/files/js/WCF.js

index c29741b4baa27db4e6dc1dc8f8c653fd6b37c630..1b1db9f0cd9141fd3e9f7a32cc1f81cf324b5cb0 100644 (file)
@@ -69,9 +69,9 @@ WCF.ACP.Application.SetAsPrimary = Class.extend({
                                $('#setAsPrimary').parent().remove();
                                
                                // insert icon
-                               WCF.DOMNodeInsertedHandler.enable();
                                $('<span class="icon icon16 icon-home jsTooltip" title="' + WCF.Language.get('wcf.acp.application.primaryApplication') + '" />').appendTo($('.boxHeadline > h1'));
-                               WCF.DOMNodeInsertedHandler.disable();
+                               
+                               WCF.DOMNodeInsertedHandler.execute();
                        }, this)
                });
        }
@@ -1155,12 +1155,10 @@ WCF.ACP.Package.Search = Class.extend({
                        this._proxy.sendRequest();
                }
                else {
-                       WCF.DOMNodeInsertedHandler.enable();
-                       
                        // show cached content
                        this._packageSearchResultList.html(this._content[this._pageNo]);
                        
-                       WCF.DOMNodeInsertedHandler.disable();
+                       WCF.DOMNodeInsertedHandler.execute();
                }
        }
 });
index ac7c406fa203fdb7b93fec455eb7fb9db3f38d3d..9d83e0bfdee36ccb1c31ed0e2f3790e9d4221bc4 100644 (file)
@@ -187,7 +187,7 @@ WCF.ACL.List = Class.extend({
                // show permissions
                this._containerElements.permissionList.show();
                
-               WCF.DOMNodeInsertedHandler.forceExecution();
+               WCF.DOMNodeInsertedHandler.execute();
        },
        
        /**
@@ -337,7 +337,7 @@ WCF.ACL.List = Class.extend({
                // add options
                this._values[type] = data.returnValues[type].option;
                
-               WCF.DOMNodeInsertedHandler.forceExecution();
+               WCF.DOMNodeInsertedHandler.execute();
        },
        
        /**
index 657b8131638814add8b950f385421690f5a8a7c3..edc9f92090f74ab6898011232fd913f36c38fa80 100644 (file)
@@ -205,7 +205,7 @@ WCF.Attachment.Upload = WCF.Upload.extend({
                        $li.css('display', 'block');
                }
                
-               WCF.DOMNodeInsertedHandler.forceExecution();
+               WCF.DOMNodeInsertedHandler.execute();
        },
        
        /**
index 61a3073775e0a1c6f4f7de8dac36ecfb12062754..e4026bc9d824551140e8e9a2b3ff4f66df83f9b1 100644 (file)
@@ -96,8 +96,6 @@ WCF.Comment.Handler = Class.extend({
                        success: $.proxy(this._success, this)
                });
                
-               WCF.DOMNodeInsertedHandler.enable();
-               
                this._initComments();
                this._initResponses();
                
@@ -106,7 +104,7 @@ WCF.Comment.Handler = Class.extend({
                        this._initAddComment();
                }
                
-               WCF.DOMNodeInsertedHandler.disable();
+               WCF.DOMNodeInsertedHandler.execute();
                WCF.DOMNodeInsertedHandler.addCallback('WCF.Comment.Handler', $.proxy(this._domNodeInserted, this));
        },
        
@@ -501,7 +499,7 @@ WCF.Comment.Handler = Class.extend({
                        break;
                }
                
-               WCF.DOMNodeInsertedHandler.forceExecution();
+               WCF.DOMNodeInsertedHandler.execute();
        },
        
        /**
index 64490bfff260e2e68da03deee00d17a46be3f376..e6d794204f9a45595d343f30dd94cb60b84e125e 100644 (file)
@@ -11,10 +11,6 @@ WCF.ImageViewer = Class.extend({
         * Initializes the ImageViewer for every a-tag with the attribute rel = imageviewer.
         */
        init: function() {
-               WCF.DOMNodeInsertedHandler.addCallback('WCF.ImageViewer', $.proxy(this._domNodeInserted, this));
-               
-               WCF.DOMNodeInsertedHandler.enable();
-               
                // navigation buttons
                $('<span class="icon icon16 icon-chevron-left jsTooltip" title="' + WCF.Language.get('wcf.imageViewer.previous') + '" />').appendTo($('#lbPrevLink'));
                $('<span class="icon icon16 icon-chevron-right jsTooltip" title="' + WCF.Language.get('wcf.imageViewer.next') + '" />').appendTo($('#lbNextLink'));
@@ -23,12 +19,13 @@ WCF.ImageViewer = Class.extend({
                $('<span class="icon icon32 icon-remove jsTooltip" title="' + WCF.Language.get('wcf.imageViewer.close') + '" />').appendTo($('#lbCloseLink'));
                var $buttonEnlarge = $('<span class="icon icon32 icon-resize-full jsTooltip" title="' + WCF.Language.get('wcf.imageViewer.enlarge') + '" id="lbEnlarge" />').insertAfter($('#lbCloseLink'));
                
-               WCF.DOMNodeInsertedHandler.disable();
-               
                // handle enlarge button
                $buttonEnlarge.click($.proxy(this._enlarge, this));
                
                this._initImageViewer();
+               
+               WCF.DOMNodeInsertedHandler.addCallback('WCF.ImageViewer', $.proxy(this._domNodeInserted, this));
+               WCF.DOMNodeInsertedHandler.execute();
        },
        
        /**
@@ -43,8 +40,6 @@ WCF.ImageViewer = Class.extend({
         * Initializes the image viewer for all links with class ".jsImageViewer"
         */
        _initImageViewer: function() {
-               WCF.DOMNodeInsertedHandler.enable();
-               
                var $links = $('a.jsImageViewer');
                if ($links.length) {
                        $links.removeClass('jsImageViewer').slimbox({
@@ -52,8 +47,6 @@ WCF.ImageViewer = Class.extend({
                                loop: true
                        });
                }
-               
-               WCF.DOMNodeInsertedHandler.disable();
        },
        
        /**
index 714cf1d854bbfb73a018a2c995d67f1974ffdede..592b994a3cde8972743e4b398f86fe507970ce77 100644 (file)
@@ -142,7 +142,7 @@ WCF.Like = Class.extend({
                        new WCF.PeriodicalExecuter(function(pe) {
                                pe.stop();
                                
-                               WCF.DOMNodeInsertedHandler.forceExecution();
+                               WCF.DOMNodeInsertedHandler.execute();
                        }, 250);
                }
        },
index 676d7bf4ef5694d9ce439c1a631b07fbd9502a6d..be8b01f5082227fa6df69284a6d507070fd82cb5 100644 (file)
@@ -31,7 +31,7 @@ WCF.Message.BBCode.CodeViewer = Class.extend({
                this._initCodeBoxes();
                
                WCF.DOMNodeInsertedHandler.addCallback('WCF.Message.BBCode.CodeViewer', $.proxy(this._initCodeBoxes, this));
-               WCF.DOMNodeInsertedHandler.forceExecution();
+               WCF.DOMNodeInsertedHandler.execute();
        },
        
        /**
@@ -1116,14 +1116,12 @@ WCF.Message.InlineEditor = Class.extend({
                if (!$button.hasClass('dropdownToggle')) {
                        var $containerID = $button.data('containerID');
                        
-                       WCF.DOMNodeInsertedHandler.enable();
-                       
                        $button.addClass('dropdownToggle').parent().addClass('dropdown');
                        
                        var $dropdownMenu = $('<ul class="dropdownMenu" />').insertAfter($button);
                        this._initDropdownMenu($containerID, $dropdownMenu);
                        
-                       WCF.DOMNodeInsertedHandler.disable();
+                       WCF.DOMNodeInsertedHandler.execute();
                        
                        this._dropdowns[this._container[$containerID].data('objectID')] = $dropdownMenu;
                        
index de629bba8064f21241495d2430afa5e30b12885f..d8fa2a59d121d05bc7bad4df0175967e80e9a507 100644 (file)
@@ -100,7 +100,7 @@ WCF.Poll.Management = Class.extend({
                        $input.focus();
                }
                
-               WCF.DOMNodeInsertedHandler.forceExecution();
+               WCF.DOMNodeInsertedHandler.execute();
        },
        
        /**
index be58d1a6d051126437c982efa24fc7f2859982d9..7d0bcc8dcd9228de1caf3f87687642d2be8c3d65 100644 (file)
@@ -2016,12 +2016,12 @@ WCF.User.Avatar.Crop = Class.extend({
                        break;
                        
                        case 'cropAvatar':
-                               WCF.DOMNodeInsertedHandler.enable();
                                $('#avatarUpload > dt > img').replaceWith($('<img src="' + data.returnValues.url + '" alt="" class="userAvatarCrop jsTooltip" title="' + WCF.Language.get('wcf.user.avatar.type.custom.crop') + '" />').css({
                                        width: '96px',
                                        height: '96px'
                                }).click($.proxy(this._showCropDialog, this)));
-                               WCF.DOMNodeInsertedHandler.disable();
+                               
+                               WCF.DOMNodeInsertedHandler.execute();
                                
                                this._dialog.wcfDialog('close');
                                
@@ -2136,7 +2136,6 @@ WCF.User.Avatar.Upload = WCF.Upload.extend({
         * @param       boolean         canCrop
         */
        _updateImage: function(url, canCrop) {
-               WCF.DOMNodeInsertedHandler.enable();
                $('#avatarUpload > dt > img').remove();
                var $image = $('<img src="' + url + '" alt="" />').css({
                        'height': 'auto',
@@ -2150,7 +2149,8 @@ WCF.User.Avatar.Upload = WCF.Upload.extend({
                }
                
                $('#avatarUpload > dt').prepend($image);
-               WCF.DOMNodeInsertedHandler.disable();
+               
+               WCF.DOMNodeInsertedHandler.execute();
        },
        
        /**
index eefea2ea78bb9a6ec00cc4ba1d4b2d7d8ae32c7b..9d59a9f36df46b51bc91dff9d4c5155f725be0ab 100755 (executable)
@@ -1834,9 +1834,6 @@ WCF.Action.Proxy = Class.extend({
         * @param       object          jqXHR
         */
        _success: function(data, textStatus, jqXHR) {
-               // enable DOMNodeInserted event
-               WCF.DOMNodeInsertedHandler.enable();
-               
                // call child method if applicable
                if ($.isFunction(this.options.success)) {
                        // trim HTML before processing, see http://jquery.com/upgrade-guide/1.9/#jquery-htmlstring-versus-jquery-selectorstring
@@ -1866,8 +1863,7 @@ WCF.Action.Proxy = Class.extend({
                        }
                }
                
-               // disable DOMNodeInserted event
-               WCF.DOMNodeInsertedHandler.disable();
+               WCF.DOMNodeInsertedHandler.execute();
                
                // fix anchor tags generated through WCF::getAnchor()
                $('a[href*=#]').each(function(index, link) {
@@ -4378,11 +4374,11 @@ WCF.Collapsible.Sidebar = Class.extend({
                this._userPanelHeight = $('#topMenu').outerHeight();
                
                // add toggle button
-               WCF.DOMNodeInsertedHandler.enable();
                this._button = $('<a class="collapsibleButton jsTooltip" title="' + WCF.Language.get('wcf.global.button.collapsible') + '" />').prependTo(this._sidebar);
                this._button.click($.proxy(this._click, this));
                this._buttonHeight = this._button.outerHeight();
-               WCF.DOMNodeInsertedHandler.disable();
+               
+               WCF.DOMNodeInsertedHandler.execute();
                
                this._proxy = new WCF.Action.Proxy({
                        showLoadingOverlay: false,
@@ -4843,30 +4839,12 @@ WCF.DOMNodeInsertedHandler = {
         */
        _callbacks: [ ],
        
-       /**
-        * true if DOMNodeInserted event should be ignored
-        * @var boolean
-        */
-       _discardEvent: true,
-       
-       /**
-        * counts requests to enable WCF.DOMNodeInsertedHandler
-        * @var integer
-        */
-       _discardEventCount: 0,
-       
        /**
         * prevent infinite loop if a callback manipulates DOM
         * @var boolean
         */
        _isExecuting: false,
        
-       /**
-        * indicates that overlay handler is listening to click events on body-tag
-        * @var boolean
-        */
-       _isListening: false,
-       
        /**
         * Adds a new callback.
         * 
@@ -4874,28 +4852,14 @@ WCF.DOMNodeInsertedHandler = {
         * @param       object          callback
         */
        addCallback: function(identifier, callback) {
-               this._discardEventCount = 0;
-               this._bindListener();
-               
                this._callbacks.push(callback);
        },
        
-       /**
-        * Binds click event handler.
-        */
-       _bindListener: function() {
-               if (this._isListening) return;
-               
-               $(document).bind('DOMNodeInserted', $.proxy(this._executeCallbacks, this));
-               
-               this._isListening = true;
-       },
-       
        /**
         * Executes callbacks on click.
         */
        _executeCallbacks: function() {
-               if (this._discardEvent || this._isExecuting) return;
+               if (this._isExecuting) return;
                
                // do not track events while executing callbacks
                this._isExecuting = true;
@@ -4909,35 +4873,10 @@ WCF.DOMNodeInsertedHandler = {
        },
        
        /**
-        * Disables DOMNodeInsertedHandler, should be used after you've enabled it.
-        */
-       disable: function() {
-               this._discardEventCount--;
-               
-               if (this._discardEventCount < 1) {
-                       this._discardEvent = true;
-                       this._discardEventCount = 0;
-               }
-       },
-       
-       /**
-        * Enables DOMNodeInsertedHandler, should be used if you're inserting HTML (e.g. via AJAX)
-        * which might contain event-related elements. You have to disable the DOMNodeInsertedHandler
-        * once you've enabled it, if you fail it will cause an infinite loop!
-        */
-       enable: function() {
-               this._discardEventCount++;
-               
-               this._discardEvent = false;
-       },
-       
-       /**
-        * Forces execution of DOMNodeInsertedHandler.
+        * Executes all callbacks.
         */
-       forceExecution: function() {
-               this.enable();
+       execute: function() {
                this._executeCallbacks();
-               this.disable();
        }
 };
 
@@ -7074,11 +7013,9 @@ WCF.Popover = Class.extend({
                
                // insert html
                if (!this._data[this._activeElementID].loading && this._data[this._activeElementID].content) {
-                       WCF.DOMNodeInsertedHandler.enable();
-                       
                        this._popoverContent.html(this._data[this._activeElementID].content);
                        
-                       WCF.DOMNodeInsertedHandler.disable();
+                       WCF.DOMNodeInsertedHandler.execute();
                }
                else {
                        this._data[this._activeElementID].loading = true;
@@ -7146,8 +7083,6 @@ WCF.Popover = Class.extend({
                
                // only update content if element id is active
                if (this._activeElementID === elementID) {
-                       WCF.DOMNodeInsertedHandler.enable();
-                       
                        if (animate) {
                                // get current dimensions
                                var $dimensions = this._popoverContent.getDimensions();
@@ -7172,21 +7107,19 @@ WCF.Popover = Class.extend({
                                        height: $newDimensions.height + 'px',
                                        width: $newDimensions.width + 'px'
                                }, 300, function() {
-                                       WCF.DOMNodeInsertedHandler.enable();
-                                       
                                        self._popover.children('span').hide();
                                        self._popoverContent.html(self._data[elementID].content).css({ opacity: 0 }).animate({ opacity: 1 }, 200);
                                        
-                                       WCF.DOMNodeInsertedHandler.disable();
+                                       WCF.DOMNodeInsertedHandler.execute();
                                });
                        }
                        else {
                                // insert new content
                                this._popover.children('span').hide();
                                this._popoverContent.html(this._data[elementID].content);
+                               
+                               WCF.DOMNodeInsertedHandler.execute();
                        }
-                       
-                       WCF.DOMNodeInsertedHandler.disable();
                }
        },
        
@@ -8233,8 +8166,6 @@ $.widget('ui.wcfDialog', {
                        this.options.closeButtonLabel = WCF.Language.get('wcf.global.button.close');
                }
                
-               WCF.DOMNodeInsertedHandler.enable();
-               
                // create dialog container
                this._container = $('<div class="dialogContainer" />').hide().css({ zIndex: this.options.zIndex }).appendTo(document.body);
                this._titlebar = $('<header class="dialogTitlebar" />').hide().appendTo(this._container);
@@ -8268,7 +8199,7 @@ $.widget('ui.wcfDialog', {
                        }
                }
                
-               WCF.DOMNodeInsertedHandler.disable();
+               WCF.DOMNodeInsertedHandler.execute();
        },
        
        /**
@@ -8286,11 +8217,9 @@ $.widget('ui.wcfDialog', {
                        }
                } else if (key == 'closable' || key == 'closeButtonLabel') {
                        if (this.options.closable) {
-                               WCF.DOMNodeInsertedHandler.enable();
-                               
                                this._closeButton.attr('title', this.options.closeButtonLabel).show().find('span').html(this.options.closeButtonLabel);
                                
-                               WCF.DOMNodeInsertedHandler.disable();
+                               WCF.DOMNodeInsertedHandler.execute();
                        } else {
                                this._closeButton.hide();
                        }