Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 1 | // Copyright 2019 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. |
| 4 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 5 | import * as Common from '../common/common.js'; |
| 6 | import * as Components from '../components/components.js'; |
| 7 | import * as DataGrid from '../data_grid/data_grid.js'; |
| 8 | import * as SDK from '../sdk/sdk.js'; |
| 9 | import * as TextUtils from '../text_utils/text_utils.js'; |
| 10 | import * as UI from '../ui/ui.js'; |
| 11 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 12 | import {Events, OverviewController} from './CSSOverviewController.js'; // eslint-disable-line no-unused-vars |
Tim van der Lippe | 9d0cb5f | 2020-01-09 14:10:38 | [diff] [blame] | 13 | import {CSSOverviewSidebarPanel, SidebarEvents} from './CSSOverviewSidebarPanel.js'; |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 14 | import {UnusedDeclaration} from './CSSOverviewUnusedDeclarations.js'; // eslint-disable-line no-unused-vars |
| 15 | |
| 16 | /** |
| 17 | * @typedef {!Map<string,!Set<number>>} |
| 18 | */ |
| 19 | // @ts-ignore typedef |
| 20 | export let NodeStyleStats; |
| 21 | |
| 22 | /** |
| 23 | * @typedef {{ |
Alex Rudenko | d55e18c | 2020-09-23 11:37:06 | [diff] [blame] | 24 | * nodeId: number, |
| 25 | * contrastRatio: number, |
| 26 | * textColor: Common.Color.Color, |
| 27 | * backgroundColor: Common.Color.Color, |
| 28 | * thresholdsViolated: !{aa: boolean, aaa:boolean}, |
| 29 | * }} |
| 30 | */ |
| 31 | // @ts-ignore typedef |
| 32 | export let ContrastIssue; |
| 33 | |
| 34 | /** |
| 35 | * @typedef {{ |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 36 | * backgroundColors: NodeStyleStats, |
| 37 | * textColors: NodeStyleStats, |
Alex Rudenko | d55e18c | 2020-09-23 11:37:06 | [diff] [blame] | 38 | * textColorContrastIssues: !Map<string, !Array<!ContrastIssue>>, |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 39 | * fillColors: NodeStyleStats, |
| 40 | * borderColors: NodeStyleStats, |
| 41 | * globalStyleStats: !{ |
| 42 | * styleRules: number, |
| 43 | * inlineStyles: number, |
| 44 | * externalSheets: number, |
| 45 | * stats: !{ |
| 46 | * type: number, |
| 47 | * class: number, |
| 48 | * id: number, |
| 49 | * universal: number, |
| 50 | * attribute: number, |
| 51 | * nonSimple: number |
| 52 | * } |
| 53 | * }, |
| 54 | * fontInfo: FontInfo, |
| 55 | * elementCount: number, |
| 56 | * mediaQueries: !Map<string, !Array<!Protocol.CSS.CSSMedia>>, |
| 57 | * unusedDeclarations: !Map<string, !Array<!UnusedDeclaration>>, |
| 58 | * }} |
| 59 | */ |
| 60 | // @ts-ignore typedef |
| 61 | export let OverviewData; |
| 62 | |
| 63 | /** |
| 64 | * @typedef {!Map<string, !Map<string, !Map<string, !Array<number>>>>} |
| 65 | */ |
| 66 | // @ts-ignore typedef |
| 67 | export let FontInfo; |
Tim van der Lippe | 9d0cb5f | 2020-01-09 14:10:38 | [diff] [blame] | 68 | |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 69 | /** |
Alex Rudenko | d3ba0ee | 2020-09-25 14:01:21 | [diff] [blame] | 70 | * @param {!Common.Color.Color} color |
| 71 | */ |
| 72 | function getBorderString(color) { |
| 73 | let [h, s, l] = color.hsla(); |
| 74 | h = Math.round(h * 360); |
| 75 | s = Math.round(s * 100); |
| 76 | l = Math.round(l * 100); |
| 77 | |
| 78 | // Reduce the lightness of the border to make sure that there's always a visible outline. |
| 79 | l = Math.max(0, l - 15); |
| 80 | |
| 81 | return `1px solid hsl(${h}deg ${s}% ${l}%)`; |
| 82 | } |
| 83 | |
| 84 | /** |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 85 | * @unrestricted |
| 86 | */ |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 87 | export class CSSOverviewCompletedView extends UI.Panel.PanelWithSidebar { |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 88 | /** |
| 89 | * @param {!OverviewController} controller |
| 90 | * @param {!SDK.SDKModel.Target} target |
| 91 | */ |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 92 | constructor(controller, target) { |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 93 | super('css_overview_completed_view'); |
Jack Franklin | 71519f8 | 2020-11-03 12:08:59 | [diff] [blame^] | 94 | this.registerRequiredCSS('css_overview/cssOverviewCompletedView.css', {enableLegacyPatching: true}); |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 95 | |
| 96 | this._controller = controller; |
| 97 | this._formatter = new Intl.NumberFormat('en-US'); |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 98 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 99 | this._mainContainer = new UI.SplitWidget.SplitWidget(true, true); |
| 100 | this._resultsContainer = new UI.Widget.VBox(); |
Paul Lewis | 4da3b30 | 2019-11-21 14:23:47 | [diff] [blame] | 101 | this._elementContainer = new DetailsView(); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 102 | |
| 103 | // If closing the last tab, collapse the sidebar. |
| 104 | this._elementContainer.addEventListener(UI.TabbedPane.Events.TabClosed, evt => { |
| 105 | if (evt.data === 0) { |
| 106 | this._mainContainer.setSidebarMinimized(true); |
| 107 | } |
| 108 | }); |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 109 | |
| 110 | // Dupe the styles into the main container because of the shadow root will prevent outer styles. |
Jack Franklin | 71519f8 | 2020-11-03 12:08:59 | [diff] [blame^] | 111 | this._mainContainer.registerRequiredCSS('css_overview/cssOverviewCompletedView.css', {enableLegacyPatching: true}); |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 112 | |
| 113 | this._mainContainer.setMainWidget(this._resultsContainer); |
| 114 | this._mainContainer.setSidebarWidget(this._elementContainer); |
| 115 | this._mainContainer.setVertical(false); |
| 116 | this._mainContainer.setSecondIsSidebar(true); |
| 117 | this._mainContainer.setSidebarMinimized(true); |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 118 | |
Tim van der Lippe | 9d0cb5f | 2020-01-09 14:10:38 | [diff] [blame] | 119 | this._sideBar = new CSSOverviewSidebarPanel(); |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 120 | this.splitWidget().setSidebarWidget(this._sideBar); |
| 121 | this.splitWidget().setMainWidget(this._mainContainer); |
| 122 | |
Sigurd Schneider | 5a5b735 | 2020-10-05 11:13:05 | [diff] [blame] | 123 | const cssModel = target.model(SDK.CSSModel.CSSModel); |
| 124 | const domModel = target.model(SDK.DOMModel.DOMModel); |
| 125 | if (!cssModel || !domModel) { |
| 126 | throw new Error('Target must provide CSS and DOM models'); |
| 127 | } |
| 128 | this._cssModel = cssModel; |
| 129 | this._domModel = domModel; |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 130 | this._domAgent = target.domAgent(); |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 131 | this._linkifier = new Components.Linkifier.Linkifier(/* maxLinkLength */ 20, /* useLinkDecorator */ true); |
Paul Lewis | 8aef901 | 2019-10-29 14:15:17 | [diff] [blame] | 132 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 133 | this._viewMap = new Map(); |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 134 | |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 135 | this._sideBar.addItem(ls`Overview summary`, 'summary'); |
| 136 | this._sideBar.addItem(ls`Colors`, 'colors'); |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 137 | this._sideBar.addItem(ls`Font info`, 'font-info'); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 138 | this._sideBar.addItem(ls`Unused declarations`, 'unused-declarations'); |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 139 | this._sideBar.addItem(ls`Media queries`, 'media-queries'); |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 140 | this._sideBar.select('summary'); |
| 141 | |
Tim van der Lippe | 9d0cb5f | 2020-01-09 14:10:38 | [diff] [blame] | 142 | this._sideBar.addEventListener(SidebarEvents.ItemSelected, this._sideBarItemSelected, this); |
| 143 | this._sideBar.addEventListener(SidebarEvents.Reset, this._sideBarReset, this); |
| 144 | this._controller.addEventListener(Events.Reset, this._reset, this); |
| 145 | this._controller.addEventListener(Events.PopulateNodes, this._createElementsView, this); |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 146 | this._resultsContainer.element.addEventListener('click', this._onClick.bind(this)); |
| 147 | |
| 148 | this._data = null; |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 149 | } |
| 150 | |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 151 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 152 | /** |
| 153 | * @override |
| 154 | */ |
| 155 | wasShown() { |
| 156 | super.wasShown(); |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 157 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 158 | // TODO(paullewis): update the links in the panels in case source has been . |
Paul Lewis | 8aef901 | 2019-10-29 14:15:17 | [diff] [blame] | 159 | } |
| 160 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 161 | /** |
| 162 | * @param {!Common.EventTarget.EventTargetEvent} event |
| 163 | */ |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 164 | _sideBarItemSelected(event) { |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 165 | const data = /** @type {string} */ (event.data); |
| 166 | const section = /** @type {!UI.Fragment.Fragment}*/ (this._fragment).$(data); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 167 | if (!section) { |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 168 | return; |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 169 | } |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 170 | |
| 171 | section.scrollIntoView(); |
| 172 | } |
| 173 | |
| 174 | _sideBarReset() { |
Tim van der Lippe | 9d0cb5f | 2020-01-09 14:10:38 | [diff] [blame] | 175 | this._controller.dispatchEventToListeners(Events.Reset); |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 176 | } |
| 177 | |
| 178 | _reset() { |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 179 | this._resultsContainer.element.removeChildren(); |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 180 | this._mainContainer.setSidebarMinimized(true); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 181 | this._elementContainer.closeTabs(); |
| 182 | this._viewMap = new Map(); |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 183 | } |
| 184 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 185 | /** |
| 186 | * @param {!Event} evt |
| 187 | */ |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 188 | _onClick(evt) { |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 189 | if (!evt.target) { |
| 190 | return; |
| 191 | } |
| 192 | const target = /** @type {!HTMLElement} */ (evt.target); |
| 193 | const dataset = target.dataset; |
| 194 | |
| 195 | const type = dataset.type; |
| 196 | if (!type || !this._data) { |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 197 | return; |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 198 | } |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 199 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 200 | let payload; |
| 201 | switch (type) { |
Alex Rudenko | d55e18c | 2020-09-23 11:37:06 | [diff] [blame] | 202 | case 'contrast': { |
| 203 | const section = dataset.section; |
| 204 | const key = dataset.key; |
| 205 | |
| 206 | if (!key) { |
| 207 | return; |
| 208 | } |
| 209 | |
| 210 | // Remap the Set to an object that is the same shape as the unused declarations. |
Alex Rudenko | d3ba0ee | 2020-09-25 14:01:21 | [diff] [blame] | 211 | const nodes = this._data.textColorContrastIssues.get(key) || []; |
Alex Rudenko | d55e18c | 2020-09-23 11:37:06 | [diff] [blame] | 212 | payload = {type, key, nodes, section}; |
| 213 | break; |
| 214 | } |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 215 | case 'color': { |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 216 | const color = dataset.color; |
| 217 | const section = dataset.section; |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 218 | if (!color) { |
| 219 | return; |
| 220 | } |
Paul Lewis | 12bc63e | 2019-10-23 10:53:29 | [diff] [blame] | 221 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 222 | let nodes; |
| 223 | switch (section) { |
| 224 | case 'text': |
| 225 | nodes = this._data.textColors.get(color); |
| 226 | break; |
Paul Lewis | 12bc63e | 2019-10-23 10:53:29 | [diff] [blame] | 227 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 228 | case 'background': |
| 229 | nodes = this._data.backgroundColors.get(color); |
| 230 | break; |
Paul Lewis | 12bc63e | 2019-10-23 10:53:29 | [diff] [blame] | 231 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 232 | case 'fill': |
| 233 | nodes = this._data.fillColors.get(color); |
| 234 | break; |
Paul Lewis | 12bc63e | 2019-10-23 10:53:29 | [diff] [blame] | 235 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 236 | case 'border': |
| 237 | nodes = this._data.borderColors.get(color); |
| 238 | break; |
| 239 | } |
| 240 | |
| 241 | if (!nodes) { |
| 242 | return; |
| 243 | } |
| 244 | |
| 245 | // Remap the Set to an object that is the same shape as the unused declarations. |
| 246 | nodes = Array.from(nodes).map(nodeId => ({nodeId})); |
| 247 | payload = {type, color, nodes, section}; |
| 248 | break; |
| 249 | } |
| 250 | |
| 251 | case 'unused-declarations': { |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 252 | const declaration = dataset.declaration; |
| 253 | if (!declaration) { |
| 254 | return; |
| 255 | } |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 256 | const nodes = this._data.unusedDeclarations.get(declaration); |
| 257 | if (!nodes) { |
| 258 | return; |
| 259 | } |
| 260 | |
| 261 | payload = {type, declaration, nodes}; |
| 262 | break; |
| 263 | } |
| 264 | |
| 265 | case 'media-queries': { |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 266 | const text = dataset.text; |
| 267 | if (!text) { |
| 268 | return; |
| 269 | } |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 270 | const nodes = this._data.mediaQueries.get(text); |
| 271 | if (!nodes) { |
| 272 | return; |
| 273 | } |
| 274 | |
| 275 | payload = {type, text, nodes}; |
| 276 | break; |
| 277 | } |
| 278 | |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 279 | case 'font-info': { |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 280 | const value = dataset.value; |
| 281 | if (!dataset.path) { |
| 282 | return; |
| 283 | } |
| 284 | |
| 285 | const [fontFamily, fontMetric] = dataset.path.split('/'); |
| 286 | if (!value) { |
| 287 | return; |
| 288 | } |
| 289 | |
| 290 | const fontFamilyInfo = this._data.fontInfo.get(fontFamily); |
| 291 | if (!fontFamilyInfo) { |
| 292 | return; |
| 293 | } |
| 294 | |
| 295 | const fontMetricInfo = fontFamilyInfo.get(fontMetric); |
| 296 | if (!fontMetricInfo) { |
| 297 | return; |
| 298 | } |
| 299 | |
| 300 | const nodesIds = /** @type {!Array<number>} */ (fontMetricInfo.get(value)); |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 301 | if (!nodesIds) { |
| 302 | return; |
| 303 | } |
| 304 | |
| 305 | const nodes = nodesIds.map(nodeId => ({nodeId})); |
| 306 | const name = `${value} (${fontFamily}, ${fontMetric})`; |
| 307 | payload = {type, name, nodes}; |
| 308 | break; |
| 309 | } |
| 310 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 311 | default: |
| 312 | return; |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 313 | } |
| 314 | |
| 315 | evt.consume(); |
Tim van der Lippe | 9d0cb5f | 2020-01-09 14:10:38 | [diff] [blame] | 316 | this._controller.dispatchEventToListeners(Events.PopulateNodes, payload); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 317 | this._mainContainer.setSidebarMinimized(false); |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 318 | } |
| 319 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 320 | /** |
| 321 | * @param {!Event} evt |
| 322 | */ |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 323 | _onMouseOver(evt) { |
| 324 | // Traverse the event path on the grid to find the nearest element with a backend node ID attached. Use |
| 325 | // that for the highlighting. |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 326 | const node = |
| 327 | (/** @type {!Array<!HTMLElement>} */ (evt.composedPath())).find(el => el.dataset && el.dataset.backendNodeId); |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 328 | if (!node) { |
| 329 | return; |
| 330 | } |
| 331 | |
| 332 | const backendNodeId = Number(node.dataset.backendNodeId); |
Tim van der Lippe | 9d0cb5f | 2020-01-09 14:10:38 | [diff] [blame] | 333 | this._controller.dispatchEventToListeners(Events.RequestNodeHighlight, backendNodeId); |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 334 | } |
| 335 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 336 | /** |
| 337 | * @param {!OverviewData} data |
| 338 | */ |
Paul Lewis | 8aef901 | 2019-10-29 14:15:17 | [diff] [blame] | 339 | async _render(data) { |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 340 | if (!data || !('backgroundColors' in data) || !('textColors' in data)) { |
| 341 | return; |
| 342 | } |
| 343 | |
| 344 | this._data = data; |
Paul Lewis | 8aef901 | 2019-10-29 14:15:17 | [diff] [blame] | 345 | const { |
| 346 | elementCount, |
| 347 | backgroundColors, |
| 348 | textColors, |
Alex Rudenko | d55e18c | 2020-09-23 11:37:06 | [diff] [blame] | 349 | textColorContrastIssues, |
Paul Lewis | 8aef901 | 2019-10-29 14:15:17 | [diff] [blame] | 350 | fillColors, |
| 351 | borderColors, |
| 352 | globalStyleStats, |
| 353 | mediaQueries, |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 354 | unusedDeclarations, |
| 355 | fontInfo |
Paul Lewis | 8aef901 | 2019-10-29 14:15:17 | [diff] [blame] | 356 | } = this._data; |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 357 | |
| 358 | // Convert rgb values from the computed styles to either undefined or HEX(A) strings. |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 359 | const sortedBackgroundColors = this._sortColorsByLuminance(backgroundColors); |
| 360 | const sortedTextColors = this._sortColorsByLuminance(textColors); |
Paul Lewis | 12bc63e | 2019-10-23 10:53:29 | [diff] [blame] | 361 | const sortedFillColors = this._sortColorsByLuminance(fillColors); |
| 362 | const sortedBorderColors = this._sortColorsByLuminance(borderColors); |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 363 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 364 | this._fragment = UI.Fragment.Fragment.build` |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 365 | <div class="vbox overview-completed-view"> |
Paul Lewis | 8aef901 | 2019-10-29 14:15:17 | [diff] [blame] | 366 | <div $="summary" class="results-section horizontally-padded summary"> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 367 | <h1>${ls`Overview summary`}</h1> |
| 368 | |
| 369 | <ul> |
| 370 | <li> |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 371 | <div class="label">${ls`Elements`}</div> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 372 | <div class="value">${this._formatter.format(elementCount)}</div> |
| 373 | </li> |
| 374 | <li> |
| 375 | <div class="label">${ls`External stylesheets`}</div> |
| 376 | <div class="value">${this._formatter.format(globalStyleStats.externalSheets)}</div> |
| 377 | </li> |
| 378 | <li> |
| 379 | <div class="label">${ls`Inline style elements`}</div> |
| 380 | <div class="value">${this._formatter.format(globalStyleStats.inlineStyles)}</div> |
| 381 | </li> |
| 382 | <li> |
| 383 | <div class="label">${ls`Style rules`}</div> |
| 384 | <div class="value">${this._formatter.format(globalStyleStats.styleRules)}</div> |
| 385 | </li> |
| 386 | <li> |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 387 | <div class="label">${ls`Media queries`}</div> |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 388 | <div class="value">${this._formatter.format(mediaQueries.size)}</div> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 389 | </li> |
| 390 | <li> |
| 391 | <div class="label">${ls`Type selectors`}</div> |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 392 | <div class="value">${this._formatter.format(globalStyleStats.stats.type)}</div> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 393 | </li> |
| 394 | <li> |
| 395 | <div class="label">${ls`ID selectors`}</div> |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 396 | <div class="value">${this._formatter.format(globalStyleStats.stats.id)}</div> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 397 | </li> |
| 398 | <li> |
| 399 | <div class="label">${ls`Class selectors`}</div> |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 400 | <div class="value">${this._formatter.format(globalStyleStats.stats.class)}</div> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 401 | </li> |
| 402 | <li> |
| 403 | <div class="label">${ls`Universal selectors`}</div> |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 404 | <div class="value">${this._formatter.format(globalStyleStats.stats.universal)}</div> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 405 | </li> |
| 406 | <li> |
| 407 | <div class="label">${ls`Attribute selectors`}</div> |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 408 | <div class="value">${this._formatter.format(globalStyleStats.stats.attribute)}</div> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 409 | </li> |
| 410 | <li> |
| 411 | <div class="label">${ls`Non-simple selectors`}</div> |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 412 | <div class="value">${this._formatter.format(globalStyleStats.stats.nonSimple)}</div> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 413 | </li> |
| 414 | </ul> |
| 415 | </div> |
| 416 | |
Paul Lewis | 8aef901 | 2019-10-29 14:15:17 | [diff] [blame] | 417 | <div $="colors" class="results-section horizontally-padded colors"> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 418 | <h1>${ls`Colors`}</h1> |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 419 | <h2>${ls`Background colors: ${sortedBackgroundColors.length}`}</h2> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 420 | <ul> |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 421 | ${sortedBackgroundColors.map(this._colorsToFragment.bind(this, 'background'))} |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 422 | </ul> |
| 423 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 424 | <h2>${ls`Text colors: ${sortedTextColors.length}`}</h2> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 425 | <ul> |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 426 | ${sortedTextColors.map(this._colorsToFragment.bind(this, 'text'))} |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 427 | </ul> |
Paul Lewis | 12bc63e | 2019-10-23 10:53:29 | [diff] [blame] | 428 | |
Alex Rudenko | d55e18c | 2020-09-23 11:37:06 | [diff] [blame] | 429 | ${textColorContrastIssues.size > 0 ? this._contrastIssuesToFragment(textColorContrastIssues) : ''} |
| 430 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 431 | <h2>${ls`Fill colors: ${sortedFillColors.length}`}</h2> |
Paul Lewis | 12bc63e | 2019-10-23 10:53:29 | [diff] [blame] | 432 | <ul> |
| 433 | ${sortedFillColors.map(this._colorsToFragment.bind(this, 'fill'))} |
| 434 | </ul> |
| 435 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 436 | <h2>${ls`Border colors: ${sortedBorderColors.length}`}</h2> |
Paul Lewis | 12bc63e | 2019-10-23 10:53:29 | [diff] [blame] | 437 | <ul> |
| 438 | ${sortedBorderColors.map(this._colorsToFragment.bind(this, 'border'))} |
| 439 | </ul> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 440 | </div> |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 441 | |
Paul Lewis | 66a15fc | 2019-11-07 11:17:11 | [diff] [blame] | 442 | <div $="font-info" class="results-section font-info"> |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 443 | <h1>${ls`Font info`}</h1> |
| 444 | ${ |
| 445 | fontInfo.size > 0 ? this._fontInfoToFragment(fontInfo) : |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 446 | UI.Fragment.Fragment.build`<div>${ls`There are no fonts.`}</div>`} |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 447 | </div> |
| 448 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 449 | <div $="unused-declarations" class="results-section unused-declarations"> |
| 450 | <h1>${ls`Unused declarations`}</h1> |
Paul Lewis | a3dcbf3 | 2019-10-29 14:41:51 | [diff] [blame] | 451 | ${ |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 452 | unusedDeclarations.size > 0 ? |
| 453 | this._groupToFragment(unusedDeclarations, 'unused-declarations', 'declaration') : |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 454 | UI.Fragment.Fragment.build`<div class="horizontally-padded">${ls`There are no unused declarations.`}</div>`} |
Paul Lewis | 8aef901 | 2019-10-29 14:15:17 | [diff] [blame] | 455 | </div> |
| 456 | |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 457 | <div $="media-queries" class="results-section media-queries"> |
| 458 | <h1>${ls`Media queries`}</h1> |
Paul Lewis | a3dcbf3 | 2019-10-29 14:41:51 | [diff] [blame] | 459 | ${ |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 460 | mediaQueries.size > 0 ? |
| 461 | this._groupToFragment(mediaQueries, 'media-queries', 'text') : |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 462 | UI.Fragment.Fragment.build`<div class="horizontally-padded">${ls`There are no media queries.`}</div>`} |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 463 | </div> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 464 | </div>`; |
| 465 | |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 466 | this._resultsContainer.element.appendChild(this._fragment.element()); |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 467 | } |
| 468 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 469 | /** |
| 470 | * @param {!Common.EventTarget.EventTargetEvent} evt |
| 471 | */ |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 472 | _createElementsView(evt) { |
| 473 | const {type, nodes} = evt.data; |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 474 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 475 | let id = ''; |
| 476 | let tabTitle = ''; |
| 477 | |
| 478 | switch (type) { |
Alex Rudenko | d55e18c | 2020-09-23 11:37:06 | [diff] [blame] | 479 | case 'contrast': { |
| 480 | const {section, key} = evt.data; |
| 481 | id = `${section}-${key}`; |
| 482 | tabTitle = ls`Contrast issues`; |
| 483 | break; |
| 484 | } |
| 485 | |
Mathias Bynens | 88e8f15 | 2020-03-25 14:33:12 | [diff] [blame] | 486 | case 'color': { |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 487 | const {section, color} = evt.data; |
| 488 | id = `${section}-${color}`; |
| 489 | tabTitle = `${color.toUpperCase()} (${section})`; |
| 490 | break; |
Mathias Bynens | 88e8f15 | 2020-03-25 14:33:12 | [diff] [blame] | 491 | } |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 492 | |
Mathias Bynens | 88e8f15 | 2020-03-25 14:33:12 | [diff] [blame] | 493 | case 'unused-declarations': { |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 494 | const {declaration} = evt.data; |
| 495 | id = `${declaration}`; |
| 496 | tabTitle = `${declaration}`; |
| 497 | break; |
Mathias Bynens | 88e8f15 | 2020-03-25 14:33:12 | [diff] [blame] | 498 | } |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 499 | |
Mathias Bynens | 88e8f15 | 2020-03-25 14:33:12 | [diff] [blame] | 500 | case 'media-queries': { |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 501 | const {text} = evt.data; |
| 502 | id = `${text}`; |
| 503 | tabTitle = `${text}`; |
| 504 | break; |
Mathias Bynens | 88e8f15 | 2020-03-25 14:33:12 | [diff] [blame] | 505 | } |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 506 | |
Mathias Bynens | 88e8f15 | 2020-03-25 14:33:12 | [diff] [blame] | 507 | case 'font-info': { |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 508 | const {name} = evt.data; |
| 509 | id = `${name}`; |
| 510 | tabTitle = `${name}`; |
| 511 | break; |
Mathias Bynens | 88e8f15 | 2020-03-25 14:33:12 | [diff] [blame] | 512 | } |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 513 | } |
| 514 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 515 | let view = this._viewMap.get(id); |
| 516 | if (!view) { |
Paul Lewis | 4da3b30 | 2019-11-21 14:23:47 | [diff] [blame] | 517 | view = new ElementDetailsView(this._controller, this._domModel, this._cssModel, this._linkifier); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 518 | view.populateNodes(nodes); |
| 519 | this._viewMap.set(id, view); |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 520 | } |
| 521 | |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 522 | this._elementContainer.appendTab(id, tabTitle, view, true); |
| 523 | } |
| 524 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 525 | /** |
| 526 | * @param {!FontInfo} fontInfo |
| 527 | */ |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 528 | _fontInfoToFragment(fontInfo) { |
| 529 | const fonts = Array.from(fontInfo.entries()); |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 530 | return UI.Fragment.Fragment.build` |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 531 | ${fonts.map(([font, fontMetrics]) => { |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 532 | return UI.Fragment.Fragment.build |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 533 | `<section class="font-family"><h2>${font}</h2> ${this._fontMetricsToFragment(font, fontMetrics)}</section>`; |
| 534 | })} |
| 535 | `; |
| 536 | } |
| 537 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 538 | /** |
| 539 | * @param {string} font |
| 540 | * @param {!Map<string, !Map<string, !Array<number>>>} fontMetrics |
| 541 | */ |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 542 | _fontMetricsToFragment(font, fontMetrics) { |
| 543 | const fontMetricInfo = Array.from(fontMetrics.entries()); |
| 544 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 545 | return UI.Fragment.Fragment.build` |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 546 | <div class="font-metric"> |
| 547 | ${fontMetricInfo.map(([label, values]) => { |
| 548 | const sanitizedPath = `${font}/${label}`; |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 549 | return UI.Fragment.Fragment.build` |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 550 | <div> |
| 551 | <h3>${label}</h3> |
| 552 | ${this._groupToFragment(values, 'font-info', 'value', sanitizedPath)} |
| 553 | </div>`; |
| 554 | })} |
| 555 | </div>`; |
| 556 | } |
| 557 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 558 | /** |
| 559 | * @param {!Map<string, !Array<number|!UnusedDeclaration|!Protocol.CSS.CSSMedia>>} items |
| 560 | * @param {string} type |
| 561 | * @param {string} dataLabel |
| 562 | * @param {string} path |
| 563 | */ |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 564 | _groupToFragment(items, type, dataLabel, path = '') { |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 565 | // Sort by number of items descending. |
| 566 | const values = Array.from(items.entries()).sort((d1, d2) => { |
| 567 | const v1Nodes = d1[1]; |
| 568 | const v2Nodes = d2[1]; |
| 569 | return v2Nodes.length - v1Nodes.length; |
| 570 | }); |
| 571 | |
| 572 | const total = values.reduce((prev, curr) => prev + curr[1].length, 0); |
| 573 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 574 | return UI.Fragment.Fragment.build`<ul> |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 575 | ${values.map(([title, nodes]) => { |
| 576 | const width = 100 * nodes.length / total; |
| 577 | const itemLabel = nodes.length === 1 ? ls`occurrence` : ls`occurrences`; |
| 578 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 579 | return UI.Fragment.Fragment.build`<li> |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 580 | <div class="title">${title}</div> |
Paul Lewis | 7d10a73 | 2019-11-06 16:11:51 | [diff] [blame] | 581 | <button data-type="${type}" data-path="${path}" data-${dataLabel}="${title}"> |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 582 | <div class="details">${ls`${nodes.length} ${itemLabel}`}</div> |
| 583 | <div class="bar-container"> |
| 584 | <div class="bar" style="width: ${width}%"></div> |
| 585 | </div> |
| 586 | </button> |
| 587 | </li>`; |
| 588 | })} |
| 589 | </ul>`; |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 590 | } |
| 591 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 592 | /** |
Alex Rudenko | d55e18c | 2020-09-23 11:37:06 | [diff] [blame] | 593 | * @param {!Map<string, !Array<!ContrastIssue>>} issues |
| 594 | */ |
| 595 | _contrastIssuesToFragment(issues) { |
| 596 | return UI.Fragment.Fragment.build` |
| 597 | <h2>${ls`Contrast issues: ${issues.size}`}</h2> |
| 598 | <ul> |
| 599 | ${[...issues.entries()].map(([key, value]) => this._contrastIssueToFragment(key, value))} |
| 600 | </ul> |
| 601 | `; |
| 602 | } |
| 603 | |
| 604 | /** |
| 605 | * @param {string} key |
| 606 | * @param {!Array<!ContrastIssue>} issues |
| 607 | */ |
| 608 | _contrastIssueToFragment(key, issues) { |
| 609 | console.assert(issues.length > 0); |
| 610 | |
| 611 | let minContrastIssue = issues[0]; |
| 612 | for (const issue of issues) { |
| 613 | if (issue.contrastRatio < minContrastIssue.contrastRatio) { |
| 614 | minContrastIssue = issue; |
| 615 | } |
| 616 | } |
| 617 | |
| 618 | const color = /** @type { string }*/ (minContrastIssue.textColor.asString(Common.Color.Format.HEXA)); |
| 619 | const backgroundColor = |
| 620 | /** @type { string }*/ (minContrastIssue.backgroundColor.asString(Common.Color.Format.HEXA)); |
| 621 | |
| 622 | const blockFragment = UI.Fragment.Fragment.build`<li> |
| 623 | <button |
| 624 | title="${ |
| 625 | ls`Text color ${color} over ${backgroundColor} background results in low contrast for ${ |
| 626 | issues.length} elements`}" |
| 627 | data-type="contrast" data-key="${key}" data-section="contrast" class="block" $="color"> |
| 628 | Text |
| 629 | </button> |
| 630 | <div class="block-title"> |
| 631 | <div class="contrast-warning" $="aa"><span class="threshold-label">${ls`AA`}</span></div> |
| 632 | <div class="contrast-warning" $="aaa"><span class="threshold-label">${ls`AAA`}</span></div> |
| 633 | </div> |
| 634 | </li>`; |
| 635 | |
| 636 | const aa = /** @type {!HTMLElement} */ (blockFragment.$('aa')); |
| 637 | if (minContrastIssue.thresholdsViolated.aa) { |
| 638 | aa.appendChild(UI.Icon.Icon.create('smallicon-no')); |
| 639 | } else { |
| 640 | aa.appendChild(UI.Icon.Icon.create('smallicon-checkmark-square')); |
| 641 | } |
| 642 | const aaa = /** @type {!HTMLElement} */ (blockFragment.$('aaa')); |
| 643 | if (minContrastIssue.thresholdsViolated.aaa) { |
| 644 | aaa.appendChild(UI.Icon.Icon.create('smallicon-no')); |
| 645 | } else { |
| 646 | aaa.appendChild(UI.Icon.Icon.create('smallicon-checkmark-square')); |
| 647 | } |
| 648 | |
| 649 | const block = /** @type {!HTMLElement} */ (blockFragment.$('color')); |
| 650 | block.style.backgroundColor = backgroundColor; |
| 651 | block.style.color = color; |
Alex Rudenko | d3ba0ee | 2020-09-25 14:01:21 | [diff] [blame] | 652 | block.style.border = getBorderString(minContrastIssue.backgroundColor); |
Alex Rudenko | d55e18c | 2020-09-23 11:37:06 | [diff] [blame] | 653 | |
| 654 | return blockFragment; |
| 655 | } |
| 656 | |
| 657 | /** |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 658 | * @param {string} section |
| 659 | * @param {string} color |
| 660 | */ |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 661 | _colorsToFragment(section, color) { |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 662 | const blockFragment = UI.Fragment.Fragment.build`<li> |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 663 | <button data-type="color" data-color="${color}" data-section="${section}" class="block" $="color"></button> |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 664 | <div class="block-title">${color}</div> |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 665 | </li>`; |
| 666 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 667 | const block = /** @type {!HTMLElement} */ (blockFragment.$('color')); |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 668 | block.style.backgroundColor = color; |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 669 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 670 | const borderColor = Common.Color.Color.parse(color); |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 671 | if (!borderColor) { |
| 672 | return; |
| 673 | } |
Alex Rudenko | d3ba0ee | 2020-09-25 14:01:21 | [diff] [blame] | 674 | block.style.border = getBorderString(borderColor); |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 675 | |
| 676 | return blockFragment; |
| 677 | } |
| 678 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 679 | /** |
| 680 | * @param {!NodeStyleStats} srcColors |
| 681 | */ |
Paul Lewis | de0224c | 2019-10-22 16:23:15 | [diff] [blame] | 682 | _sortColorsByLuminance(srcColors) { |
| 683 | return Array.from(srcColors.keys()).sort((colA, colB) => { |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 684 | const colorA = Common.Color.Color.parse(colA); |
| 685 | const colorB = Common.Color.Color.parse(colB); |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 686 | if (!colorA || !colorB) { |
| 687 | return 0; |
| 688 | } |
Alex Rudenko | 91403e7 | 2020-06-04 07:10:49 | [diff] [blame] | 689 | return Common.ColorUtils.luminance(colorB.rgba()) - Common.ColorUtils.luminance(colorA.rgba()); |
Paul Lewis | 8db3fa8 | 2019-10-10 11:55:53 | [diff] [blame] | 690 | }); |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 691 | } |
| 692 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 693 | /** |
| 694 | * @param {!OverviewData} data |
| 695 | */ |
Paul Lewis | 8cddf993 | 2019-09-27 16:40:07 | [diff] [blame] | 696 | setOverviewData(data) { |
| 697 | this._render(data); |
| 698 | } |
Paul Lewis | 4da3b30 | 2019-11-21 14:23:47 | [diff] [blame] | 699 | } |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 700 | |
Paul Lewis | 4da3b30 | 2019-11-21 14:23:47 | [diff] [blame] | 701 | CSSOverviewCompletedView.pushedNodes = new Set(); |
| 702 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 703 | export class DetailsView extends UI.Widget.VBox { |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 704 | constructor() { |
| 705 | super(); |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 706 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 707 | this._tabbedPane = new UI.TabbedPane.TabbedPane(); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 708 | this._tabbedPane.show(this.element); |
| 709 | this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabClosed, () => { |
| 710 | this.dispatchEventToListeners(UI.TabbedPane.Events.TabClosed, this._tabbedPane.tabIds().length); |
| 711 | }); |
| 712 | } |
| 713 | |
| 714 | /** |
| 715 | * @param {string} id |
| 716 | * @param {string} tabTitle |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 717 | * @param {!UI.Widget.Widget} view |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 718 | * @param {boolean=} isCloseable |
| 719 | */ |
| 720 | appendTab(id, tabTitle, view, isCloseable) { |
| 721 | if (!this._tabbedPane.hasTab(id)) { |
| 722 | this._tabbedPane.appendTab(id, tabTitle, view, undefined, undefined, isCloseable); |
| 723 | } |
| 724 | |
| 725 | this._tabbedPane.selectTab(id); |
| 726 | } |
| 727 | |
| 728 | closeTabs() { |
| 729 | this._tabbedPane.closeTabs(this._tabbedPane.tabIds()); |
| 730 | } |
Paul Lewis | 4da3b30 | 2019-11-21 14:23:47 | [diff] [blame] | 731 | } |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 732 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 733 | export class ElementDetailsView extends UI.Widget.Widget { |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 734 | /** |
| 735 | * @param {!OverviewController} controller |
| 736 | * @param {!SDK.DOMModel.DOMModel} domModel |
| 737 | * @param {!SDK.CSSModel.CSSModel} cssModel |
| 738 | * @param {!Components.Linkifier.Linkifier} linkifier |
| 739 | */ |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 740 | constructor(controller, domModel, cssModel, linkifier) { |
| 741 | super(); |
| 742 | |
| 743 | this._controller = controller; |
| 744 | this._domModel = domModel; |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 745 | this._cssModel = cssModel; |
| 746 | this._linkifier = linkifier; |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 747 | |
| 748 | this._elementGridColumns = [ |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 749 | { |
| 750 | id: 'nodeId', |
| 751 | title: ls`Element`, |
| 752 | sortable: true, |
| 753 | weight: 50, |
| 754 | titleDOMFragment: undefined, |
| 755 | sort: undefined, |
| 756 | align: undefined, |
Sigurd Schneider | 2533de1 | 2020-09-24 10:28:44 | [diff] [blame] | 757 | width: undefined, |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 758 | fixedWidth: undefined, |
| 759 | editable: undefined, |
| 760 | nonSelectable: undefined, |
| 761 | longText: undefined, |
| 762 | disclosure: undefined, |
| 763 | allowInSortByEvenWhenHidden: undefined, |
| 764 | dataType: undefined, |
| 765 | defaultWeight: undefined, |
| 766 | }, |
| 767 | { |
| 768 | id: 'declaration', |
| 769 | title: ls`Declaration`, |
| 770 | sortable: true, |
| 771 | weight: 50, |
| 772 | titleDOMFragment: undefined, |
| 773 | sort: undefined, |
| 774 | align: undefined, |
Sigurd Schneider | 2533de1 | 2020-09-24 10:28:44 | [diff] [blame] | 775 | width: undefined, |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 776 | fixedWidth: undefined, |
| 777 | editable: undefined, |
| 778 | nonSelectable: undefined, |
| 779 | longText: undefined, |
| 780 | disclosure: undefined, |
| 781 | allowInSortByEvenWhenHidden: undefined, |
| 782 | dataType: undefined, |
| 783 | defaultWeight: undefined, |
| 784 | }, |
| 785 | { |
| 786 | id: 'sourceURL', |
| 787 | title: ls`Source`, |
| 788 | sortable: false, |
| 789 | weight: 100, |
| 790 | titleDOMFragment: undefined, |
| 791 | sort: undefined, |
| 792 | align: undefined, |
Sigurd Schneider | 2533de1 | 2020-09-24 10:28:44 | [diff] [blame] | 793 | width: undefined, |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 794 | fixedWidth: undefined, |
| 795 | editable: undefined, |
| 796 | nonSelectable: undefined, |
| 797 | longText: undefined, |
| 798 | disclosure: undefined, |
| 799 | allowInSortByEvenWhenHidden: undefined, |
| 800 | dataType: undefined, |
| 801 | defaultWeight: undefined, |
| 802 | }, |
Alex Rudenko | d3ba0ee | 2020-09-25 14:01:21 | [diff] [blame] | 803 | { |
| 804 | id: 'contrastRatio', |
| 805 | title: ls`Contrast ratio`, |
| 806 | sortable: true, |
| 807 | weight: 25, |
| 808 | titleDOMFragment: undefined, |
| 809 | sort: undefined, |
| 810 | align: undefined, |
| 811 | width: undefined, |
| 812 | fixedWidth: undefined, |
| 813 | editable: undefined, |
| 814 | nonSelectable: undefined, |
| 815 | longText: undefined, |
| 816 | disclosure: undefined, |
| 817 | allowInSortByEvenWhenHidden: undefined, |
| 818 | dataType: undefined, |
| 819 | defaultWeight: undefined, |
| 820 | }, |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 821 | ]; |
| 822 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 823 | this._elementGrid = new DataGrid.SortableDataGrid.SortableDataGrid({ |
| 824 | displayName: ls`CSS Overview Elements`, |
| 825 | columns: this._elementGridColumns, |
| 826 | editCallback: undefined, |
| 827 | deleteCallback: undefined, |
| 828 | refreshCallback: undefined |
| 829 | }); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 830 | this._elementGrid.element.classList.add('element-grid'); |
| 831 | this._elementGrid.element.addEventListener('mouseover', this._onMouseOver.bind(this)); |
| 832 | this._elementGrid.setStriped(true); |
| 833 | this._elementGrid.addEventListener( |
| 834 | DataGrid.DataGrid.Events.SortingChanged, this._sortMediaQueryDataGrid.bind(this)); |
| 835 | |
| 836 | this.element.appendChild(this._elementGrid.element); |
| 837 | } |
| 838 | |
| 839 | _sortMediaQueryDataGrid() { |
| 840 | const sortColumnId = this._elementGrid.sortColumnId(); |
| 841 | if (!sortColumnId) { |
| 842 | return; |
| 843 | } |
| 844 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 845 | const comparator = DataGrid.SortableDataGrid.SortableDataGrid.StringComparator.bind(null, sortColumnId); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 846 | this._elementGrid.sortNodes(comparator, !this._elementGrid.isSortOrderAscending()); |
| 847 | } |
| 848 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 849 | /** |
| 850 | * @param {!Event} evt |
| 851 | */ |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 852 | _onMouseOver(evt) { |
| 853 | // Traverse the event path on the grid to find the nearest element with a backend node ID attached. Use |
| 854 | // that for the highlighting. |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 855 | const node = |
| 856 | (/** @type {!Array<!HTMLElement>} */ (evt.composedPath())).find(el => el.dataset && el.dataset.backendNodeId); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 857 | if (!node) { |
| 858 | return; |
| 859 | } |
| 860 | |
| 861 | const backendNodeId = Number(node.dataset.backendNodeId); |
Tim van der Lippe | 9d0cb5f | 2020-01-09 14:10:38 | [diff] [blame] | 862 | this._controller.dispatchEventToListeners(Events.RequestNodeHighlight, backendNodeId); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 863 | } |
| 864 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 865 | /** |
| 866 | * @param {!Array<!Object<string, *>>} data |
| 867 | */ |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 868 | async populateNodes(data) { |
| 869 | this._elementGrid.rootNode().removeChildren(); |
| 870 | |
| 871 | if (!data.length) { |
| 872 | return; |
| 873 | } |
| 874 | |
| 875 | const [firstItem] = data; |
Sigurd Schneider | 2ee231d | 2020-10-30 16:11:26 | [diff] [blame] | 876 | const visibility = new Set(); |
| 877 | firstItem.nodeId && visibility.add('nodeId'); |
| 878 | firstItem.declaration && visibility.add('declaration'); |
| 879 | firstItem.sourceURL && visibility.add('sourceURL'); |
| 880 | firstItem.contrastRatio && visibility.add('contrastRatio'); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 881 | |
| 882 | let relatedNodesMap; |
Sigurd Schneider | 2ee231d | 2020-10-30 16:11:26 | [diff] [blame] | 883 | if (visibility.has('nodeId')) { |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 884 | // Grab the nodes from the frontend, but only those that have not been |
| 885 | // retrieved already. |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 886 | const nodeIds = /** @type {!Set<number>} */ (data.reduce((prev, curr) => { |
Tim van der Lippe | 9d0cb5f | 2020-01-09 14:10:38 | [diff] [blame] | 887 | if (CSSOverviewCompletedView.pushedNodes.has(curr.nodeId)) { |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 888 | return prev; |
| 889 | } |
| 890 | |
Tim van der Lippe | 9d0cb5f | 2020-01-09 14:10:38 | [diff] [blame] | 891 | CSSOverviewCompletedView.pushedNodes.add(curr.nodeId); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 892 | return prev.add(curr.nodeId); |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 893 | }, new Set())); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 894 | relatedNodesMap = await this._domModel.pushNodesByBackendIdsToFrontend(nodeIds); |
| 895 | } |
| 896 | |
| 897 | for (const item of data) { |
Sigurd Schneider | 2ee231d | 2020-10-30 16:11:26 | [diff] [blame] | 898 | if (visibility.has('nodeId')) { |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 899 | if (!relatedNodesMap) { |
| 900 | continue; |
| 901 | } |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 902 | const frontendNode = relatedNodesMap.get(item.nodeId); |
| 903 | if (!frontendNode) { |
| 904 | continue; |
| 905 | } |
| 906 | |
| 907 | item.node = frontendNode; |
| 908 | } |
| 909 | |
Paul Lewis | 4da3b30 | 2019-11-21 14:23:47 | [diff] [blame] | 910 | const node = new ElementNode(this._elementGrid, item, this._linkifier, this._cssModel); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 911 | node.selectable = false; |
| 912 | this._elementGrid.insertChild(node); |
| 913 | } |
| 914 | |
| 915 | this._elementGrid.setColumnsVisiblity(visibility); |
| 916 | this._elementGrid.renderInline(); |
| 917 | this._elementGrid.wasShown(); |
| 918 | } |
Paul Lewis | 4da3b30 | 2019-11-21 14:23:47 | [diff] [blame] | 919 | } |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 920 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 921 | /** |
| 922 | * @extends {DataGrid.SortableDataGrid.SortableDataGridNode<!ElementNode>} |
| 923 | */ |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 924 | export class ElementNode extends DataGrid.SortableDataGrid.SortableDataGridNode { |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 925 | /** |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 926 | * @param {!DataGrid.SortableDataGrid.SortableDataGrid<!ElementNode>} dataGrid |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 927 | * @param {!Object<string,*>} data |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 928 | * @param {!Components.Linkifier.Linkifier} linkifier |
| 929 | * @param {!SDK.CSSModel.CSSModel} cssModel |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 930 | */ |
| 931 | constructor(dataGrid, data, linkifier, cssModel) { |
| 932 | super(dataGrid, data.hasChildren); |
| 933 | |
| 934 | this.data = data; |
| 935 | this._linkifier = linkifier; |
| 936 | this._cssModel = cssModel; |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 937 | } |
| 938 | |
| 939 | /** |
| 940 | * @override |
| 941 | * @param {string} columnId |
Sigurd Schneider | 1165791 | 2020-06-30 13:26:52 | [diff] [blame] | 942 | * @return {!HTMLElement} |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 943 | */ |
| 944 | createCell(columnId) { |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 945 | // Nodes. |
| 946 | if (columnId === 'nodeId') { |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 947 | const cell = this.createTD(columnId); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 948 | cell.textContent = '...'; |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 949 | |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 950 | Common.Linkifier.Linkifier.linkify(this.data.node).then(link => { |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 951 | cell.textContent = ''; |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 952 | /** @type {!HTMLElement} */ (link).dataset.backendNodeId = this.data.node.backendNodeId(); |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 953 | cell.appendChild(link); |
Alex Rudenko | b7419b7 | 2020-09-29 11:10:08 | [diff] [blame] | 954 | const button = document.createElement('button'); |
| 955 | button.classList.add('show-element'); |
| 956 | button.title = ls`Show element`; |
| 957 | button.tabIndex = 0; |
| 958 | button.onclick = () => this.data.node.scrollIntoView(); |
| 959 | cell.appendChild(button); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 960 | }); |
| 961 | return cell; |
| 962 | } |
| 963 | |
| 964 | // Links to CSS. |
| 965 | if (columnId === 'sourceURL') { |
| 966 | const cell = this.createTD(columnId); |
| 967 | |
| 968 | if (this.data.range) { |
| 969 | const link = this._linkifyRuleLocation( |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 970 | this._cssModel, this._linkifier, this.data.styleSheetId, |
| 971 | TextUtils.TextRange.TextRange.fromObject(this.data.range)); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 972 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 973 | if (!link || link.textContent === '') { |
Mathias Bynens | 23ee1aa | 2020-03-02 12:06:38 | [diff] [blame] | 974 | cell.textContent = '(unable to link)'; |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 975 | } else { |
| 976 | cell.appendChild(link); |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 977 | } |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 978 | } else { |
Paul Lewis | ed808ce | 2019-11-06 14:21:54 | [diff] [blame] | 979 | cell.textContent = '(unable to link to inlined styles)'; |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 980 | } |
| 981 | return cell; |
| 982 | } |
| 983 | |
Alex Rudenko | d3ba0ee | 2020-09-25 14:01:21 | [diff] [blame] | 984 | if (columnId === 'contrastRatio') { |
| 985 | const cell = this.createTD(columnId); |
| 986 | const contrastFragment = UI.Fragment.Fragment.build` |
| 987 | <div class="contrast-container-in-grid" $="container"> |
| 988 | <span class="contrast-preview" style="border: ${getBorderString(this.data.backgroundColor)}; color: ${ |
| 989 | this.data.textColor.asString()}; background-color: ${this.data.backgroundColor.asString()};">Aa</span> |
| 990 | <span>${this.data.contrastRatio.toFixed(2)}</span> |
| 991 | </div> |
| 992 | `; |
| 993 | const container = contrastFragment.$('container'); |
| 994 | container.append(UI.Fragment.Fragment.build`<span>${ls`AA`}</span>`.element()); |
| 995 | if (this.data.thresholdsViolated.aa) { |
| 996 | container.appendChild(UI.Icon.Icon.create('smallicon-no')); |
| 997 | } else { |
| 998 | container.appendChild(UI.Icon.Icon.create('smallicon-checkmark-square')); |
| 999 | } |
| 1000 | container.append(UI.Fragment.Fragment.build`<span>${ls`AAA`}</span>`.element()); |
| 1001 | if (this.data.thresholdsViolated.aaa) { |
| 1002 | container.appendChild(UI.Icon.Icon.create('smallicon-no')); |
| 1003 | } else { |
| 1004 | container.appendChild(UI.Icon.Icon.create('smallicon-checkmark-square')); |
| 1005 | } |
| 1006 | cell.appendChild(contrastFragment.element()); |
| 1007 | return cell; |
| 1008 | } |
| 1009 | |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 1010 | return super.createCell(columnId); |
| 1011 | } |
| 1012 | |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 1013 | /** |
| 1014 | * @param {!SDK.CSSModel.CSSModel} cssModel |
| 1015 | * @param {!Components.Linkifier.Linkifier} linkifier |
| 1016 | * @param {!Protocol.CSS.StyleSheetId} styleSheetId |
| 1017 | * @param {!TextUtils.TextRange.TextRange} ruleLocation |
| 1018 | */ |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 1019 | _linkifyRuleLocation(cssModel, linkifier, styleSheetId, ruleLocation) { |
| 1020 | const styleSheetHeader = cssModel.styleSheetHeaderForId(styleSheetId); |
Andres Olivares | 3dcefe4 | 2020-09-14 16:15:42 | [diff] [blame] | 1021 | if (!styleSheetHeader) { |
| 1022 | return; |
| 1023 | } |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 1024 | const lineNumber = styleSheetHeader.lineNumberInSource(ruleLocation.startLine); |
| 1025 | const columnNumber = styleSheetHeader.columnNumberInSource(ruleLocation.startLine, ruleLocation.startColumn); |
Tim van der Lippe | 7946bbc | 2020-02-13 13:58:42 | [diff] [blame] | 1026 | const matchingSelectorLocation = new SDK.CSSModel.CSSLocation(styleSheetHeader, lineNumber, columnNumber); |
Paul Lewis | ebc4719 | 2019-10-09 15:06:41 | [diff] [blame] | 1027 | return linkifier.linkifyCSSLocation(matchingSelectorLocation); |
| 1028 | } |
Paul Lewis | 4da3b30 | 2019-11-21 14:23:47 | [diff] [blame] | 1029 | } |