- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / docs / examples / extensions / benchmark / jst / util.js
1 // Copyright 2006 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 // implied. See the License for the specific language governing
13 // permissions and limitations under the License.
14 /**
15  * @fileoverview Miscellaneous constants and functions referenced in
16  * the main source files.
17  *
18  * @author Steffen Meschkat (mesch@google.com)
19  */
20
21 var MAPS_DEBUG = false;
22
23 function log(msg) {}
24
25 // String literals defined globally and not to be inlined. (IE6 perf)
26 /** @const */ var STRING_empty = '';
27
28 /** @const */ var CSS_display = 'display';
29 /** @const */ var CSS_position = 'position';
30
31 // Constants for possible values of the typeof operator.
32 var TYPE_boolean = 'boolean';
33 var TYPE_number = 'number';
34 var TYPE_object = 'object';
35 var TYPE_string = 'string';
36 var TYPE_function = 'function';
37 var TYPE_undefined = 'undefined';
38
39
40 /**
41  * Wrapper for the eval() builtin function to evaluate expressions and
42  * obtain their value. It wraps the expression in parentheses such
43  * that object literals are really evaluated to objects. Without the
44  * wrapping, they are evaluated as block, and create syntax
45  * errors. Also protects against other syntax errors in the eval()ed
46  * code and returns null if the eval throws an exception.
47  *
48  * @param {string} expr
49  * @return {Object|null}
50  */
51 function jsEval(expr) {
52   try {
53     // NOTE(mesch): An alternative idiom would be:
54     //
55     //   eval('(' + expr + ')');
56     //
57     // Note that using the square brackets as below, "" evals to undefined.
58     // The alternative of using parentheses does not work when evaluating
59     // function literals in IE.
60     // e.g. eval("(function() {})") returns undefined, and not a function
61     // object, in IE.
62     return eval('[' + expr + '][0]');
63   } catch (e) {
64     log('EVAL FAILED ' + expr + ': ' + e);
65     return null;
66   }
67 }
68
69 function jsLength(obj) {
70   return obj.length;
71 }
72
73 function assert(obj) {}
74
75 /**
76  * Copies all properties from second object to the first.  Modifies to.
77  *
78  * @param {Object} to  The target object.
79  * @param {Object} from  The source object.
80  */
81 function copyProperties(to, from) {
82   for (var p in from) {
83     to[p] = from[p];
84   }
85 }
86
87
88 /**
89  * @param {Object|null|undefined} value The possible value to use.
90  * @param {Object} defaultValue The default if the value is not set.
91  * @return {Object} The value, if it is
92  * defined and not null; otherwise the default
93  */
94 function getDefaultObject(value, defaultValue) {
95   if (typeof value != TYPE_undefined && value != null) {
96     return /** @type Object */(value);
97   } else {
98     return defaultValue;
99   }
100 }
101
102 /**
103  * Detect if an object looks like an Array.
104  * Note that instanceof Array is not robust; for example an Array
105  * created in another iframe fails instanceof Array.
106  * @param {Object|null} value Object to interrogate
107  * @return {boolean} Is the object an array?
108  */
109 function isArray(value) {
110   return value != null &&
111       typeof value == TYPE_object &&
112       typeof value.length == TYPE_number;
113 }
114
115
116 /**
117  * Finds a slice of an array.
118  *
119  * @param {Array} array  Array to be sliced.
120  * @param {number} start  The start of the slice.
121  * @param {number} opt_end  The end of the slice (optional).
122  * @return {Array} array  The slice of the array from start to end.
123  */
124 function arraySlice(array, start, opt_end) {
125   // Use
126   //   return Function.prototype.call.apply(Array.prototype.slice, arguments);
127   // instead of the simpler
128   //   return Array.prototype.slice.call(array, start, opt_end);
129   // here because of a bug in the FF and IE implementations of
130   // Array.prototype.slice which causes this function to return an empty list
131   // if opt_end is not provided.
132   return Function.prototype.call.apply(Array.prototype.slice, arguments);
133 }
134
135
136 /**
137  * Jscompiler wrapper for parseInt() with base 10.
138  *
139  * @param {string} s string repersentation of a number.
140  *
141  * @return {number} The integer contained in s, converted on base 10.
142  */
143 function parseInt10(s) {
144   return parseInt(s, 10);
145 }
146
147
148 /**
149  * Clears the array by setting the length property to 0. This usually
150  * works, and if it should turn out not to work everywhere, here would
151  * be the place to implement the browser specific workaround.
152  *
153  * @param {Array} array  Array to be cleared.
154  */
155 function arrayClear(array) {
156   array.length = 0;
157 }
158
159
160 /**
161  * Prebinds "this" within the given method to an object, but ignores all 
162  * arguments passed to the resulting function.
163  * I.e. var_args are all the arguments that method is invoked with when
164  * invoking the bound function.
165  *
166  * @param {Object|null} object  The object that the method call targets.
167  * @param {Function} method  The target method.
168  * @return {Function}  Method with the target object bound to it and curried by
169  *                     the provided arguments.
170  */
171 function bindFully(object, method, var_args) {
172   var args = arraySlice(arguments, 2);
173   return function() {
174     return method.apply(object, args);
175   }
176 }
177
178 // Based on <http://www.w3.org/TR/2000/ REC-DOM-Level-2-Core-20001113/
179 // core.html#ID-1950641247>.
180 var DOM_ELEMENT_NODE = 1;
181 var DOM_ATTRIBUTE_NODE = 2;
182 var DOM_TEXT_NODE = 3;
183 var DOM_CDATA_SECTION_NODE = 4;
184 var DOM_ENTITY_REFERENCE_NODE = 5;
185 var DOM_ENTITY_NODE = 6;
186 var DOM_PROCESSING_INSTRUCTION_NODE = 7;
187 var DOM_COMMENT_NODE = 8;
188 var DOM_DOCUMENT_NODE = 9;
189 var DOM_DOCUMENT_TYPE_NODE = 10;
190 var DOM_DOCUMENT_FRAGMENT_NODE = 11;
191 var DOM_NOTATION_NODE = 12;
192
193
194
195 function domGetElementById(document, id) {
196   return document.getElementById(id);
197 }
198
199 /**
200  * Creates a new node in the given document
201  *
202  * @param {Document} doc  Target document.
203  * @param {string} name  Name of new element (i.e. the tag name)..
204  * @return {Element}  Newly constructed element.
205  */
206 function domCreateElement(doc, name) {
207   return doc.createElement(name);
208 }
209
210 /**
211  * Traverses the element nodes in the DOM section underneath the given
212  * node and invokes the given callback as a method on every element
213  * node encountered.
214  *
215  * @param {Element} node  Parent element of the subtree to traverse.
216  * @param {Function} callback  Called on each node in the traversal.
217  */
218 function domTraverseElements(node, callback) {
219   var traverser = new DomTraverser(callback);
220   traverser.run(node);
221 }
222
223 /**
224  * A class to hold state for a dom traversal.
225  * @param {Function} callback  Called on each node in the traversal.
226  * @constructor
227  * @class
228  */
229 function DomTraverser(callback) {
230   this.callback_ = callback;
231 }
232
233 /**
234  * Processes the dom tree in breadth-first order.
235  * @param {Element} root  The root node of the traversal.
236  */
237 DomTraverser.prototype.run = function(root) {
238   var me = this;
239   me.queue_ = [ root ];
240   while (jsLength(me.queue_)) {
241     me.process_(me.queue_.shift());
242   }
243 }
244
245 /**
246  * Processes a single node.
247  * @param {Element} node  The current node of the traversal.
248  */
249 DomTraverser.prototype.process_ = function(node) {
250   var me = this;
251
252   me.callback_(node);
253
254   for (var c = node.firstChild; c; c = c.nextSibling) {
255     if (c.nodeType == DOM_ELEMENT_NODE) {
256       me.queue_.push(c);
257     }
258   }
259 }
260
261 /**
262  * Get an attribute from the DOM.  Simple redirect, exists to compress code.
263  *
264  * @param {Element} node  Element to interrogate.
265  * @param {string} name  Name of parameter to extract.
266  * @return {string|null}  Resulting attribute.
267  */
268 function domGetAttribute(node, name) {
269   return node.getAttribute(name);
270   // NOTE(mesch): Neither in IE nor in Firefox, HTML DOM attributes
271   // implement namespaces. All items in the attribute collection have
272   // null localName and namespaceURI attribute values. In IE, we even
273   // encounter DIV elements that don't implement the method
274   // getAttributeNS().
275 }
276
277
278 /**
279  * Set an attribute in the DOM.  Simple redirect to compress code.
280  *
281  * @param {Element} node  Element to interrogate.
282  * @param {string} name  Name of parameter to set.
283  * @param {string|number} value  Set attribute to this value.
284  */
285 function domSetAttribute(node, name, value) {
286   node.setAttribute(name, value);
287 }
288
289 /**
290  * Remove an attribute from the DOM.  Simple redirect to compress code.
291  *
292  * @param {Element} node  Element to interrogate.
293  * @param {string} name  Name of parameter to remove.
294  */
295 function domRemoveAttribute(node, name) {
296   node.removeAttribute(name);
297 }
298
299 /**
300  * Clone a node in the DOM.
301  *
302  * @param {Node} node  Node to clone.
303  * @return {Node}  Cloned node.
304  */
305 function domCloneNode(node) {
306   return node.cloneNode(true);
307   // NOTE(mesch): we never so far wanted to use cloneNode(false),
308   // hence the default.
309 }
310
311 /**
312  * Clone a element in the DOM.
313  *
314  * @param {Element} element  Element to clone.
315  * @return {Element}  Cloned element.
316  */
317 function domCloneElement(element) {
318   return /** @type {Element} */(domCloneNode(element));
319 }
320
321 /**
322  * Returns the document owner of the given element. In particular,
323  * returns window.document if node is null or the browser does not
324  * support ownerDocument.  If the node is a document itself, returns
325  * itself.
326  *
327  * @param {Node|null|undefined} node  The node whose ownerDocument is required.
328  * @returns {Document}  The owner document or window.document if unsupported.
329  */
330 function ownerDocument(node) {
331   if (!node) {
332     return document;
333   } else if (node.nodeType == DOM_DOCUMENT_NODE) {
334     return /** @type Document */(node);
335   } else {
336     return node.ownerDocument || document;
337   }
338 }
339
340 /**
341  * Creates a new text node in the given document.
342  *
343  * @param {Document} doc  Target document.
344  * @param {string} text  Text composing new text node.
345  * @return {Text}  Newly constructed text node.
346  */
347 function domCreateTextNode(doc, text) {
348   return doc.createTextNode(text);
349 }
350
351 /**
352  * Appends a new child to the specified (parent) node.
353  *
354  * @param {Element} node  Parent element.
355  * @param {Node} child  Child node to append.
356  * @return {Node}  Newly appended node.
357  */
358 function domAppendChild(node, child) {
359   return node.appendChild(child);
360 }
361
362 /**
363  * Sets display to default.
364  *
365  * @param {Element} node  The dom element to manipulate.
366  */
367 function displayDefault(node) {
368   node.style[CSS_display] = '';
369 }
370
371 /**
372  * Sets display to none. Doing this as a function saves a few bytes for
373  * the 'style.display' property and the 'none' literal.
374  *
375  * @param {Element} node  The dom element to manipulate.
376  */
377 function displayNone(node) {
378   node.style[CSS_display] = 'none';
379 }
380
381
382 /**
383  * Sets position style attribute to absolute.
384  *
385  * @param {Element} node  The dom element to manipulate.
386  */
387 function positionAbsolute(node) {
388   node.style[CSS_position] = 'absolute';
389 }
390
391
392 /**
393  * Inserts a new child before a given sibling.
394  *
395  * @param {Node} newChild  Node to insert.
396  * @param {Node} oldChild  Sibling node.
397  * @return {Node}  Reference to new child.
398  */
399 function domInsertBefore(newChild, oldChild) {
400   return oldChild.parentNode.insertBefore(newChild, oldChild);
401 }
402
403 /**
404  * Replaces an old child node with a new child node.
405  *
406  * @param {Node} newChild  New child to append.
407  * @param {Node} oldChild  Old child to remove.
408  * @return {Node}  Replaced node.
409  */
410 function domReplaceChild(newChild, oldChild) {
411   return oldChild.parentNode.replaceChild(newChild, oldChild);
412 }
413
414 /**
415  * Removes a node from the DOM.
416  *
417  * @param {Node} node  The node to remove.
418  * @return {Node}  The removed node.
419  */
420 function domRemoveNode(node) {
421   return domRemoveChild(node.parentNode, node);
422 }
423
424 /**
425  * Remove a child from the specified (parent) node.
426  *
427  * @param {Element} node  Parent element.
428  * @param {Node} child  Child node to remove.
429  * @return {Node}  Removed node.
430  */
431 function domRemoveChild(node, child) {
432   return node.removeChild(child);
433 }
434
435
436 /**
437  * Trim whitespace from begin and end of string.
438  *
439  * @see testStringTrim();
440  *
441  * @param {string} str  Input string.
442  * @return {string}  Trimmed string.
443  */
444 function stringTrim(str) {
445   return stringTrimRight(stringTrimLeft(str));
446 }
447
448 /**
449  * Trim whitespace from beginning of string.
450  *
451  * @see testStringTrimLeft();
452  *
453  * @param {string} str  Input string.
454  * @return {string}  Trimmed string.
455  */
456 function stringTrimLeft(str) {
457   return str.replace(/^\s+/, "");
458 }
459
460 /**
461  * Trim whitespace from end of string.
462  *
463  * @see testStringTrimRight();
464  *
465  * @param {string} str  Input string.
466  * @return {string}  Trimmed string.
467   */
468 function stringTrimRight(str) {
469   return str.replace(/\s+$/, "");
470 }
471