Bumping the PLT count back to 5.
[WebKit-https.git] / WebKit / WebInspector / webInspector / inspector.js
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 var Inspector = null;
30
31 function loaded()
32 {
33     treeScrollbar = new AppleVerticalScrollbar(document.getElementById("treeScrollbar"));
34
35     treeScrollbar.setTrackStart("Images/scrollTrackTop.png", 18);
36     treeScrollbar.setTrackMiddle("Images/scrollTrackMiddle.png");
37     treeScrollbar.setTrackEnd("Images/scrollTrackBottom.png", 18);
38     treeScrollbar.setThumbStart("Images/scrollThumbTop.png", 9);
39     treeScrollbar.setThumbMiddle("Images/scrollThumbMiddle.png");
40     treeScrollbar.setThumbEnd("Images/scrollThumbBottom.png", 9);
41
42     nodeContentsScrollbar = new AppleVerticalScrollbar(document.getElementById("nodeContentsScrollbar"));
43     nodeContentsScrollArea = new AppleScrollArea(document.getElementById("nodeContentsScrollview"), nodeContentsScrollbar);
44
45     nodeContentsScrollbar.setTrackStart("Images/scrollTrackTop.png", 18);
46     nodeContentsScrollbar.setTrackMiddle("Images/scrollTrackMiddle.png");
47     nodeContentsScrollbar.setTrackEnd("Images/scrollTrackBottom.png", 18);
48     nodeContentsScrollbar.setThumbStart("Images/scrollThumbTop.png", 9);
49     nodeContentsScrollbar.setThumbMiddle("Images/scrollThumbMiddle.png");
50     nodeContentsScrollbar.setThumbEnd("Images/scrollThumbBottom.png", 9);
51
52     elementAttributesScrollbar = new AppleVerticalScrollbar(document.getElementById("elementAttributesScrollbar"));
53     elementAttributesScrollArea = new AppleScrollArea(document.getElementById("elementAttributesScrollview"), elementAttributesScrollbar);
54     
55     elementAttributesScrollbar.setTrackStart("Images/scrollTrackTop.png", 18);
56     elementAttributesScrollbar.setTrackMiddle("Images/scrollTrackMiddle.png");
57     elementAttributesScrollbar.setTrackEnd("Images/scrollTrackBottom.png", 18);
58     elementAttributesScrollbar.setThumbStart("Images/scrollThumbTop.png", 9);
59     elementAttributesScrollbar.setThumbMiddle("Images/scrollThumbMiddle.png");
60     elementAttributesScrollbar.setThumbEnd("Images/scrollThumbBottom.png", 9);
61     
62     styleRulesScrollbar = new AppleVerticalScrollbar(document.getElementById("styleRulesScrollbar"));
63     styleRulesScrollArea = new AppleScrollArea(document.getElementById("styleRulesScrollview"), styleRulesScrollbar);
64
65     styleRulesScrollbar.setTrackStart("Images/scrollTrackTop.png", 18);
66     styleRulesScrollbar.setTrackMiddle("Images/scrollTrackMiddle.png");
67     styleRulesScrollbar.setTrackEnd("Images/scrollTrackBottom.png", 18);
68     styleRulesScrollbar.setThumbStart("Images/scrollThumbTop.png", 9);
69     styleRulesScrollbar.setThumbMiddle("Images/scrollThumbMiddle.png");
70     styleRulesScrollbar.setThumbEnd("Images/scrollThumbBottom.png", 9);
71
72     stylePropertiesScrollbar = new AppleVerticalScrollbar(document.getElementById("stylePropertiesScrollbar"));
73     stylePropertiesScrollArea = new AppleScrollArea(document.getElementById("stylePropertiesScrollview"), stylePropertiesScrollbar);
74
75     stylePropertiesScrollbar.setTrackStart("Images/scrollTrackTop.png", 18);
76     stylePropertiesScrollbar.setTrackMiddle("Images/scrollTrackMiddle.png");
77     stylePropertiesScrollbar.setTrackEnd("Images/scrollTrackBottom.png", 18);
78     stylePropertiesScrollbar.setThumbStart("Images/scrollThumbTop.png", 9);
79     stylePropertiesScrollbar.setThumbMiddle("Images/scrollThumbMiddle.png");
80     stylePropertiesScrollbar.setThumbEnd("Images/scrollThumbBottom.png", 9);
81
82     treeScrollbar._getViewToContentRatio = function() {
83         var contentHeight = Inspector.treeViewScrollHeight();
84         var height = document.getElementById("treeScrollArea").offsetHeight;
85         if (contentHeight > height)
86             return height / contentHeight;
87         return 1.0;
88     }
89
90     treeScrollbar._computeTrackOffset = function() { return Inspector.treeViewOffsetTop(); }
91     treeScrollbar._getContentLength = function() { return Inspector.treeViewScrollHeight(); }
92     treeScrollbar._getViewLength = function() { return document.getElementById("treeScrollArea").offsetHeight; }
93     treeScrollbar._canScroll = function() { return true; }
94
95     treeScrollbar.scrollTo = function(pos) {
96         Inspector.treeViewScrollTo(pos);
97         this.verticalHasScrolled();
98     }
99
100     treeScrollbar.verticalHasScrolled = function() {
101         var new_thumb_pos = this._thumbPositionForContentPosition(Inspector.treeViewOffsetTop());
102         this._thumbStart = new_thumb_pos;
103         this._thumb.style.top = new_thumb_pos + "px";
104     }
105
106     // much better AppleScrollArea reveal
107     AppleScrollArea.prototype.reveal = function(node) {
108         var offsetY = 0;
109         var obj = node;
110         do {
111             offsetY += obj.offsetTop;
112             obj = obj.offsetParent;
113         } while (obj && obj != this.content);
114
115         var offsetX = 0;
116         obj = node;
117         do {
118             offsetX += obj.offsetLeft;
119             obj = obj.offsetParent;
120         } while (obj && obj != this.content);
121
122         var top = this.content.scrollTop;
123         var height = this.viewHeight;
124         if ((top + height) < (offsetY + node.clientHeight)) 
125             this.verticalScrollTo(offsetY - height + node.clientHeight);
126         else if (top > offsetY)
127             this.verticalScrollTo(offsetY);
128
129         var left = this.content.scrollLeft;
130         var width = this.viewWidth;
131         if ((left + width) < (offsetX + node.clientWidth)) 
132             this.horizontalScrollTo(offsetX - width + node.clientWidth);
133         else if (left > offsetX)
134             this.horizontalScrollTo(offsetX);
135     }
136
137     // Change the standard show/hide to include the parentNode.
138     // This lets out content reflow when hidden.
139     AppleScrollbar.prototype.hide = function() {
140         this._track.style.display = "none";
141         this.scrollbar.style.display = "none";
142         this.hidden = true;
143     }
144
145     AppleScrollbar.prototype.show = function() {
146         this._track.style.display = "block";
147         this.scrollbar.style.display = null;
148         if (this.hidden) {
149             this.hidden = false;
150             this.refresh();
151         }
152     }
153
154     window.addEventListener("resize", refreshScrollbars, false);
155 }
156
157 function refreshScrollbars()
158 {
159     if (currentPane == "node") {
160         nodeContentsScrollArea.refresh();
161         elementAttributesScrollArea.refresh();
162     } else if (currentPane == "style") {
163         styleRulesScrollArea.refresh();
164         stylePropertiesScrollArea.refresh();
165     }
166 }
167
168 var searchActive = false;
169
170 function performSearch(query)
171 {
172     var treePopup = document.getElementById("treePopup");
173     var searchField = document.getElementById("search");
174     var searchCount = document.getElementById("searchCount");
175
176     if (query.length && !searchActive) {
177         treePopup.style.display = "none";
178         searchCount.style.display = "block";
179         searchField.style.width = "150px";
180         searchActive = true;
181     } else if (!query.length && searchActive) {
182         treePopup.style.display = null;
183         searchCount.style.display = null;
184         searchField.style.width = null;
185         searchActive = false;
186     }
187
188     Inspector.searchPerformed(query);
189 }
190
191 var tabNames = ["node","metrics","style","properties"];
192 var currentPane = "node";
193 var paneUpdateState = new Array();
194 var noSelection = false;
195
196 function toggleNoSelection(state)
197 {
198     noSelection = state;
199     if (noSelection) {
200         for (var i = 0; i < tabNames.length; i++)
201             document.getElementById(tabNames[i] + "Pane").style.display = "none";
202         document.getElementById("noSelection").style.display = null;
203     } else {
204         document.getElementById("noSelection").style.display = "none";
205         switchPane(currentPane);
206     }
207 }
208
209 function switchPane(pane)
210 {
211     currentPane = pane;
212     for (var i = 0; i < tabNames.length; i++) {
213         if (pane == tabNames[i]) {
214             if (!noSelection)
215                 document.getElementById(tabNames[i] + "Pane").style.display = null;
216             document.getElementById(tabNames[i] + "Button").className = "square selected";
217         } else {
218             document.getElementById(tabNames[i] + "Pane").style.display = "none";
219             document.getElementById(tabNames[i] + "Button").className = "square";
220         }
221     }
222
223     if (noSelection)
224         return;
225
226     if (!paneUpdateState[pane]) {
227         eval("update" + pane.charAt(0).toUpperCase() + pane.substr(1) + "Pane()");
228         paneUpdateState[pane] = true;
229     } else {
230         refreshScrollbars();
231     }
232 }
233
234 function nodeTypeName(node)
235 {
236     switch (node.nodeType) {
237         case Node.ELEMENT_NODE: return "Element";
238         case Node.ATTRIBUTE_NODE: return "Attribute";
239         case Node.TEXT_NODE: return "Text";
240         case Node.CDATA_SECTION_NODE: return "Character Data";
241         case Node.ENTITY_REFERENCE_NODE: return "Entity Reference";
242         case Node.ENTITY_NODE: return "Entity";
243         case Node.PROCESSING_INSTRUCTION_NODE: return "Processing Instruction";
244         case Node.COMMENT_NODE: return "Comment";
245         case Node.DOCUMENT_NODE: return "Document";
246         case Node.DOCUMENT_TYPE_NODE: return "Document Type";
247         case Node.DOCUMENT_FRAGMENT_NODE: return "Document Fragment";
248         case Node.NOTATION_NODE: return "Notation";
249     }
250     return "(unknown)";
251 }
252
253 function updatePanes()
254 {
255     for (var i = 0; i < tabNames.length; i++)
256         paneUpdateState[tabNames[i]] = false;
257     if (noSelection)
258         return;
259     eval("update" + currentPane.charAt(0).toUpperCase() + currentPane.substr(1) + "Pane()");    
260     paneUpdateState[currentPane] = true;
261 }
262
263 function updateElementAttributes()
264 {
265     var focusedNode = Inspector.focusedDOMNode();
266     var attributesList = document.getElementById("elementAttributesList")
267
268     attributesList.innerHTML = "";
269
270     if (!focusedNode.attributes.length)
271         attributesList.innerHTML = "<span class=\"disabled\">(none)</span>";
272
273     for (i = 0; i < focusedNode.attributes.length; i++) {
274         var attr = focusedNode.attributes[i];
275         var li = document.createElement("li");
276
277         var span = document.createElement("span");
278         span.className = "property";
279         if (attr.namespaceURI)
280             span.title = attr.namespaceURI;
281         span.textContent = attr.name;
282         li.appendChild(span);
283
284         span = document.createElement("span");
285         span.className = "value";
286         span.textContent = attr.value;
287         span.title = span.textContent;
288         li.appendChild(span);
289
290         if (attr.style) {
291             span = document.createElement("span");
292             span.className = "mapped";
293             span.innerHTML = "(<a href=\"javascript:selectMappedStyleRule('" + attr.name + "')\">mapped style</a>)";
294             li.appendChild(span);
295         }
296
297         attributesList.appendChild(li);
298     }
299
300     elementAttributesScrollArea.refresh();
301 }
302
303 function updateNodePane() {
304     var focusedNode = Inspector.focusedDOMNode();
305
306     if (focusedNode.nodeType == Node.TEXT_NODE) {
307         document.getElementById("nodeNamespaceRow").style.display = "none";
308         document.getElementById("elementAttributes").style.display = "none";
309         document.getElementById("nodeContents").style.display = null;
310
311         document.getElementById("nodeContentsScrollview").textContent = focusedNode.nodeValue;
312         nodeContentsScrollArea.refresh();
313     } else if (focusedNode.nodeType == Node.ELEMENT_NODE) {
314         document.getElementById("elementAttributes").style.display = null;
315         document.getElementById("nodeContents").style.display = null;
316         
317         updateElementAttributes();
318         
319         if (focusedNode.namespaceURI.length > 0) {
320             document.getElementById("nodeNamespace").textContent = focusedNode.namespaceURI;
321             document.getElementById("nodeNamespace").title = focusedNode.namespaceURI;
322             document.getElementById("nodeNamespaceRow").style.display = null;
323         } else {
324             document.getElementById("nodeNamespaceRow").style.display = "none";
325         }
326
327         document.getElementById("nodeContentsScrollview").innerHTML = "<span class=\"disabled\">Loading...</span>";
328         nodeContentsScrollArea.refresh();
329
330         clearTimeout(nodeUpdateTimeout);
331         nodeUpdateTimeout = setTimeout("delayedNodePaneUpdate()", 250);
332     } else if (focusedNode.nodeType == Node.DOCUMENT_NODE) {
333         document.getElementById("nodeNamespaceRow").style.display = "none";
334         document.getElementById("elementAttributes").style.display = "none";
335         document.getElementById("nodeContents").style.display = "none";
336     }
337
338     document.getElementById("nodeType").textContent = nodeTypeName(focusedNode);
339     document.getElementById("nodeName").textContent = focusedNode.nodeName;
340 }
341
342 var nodeUpdateTimeout = null;
343 function delayedNodePaneUpdate()
344 {
345     var focusedNode = Inspector.focusedDOMNode();
346     var serializer = new XMLSerializer();
347     document.getElementById("nodeContentsScrollview").textContent = serializer.serializeToString(focusedNode);
348     nodeContentsScrollArea.refresh();
349 }
350
351 var styleRules = null;
352 var selectedStyleRuleIndex = 0;
353 var styleProperties = null;
354 var expandedStyleShorthands = new Array();
355
356 function updateStylePane()
357 {
358     var focusedNode = Inspector.focusedDOMNode();
359     var rulesArea = document.getElementById("styleRulesScrollview");
360     var propertiesArea = document.getElementById("stylePropertiesTree");
361
362     rulesArea.innerHTML = "";
363     propertiesArea.innerHTML = "";
364     styleRules = new Array();
365     styleProperties = new Array();
366
367     if (focusedNode.nodeType == Node.ELEMENT_NODE) {
368         document.getElementById("styleRules").style.display = null;
369         document.getElementById("styleProperties").style.display = null;
370         document.getElementById("noStyle").style.display = "none";
371
372         var propertyCount = new Array();
373
374         var computedStyle = focusedNode.ownerDocument.defaultView.getComputedStyle(focusedNode, "");
375         if (computedStyle) {
376             var computedObj = new Object();
377             computedObj.computedStyle = true;
378             computedObj.selectorText = "Computed Style";
379             computedObj.style = computedStyle;
380             computedObj.subtitle = "";
381             styleRules.push(computedObj);
382         }
383
384         var focusedNodeName = focusedNode.nodeName.toLowerCase();
385         for (var i = 0; i < focusedNode.attributes.length; i++) {
386             var attr = focusedNode.attributes[i];
387             if (attr.style) {
388                 var attrStyle = new Object();
389                 attrStyle.attr = attr.name;
390                 attrStyle.selectorText = focusedNodeName + "[" + attr.name;
391                 if (attr.value.length)
392                     attrStyle.selectorText += "=" + attr.value;
393                 attrStyle.selectorText += "]";
394                 attrStyle.style = attr.style;
395                 attrStyle.subtitle = "element's \"" + attr.name + "\" attribute";
396                 styleRules.push(attrStyle);
397             }
398         }
399
400         var matchedStyleRules = focusedNode.ownerDocument.defaultView.getMatchedCSSRules(focusedNode, "");
401         if (matchedStyleRules) {
402             for (var i = 0; i < matchedStyleRules.length; i++) {
403                 styleRules.push(matchedStyleRules[i]);
404             }
405         }
406
407         if (focusedNode.style.length) {
408             var inlineStyle = new Object();
409             inlineStyle.selectorText = "Inline Style Attribute";
410             inlineStyle.style = focusedNode.style;
411             inlineStyle.subtitle = "element's \"style\" attribute";
412             styleRules.push(inlineStyle);
413         }
414
415         if (styleRules.length && selectedStyleRuleIndex >= styleRules.length)
416             selectedStyleRuleIndex = (styleRules.length - 1);
417
418         var priorityUsed = false;
419         for (var i = (styleRules.length - 1); i >= 0; --i) {
420             styleProperties[i] = new Array();
421
422             var row = document.createElement("div");
423             row.className = "row";
424             if (i == selectedStyleRuleIndex)
425                 row.className += " focused";
426             if (styleRules[i].computedStyle)
427                 row.className += " computedStyle";
428
429             var cell = document.createElement("div");
430             cell.className = "cell selector";
431             cell.title = styleRules[i].selectorText;
432             cell.textContent = cell.title;
433             row.appendChild(cell);
434
435             cell = document.createElement("div");
436             cell.className = "cell stylesheet";
437             if (styleRules[i].subtitle != null)
438                 cell.title = styleRules[i].subtitle;
439             else if (styleRules[i].parentStyleSheet && styleRules[i].parentStyleSheet.href)
440                 cell.title = styleRules[i].parentStyleSheet.href;
441             else
442                 cell.title = "inline stylesheet";
443             cell.textContent = cell.title;
444             row.appendChild(cell);
445
446             row.styleRuleIndex = i;
447             row.addEventListener("click", styleRuleSelect, true);
448
449             var style = styleRules[i].style;
450             var styleShorthandLookup = new Array();
451             for (var j = 0; j < style.length; j++) {
452                 var prop = null;
453                 var name = style[j];
454                 var shorthand = style.getPropertyShorthand(name);
455                 if (shorthand)
456                     prop = styleShorthandLookup[shorthand];
457
458                 if (!priorityUsed && style.getPropertyPriority(name).length)
459                     priorityUsed = true;
460
461                 if (prop) {
462                     prop.subProperties.push(name);
463                 } else {
464                     prop = new Object();
465                     prop.style = style;
466                     prop.subProperties = new Array(name);
467                     prop.unusedProperties = new Array();
468                     prop.name = (shorthand ? shorthand : name);
469                     styleProperties[i].push(prop);
470                     if (shorthand) {
471                         styleShorthandLookup[shorthand] = prop;
472                         if (!propertyCount[shorthand]) {
473                             propertyCount[shorthand] = 1;
474                         } else {
475                             prop.unusedProperties[shorthand] = true;
476                             propertyCount[shorthand]++;
477                         }
478                     }
479                 }
480
481                 if (styleRules[i].computedStyle)
482                     continue;
483
484                 if (!propertyCount[name]) {
485                     propertyCount[name] = 1;
486                 } else {
487                     prop.unusedProperties[name] = true;
488                     propertyCount[name]++;
489                 }
490             }
491
492             if (styleRules[i].computedStyle && styleRules.length > 1) {
493                 var divider = document.createElement("hr");
494                 divider.className = "divider";
495                 rulesArea.insertBefore(divider, rulesArea.firstChild);
496             }
497
498             if (rulesArea.firstChild)
499                 rulesArea.insertBefore(row, rulesArea.firstChild);
500             else
501                 rulesArea.appendChild(row);
502         }
503
504         if (priorityUsed) {
505             // walk the properties again and account for !important
506             var priorityCount = new Array();
507             for (var i = 0; i < styleRules.length; i++) {
508                 var style = styleRules[i].style;
509                 if (style.computedStyle)
510                     continue;
511                 for (var j = 0; j < styleProperties[i].length; j++) {
512                     var prop = styleProperties[i][j];
513                     for (var k = 0; k < prop.subProperties.length; k++) {
514                         var name = prop.subProperties[k];
515                         if (style.getPropertyPriority(name).length) {
516                             if (!priorityCount[name]) {
517                                 if (prop.unusedProperties[name])
518                                     prop.unusedProperties[name] = false;
519                                 priorityCount[name] = 1;
520                             } else {
521                                 priorityCount[name]++;
522                             }
523                         } else if (priorityCount[name]) {
524                             prop.unusedProperties[name] = true;
525                         }
526                     }
527                 }
528             }
529         }
530
531         updateStyleProperties();
532     } else {
533         var noStyle = document.getElementById("noStyle");
534         noStyle.textContent = "Can't style " + nodeTypeName(focusedNode) + " nodes.";
535         document.getElementById("styleRules").style.display = "none";
536         document.getElementById("styleProperties").style.display = "none";
537         noStyle.style.display = null;
538     }
539
540     styleRulesScrollArea.refresh();
541 }
542
543 function styleRuleSelect(event)
544 {
545     var row = document.getElementById("styleRulesScrollview").firstChild;
546     while (row) {
547         if (row.nodeName == "DIV")
548             row.className = "row";
549         row = row.nextSibling;
550     }
551
552     row = event.currentTarget;
553     row.className = "row focused";
554
555     selectedStyleRuleIndex = row.styleRuleIndex;
556     updateStyleProperties();
557 }
558
559 function updateStyleProperties()
560 {
561     var focusedNode = Inspector.focusedDOMNode();
562     var propertiesTree = document.getElementById("stylePropertiesTree");
563     propertiesTree.innerHTML = "";
564
565     if (selectedStyleRuleIndex >= styleProperties.length) {
566         stylePropertiesScrollArea.refresh();
567         return;
568     }
569
570     var properties = styleProperties[selectedStyleRuleIndex];
571     for (var i = 0; i < properties.length; i++) {
572         var prop = properties[i];
573         var mainli = document.createElement("li");
574         if (prop.subProperties.length > 1) {
575             mainli.className = "hasChildren";
576             if (expandedStyleShorthands[prop.name])
577                 mainli.className += " expanded";
578             mainli.shorthand = prop.name;
579             var button = document.createElement("button");
580             button.addEventListener("click", toggleStyleShorthand, false);
581             mainli.appendChild(button);
582         }
583
584         var span = document.createElement("span");
585         span.className = "property";
586         span.textContent = prop.name;
587         mainli.appendChild(span);
588
589         span = document.createElement("span");
590         span.className = "value";
591         span.title = prop.style.getPropertyValue(prop.name);
592         if (prop.style.getPropertyPriority(prop.name).length)
593             span.title += " !" + prop.style.getPropertyPriority(prop.name);
594         span.textContent = span.title;
595         mainli.appendChild(span);
596
597         propertiesTree.appendChild(mainli);
598
599         var overloadCount = 0;
600         if (prop.subProperties && prop.subProperties.length > 1) {
601             var subTree = document.createElement("ul");
602             if (!expandedStyleShorthands[prop.name])
603                 subTree.style.display = "none";
604
605             for (var j = 0; j < prop.subProperties.length; j++) {
606                 var name = prop.subProperties[j];
607                 var li = document.createElement("li");
608                 if (prop.style.isPropertyImplicit(name) || prop.style.getPropertyValue(name) == "initial")
609                     li.className = "implicit";
610
611                 if (prop.unusedProperties[name] || prop.unusedProperties[prop.name]) {
612                     li.className += " overloaded";
613                     overloadCount++;
614                 }
615
616                 var span = document.createElement("span");
617                 span.className = "property";
618                 span.textContent = name;
619                 li.appendChild(span);
620
621                 span = document.createElement("span");
622                 span.className = "value";
623                 span.title = prop.style.getPropertyValue(name);
624                 if (prop.style.getPropertyPriority(name).length)
625                     span.title += " !" + prop.style.getPropertyPriority(name);
626                 span.textContent = span.title;
627                 li.appendChild(span);
628
629                 subTree.appendChild(li);
630             }
631
632             propertiesTree.appendChild(subTree);
633         }
634
635         if (prop.unusedProperties[prop.name] || overloadCount == prop.subProperties.length)
636             mainli.className += " overloaded";
637     }
638
639     stylePropertiesScrollArea.refresh();
640 }
641
642 function toggleStyleShorthand(event)
643 {
644     var li = event.currentTarget.parentNode;
645     if (li.className.indexOf("expanded") != -1) {
646         li.className = li.className.replace(/ expanded/, "");
647         li.nextSibling.style.display = "none";
648         expandedStyleShorthands[li.shorthand] = false;
649     } else {
650         li.className += " expanded";
651         li.nextSibling.style.display = null;
652         expandedStyleShorthands[li.shorthand] = true;
653     }
654
655     stylePropertiesScrollArea.refresh();
656 }
657
658 function selectMappedStyleRule(attrName)
659 {
660     if (!paneUpdateState["style"])
661         updateStylePane();
662
663     for (var i = 0; i < styleRules.length; i++)
664         if (styleRules[i].attr == attrName)
665             break;
666
667     selectedStyleRuleIndex = i;
668
669     var row = document.getElementById("styleRulesScrollview").firstChild;
670     while (row) {
671         if (row.nodeName == "DIV") {
672             if (row.styleRuleIndex == selectedStyleRuleIndex)
673                 row.className = "row focused";
674             else
675                 row.className = "row";
676         }
677         row = row.nextSibling;
678     }
679
680     styleRulesScrollArea.refresh();
681
682     updateStyleProperties();
683     switchPane("style");
684 }
685
686 function updateMetricsPane()
687 {
688 }
689
690 function updatePropertiesPane()
691 {
692 }