1/* 2 * Copyright (C) 2013 Apple 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 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26WebInspector.Section = function(title, subtitle) 27{ 28 WebInspector.Object.call(this); 29 30 this.element = document.createElement("div"); 31 this.element.className = "section"; 32 this.element._section = this; 33 34 if (typeof title === "string" || title instanceof Node || typeof subtitle === "string") { 35 this.headerElement = document.createElement("div"); 36 this.headerElement.className = "header"; 37 38 this.titleElement = document.createElement("div"); 39 this.titleElement.className = "title"; 40 41 this.subtitleElement = document.createElement("div"); 42 this.subtitleElement.className = "subtitle"; 43 44 this.headerElement.appendChild(this.subtitleElement); 45 this.headerElement.appendChild(this.titleElement); 46 47 this.headerElement.addEventListener("click", this.handleClick.bind(this), false); 48 this.element.appendChild(this.headerElement); 49 50 this.title = title; 51 this.subtitle = subtitle; 52 } else 53 this.element.classList.add("no-header"); 54 55 this._expanded = false; 56 57 if (!this.headerElement) 58 this.expand(); 59}; 60 61WebInspector.Section.Event = { 62 VisibleContentDidChange: "section-visible-content-did-change" 63}; 64 65WebInspector.Section.prototype = { 66 get title() 67 { 68 return this._title; 69 }, 70 71 set title(x) 72 { 73 if (this._title === x) 74 return; 75 this._title = x; 76 77 if (x instanceof Node) { 78 this.titleElement.removeChildren(); 79 this.titleElement.appendChild(x); 80 } else 81 this.titleElement.textContent = x; 82 }, 83 84 get subtitle() 85 { 86 return this._subtitle; 87 }, 88 89 set subtitle(x) 90 { 91 if (this._subtitle === x) 92 return; 93 this._subtitle = x; 94 this.subtitleElement.textContent = x; 95 }, 96 97 get subtitleAsTextForTest() 98 { 99 var result = this.subtitleElement.textContent; 100 var child = this.subtitleElement.querySelector("[data-uncopyable]"); 101 if (child) { 102 var linkData = child.getAttribute("data-uncopyable"); 103 if (linkData) 104 result += linkData; 105 } 106 return result; 107 }, 108 109 get expanded() 110 { 111 return this._expanded; 112 }, 113 114 set expanded(x) 115 { 116 if (x) 117 this.expand(); 118 else 119 this.collapse(); 120 }, 121 122 get populated() 123 { 124 return this._populated; 125 }, 126 127 set populated(x) 128 { 129 this._populated = x; 130 if (!x && this._expanded) { 131 this.onpopulate(); 132 this._populated = true; 133 } 134 }, 135 136 onpopulate: function() 137 { 138 // Overriden by subclasses. 139 }, 140 141 get firstSibling() 142 { 143 var parent = this.element.parentElement; 144 if (!parent) 145 return null; 146 147 var childElement = parent.firstChild; 148 while (childElement) { 149 if (childElement._section) 150 return childElement._section; 151 childElement = childElement.nextSibling; 152 } 153 154 return null; 155 }, 156 157 get lastSibling() 158 { 159 var parent = this.element.parentElement; 160 if (!parent) 161 return null; 162 163 var childElement = parent.lastChild; 164 while (childElement) { 165 if (childElement._section) 166 return childElement._section; 167 childElement = childElement.previousSibling; 168 } 169 170 return null; 171 }, 172 173 get nextSibling() 174 { 175 var curElement = this.element; 176 do { 177 curElement = curElement.nextSibling; 178 } while (curElement && !curElement._section); 179 180 return curElement ? curElement._section : null; 181 }, 182 183 get previousSibling() 184 { 185 var curElement = this.element; 186 do { 187 curElement = curElement.previousSibling; 188 } while (curElement && !curElement._section); 189 190 return curElement ? curElement._section : null; 191 }, 192 193 expand: function() 194 { 195 if (this._expanded) 196 return; 197 this._expanded = true; 198 this.element.classList.add("expanded"); 199 200 if (!this._populated) { 201 this.onpopulate(); 202 this._populated = true; 203 } else 204 this.dispatchEventToListeners(WebInspector.Section.Event.VisibleContentDidChange); 205 }, 206 207 collapse: function() 208 { 209 if (!this._expanded) 210 return; 211 this._expanded = false; 212 this.element.classList.remove("expanded"); 213 }, 214 215 toggleExpanded: function() 216 { 217 this.expanded = !this.expanded; 218 }, 219 220 handleClick: function(e) 221 { 222 this.toggleExpanded(); 223 e.stopPropagation(); 224 } 225}; 226 227WebInspector.Section.prototype.__proto__ = WebInspector.Object.prototype; 228