-
Notifications
You must be signed in to change notification settings - Fork 1
/
demo-performance.html
153 lines (130 loc) · 4.92 KB
/
demo-performance.html
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<html>
<meta charset="utf-8"/>
<style>
.highlighted-with-span {
background-color: yellow;
color: red;
}
::highlight(example-highlight) {
background-color: cyan;
color: blue;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
text-align: justify;
font-size: 6px;
}
button {
font-size: 16;
}
div{
font-size: 18;
}
#parent-span > span {
margin-right: 5px;
}
input {
font-size: 16;
width: 80px;
}
</style>
<body>
<div>
This demo is meant to compare the performance of using the Highlight API to using the traditional way of inserting spans to format text.<br>
Clicking any of the buttons below will give (or clear) format to the big chunk of text below the buttons.<br>
Each word in the text is a different span that will be formatted separately with the method chosen.
</div>
<br>
<button type="button" onclick="measureTime(highlightWithAPIRanges)">Highlight with API using Ranges</button>
<button type="button" onclick="measureTime(highlightWithAPIStaticRanges)">Highlight with API using StaticRanges</button>
<button type="button" onclick="measureTime(restoreWithAPI)">Clear API highlights</button>
<br><br>
<button type="button" onclick="measureTime(highlightWithSpans)">Highlight with spans</button>
<button type="button" onclick="measureTime(restoreWithSpans)">Clear highlighted spans</button>
<br><br>
<div>You can also change the number of independent words in the text: </div>
<input type="number" id="span-quantity" value="10000"><button type="button" id="generate-content-button" onclick="generateContent()">Regenerate text</button>
<br><br>
<div>Last operation took <span id="performance-span">0</span>ms</div>
<br>
<span id="parent-span"></span>
<script>
const highlightedWithSpanClass = "highlighted-with-span";
function generateContent() {
let spansQuantity = document.getElementById("span-quantity").valueAsNumber;
let contentTemplate = "<span>qwertyuiopasdfghjklzxcvbnm</span><wbr>";
document.getElementById("parent-span").innerHTML = contentTemplate.repeat(spansQuantity);
}
generateContent();
function measureTime(fun) {
const start = Date.now();
fun();
// Force frame update before measuring end time.
requestAnimationFrame(()=>setTimeout(()=>{
const end = Date.now();
let span = document.getElementById("performance-span");
span.textContent = `${end-start}`;
}, 0));
}
function doForEveryTextNode(root, operation) {
let all = [];
for (let node = root.firstChild; node; node = node.nextSibling) {
if (node.nodeType == Node.TEXT_NODE) operation(node)
else if (node.nodeName == "SCRIPT" || node.nodeName == "STYLE") continue;
else doForEveryTextNode(node, operation);
}
return all;
}
// Fire a click event on #generate-content-button when pressing Enter key while in #span-quantity
document.querySelector("#span-quantity").addEventListener("keyup", event => {
if(event.key !== "Enter") return;
document.querySelector("#generate-content-button").click();
event.preventDefault();
});
/************************************************************************/
const parentSpan = document.getElementById('parent-span');
function highlightWithSpans() {
doForEveryTextNode(parentSpan, wrapTextWithSpan);
}
function highlightWithAPIRanges() {
let highlight = new Highlight();
doForEveryTextNode(parentSpan, (node) => { wrapTextWithHighlightAPIRange(highlight, node) } );
CSS.highlights.set("example-highlight", highlight);
}
function highlightWithAPIStaticRanges() {
let highlight = new Highlight();
doForEveryTextNode(parentSpan, (node) => { wrapTextWithHighlightAPIStaticRange(highlight, node) } );
CSS.highlights.set("example-highlight", highlight);
}
/************************************************************************/
function wrapTextWithSpan(textNode) {
let span = document.createElement('span');
span.className = "highlighted-with-span";
textNode.parentNode.insertBefore(span, textNode.nextSibling);
span.appendChild(textNode);
}
function wrapTextWithHighlightAPIRange(highlight, textNode) {
let r = new Range();
r.setStart(textNode, 0);
r.setEnd(textNode, textNode.nodeValue.length);
highlight.add(r);
}
function wrapTextWithHighlightAPIStaticRange(highlight, textNode) {
let r = new StaticRange({startContainer: textNode, startOffset: 0, endContainer: textNode, endOffset: textNode.nodeValue.length});
highlight.add(r);
}
/************************************************************************/
function restoreWithSpans() {
let spans = document.getElementsByClassName(highlightedWithSpanClass);
while(spans.length) {
let span = spans[0];
span.parentNode.insertBefore(span.firstChild, span);
span.parentNode.removeChild(span);
}
}
function restoreWithAPI() {
CSS.highlights.delete("example-highlight");
}
</script>
</body>
</html>