Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / third_party / tvcm / src / tvcm / ui / __init__.js
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 tvcm.exportTo('tvcm.ui', function() {
8
9   /**
10    * Decorates elements as an instance of a class.
11    * @param {string|!Element} source The way to find the element(s) to decorate.
12    *     If this is a string then {@code querySeletorAll} is used to find the
13    *     elements to decorate.
14    * @param {!Function} constr The constructor to decorate with. The constr
15    *     needs to have a {@code decorate} function.
16    */
17   function decorate(source, constr) {
18     var elements;
19     if (typeof source == 'string')
20       elements = tvcm.doc.querySelectorAll(source);
21     else
22       elements = [source];
23
24     for (var i = 0, el; el = elements[i]; i++) {
25       if (!(el instanceof constr))
26         constr.decorate(el);
27     }
28   }
29
30   /**
31    * Defines a tracing UI component, a function that can be called to construct
32    * the component.
33    *
34    * Tvcm class:
35    * <pre>
36    * var List = tvcm.ui.define('list');
37    * List.prototype = {
38    *   __proto__: HTMLUListElement.prototype,
39    *   decorate: function() {
40    *     ...
41    *   },
42    *   ...
43    * };
44    * </pre>
45    *
46    * Derived class:
47    * <pre>
48    * var CustomList = tvcm.ui.define('custom-list', List);
49    * CustomList.prototype = {
50    *   __proto__: List.prototype,
51    *   decorate: function() {
52    *     ...
53    *   },
54    *   ...
55    * };
56    * </pre>
57    *
58    * @param {string} className The className of the newly created subtype. If
59    *     subclassing by passing in opt_parentConstructor, this is used for
60    *     debugging. If not subclassing, then it is the tag name that will be
61    *     created by the component.
62
63    * @param {function=} opt_parentConstructor The parent class for this new
64    *     element, if subclassing is desired. If provided, the parent class must
65    *     be also a function created by tvcm.ui.define.
66    *
67    * @param {string=} opt_tagNS The namespace in which to create the base
68    *     element. Has no meaning when opt_parentConstructor is passed and must
69    *     either be undefined or the same namespace as the parent class.
70    *
71    * @return {function(Object=):Element} The newly created component
72    *     constructor.
73    */
74   function define(className, opt_parentConstructor, opt_tagNS) {
75     if (typeof className == 'function') {
76       throw new Error('Passing functions as className is deprecated. Please ' +
77                       'use (className, opt_parentConstructor) to subclass');
78     }
79
80     var className = className.toLowerCase();
81     if (opt_parentConstructor && !opt_parentConstructor.tagName)
82       throw new Error('opt_parentConstructor was not ' +
83                       'created by tvcm.ui.define');
84
85     // Walk up the parent constructors until we can find the type of tag
86     // to create.
87     var tagName = className;
88     var tagNS = undefined;
89     if (opt_parentConstructor) {
90       if (opt_tagNS)
91         throw new Error('Must not specify tagNS if parentConstructor is given');
92       var parent = opt_parentConstructor;
93       while (parent && parent.tagName) {
94         tagName = parent.tagName;
95         tagNS = parent.tagNS;
96         parent = parent.parentConstructor;
97       }
98     } else {
99       tagNS = opt_tagNS;
100     }
101
102     /**
103      * Creates a new UI element constructor.
104      * Arguments passed to the constuctor are provided to the decorate method.
105      * You will need to call the parent elements decorate method from within
106      * your decorate method and pass any required parameters.
107      * @constructor
108      */
109     function f() {
110       if (opt_parentConstructor &&
111           f.prototype.__proto__ != opt_parentConstructor.prototype) {
112         throw new Error(
113             className + ' prototye\'s __proto__ field is messed up. ' +
114             'It MUST be the prototype of ' + opt_parentConstructor.tagName);
115       }
116
117       var el;
118       if (tagNS === undefined)
119         el = tvcm.doc.createElement(tagName);
120       else
121         el = tvcm.doc.createElementNS(tagNS, tagName);
122       f.decorate.call(this, el, arguments);
123       return el;
124     }
125
126     /**
127      * Decorates an element as a UI element class.
128      * @param {!Element} el The element to decorate.
129      */
130     f.decorate = function(el) {
131       el.__proto__ = f.prototype;
132       el.decorate.apply(el, arguments[1]);
133       el.constructor = f;
134     };
135
136     f.className = className;
137     f.tagName = tagName;
138     f.tagNS = tagNS;
139     f.parentConstructor = (opt_parentConstructor ? opt_parentConstructor :
140                                                    undefined);
141     f.toString = function() {
142       if (!f.parentConstructor)
143         return f.tagName;
144       return f.parentConstructor.toString() + '::' + f.className;
145     };
146
147     return f;
148   }
149
150   function elementIsChildOf(el, potentialParent) {
151     if (el == potentialParent)
152       return false;
153
154     var cur = el;
155     while (cur.parentNode) {
156       if (cur == potentialParent)
157         return true;
158       cur = cur.parentNode;
159     }
160     return false;
161   };
162
163   return {
164     decorate: decorate,
165     define: define,
166     elementIsChildOf: elementIsChildOf
167   };
168 });