@@ -163,6 +163,8 @@ class CategoryRenderer {
163163 const titleEl = this . _dom . createChildOf ( summary , 'div' , 'lh-perf-hint__title' ) ;
164164 titleEl . textContent = audit . result . description ;
165165
166+ this . _dom . createChildOf ( summary , 'div' , 'lh-toggle-arrow' , { title : 'See resources' } ) ;
167+
166168 if ( ! extendedInfo || typeof audit . result . rawValue !== 'number' ) {
167169 const debugStrEl = this . _dom . createChildOf ( summary , 'div' , 'lh-debug' ) ;
168170 debugStrEl . textContent = audit . result . debugString || 'Report error: no extended information' ;
@@ -179,8 +181,6 @@ class CategoryRenderer {
179181 const statsMsEl = this . _dom . createChildOf ( statsEl , 'div' , 'lh-perf-hint__primary-stat' ) ;
180182 statsMsEl . textContent = Util . formatMilliseconds ( audit . result . rawValue ) ;
181183
182- this . _dom . createChildOf ( summary , 'div' , 'lh-toggle-arrow' , { title : 'See resources' } ) ;
183-
184184 if ( extendedInfo . value . wastedKb ) {
185185 const statsKbEl = this . _dom . createChildOf ( statsEl , 'div' , 'lh-perf-hint__secondary-stat' ) ;
186186 statsKbEl . textContent = Util . formatNumber ( extendedInfo . value . wastedKb ) + ' KB' ;
@@ -190,9 +190,8 @@ class CategoryRenderer {
190190 descriptionEl . appendChild ( this . _dom . convertMarkdownLinkSnippets ( audit . result . helpText ) ) ;
191191
192192 if ( audit . result . debugString ) {
193- const debugStrEl = this . _dom . createChildOf ( element , 'div' , 'lh-debug' ) ;
193+ const debugStrEl = this . _dom . createChildOf ( summary , 'div' , 'lh-debug' ) ;
194194 debugStrEl . textContent = audit . result . debugString ;
195- element . open = true ;
196195 }
197196
198197 if ( audit . result . details ) {
@@ -206,31 +205,27 @@ class CategoryRenderer {
206205 * Renders the group container for a group of audits. Individual audit elements can be added
207206 * directly to the returned element.
208207 * @param {!ReportRenderer.GroupJSON } group
209- * @return {!HTMLDetailsElement }
208+ * @param {{expandable: boolean} } opts
209+ * @return {!Element }
210210 */
211- _renderAuditGroup ( group ) {
212- const auditGroupElem = /** @type {!HTMLDetailsElement } */ ( this . _dom . createElement ( 'details' ,
213- 'lh-audit-group lh-expandable-details' ) ) ;
214- const auditGroupHeader = this . _dom . createElement ( 'div' ,
215- 'lh-audit-group__header lh-expandable-details__header' ) ;
216- auditGroupHeader . textContent = group . title ;
217-
218- const auditGroupSummary = this . _dom . createElement ( 'summary' ,
219- 'lh-audit-group__summary lh-expandable-details__summary' ) ;
220- const auditGroupArrow = this . _dom . createElement ( 'div' , 'lh-toggle-arrow' , {
221- title : 'See audits' ,
222- } ) ;
223- auditGroupSummary . appendChild ( auditGroupHeader ) ;
224- auditGroupSummary . appendChild ( auditGroupArrow ) ;
225- auditGroupElem . appendChild ( auditGroupSummary ) ;
211+ _renderAuditGroup ( group , opts ) {
212+ const expandable = opts . expandable ;
213+ const element = this . _dom . createElement ( expandable ? 'details' :'div' , 'lh-audit-group' ) ;
214+ const summmaryEl = this . _dom . createChildOf ( element , 'summary' , 'lh-audit-group__summary' ) ;
215+ const headerEl = this . _dom . createChildOf ( summmaryEl , 'div' , 'lh-audit-group__header' ) ;
216+ this . _dom . createChildOf ( summmaryEl , 'div' ,
217+ `lh-toggle-arrow ${ expandable ? '' : ' lh-toggle-arrow-unexpandable' } ` , {
218+ title : 'See audits' ,
219+ } ) ;
226220
227221 if ( group . description ) {
228222 const auditGroupDescription = this . _dom . createElement ( 'div' , 'lh-audit-group__description' ) ;
229223 auditGroupDescription . appendChild ( this . _dom . convertMarkdownLinkSnippets ( group . description ) ) ;
230- auditGroupElem . appendChild ( auditGroupDescription ) ;
224+ element . appendChild ( auditGroupDescription ) ;
231225 }
226+ headerEl . textContent = group . title ;
232227
233- return auditGroupElem ;
228+ return element ;
234229 }
235230
236231 /**
@@ -240,7 +235,7 @@ class CategoryRenderer {
240235 _renderPassedAuditsSection ( elements ) {
241236 const passedElem = this . _renderAuditGroup ( {
242237 title : `${ elements . length } Passed Audits` ,
243- } ) ;
238+ } , { expandable : true } ) ;
244239 passedElem . classList . add ( 'lh-passed-audits' ) ;
245240 elements . forEach ( elem => passedElem . appendChild ( elem ) ) ;
246241 return passedElem ;
@@ -262,7 +257,7 @@ class CategoryRenderer {
262257
263258 Object . keys ( auditsGroupedByGroup ) . forEach ( groupId => {
264259 const group = groupDefinitions [ groupId ] ;
265- const auditGroupElem = this . _renderAuditGroup ( group ) ;
260+ const auditGroupElem = this . _renderAuditGroup ( group , { expandable : true } ) ;
266261 auditGroupElem . classList . add ( 'lh-audit-group--manual' ) ;
267262
268263 auditsGroupedByGroup [ groupId ] . forEach ( audit => {
@@ -333,7 +328,7 @@ class CategoryRenderer {
333328 */
334329 _renderDefaultCategory ( category , groupDefinitions ) {
335330 const element = this . _dom . createElement ( 'div' , 'lh-category' ) ;
336- element . id = category . id ;
331+ this . _createPermalinkSpan ( element , category . id ) ;
337332 element . appendChild ( this . _renderCategoryScore ( category ) ) ;
338333
339334 const manualAudits = category . audits . filter ( audit => audit . result . manual ) ;
@@ -344,8 +339,8 @@ class CategoryRenderer {
344339
345340 const nonPassedElem = this . _renderAuditGroup ( {
346341 title : `${ nonPassedAudits . length } failed audits` ,
347- } ) ;
348- nonPassedElem . open = true ;
342+ } , { expandable : false } ) ;
343+ nonPassedElem . classList . add ( 'lh-failed-audits' ) ;
349344 nonPassedAudits . forEach ( audit => nonPassedElem . appendChild ( this . _renderAudit ( audit ) ) ) ;
350345 element . appendChild ( nonPassedElem ) ;
351346
@@ -370,11 +365,11 @@ class CategoryRenderer {
370365 */
371366 _renderPerformanceCategory ( category , groups ) {
372367 const element = this . _dom . createElement ( 'div' , 'lh-category' ) ;
373- element . id = category . id ;
368+ this . _createPermalinkSpan ( element , category . id ) ;
374369 element . appendChild ( this . _renderCategoryScore ( category ) ) ;
375370
376371 const metricAudits = category . audits . filter ( audit => audit . group === 'perf-metric' ) ;
377- const metricAuditsEl = this . _renderAuditGroup ( groups [ 'perf-metric' ] ) ;
372+ const metricAuditsEl = this . _renderAuditGroup ( groups [ 'perf-metric' ] , { expandable : false } ) ;
378373 const timelineContainerEl = this . _dom . createChildOf ( metricAuditsEl , 'div' ,
379374 'lh-timeline-container' ) ;
380375 const timelineEl = this . _dom . createChildOf ( timelineContainerEl , 'div' , 'lh-timeline' ) ;
@@ -413,7 +408,7 @@ class CategoryRenderer {
413408 if ( hintAudits . length ) {
414409 const maxWaste = Math . max ( ...hintAudits . map ( audit => audit . result . rawValue ) ) ;
415410 const scale = Math . ceil ( maxWaste / 1000 ) * 1000 ;
416- const hintAuditsEl = this . _renderAuditGroup ( groups [ 'perf-hint' ] ) ;
411+ const hintAuditsEl = this . _renderAuditGroup ( groups [ 'perf-hint' ] , { expandable : false } ) ;
417412 hintAudits . forEach ( item => hintAuditsEl . appendChild ( this . _renderPerfHintAudit ( item , scale ) ) ) ;
418413 hintAuditsEl . open = true ;
419414 element . appendChild ( hintAuditsEl ) ;
@@ -422,7 +417,7 @@ class CategoryRenderer {
422417 const infoAudits = category . audits
423418 . filter ( audit => audit . group === 'perf-info' && audit . score < 100 ) ;
424419 if ( infoAudits . length ) {
425- const infoAuditsEl = this . _renderAuditGroup ( groups [ 'perf-info' ] ) ;
420+ const infoAuditsEl = this . _renderAuditGroup ( groups [ 'perf-info' ] , { expandable : false } ) ;
426421 infoAudits . forEach ( item => infoAuditsEl . appendChild ( this . _renderAudit ( item ) ) ) ;
427422 infoAuditsEl . open = true ;
428423 element . appendChild ( infoAuditsEl ) ;
@@ -447,7 +442,7 @@ class CategoryRenderer {
447442 */
448443 _renderAccessibilityCategory ( category , groupDefinitions ) {
449444 const element = this . _dom . createElement ( 'div' , 'lh-category' ) ;
450- element . id = category . id ;
445+ this . _createPermalinkSpan ( element , category . id ) ;
451446 element . appendChild ( this . _renderCategoryScore ( category ) ) ;
452447
453448 const auditsGroupedByGroup = /** @type {!Object<string,
@@ -471,14 +466,14 @@ class CategoryRenderer {
471466 const group = groupDefinitions [ groupId ] ;
472467 const groups = auditsGroupedByGroup [ groupId ] ;
473468 if ( groups . failed . length ) {
474- const auditGroupElem = this . _renderAuditGroup ( group ) ;
469+ const auditGroupElem = this . _renderAuditGroup ( group , { expandable : false } ) ;
475470 groups . failed . forEach ( item => auditGroupElem . appendChild ( this . _renderAudit ( item ) ) ) ;
476471 auditGroupElem . open = true ;
477472 element . appendChild ( auditGroupElem ) ;
478473 }
479474
480475 if ( groups . passed . length ) {
481- const auditGroupElem = this . _renderAuditGroup ( group ) ;
476+ const auditGroupElem = this . _renderAuditGroup ( group , { expandable : true } ) ;
482477 groups . passed . forEach ( item => auditGroupElem . appendChild ( this . _renderAudit ( item ) ) ) ;
483478 passedElements . push ( auditGroupElem ) ;
484479 }
@@ -491,6 +486,16 @@ class CategoryRenderer {
491486 element . appendChild ( passedElem ) ;
492487 return element ;
493488 }
489+
490+ /**
491+ * Create a non-semantic span used for hash navigation of categories
492+ * @param {!Element } element
493+ * @param {string } id
494+ */
495+ _createPermalinkSpan ( element , id ) {
496+ const permalinkEl = this . _dom . createChildOf ( element , 'span' , 'lh-permalink' ) ;
497+ permalinkEl . id = id ;
498+ }
494499}
495500
496501if ( typeof module !== 'undefined' && module . exports ) {
0 commit comments