summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorSamuel Degueldre <sad@odoo.com>2020-04-23 12:18:37 +0000
committerqsm-odoo <qsm@odoo.com>2020-05-19 06:55:42 +0000
commita814b671ed2d7359c45d4b4ca0ef2c14da62b43c (patch)
tree06f42cd645454d5a93ae5bd31a6000a3e3176d99 /addons
parentee7e75d74b0bd0eb51c6c41b400a8b6ec3e0ff6e (diff)
[IMP] web_editor: optimize selector functions for snippetOptions
Because of cross-browser compatibility concerns, jQuery's selector engine makes using :has selector relatively slow. This is usually acceptable, but in the case of snippet options, some options also need to use :has in their data-target selector, and nested :has selectors' performance degrade exponentially with the level of nesting. Additionaly, jQuery evaluates complex selectors right-to-left, which makes the :not operator quite inefficient. Because of that, this commit removes :has and :not from the conditions that were added at the end of the data-selector, and speeds up the selector by a factor of ~15-40 Lastly, the addDropSelector options was actually unused, and a leftover from the editor revert, as such it has been removed. closes odoo/odoo#50073 Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Diffstat (limited to 'addons')
-rw-r--r--addons/web_editor/static/src/js/editor/snippets.editor.js47
1 files changed, 17 insertions, 30 deletions
diff --git a/addons/web_editor/static/src/js/editor/snippets.editor.js b/addons/web_editor/static/src/js/editor/snippets.editor.js
index 9b0b5ed2e7f..5f959da3778 100644
--- a/addons/web_editor/static/src/js/editor/snippets.editor.js
+++ b/addons/web_editor/static/src/js/editor/snippets.editor.js
@@ -1386,11 +1386,11 @@ var SnippetsMenu = Widget.extend({
* See implementation for function details.
*
* @private
- * @param {string} include
+ * @param {string} selector
* jQuery selector that DOM elements must match to be considered as
* potential snippet.
* @param {string} exclude
- * jQuery selector that DOM elements must *not* match the be
+ * jQuery selector that DOM elements must *not* match to be
* considered as potential snippet.
* @param {string|false} target
* jQuery selector that at least one child of a DOM element must
@@ -1403,46 +1403,33 @@ var SnippetsMenu = Widget.extend({
* considered (@see noCheck), this is true if the DOM elements'
* parent must also be in an editable environment to be considered.
*/
- _computeSelectorFunctions: function (include, exclude, target, noCheck, isChildren) {
+ _computeSelectorFunctions: function (selector, exclude, target, noCheck, isChildren) {
var self = this;
- // Convert the selector for elements to include into a list
- var selectorList = _.compact(include.split(/\s*,\s*/));
+ exclude += `${exclude && ', '}.o_snippet_not_selectable`;
- // Convert the selector for elements to exclude into a list
- var excludeList = _.compact(exclude.split(/\s*,\s*/));
- excludeList.push('.o_snippet_not_selectable');
-
- // Prepare the condition that will be added to each subselector for
- // elements to include: 'not the elements to exclude and only the
- // editable ones if needed'
- var selectorConditions = _.map(excludeList, function (exc) {
- return ':not(' + exc + ')';
- }).join('');
+ let filterFunc = function () {
+ return !$(this).is(exclude);
+ };
if (target) {
- selectorConditions += ':has(' + target + ')';
- }
- if (!noCheck) {
- selectorConditions = (this.options.addDropSelector || '') + selectorConditions;
+ const oldFilter = filterFunc;
+ filterFunc = function () {
+ return oldFilter.apply(this) && $(this).find(target).length !== 0;
+ };
}
- // (Re)join the subselectors
- var selector = _.map(selectorList, function (s) {
- return s + selectorConditions;
- }).join(', ');
-
// Prepare the functions
var functions = {
is: function ($from) {
- return $from.is(selector);
+ return $from.is(selector) && $from.filter(filterFunc).length !== 0;
},
};
if (noCheck) {
functions.closest = function ($from, parentNode) {
- return $from.closest(selector, parentNode);
+ return $from.closest(selector, parentNode).filter(filterFunc);
};
functions.all = function ($from) {
- return $from ? dom.cssFind($from, selector) : $(selector);
+ return ($from ? dom.cssFind($from, selector) : $(selector)).filter(filterFunc);
};
} else {
functions.closest = function ($from, parentNode) {
@@ -1456,13 +1443,13 @@ var SnippetsMenu = Widget.extend({
node = node.parentNode;
}
return false;
- });
+ }).filter(filterFunc);
};
functions.all = isChildren ? function ($from) {
- return dom.cssFind($from || self.getEditableArea(), selector);
+ return dom.cssFind($from || self.getEditableArea(), selector).filter(filterFunc);
} : function ($from) {
$from = $from || self.getEditableArea();
- return $from.filter(selector).add(dom.cssFind($from, selector));
+ return $from.filter(selector).add(dom.cssFind($from, selector)).filter(filterFunc);
};
}
return functions;