|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 "use strict"; |
|
5 |
|
6 this.EXPORTED_SYMBOLS = ["ContentUtil"]; |
|
7 |
|
8 const XHTML_NS = "http://www.w3.org/1999/xhtml"; |
|
9 const nsIDOMKeyEvent = Components.interfaces.nsIDOMKeyEvent; |
|
10 |
|
11 this.ContentUtil = { |
|
12 populateFragmentFromString: function populateFragmentFromString(fragment, str) { |
|
13 let re = /^([^#]*)#(\d+)\b([^#]*)/, |
|
14 document = fragment.ownerDocument, |
|
15 // the remaining arguments are our {text, className} values |
|
16 replacements = Array.slice(arguments, 2), |
|
17 match; |
|
18 |
|
19 // walk over the string, building textNode/spans as nec. with replacement content |
|
20 // note that #1,#2 etc. may not appear in numerical order in the string |
|
21 while ((match = re.exec(str))) { |
|
22 let [mstring,pre,num,post] = match, |
|
23 replaceText = "", |
|
24 replaceClass, |
|
25 idx = num-1; // markers are 1-based, replacement indices 0 based |
|
26 |
|
27 str = str.substring(re.lastIndex+mstring.length); |
|
28 |
|
29 if (pre) |
|
30 fragment.appendChild(document.createTextNode(pre)); |
|
31 |
|
32 if (replacements[idx]) { |
|
33 replaceText = replacements[idx].text; |
|
34 let spanNode = document.createElementNS(XHTML_NS, "span"); |
|
35 spanNode.appendChild(document.createTextNode(replaceText)); |
|
36 // add class to the span when provided |
|
37 if(replacements[idx].className) |
|
38 spanNode.classList.add(replacements[idx].className); |
|
39 |
|
40 fragment.appendChild(spanNode); |
|
41 } else { |
|
42 // put it back if no replacement was provided |
|
43 fragment.appendChild(document.createTextNode("#"+num)); |
|
44 } |
|
45 |
|
46 if(post) |
|
47 fragment.appendChild(document.createTextNode(post)); |
|
48 } |
|
49 if(str) |
|
50 fragment.appendChild(document.createTextNode(str)); |
|
51 |
|
52 return fragment; |
|
53 }, |
|
54 |
|
55 // Pass several objects in and it will combine them all into the first object and return it. |
|
56 // NOTE: Deep copy is not supported |
|
57 extend: function extend() { |
|
58 // copy reference to target object |
|
59 let target = arguments[0] || {}; |
|
60 let length = arguments.length; |
|
61 |
|
62 if (length === 1) { |
|
63 return target; |
|
64 } |
|
65 |
|
66 // Handle case when target is a string or something |
|
67 if (typeof target != "object" && typeof target != "function") { |
|
68 target = {}; |
|
69 } |
|
70 |
|
71 for (let i = 1; i < length; i++) { |
|
72 // Only deal with non-null/undefined values |
|
73 let options = arguments[i]; |
|
74 if (options != null) { |
|
75 // Extend the base object |
|
76 for (let name in options) { |
|
77 let copy = options[name]; |
|
78 |
|
79 // Prevent never-ending loop |
|
80 if (target === copy) |
|
81 continue; |
|
82 |
|
83 if (copy !== undefined) |
|
84 target[name] = copy; |
|
85 } |
|
86 } |
|
87 } |
|
88 |
|
89 // Return the modified object |
|
90 return target; |
|
91 }, |
|
92 |
|
93 // Checks if a keycode is used for list navigation. |
|
94 isNavigationKey: function (keyCode) { |
|
95 let navigationKeys = [ |
|
96 nsIDOMKeyEvent.DOM_VK_DOWN, |
|
97 nsIDOMKeyEvent.DOM_VK_UP, |
|
98 nsIDOMKeyEvent.DOM_VK_LEFT, |
|
99 nsIDOMKeyEvent.DOM_VK_RIGHT, |
|
100 nsIDOMKeyEvent.DOM_VK_PAGE_UP, |
|
101 nsIDOMKeyEvent.DOM_VK_PAGE_DOWN, |
|
102 nsIDOMKeyEvent.DOM_VK_ESCAPE]; |
|
103 |
|
104 return navigationKeys.indexOf(keyCode) != -1; |
|
105 } |
|
106 }; |