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.
7 * @param {!WebInspector.RemoteObject} object
9 WebInspector
.CustomPreviewSection = function(object
)
11 this._sectionElement
= createElementWithClass("span", "custom-expandable-section");
12 this._object
= object
;
13 this._expanded
= false;
14 this._cachedContent
= null;
15 var customPreview
= object
.customPreview();
18 var headerJSON
= JSON
.parse(customPreview
.header
);
20 WebInspector
.console
.error("Broken formatter: header is invalid json " + e
);
23 this._header
= this._renderJSONMLTag(headerJSON
);
24 if (this._header
.nodeType
=== Node
.TEXT_NODE
) {
25 WebInspector
.console
.error("Broken formatter: header should be an element node.");
29 if (customPreview
.hasBody
) {
30 this._header
.classList
.add("custom-expandable-section-header");
31 this._header
.addEventListener("click", this._onClick
.bind(this), false);
34 this._sectionElement
.appendChild(this._header
);
39 * @param {!WebInspector.RemoteObject} object
41 WebInspector
.CustomPreviewComponent = function(object
)
43 this._object
= object
;
44 this._customPreviewSection
= new WebInspector
.CustomPreviewSection(object
);
45 this.element
= createElementWithClass("span", "source-code");
46 var shadowRoot
= WebInspector
.createShadowRootWithCoreStyles(this.element
);
47 this.element
.addEventListener("contextmenu", this._contextMenuEventFired
.bind(this), false);
48 shadowRoot
.appendChild(WebInspector
.Widget
.createStyleElement("components/customPreviewSection.css"));
49 shadowRoot
.appendChild(this._customPreviewSection
.element());
52 WebInspector
.CustomPreviewComponent
.prototype = {
53 expandIfPossible: function()
55 if (this._object
.customPreview().hasBody
&& this._customPreviewSection
)
56 this._customPreviewSection
._loadBody();
60 * @param {!Event} event
62 _contextMenuEventFired: function(event
)
64 var contextMenu
= new WebInspector
.ContextMenu(event
);
65 if (this._customPreviewSection
)
66 contextMenu
.appendItem(WebInspector
.UIString
.capitalize("Show as Javascript ^object" ), this._disassemble
.bind(this));
67 contextMenu
.appendApplicableItems(this._object
);
71 _disassemble: function()
73 this.element
.shadowRoot
.textContent
= "";
74 this._customPreviewSection
= null;
75 this.element
.shadowRoot
.appendChild(WebInspector
.ObjectPropertiesSection
.defaultObjectPresentation(this._object
));
79 WebInspector
.CustomPreviewSection
._tagsWhiteList
= new Set(["span", "div", "ol", "li","table", "tr", "td"]);
81 WebInspector
.CustomPreviewSection
.prototype = {
88 return this._sectionElement
;
95 _renderJSONMLTag: function(jsonML
)
97 if (!Array
.isArray(jsonML
))
98 return createTextNode(jsonML
+ "");
100 var array
= /** @type {!Array.<*>} */(jsonML
);
101 if (array
[0] === "object")
102 return this._layoutObjectTag(array
);
104 return this._renderElement(array
);
109 * @param {!Array.<*>} object
112 _renderElement: function(object
)
114 var tagName
= object
.shift();
115 if (!WebInspector
.CustomPreviewSection
._tagsWhiteList
.has(tagName
)) {
116 WebInspector
.console
.error("Broken formatter: element " + tagName
+ " is not allowed!");
117 return createElement("span");
119 var element
= createElement(/** @type {string} */ (tagName
));
120 if ((typeof object
[0] == "object") && !Array
.isArray(object
[0])) {
121 var attributes
= object
.shift();
122 for (var key
in attributes
) {
123 var value
= attributes
[key
];
124 if ((key
!== "style") || (typeof value
!== "string"))
127 element
.setAttribute(key
, value
);
131 this._appendJsonMLTags(element
, object
);
136 * @param {!Array.<*>} objectTag
139 _layoutObjectTag: function(objectTag
)
142 var attributes
= objectTag
.shift();
143 var remoteObject
= this._object
.target().runtimeModel
.createRemoteObject(/** @type {!RuntimeAgent.RemoteObject} */ (attributes
));
144 if (remoteObject
.customPreview())
145 return (new WebInspector
.CustomPreviewSection(remoteObject
)).element();
147 var sectionElement
= WebInspector
.ObjectPropertiesSection
.defaultObjectPresentation(remoteObject
);
148 sectionElement
.classList
.toggle("custom-expandable-section-standard-section", remoteObject
.hasChildren
);
149 return sectionElement
;
153 * @param {!Node} parentElement
154 * @param {!Array.<*>} jsonMLTags
156 _appendJsonMLTags: function(parentElement
, jsonMLTags
)
158 for (var i
= 0; i
< jsonMLTags
.length
; ++i
)
159 parentElement
.appendChild(this._renderJSONMLTag(jsonMLTags
[i
]));
163 * @param {!Event} event
165 _onClick: function(event
)
168 if (this._cachedContent
)
169 this._toggleExpand();
174 _toggleExpand: function()
176 this._expanded
= !this._expanded
;
177 this._header
.classList
.toggle("expanded", this._expanded
);
178 this._cachedContent
.classList
.toggle("hidden", !this._expanded
);
181 _loadBody: function()
184 * @suppressReceiverCheck
185 * @suppressGlobalPropertiesCheck
186 * @suppress {undefinedVars}
188 * @param {*=} formatter
191 function load(formatter
, config
)
194 * @param {*} jsonMLObject
195 * @throws {string} error message
197 function substituteObjectTagsInCustomPreview(jsonMLObject
)
199 if (!jsonMLObject
|| (typeof jsonMLObject
!== "object") || (typeof jsonMLObject
.splice
!== "function"))
202 var obj
= jsonMLObject
.length
;
203 if (!(typeof obj
=== "number" && obj
>>> 0 === obj
&& (obj
> 0 || 1 / obj
> 0)))
207 if (jsonMLObject
[0] === "object") {
208 var attributes
= jsonMLObject
[1];
209 var originObject
= attributes
["object"];
210 var config
= attributes
["config"];
211 if (typeof originObject
=== "undefined")
212 throw "Illegal format: obligatory attribute \"object\" isn't specified";
214 jsonMLObject
[1] = bindRemoteObject(originObject
, false, false, null, false, config
);
217 for (var i
= startIndex
; i
< jsonMLObject
.length
; ++i
)
218 substituteObjectTagsInCustomPreview(jsonMLObject
[i
]);
222 var body
= formatter
.body(this, config
);
223 substituteObjectTagsInCustomPreview(body
);
226 console
.error("Custom Formatter Failed: " + e
);
231 var customPreview
= this._object
.customPreview();
232 var args
= [{objectId
: customPreview
.formatterObjectId
}];
233 if (customPreview
.configObjectId
)
234 args
.push({objectId
: customPreview
.configObjectId
});
235 this._object
.callFunctionJSON(load
, args
, onBodyLoaded
.bind(this));
238 * @param {*} bodyJsonML
239 * @this {WebInspector.CustomPreviewSection}
241 function onBodyLoaded(bodyJsonML
)
246 this._cachedContent
= this._renderJSONMLTag(bodyJsonML
);
247 this._sectionElement
.appendChild(this._cachedContent
);
248 this._toggleExpand();