]>
Commit | Line | Data |
---|---|---|
9a86dd57 JN |
1 | // Copyright (C) 2007, Fredrik Kuivinen <frekui@gmail.com> |
2 | // 2007, Petr Baudis <pasky@suse.cz> | |
3 | // 2008-2011, Jakub Narebski <jnareb@gmail.com> | |
4 | ||
5 | /** | |
6 | * @fileOverview Generic JavaScript code (helper functions) | |
7 | * @license GPLv2 or later | |
8 | */ | |
9 | ||
10 | ||
11 | /* ============================================================ */ | |
12 | /* ............................................................ */ | |
13 | /* Padding */ | |
14 | ||
15 | /** | |
e2895de4 JN |
16 | * pad INPUT on the left with STR that is assumed to have visible |
17 | * width of single character (for example nonbreakable spaces), | |
18 | * to WIDTH characters | |
19 | * | |
9a86dd57 JN |
20 | * example: padLeftStr(12, 3, '\u00A0') == '\u00A012' |
21 | * ('\u00A0' is nonbreakable space) | |
22 | * | |
23 | * @param {Number|String} input: number to pad | |
24 | * @param {Number} width: visible width of output | |
4dfa207e | 25 | * @param {String} str: string to prefix to string, defaults to '\u00A0' |
e2895de4 | 26 | * @returns {String} INPUT prefixed with STR x (WIDTH - INPUT.length) |
9a86dd57 JN |
27 | */ |
28 | function padLeftStr(input, width, str) { | |
29 | var prefix = ''; | |
4dfa207e JN |
30 | if (typeof str === 'undefined') { |
31 | ch = '\u00A0'; // using ' ' doesn't work in all browsers | |
32 | } | |
9a86dd57 JN |
33 | |
34 | width -= input.toString().length; | |
35 | while (width > 0) { | |
36 | prefix += str; | |
37 | width--; | |
38 | } | |
39 | return prefix + input; | |
40 | } | |
41 | ||
42 | /** | |
e2895de4 | 43 | * Pad INPUT on the left to WIDTH, using given padding character CH, |
4dfa207e JN |
44 | * for example padLeft('a', 3, '_') is '__a' |
45 | * padLeft(4, 2) is '04' (same as padLeft(4, 2, '0')) | |
9a86dd57 JN |
46 | * |
47 | * @param {String} input: input value converted to string. | |
48 | * @param {Number} width: desired length of output. | |
4dfa207e | 49 | * @param {String} ch: single character to prefix to string, defaults to '0'. |
9a86dd57 JN |
50 | * |
51 | * @returns {String} Modified string, at least SIZE length. | |
52 | */ | |
53 | function padLeft(input, width, ch) { | |
54 | var s = input + ""; | |
4dfa207e JN |
55 | if (typeof ch === 'undefined') { |
56 | ch = '0'; | |
57 | } | |
58 | ||
9a86dd57 JN |
59 | while (s.length < width) { |
60 | s = ch + s; | |
61 | } | |
62 | return s; | |
63 | } | |
64 | ||
65 | ||
66 | /* ............................................................ */ | |
2ae8da25 | 67 | /* Handling browser incompatibilities */ |
9a86dd57 JN |
68 | |
69 | /** | |
70 | * Create XMLHttpRequest object in cross-browser way | |
71 | * @returns XMLHttpRequest object, or null | |
72 | */ | |
73 | function createRequestObject() { | |
74 | try { | |
75 | return new XMLHttpRequest(); | |
76 | } catch (e) {} | |
77 | try { | |
78 | return window.createRequest(); | |
79 | } catch (e) {} | |
80 | try { | |
81 | return new ActiveXObject("Msxml2.XMLHTTP"); | |
82 | } catch (e) {} | |
83 | try { | |
84 | return new ActiveXObject("Microsoft.XMLHTTP"); | |
85 | } catch (e) {} | |
86 | ||
87 | return null; | |
88 | } | |
89 | ||
90 | ||
2ae8da25 JWH |
91 | /** |
92 | * Insert rule giving specified STYLE to given SELECTOR at the end of | |
93 | * first CSS stylesheet. | |
94 | * | |
95 | * @param {String} selector: CSS selector, e.g. '.class' | |
96 | * @param {String} style: rule contents, e.g. 'background-color: red;' | |
97 | */ | |
98 | function addCssRule(selector, style) { | |
99 | var stylesheet = document.styleSheets[0]; | |
100 | ||
101 | var theRules = []; | |
102 | if (stylesheet.cssRules) { // W3C way | |
103 | theRules = stylesheet.cssRules; | |
104 | } else if (stylesheet.rules) { // IE way | |
105 | theRules = stylesheet.rules; | |
106 | } | |
107 | ||
108 | if (stylesheet.insertRule) { // W3C way | |
109 | stylesheet.insertRule(selector + ' { ' + style + ' }', theRules.length); | |
110 | } else if (stylesheet.addRule) { // IE way | |
111 | stylesheet.addRule(selector, style); | |
112 | } | |
113 | } | |
114 | ||
115 | ||
1cae3ee7 JN |
116 | /* ............................................................ */ |
117 | /* Support for legacy browsers */ | |
118 | ||
119 | /** | |
120 | * Provides getElementsByClassName method, if there is no native | |
121 | * implementation of this method. | |
122 | * | |
123 | * NOTE that there are limits and differences compared to native | |
124 | * getElementsByClassName as defined by e.g.: | |
125 | * https://developer.mozilla.org/en/DOM/document.getElementsByClassName | |
d05b08cd JS |
126 | * https://www.whatwg.org/specs/web-apps/current-work/multipage/dom.html#dom-getelementsbyclassname |
127 | * https://www.whatwg.org/specs/web-apps/current-work/multipage/dom.html#dom-document-getelementsbyclassname | |
1cae3ee7 JN |
128 | * |
129 | * Namely, this implementation supports only single class name as | |
130 | * argument and not set of space-separated tokens representing classes, | |
131 | * it returns Array of nodes rather than live NodeList, and has | |
132 | * additional optional argument where you can limit search to given tags | |
133 | * (via getElementsByTagName). | |
134 | * | |
135 | * Based on | |
d05b08cd | 136 | * https://code.google.com/p/getelementsbyclassname/ |
1cae3ee7 | 137 | * http://www.dustindiaz.com/getelementsbyclass/ |
d05b08cd | 138 | * https://stackoverflow.com/questions/1818865/do-we-have-getelementsbyclassname-in-javascript |
1cae3ee7 | 139 | * |
65175d9e | 140 | * See also https://johnresig.com/blog/getelementsbyclassname-speed-comparison/ |
1cae3ee7 JN |
141 | * |
142 | * @param {String} class: name of _single_ class to find | |
143 | * @param {String} [taghint] limit search to given tags | |
144 | * @returns {Node[]} array of matching elements | |
145 | */ | |
146 | if (!('getElementsByClassName' in document)) { | |
147 | document.getElementsByClassName = function (classname, taghint) { | |
148 | taghint = taghint || "*"; | |
149 | var elements = (taghint === "*" && document.all) ? | |
150 | document.all : | |
151 | document.getElementsByTagName(taghint); | |
152 | var pattern = new RegExp("(^|\\s)" + classname + "(\\s|$)"); | |
153 | var matches= []; | |
154 | for (var i = 0, j = 0, n = elements.length; i < n; i++) { | |
155 | var el= elements[i]; | |
156 | if (el.className && pattern.test(el.className)) { | |
157 | // matches.push(el); | |
158 | matches[j] = el; | |
159 | j++; | |
160 | } | |
161 | } | |
162 | return matches; | |
163 | }; | |
164 | } // end if | |
165 | ||
166 | ||
9a86dd57 JN |
167 | /* ............................................................ */ |
168 | /* unquoting/unescaping filenames */ | |
169 | ||
170 | /**#@+ | |
171 | * @constant | |
172 | */ | |
173 | var escCodeRe = /\\([^0-7]|[0-7]{1,3})/g; | |
174 | var octEscRe = /^[0-7]{1,3}$/; | |
175 | var maybeQuotedRe = /^\"(.*)\"$/; | |
176 | /**#@-*/ | |
177 | ||
178 | /** | |
e2895de4 JN |
179 | * unquote maybe C-quoted filename (as used by git, i.e. it is |
180 | * in double quotes '"' if there is any escape character used) | |
9a86dd57 JN |
181 | * e.g. 'aa' -> 'aa', '"a\ta"' -> 'a a' |
182 | * | |
183 | * @param {String} str: git-quoted string | |
184 | * @returns {String} Unquoted and unescaped string | |
185 | * | |
186 | * @globals escCodeRe, octEscRe, maybeQuotedRe | |
187 | */ | |
188 | function unquote(str) { | |
189 | function unq(seq) { | |
190 | var es = { | |
191 | // character escape codes, aka escape sequences (from C) | |
192 | // replacements are to some extent JavaScript specific | |
193 | t: "\t", // tab (HT, TAB) | |
194 | n: "\n", // newline (NL) | |
195 | r: "\r", // return (CR) | |
196 | f: "\f", // form feed (FF) | |
197 | b: "\b", // backspace (BS) | |
198 | a: "\x07", // alarm (bell) (BEL) | |
199 | e: "\x1B", // escape (ESC) | |
200 | v: "\v" // vertical tab (VT) | |
201 | }; | |
202 | ||
203 | if (seq.search(octEscRe) !== -1) { | |
204 | // octal char sequence | |
205 | return String.fromCharCode(parseInt(seq, 8)); | |
206 | } else if (seq in es) { | |
207 | // C escape sequence, aka character escape code | |
208 | return es[seq]; | |
209 | } | |
210 | // quoted ordinary character | |
211 | return seq; | |
212 | } | |
213 | ||
214 | var match = str.match(maybeQuotedRe); | |
215 | if (match) { | |
216 | str = match[1]; | |
217 | // perhaps str = eval('"'+str+'"'); would be enough? | |
218 | str = str.replace(escCodeRe, | |
219 | function (substr, p1, offset, s) { return unq(p1); }); | |
220 | } | |
221 | return str; | |
222 | } | |
223 | ||
224 | /* end of common-lib.js */ |