799113f5e7e3bda0df649ccbfb9f661d9b160f8c
[WebKit.git] / Websites / perf.webkit.org / public / shared / common-component-base.js
1
2 class CommonComponentBase {
3
4     renderReplace(element, content) { CommonComponentBase.renderReplace(element, content); }
5
6     // FIXME: Deprecate these static functions.
7     static renderReplace(element, content)
8     {
9         element.textContent = '';
10         if (content)
11             ComponentBase._addContentToElement(element, content);
12     }
13
14     _recursivelyUpgradeUnknownElements(parent, findUpgrade, didConstructComponent = () => { })
15     {
16         let nextSibling;
17         for (let child of parent.childNodes) {
18             const componentClass = findUpgrade(child);
19             if (componentClass) {
20                 const intance = this._upgradeUnknownElement(parent, child, componentClass);
21                 didConstructComponent(intance);
22             }
23             if (child.childNodes)
24                 this._recursivelyUpgradeUnknownElements(child, findUpgrade, didConstructComponent);
25         }
26     }
27
28     _upgradeUnknownElement(parent, unknownElement, componentClass)
29     {
30         const instance = new componentClass;
31         const newElement = instance.element();
32
33         for (let i = 0; i < unknownElement.attributes.length; i++) {
34             const attr = unknownElement.attributes[i];
35             newElement.setAttribute(attr.name, attr.value);
36         }
37         parent.replaceChild(newElement, unknownElement);
38
39         for (const child of Array.from(unknownElement.childNodes))
40             newElement.appendChild(child);
41
42         return instance;
43     }
44
45     static _constructStylesheetFromTemplate(styleTemplate, didCreateRule = (selector, rule) => selector)
46     {
47         let stylesheet = '';
48         for (const selector in styleTemplate) {
49             const rules = styleTemplate[selector];
50
51             let ruleText = '';
52             for (const property in rules) {
53                 const value = rules[property];
54                 ruleText += `    ${property}: ${value};\n`;
55             }
56
57             const modifiedSelector = didCreateRule(selector, ruleText);
58
59             stylesheet += modifiedSelector + ' {\n' + ruleText + '}\n\n';
60         }
61         return stylesheet;
62     }
63
64     static _constructNodeTreeFromTemplate(template, didCreateElement = (element) => { })
65     {
66         if (typeof(template) == 'string')
67             return [CommonComponentBase._context.createTextNode(template)];
68         console.assert(Array.isArray(template));
69         if (typeof(template[0]) == 'string') {
70             const tagName = template[0];
71             let attributes = {};
72             let content = null;
73             if (Array.isArray(template[1])) {
74                 content = template[1];
75             } else {
76                 attributes = template[1];
77                 content = template[2];
78             }
79             const element = this.createElement(tagName, attributes);
80             didCreateElement(element);
81             const children = content && content.length ? this._constructNodeTreeFromTemplate(content, didCreateElement) : [];
82             for (const child of children)
83                 element.appendChild(child);
84             return [element];
85         } else {
86             let result = [];
87             for (const item of template) {
88                 if (typeof(item) == 'string')
89                     result.push(CommonComponentBase._context.createTextNode(item));
90                 else
91                     result = result.concat(this._constructNodeTreeFromTemplate(item, didCreateElement));
92             }
93             return result;
94         }
95     }
96
97     createElement(name, attributes, content) { return CommonComponentBase.createElement(name, attributes, content); }
98
99     static createElement(name, attributes, content)
100     {
101         const element = CommonComponentBase._context.createElement(name);
102         if (!content && (Array.isArray(attributes) || CommonComponentBase._isNode(attributes)
103             || attributes instanceof CommonComponentBase._baseClass || typeof(attributes) != 'object')) {
104             content = attributes;
105             attributes = {};
106         }
107
108         if (attributes) {
109             for (const name in attributes) {
110                 if (name.startsWith('on'))
111                     element.addEventListener(name.substring(2), attributes[name]);
112                 else if (attributes[name] === true)
113                     element.setAttribute(name, '');
114                 else if (attributes[name] !== false)
115                     element.setAttribute(name, attributes[name]);
116             }
117         }
118         
119         if (content)
120             CommonComponentBase._addContentToElement(element, content);
121
122         return element;
123     }
124
125     static _addContentToElement(element, content)
126     {
127         if (Array.isArray(content)) {
128             for (var nestedChild of content)
129                 this._addContentToElement(element, nestedChild);
130         } else if (CommonComponentBase._isNode(content))
131             element.appendChild(content);
132          else if (content instanceof CommonComponentBase._baseClass)
133             element.appendChild(content.element());
134         else
135             element.appendChild(CommonComponentBase._context.createTextNode(content));
136     }
137
138     createLink(content, titleOrCallback, callback, isExternal)
139     {
140         return CommonComponentBase.createLink(content, titleOrCallback, callback, isExternal);
141     }
142
143     static createLink(content, titleOrCallback, callback, isExternal)
144     {
145         var title = titleOrCallback;
146         if (callback === undefined) {
147             title = content;
148             callback = titleOrCallback;
149         }
150
151         var attributes = {
152             href: '#',
153             title: title,
154         };
155
156         if (typeof(callback) === 'string')
157             attributes['href'] = callback;
158         else
159             attributes['onclick'] = CommonComponentBase._baseClass.createEventHandler(callback);
160
161         if (isExternal)
162             attributes['target'] = '_blank';
163         return CommonComponentBase.createElement('a', attributes, content);
164     }
165 };
166
167 CommonComponentBase._context = null;
168 CommonComponentBase._isNode = null;
169 CommonComponentBase._baseClass = null;
170
171 if (typeof module != 'undefined')
172     module.exports.CommonComponentBase = CommonComponentBase;