| OLD | NEW |
| (Empty) |
| 1 | |
| 2 | |
| 3 (function(scope) { | |
| 4 | |
| 5 scope = scope || (window.Inspector = {}); | |
| 6 | |
| 7 var inspector; | |
| 8 | |
| 9 window.sinspect = function(inNode, inProxy) { | |
| 10 if (!inspector) { | |
| 11 inspector = window.open('', 'ShadowDOM Inspector', null, true); | |
| 12 inspector.document.write(inspectorHTML); | |
| 13 //inspector.document.close(); | |
| 14 inspector.api = { | |
| 15 shadowize: shadowize | |
| 16 }; | |
| 17 } | |
| 18 inspect(inNode || wrap(document.body), inProxy); | |
| 19 }; | |
| 20 | |
| 21 var inspectorHTML = [ | |
| 22 '<!DOCTYPE html>', | |
| 23 '<html>', | |
| 24 ' <head>', | |
| 25 ' <title>ShadowDOM Inspector</title>', | |
| 26 ' <style>', | |
| 27 ' body {', | |
| 28 ' }', | |
| 29 ' pre {', | |
| 30 ' font: 9pt "Courier New", monospace;', | |
| 31 ' line-height: 1.5em;', | |
| 32 ' }', | |
| 33 ' tag {', | |
| 34 ' color: purple;', | |
| 35 ' }', | |
| 36 ' ul {', | |
| 37 ' margin: 0;', | |
| 38 ' padding: 0;', | |
| 39 ' list-style: none;', | |
| 40 ' }', | |
| 41 ' li {', | |
| 42 ' display: inline-block;', | |
| 43 ' background-color: #f1f1f1;', | |
| 44 ' padding: 4px 6px;', | |
| 45 ' border-radius: 4px;', | |
| 46 ' margin-right: 4px;', | |
| 47 ' }', | |
| 48 ' button {', | |
| 49 ' display: inline-block;', | |
| 50 ' color: purple;', | |
| 51 ' font-weight: bold;', | |
| 52 ' background: none;', | |
| 53 ' border: none;', | |
| 54 ' outline: none;', | |
| 55 ' padding: 0;', | |
| 56 ' margin: 0;', | |
| 57 ' }', | |
| 58 ' </style>', | |
| 59 ' </head>', | |
| 60 ' <body>', | |
| 61 ' <ul id="crumbs">', | |
| 62 ' </ul>', | |
| 63 ' <div id="tree"></div>', | |
| 64 ' </body>', | |
| 65 '</html>' | |
| 66 ].join('\n'); | |
| 67 | |
| 68 var crumbs = []; | |
| 69 | |
| 70 var displayCrumbs = function() { | |
| 71 // alias our document | |
| 72 var d = inspector.document; | |
| 73 // get crumbbar | |
| 74 var cb = d.querySelector('#crumbs'); | |
| 75 // clear crumbs | |
| 76 cb.textContent = ''; | |
| 77 // build new crumbs | |
| 78 for (var i=0, c; c=crumbs[i]; i++) { | |
| 79 var a = d.createElement('a'); | |
| 80 a.href = '#'; | |
| 81 a.textContent = c.localName; | |
| 82 a.idx = i; | |
| 83 a.onclick = function(event) { | |
| 84 var c; | |
| 85 while (crumbs.length > this.idx) { | |
| 86 c = crumbs.pop(); | |
| 87 } | |
| 88 inspect(c.shadow || c, c); | |
| 89 event.preventDefault(); | |
| 90 }; | |
| 91 cb.appendChild(d.createElement('li')).appendChild(a); | |
| 92 } | |
| 93 }; | |
| 94 | |
| 95 var inspect = function(inNode, inProxy) { | |
| 96 // alias our document | |
| 97 var d = inspector.document; | |
| 98 // reset list of drillable nodes | |
| 99 drillable = []; | |
| 100 // memoize our crumb proxy | |
| 101 var proxy = inProxy || inNode; | |
| 102 crumbs.push(proxy); | |
| 103 // update crumbs | |
| 104 displayCrumbs(); | |
| 105 // reflect local tree | |
| 106 d.body.querySelector('#tree').innerHTML = | |
| 107 '<pre>' + output(inNode, getLocalNodes(inNode)) + '</pre>'; | |
| 108 }; | |
| 109 | |
| 110 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); | |
| 111 | |
| 112 var blacklisted = {STYLE:1, SCRIPT:1, "#comment": 1, TEMPLATE: 1}; | |
| 113 var blacklist = function(inNode) { | |
| 114 return blacklisted[inNode.nodeName]; | |
| 115 }; | |
| 116 | |
| 117 var output = function(inNode, inChildNodes, inIndent) { | |
| 118 if (blacklist(inNode)) { | |
| 119 return ''; | |
| 120 } | |
| 121 var indent = inIndent || ''; | |
| 122 if (inNode.localName || inNode.domRoot) { | |
| 123 var name = inNode.localName || ROOT_NAME; | |
| 124 //inChildNodes = ShadowDOM.localNodes(inNode); | |
| 125 var info = indent + describe(inNode); | |
| 126 // if only textNodes | |
| 127 // TODO(sjmiles): make correct for ShadowDOM | |
| 128 /*if (!inNode.children.length && inNode.localName !== 'content' && inNode.
localName !== 'shadow') { | |
| 129 info += catTextContent(inChildNodes); | |
| 130 } else*/ { | |
| 131 // TODO(sjmiles): native <shadow> has no reference to its projection | |
| 132 if (name == 'content' /*|| name == 'shadow'*/) { | |
| 133 inChildNodes = getDistributedNodes(inNode); | |
| 134 } | |
| 135 info += '<br/>'; | |
| 136 var ind = indent + ' '; | |
| 137 //console.group('output ' + inNode.localName); | |
| 138 //console.log(inChildNodes); | |
| 139 forEach(inChildNodes, function(n) { | |
| 140 info += output(n, getLightNodes(n), ind); | |
| 141 }); | |
| 142 //console.groupEnd('output ' + inNode.localName); | |
| 143 info += indent; | |
| 144 } | |
| 145 if (!({br:1}[name])) { | |
| 146 info += '<tag></' + name + '></tag>'; | |
| 147 info += '<br/>'; | |
| 148 } | |
| 149 } else { | |
| 150 var text = inNode.textContent.trim(); | |
| 151 info = text ? indent + '"' + text + '"' + '<br/>' : ''; | |
| 152 } | |
| 153 return info; | |
| 154 }; | |
| 155 | |
| 156 var catTextContent = function(inChildNodes) { | |
| 157 var info = ''; | |
| 158 forEach(inChildNodes, function(n) { | |
| 159 info += n.textContent.trim(); | |
| 160 }); | |
| 161 return info; | |
| 162 }; | |
| 163 | |
| 164 var drillable = []; | |
| 165 | |
| 166 var describe = function(inNode) { | |
| 167 var tag = '<tag>' + '<'; | |
| 168 var name = inNode.localName || ROOT_NAME; | |
| 169 if (hasRoot(inNode)) { | |
| 170 tag += '<button idx="' + drillable.length + | |
| 171 '" onclick="api.shadowize.call(this)">' + name + '</button>'; | |
| 172 drillable.push(inNode); | |
| 173 } else { | |
| 174 tag += name || ROOT_NAME; | |
| 175 } | |
| 176 if (inNode.attributes) { | |
| 177 forEach(inNode.attributes, function(a) { | |
| 178 tag += ' ' + a.name + (a.value ? '="' + a.value + '"' : ''); | |
| 179 }); | |
| 180 } | |
| 181 tag += '>'+ '</tag>'; | |
| 182 return tag; | |
| 183 }; | |
| 184 | |
| 185 // remote api | |
| 186 | |
| 187 shadowize = function() { | |
| 188 var idx = Number(this.attributes.idx.value); | |
| 189 //alert(idx); | |
| 190 var node = drillable[idx]; | |
| 191 if (node) { | |
| 192 inspect(node, node) | |
| 193 } else { | |
| 194 console.log("bad shadowize node"); | |
| 195 console.dir(this); | |
| 196 } | |
| 197 }; | |
| 198 | |
| 199 // util | |
| 200 | |
| 201 var ROOT_NAME = 'local-root'; | |
| 202 | |
| 203 function hasRoot(node) { | |
| 204 return (node.shadyRoot || node.shadowRoot); | |
| 205 } | |
| 206 | |
| 207 function getLocalNodes(n) { | |
| 208 return Polymer.dom.childNodes(n.root); | |
| 209 } | |
| 210 | |
| 211 function getLightNodes(n) { | |
| 212 return Polymer.dom.childNodes(n); | |
| 213 } | |
| 214 | |
| 215 function getDistributedNodes(node) { | |
| 216 Polymer.dom.distributedNodes(node); | |
| 217 } | |
| 218 | |
| 219 | |
| 220 // export | |
| 221 | |
| 222 scope.output = output; | |
| 223 | |
| 224 })(window.Inspector); | |
| 225 | |
| OLD | NEW |