From: Alexander Ebert Date: Fri, 1 Sep 2017 10:18:16 +0000 (+0200) Subject: Improved tooltip setup performance X-Git-Tag: 3.1.0_Alpha_3~4^2~10 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=9bac3eb6c28abed120852f5e61c4af1ec81e57d8;p=GitHub%2FWoltLab%2FWCF.git Improved tooltip setup performance The live collection of `getElementsByClass()` shows a bad performance when a large list of elements gets remove one-by-one. It took around 1 second to process 4k elements and stripping the class from each one. Using `querySelectorAll` instead does the same job in less than 40ms. The check against `_elements` is still in place, because it performs pretty well with large sets of DOM elements (tested with ~16k elements) and allows us to return early without invoking the costly `querySelectorAll`, which even without results hit with 0,2 seconds during tests. --- diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Tooltip.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Tooltip.js index 09f32ec57e..5fc7f59142 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Tooltip.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Tooltip.js @@ -9,6 +9,8 @@ define(['Environment', 'Dom/ChangeListener', 'Ui/Alignment'], function(Environment, DomChangeListener, UiAlignment) { "use strict"; + var _callbackMouseEnter = null; + var _callbackMouseLeave = null; var _elements = null; var _pointer = null; var _text = null; @@ -49,6 +51,9 @@ define(['Environment', 'Dom/ChangeListener', 'Ui/Alignment'], function(Environme _elements = elByClass('jsTooltip'); + _callbackMouseEnter = this._mouseEnter.bind(this); + _callbackMouseLeave = this._mouseLeave.bind(this); + this.init(); DomChangeListener.add('WoltLabSuite/Core/Ui/Tooltip', this.init.bind(this)); @@ -59,21 +64,23 @@ define(['Environment', 'Dom/ChangeListener', 'Ui/Alignment'], function(Environme * Initializes tooltip elements. */ init: function() { - var element, title; - while (_elements.length) { - element = _elements[0]; + if (_elements.length === 0) { + return; + } + + elBySelAll('.jsTooltip', undefined, function (element) { element.classList.remove('jsTooltip'); - title = elAttr(element, 'title').trim(); + var title = elAttr(element, 'title').trim(); if (title.length) { elData(element, 'tooltip', title); element.removeAttribute('title'); - element.addEventListener('mouseenter', this._mouseEnter.bind(this)); - element.addEventListener('mouseleave', this._mouseLeave.bind(this)); - element.addEventListener(WCF_CLICK_EVENT, this._mouseLeave.bind(this)); + element.addEventListener('mouseenter', _callbackMouseEnter); + element.addEventListener('mouseleave', _callbackMouseLeave); + element.addEventListener(WCF_CLICK_EVENT, _callbackMouseLeave); } - } + }); }, /**