1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
isNodeValid,
} = require("resource://devtools/server/actors/highlighters/utils/markup.js");
const {
BoxModelHighlighter,
} = require("resource://devtools/server/actors/highlighters/box-model.js");
// How many maximum nodes can be highlighted at the same time by the SelectorHighlighter
const MAX_HIGHLIGHTED_ELEMENTS = 100;
/**
* The SelectorHighlighter runs a given selector through querySelectorAll on the
* document of the provided context node and then uses the BoxModelHighlighter
* to highlight the matching nodes
*/
class SelectorHighlighter {
constructor(highlighterEnv) {
this.highlighterEnv = highlighterEnv;
this._highlighters = [];
}
/**
* Show a BoxModelHighlighter on each node that matches a given selector.
*
* @param {DOMNode} node
* A context node used to get the document element on which to run
* querySelectorAll(). This node will not be highlighted.
* @param {Object} options
* Configuration options for SelectorHighlighter.
* All of the options for BoxModelHighlighter.show() are also valid here.
* @param {String} options.selector
* Required. CSS selector used with querySelectorAll() to find matching elements.
*/
async show(node, options = {}) {
this.hide();
if (!isNodeValid(node) || !options.selector) {
return false;
}
let nodes = [];
try {
nodes = [...node.ownerDocument.querySelectorAll(options.selector)];
} catch (e) {
// It's fine if the provided selector is invalid, `nodes` will be an empty array.
}
// Prevent passing the `selector` option to BoxModelHighlighter
delete options.selector;
const promises = [];
for (let i = 0; i < Math.min(nodes.length, MAX_HIGHLIGHTED_ELEMENTS); i++) {
promises.push(this._showHighlighter(nodes[i], options));
}
await Promise.all(promises);
return true;
}
/**
* Create an instance of BoxModelHighlighter, wait for it to be ready
* (see CanvasFrameAnonymousContentHelper.initialize()),
* then show the highlighter on the given node with the given configuration options.
*
* @param {DOMNode} node
* Node to be highlighted
* @param {Object} options
* Configuration options for the BoxModelHighlighter
* @return {Promise} Promise that resolves when the BoxModelHighlighter is ready
*/
async _showHighlighter(node, options) {
const highlighter = new BoxModelHighlighter(this.highlighterEnv);
await highlighter.isReady;
highlighter.show(node, options);
this._highlighters.push(highlighter);
}
hide() {
for (const highlighter of this._highlighters) {
highlighter.destroy();
}
this._highlighters = [];
}
destroy() {
this.hide();
this.highlighterEnv = null;
}
}
exports.SelectorHighlighter = SelectorHighlighter;
|