Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/components/CustomPreviewComponent.js

Issue 2712513002: DevTools: extract ObjectUI module from Components (Closed)
Patch Set: fix build.gn Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 * @unrestricted
6 */
7 Components.CustomPreviewSection = class {
8 /**
9 * @param {!SDK.RemoteObject} object
10 */
11 constructor(object) {
12 this._sectionElement = createElementWithClass('span', 'custom-expandable-sec tion');
13 this._object = object;
14 this._expanded = false;
15 this._cachedContent = null;
16 var customPreview = object.customPreview();
17
18 try {
19 var headerJSON = JSON.parse(customPreview.header);
20 } catch (e) {
21 Common.console.error('Broken formatter: header is invalid json ' + e);
22 return;
23 }
24 this._header = this._renderJSONMLTag(headerJSON);
25 if (this._header.nodeType === Node.TEXT_NODE) {
26 Common.console.error('Broken formatter: header should be an element node.' );
27 return;
28 }
29
30 if (customPreview.hasBody) {
31 this._header.classList.add('custom-expandable-section-header');
32 this._header.addEventListener('click', this._onClick.bind(this), false);
33 this._expandIcon = UI.Icon.create('smallicon-triangle-right', 'custom-expa nd-icon');
34 this._header.insertBefore(this._expandIcon, this._header.firstChild);
35 }
36
37 this._sectionElement.appendChild(this._header);
38 }
39
40 /**
41 * @return {!Element}
42 */
43 element() {
44 return this._sectionElement;
45 }
46
47 /**
48 * @param {*} jsonML
49 * @return {!Node}
50 */
51 _renderJSONMLTag(jsonML) {
52 if (!Array.isArray(jsonML))
53 return createTextNode(jsonML + '');
54
55 var array = /** @type {!Array.<*>} */ (jsonML);
56 return array[0] === 'object' ? this._layoutObjectTag(array) : this._renderEl ement(array);
57 }
58
59 /**
60 *
61 * @param {!Array.<*>} object
62 * @return {!Node}
63 */
64 _renderElement(object) {
65 var tagName = object.shift();
66 if (!Components.CustomPreviewSection._tagsWhiteList.has(tagName)) {
67 Common.console.error('Broken formatter: element ' + tagName + ' is not all owed!');
68 return createElement('span');
69 }
70 var element = createElement(/** @type {string} */ (tagName));
71 if ((typeof object[0] === 'object') && !Array.isArray(object[0])) {
72 var attributes = object.shift();
73 for (var key in attributes) {
74 var value = attributes[key];
75 if ((key !== 'style') || (typeof value !== 'string'))
76 continue;
77
78 element.setAttribute(key, value);
79 }
80 }
81
82 this._appendJsonMLTags(element, object);
83 return element;
84 }
85
86 /**
87 * @param {!Array.<*>} objectTag
88 * @return {!Node}
89 */
90 _layoutObjectTag(objectTag) {
91 objectTag.shift();
92 var attributes = objectTag.shift();
93 var remoteObject = this._object.target().runtimeModel.createRemoteObject(
94 /** @type {!Protocol.Runtime.RemoteObject} */ (attributes));
95 if (remoteObject.customPreview())
96 return (new Components.CustomPreviewSection(remoteObject)).element();
97
98 var sectionElement = Components.ObjectPropertiesSection.defaultObjectPresent ation(remoteObject);
99 sectionElement.classList.toggle('custom-expandable-section-standard-section' , remoteObject.hasChildren);
100 return sectionElement;
101 }
102
103 /**
104 * @param {!Node} parentElement
105 * @param {!Array.<*>} jsonMLTags
106 */
107 _appendJsonMLTags(parentElement, jsonMLTags) {
108 for (var i = 0; i < jsonMLTags.length; ++i)
109 parentElement.appendChild(this._renderJSONMLTag(jsonMLTags[i]));
110 }
111
112 /**
113 * @param {!Event} event
114 */
115 _onClick(event) {
116 event.consume(true);
117 if (this._cachedContent)
118 this._toggleExpand();
119 else
120 this._loadBody();
121 }
122
123 _toggleExpand() {
124 this._expanded = !this._expanded;
125 this._header.classList.toggle('expanded', this._expanded);
126 this._cachedContent.classList.toggle('hidden', !this._expanded);
127 if (this._expanded)
128 this._expandIcon.setIconType('smallicon-triangle-down');
129 else
130 this._expandIcon.setIconType('smallicon-triangle-right');
131 }
132
133 _loadBody() {
134 /**
135 * @suppressReceiverCheck
136 * @suppressGlobalPropertiesCheck
137 * @suppress {undefinedVars}
138 * @this {Object}
139 * @param {function(!Object, *):*} bindRemoteObject
140 * @param {*=} formatter
141 * @param {*=} config
142 */
143 function load(bindRemoteObject, formatter, config) {
144 /**
145 * @param {*} jsonMLObject
146 * @throws {string} error message
147 */
148 function substituteObjectTagsInCustomPreview(jsonMLObject) {
149 if (!jsonMLObject || (typeof jsonMLObject !== 'object') || (typeof jsonM LObject.splice !== 'function'))
150 return;
151
152 var obj = jsonMLObject.length;
153 if (!(typeof obj === 'number' && obj >>> 0 === obj && (obj > 0 || 1 / ob j > 0)))
154 return;
155
156 var startIndex = 1;
157 if (jsonMLObject[0] === 'object') {
158 var attributes = jsonMLObject[1];
159 var originObject = attributes['object'];
160 var config = attributes['config'];
161 if (typeof originObject === 'undefined')
162 throw 'Illegal format: obligatory attribute "object" isn\'t specifie d';
163
164 jsonMLObject[1] = bindRemoteObject(originObject, config);
165 startIndex = 2;
166 }
167 for (var i = startIndex; i < jsonMLObject.length; ++i)
168 substituteObjectTagsInCustomPreview(jsonMLObject[i]);
169 }
170
171 try {
172 var body = formatter.body(this, config);
173 substituteObjectTagsInCustomPreview(body);
174 return body;
175 } catch (e) {
176 console.error('Custom Formatter Failed: ' + e);
177 return null;
178 }
179 }
180
181 var customPreview = this._object.customPreview();
182 var args = [{objectId: customPreview.bindRemoteObjectFunctionId}, {objectId: customPreview.formatterObjectId}];
183 if (customPreview.configObjectId)
184 args.push({objectId: customPreview.configObjectId});
185 this._object.callFunctionJSON(load, args, onBodyLoaded.bind(this));
186
187 /**
188 * @param {*} bodyJsonML
189 * @this {Components.CustomPreviewSection}
190 */
191 function onBodyLoaded(bodyJsonML) {
192 if (!bodyJsonML)
193 return;
194
195 this._cachedContent = this._renderJSONMLTag(bodyJsonML);
196 this._sectionElement.appendChild(this._cachedContent);
197 this._toggleExpand();
198 }
199 }
200 };
201
202 /**
203 * @unrestricted
204 */
205 Components.CustomPreviewComponent = class {
206 /**
207 * @param {!SDK.RemoteObject} object
208 */
209 constructor(object) {
210 this._object = object;
211 this._customPreviewSection = new Components.CustomPreviewSection(object);
212 this.element = createElementWithClass('span', 'source-code');
213 var shadowRoot = UI.createShadowRootWithCoreStyles(this.element, 'components /customPreviewComponent.css');
214 this.element.addEventListener('contextmenu', this._contextMenuEventFired.bin d(this), false);
215 shadowRoot.appendChild(this._customPreviewSection.element());
216 }
217
218 expandIfPossible() {
219 if (this._object.customPreview().hasBody && this._customPreviewSection)
220 this._customPreviewSection._loadBody();
221 }
222
223 /**
224 * @param {!Event} event
225 */
226 _contextMenuEventFired(event) {
227 var contextMenu = new UI.ContextMenu(event);
228 if (this._customPreviewSection)
229 contextMenu.appendItem(Common.UIString.capitalize('Show as Javascript ^obj ect'), this._disassemble.bind(this));
230 contextMenu.appendApplicableItems(this._object);
231 contextMenu.show();
232 }
233
234 _disassemble() {
235 this.element.shadowRoot.textContent = '';
236 this._customPreviewSection = null;
237 this.element.shadowRoot.appendChild(Components.ObjectPropertiesSection.defau ltObjectPresentation(this._object));
238 }
239 };
240
241 Components.CustomPreviewSection._tagsWhiteList = new Set(['span', 'div', 'ol', ' li', 'table', 'tr', 'td']);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698