Commit 193ed603 authored by Paul Lewis's avatar Paul Lewis Committed by Commit Bot

[DevTools] Adds media queries to CSS Overview

Bug: 1007284
Change-Id: I8c24adddf91da3bd621b61db6eac49233b8a1db4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1849671
Commit-Queue: Paul Lewis <aerotwist@chromium.org>
Reviewed-by: default avatarTim van der Lippe <tvanderlippe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704192}
parent f46729a8
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* @unrestricted * @unrestricted
*/ */
CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar { CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar {
constructor(controller) { constructor(controller, target) {
super('css_overview_completed_view'); super('css_overview_completed_view');
this.registerRequiredCSS('css_overview/cssOverviewCompletedView.css'); this.registerRequiredCSS('css_overview/cssOverviewCompletedView.css');
...@@ -18,8 +18,23 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar { ...@@ -18,8 +18,23 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar {
this.splitWidget().setSidebarWidget(this._sideBar); this.splitWidget().setSidebarWidget(this._sideBar);
this.splitWidget().setMainWidget(this._mainContainer); this.splitWidget().setMainWidget(this._mainContainer);
this._cssModel = target.model(SDK.CSSModel);
this._linkifier = new Components.Linkifier(/* maxLinkLength */ 20, /* useLinkDecorator */ true);
this._columns = [
{id: 'text', title: ls`Text`, visible: true, sortable: true, weight: 60},
{id: 'sourceURL', title: ls`Source`, visible: true, sortable: true, weight: 40}
];
this._mediaQueryGrid = new DataGrid.SortableDataGrid(this._columns);
this._mediaQueryGrid.element.classList.add('media-query-grid');
this._mediaQueryGrid.setStriped(true);
this._mediaQueryGrid.addEventListener(
DataGrid.DataGrid.Events.SortingChanged, this._sortMediaQueryDataGrid.bind(this));
this._sideBar.addItem(ls`Overview summary`, 'summary'); this._sideBar.addItem(ls`Overview summary`, 'summary');
this._sideBar.addItem(ls`Colors`, 'colors'); this._sideBar.addItem(ls`Colors`, 'colors');
this._sideBar.addItem(ls`Media queries`, 'media-queries');
this._sideBar.select('summary'); this._sideBar.select('summary');
this._sideBar.addEventListener(CssOverview.SidebarEvents.ItemSelected, this._sideBarItemSelected, this); this._sideBar.addEventListener(CssOverview.SidebarEvents.ItemSelected, this._sideBarItemSelected, this);
...@@ -28,6 +43,16 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar { ...@@ -28,6 +43,16 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar {
this._render({}); this._render({});
} }
_sortMediaQueryDataGrid() {
const sortColumnId = this._mediaQueryGrid.sortColumnId();
if (!sortColumnId) {
return;
}
const comparator = DataGrid.SortableDataGrid.StringComparator.bind(null, sortColumnId);
this._mediaQueryGrid.sortNodes(comparator, !this._mediaQueryGrid.isSortOrderAscending());
}
_sideBarItemSelected(event) { _sideBarItemSelected(event) {
const section = this._fragment.$(event.data); const section = this._fragment.$(event.data);
if (!section) { if (!section) {
...@@ -43,6 +68,7 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar { ...@@ -43,6 +68,7 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar {
_reset() { _reset() {
this._mainContainer.element.removeChildren(); this._mainContainer.element.removeChildren();
this._mediaQueryGrid.rootNode().removeChildren();
} }
_render(data) { _render(data) {
...@@ -50,7 +76,7 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar { ...@@ -50,7 +76,7 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar {
return; return;
} }
const {elementStyleStats, elementCount, backgroundColors, textColors, globalStyleStats} = data; const {elementStyleStats, elementCount, backgroundColors, textColors, globalStyleStats, mediaQueries} = data;
// Convert rgb values from the computed styles to either undefined or HEX(A) strings. // Convert rgb values from the computed styles to either undefined or HEX(A) strings.
const nonTransparentBackgroundColors = this._getNonTransparentColorStrings(backgroundColors); const nonTransparentBackgroundColors = this._getNonTransparentColorStrings(backgroundColors);
...@@ -79,8 +105,8 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar { ...@@ -79,8 +105,8 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar {
<div class="value">${this._formatter.format(globalStyleStats.styleRules)}</div> <div class="value">${this._formatter.format(globalStyleStats.styleRules)}</div>
</li> </li>
<li> <li>
<div class="label">${ls`Media rules`}</div> <div class="label">${ls`Media queries`}</div>
<div class="value">${this._formatter.format(globalStyleStats.mediaRules)}</div> <div class="value">${this._formatter.format(mediaQueries.length)}</div>
</li> </li>
<li> <li>
<div class="label">${ls`Type selectors`}</div> <div class="label">${ls`Type selectors`}</div>
...@@ -121,9 +147,24 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar { ...@@ -121,9 +147,24 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar {
${nonTransparentTextColors.map(this._colorsToFragment)} ${nonTransparentTextColors.map(this._colorsToFragment)}
</ul> </ul>
</div> </div>
<div $="media-queries" class="results-section media-queries">
<h1>${ls`Media queries`}</h1>
${this._mediaQueryGrid.element}
</div>
</div>`; </div>`;
// Media Queries.
for (const mediaQuery of mediaQueries) {
const mediaQueryNode = new CssOverview.CSSOverviewCompletedView.MediaQueryNode(
this._mediaQueryGrid, mediaQuery, this._cssModel, this._linkifier);
mediaQueryNode.selectable = false;
this._mediaQueryGrid.insertChild(mediaQueryNode);
}
this._mainContainer.element.appendChild(this._fragment.element()); this._mainContainer.element.appendChild(this._fragment.element());
this._mediaQueryGrid.renderInline();
this._mediaQueryGrid.wasShown();
} }
_colorsToFragment(color) { _colorsToFragment(color) {
...@@ -168,3 +209,49 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar { ...@@ -168,3 +209,49 @@ CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar {
this._render(data); this._render(data);
} }
}; };
CssOverview.CSSOverviewCompletedView.MediaQueryNode = class extends DataGrid.SortableDataGridNode {
/**
* @param {!DataGrid.SortableDataGrid} dataGrid
* @param {!Object<string,*>} mediaQueryData
* @param {!SDK.CSSModel} cssModel
* @param {!Components.Linkifier} linkifier
*/
constructor(dataGrid, mediaQueryData, cssModel, linkifier) {
super(dataGrid, mediaQueryData.hasChildren);
this.data = mediaQueryData;
this._cssModel = cssModel;
this._linkifier = linkifier;
}
/**
* @override
* @param {string} columnId
* @return {!Element}
*/
createCell(columnId) {
if (this.data.range && columnId === 'sourceURL') {
const cell = this.createTD(columnId);
const link = this._linkifyRuleLocation(
this._cssModel, this._linkifier, this.data.styleSheetId, TextUtils.TextRange.fromObject(this.data.range));
if (link.textContent !== '') {
cell.appendChild(link);
} else {
cell.textContent = `${this.data.sourceURL} (not available)`;
}
return cell;
}
return super.createCell(columnId);
}
_linkifyRuleLocation(cssModel, linkifier, styleSheetId, ruleLocation) {
const styleSheetHeader = cssModel.styleSheetHeaderForId(styleSheetId);
const lineNumber = styleSheetHeader.lineNumberInSource(ruleLocation.startLine);
const columnNumber = styleSheetHeader.columnNumberInSource(ruleLocation.startLine, ruleLocation.startColumn);
const matchingSelectorLocation = new SDK.CSSLocation(styleSheetHeader, lineNumber, columnNumber);
return linkifier.linkifyCSSLocation(matchingSelectorLocation);
}
};
...@@ -25,12 +25,17 @@ CssOverview.CSSOverviewModel = class extends SDK.SDKModel { ...@@ -25,12 +25,17 @@ CssOverview.CSSOverviewModel = class extends SDK.SDKModel {
return this._cssAgent.getComputedStyleForNode(nodeId); return this._cssAgent.getComputedStyleForNode(nodeId);
} }
async getMediaQueries() {
// Ignore media queries applied to stylesheets; instead only use declared media rules.
const queries = await this._cssAgent.getMediaQueries();
return queries.filter(query => query.source !== 'linkedSheet');
}
async getGlobalStylesheetStats() { async getGlobalStylesheetStats() {
// There are no ways to pull CSSOM values directly today, due to its unserializable format, // There are no ways to pull CSSOM values directly today, due to its unserializable format,
// so instead we execute some JS within the page that extracts the relevant data and send that instead. // so instead we execute some JS within the page that extracts the relevant data and send that instead.
const expression = `(function() { const expression = `(function() {
let styleRules = 0; let styleRules = 0;
let mediaRules = 0;
let inlineStyles = 0; let inlineStyles = 0;
let externalSheets = 0; let externalSheets = 0;
for (const { rules, href } of document.styleSheets) { for (const { rules, href } of document.styleSheets) {
...@@ -43,15 +48,12 @@ CssOverview.CSSOverviewModel = class extends SDK.SDKModel { ...@@ -43,15 +48,12 @@ CssOverview.CSSOverviewModel = class extends SDK.SDKModel {
for (const rule of rules) { for (const rule of rules) {
if ('selectorText' in rule) { if ('selectorText' in rule) {
styleRules++; styleRules++;
} else if ('conditionText' in rule) {
mediaRules++;
} }
} }
} }
return { return {
styleRules, styleRules,
mediaRules,
inlineStyles, inlineStyles,
externalSheets externalSheets
} }
......
...@@ -11,13 +11,14 @@ CssOverview.CSSOverviewPanel = class extends UI.Panel { ...@@ -11,13 +11,14 @@ CssOverview.CSSOverviewPanel = class extends UI.Panel {
this.registerRequiredCSS('css_overview/cssOverview.css'); this.registerRequiredCSS('css_overview/cssOverview.css');
this.element.classList.add('css-overview-panel'); this.element.classList.add('css-overview-panel');
const [model] = SDK.targetManager.models(CssOverview.CSSOverviewModel);
this._model = model;
this._controller = new CssOverview.OverviewController(); this._controller = new CssOverview.OverviewController();
this._startView = new CssOverview.CSSOverviewStartView(this._controller); this._startView = new CssOverview.CSSOverviewStartView(this._controller);
this._processingView = new CssOverview.CSSOverviewProcessingView(this._controller); this._processingView = new CssOverview.CSSOverviewProcessingView(this._controller);
this._completedView = new CssOverview.CSSOverviewCompletedView(this._controller); this._completedView = new CssOverview.CSSOverviewCompletedView(this._controller, model.target());
const [model] = SDK.targetManager.models(CssOverview.CSSOverviewModel);
this._model = model;
this._controller.addEventListener(CssOverview.Events.RequestOverviewStart, this._startOverview, this); this._controller.addEventListener(CssOverview.Events.RequestOverviewStart, this._startOverview, this);
this._controller.addEventListener(CssOverview.Events.RequestOverviewCancel, this._cancelOverview, this); this._controller.addEventListener(CssOverview.Events.RequestOverviewCancel, this._cancelOverview, this);
this._controller.addEventListener(CssOverview.Events.OverviewCompleted, this._overviewCompleted, this); this._controller.addEventListener(CssOverview.Events.OverviewCompleted, this._overviewCompleted, this);
...@@ -30,6 +31,7 @@ CssOverview.CSSOverviewPanel = class extends UI.Panel { ...@@ -30,6 +31,7 @@ CssOverview.CSSOverviewPanel = class extends UI.Panel {
this._backgroundColors = new Set(); this._backgroundColors = new Set();
this._textColors = new Set(); this._textColors = new Set();
this._fontSizes = new Map(); this._fontSizes = new Map();
this._mediaQueries = [];
this._elementCount = 0; this._elementCount = 0;
this._elementStyleStats = { this._elementStyleStats = {
// Simple. // Simple.
...@@ -43,7 +45,7 @@ CssOverview.CSSOverviewPanel = class extends UI.Panel { ...@@ -43,7 +45,7 @@ CssOverview.CSSOverviewPanel = class extends UI.Panel {
nonSimple: new Set() nonSimple: new Set()
}; };
this._cancelled = false; this._cancelled = false;
this._globalStyleStats = {styleRules: 0, mediaRules: 0, inlineStyles: 0, externalSheets: 0}; this._globalStyleStats = {styleRules: 0, inlineStyles: 0, externalSheets: 0};
this._renderInitialView(); this._renderInitialView();
} }
...@@ -73,7 +75,8 @@ CssOverview.CSSOverviewPanel = class extends UI.Panel { ...@@ -73,7 +75,8 @@ CssOverview.CSSOverviewPanel = class extends UI.Panel {
globalStyleStats: this._globalStyleStats, globalStyleStats: this._globalStyleStats,
elementStyleStats: this._elementStyleStats, elementStyleStats: this._elementStyleStats,
fontSizes: this._fontSizes, fontSizes: this._fontSizes,
elementCount: this._elementCount elementCount: this._elementCount,
mediaQueries: this._mediaQueries
}); });
} }
...@@ -92,6 +95,11 @@ CssOverview.CSSOverviewPanel = class extends UI.Panel { ...@@ -92,6 +95,11 @@ CssOverview.CSSOverviewPanel = class extends UI.Panel {
this._globalStyleStats = globalStyleStats; this._globalStyleStats = globalStyleStats;
} }
const mediaQueries = await this._model.getMediaQueries();
if (mediaQueries) {
this._mediaQueries = mediaQueries;
}
// 2. Get the total element count. // 2. Get the total element count.
this._elementCount = document.length; this._elementCount = document.length;
......
...@@ -46,6 +46,17 @@ ...@@ -46,6 +46,17 @@
font-weight: bold; font-weight: bold;
} }
.media-query-grid .header-container,
.media-query-grid .data-container,
.media-query-grid table.data {
position: relative;
}
.media-query-grid .data-container {
top: 0;
max-height: 400px;
}
.block { .block {
width: 65px; width: 65px;
height: 25px; height: 25px;
......
...@@ -27,9 +27,6 @@ ...@@ -27,9 +27,6 @@
<message name="IDS_DEVTOOLS_5d50889672f6f860d14f502de3de1957" desc="Title of colors subsection in the CSS Overview Panel"> <message name="IDS_DEVTOOLS_5d50889672f6f860d14f502de3de1957" desc="Title of colors subsection in the CSS Overview Panel">
Colors Colors
</message> </message>
<message name="IDS_DEVTOOLS_62d79b9db9edfb64bd8c538cb9ed0190" desc="Label for the number of media rules in the CSS Overview report">
Media rules
</message>
<message name="IDS_DEVTOOLS_6ad170a0581c9c116ca254758bd0c5b9" desc="Label for the number of ID selectors in the CSS Overview report"> <message name="IDS_DEVTOOLS_6ad170a0581c9c116ca254758bd0c5b9" desc="Label for the number of ID selectors in the CSS Overview report">
ID selectors ID selectors
</message> </message>
...@@ -57,6 +54,9 @@ ...@@ -57,6 +54,9 @@
<message name="IDS_DEVTOOLS_d4a993a4b0d13c2cc4ce9387af1604ce" desc="Label for the 'Clear overview' button in the CSS Overview report"> <message name="IDS_DEVTOOLS_d4a993a4b0d13c2cc4ce9387af1604ce" desc="Label for the 'Clear overview' button in the CSS Overview report">
Clear overview Clear overview
</message> </message>
<message name="IDS_DEVTOOLS_daee0f0fc555c02342c4e00a1dbf642a" desc="Label for the number of media rules in the CSS Overview report">
Media queries
</message>
<message name="IDS_DEVTOOLS_e9c6934e961dad71d311f68c679dfd3b" desc="Label for the capture button in the CSS Overview Panel"> <message name="IDS_DEVTOOLS_e9c6934e961dad71d311f68c679dfd3b" desc="Label for the capture button in the CSS Overview Panel">
Capture overview Capture overview
</message> </message>
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
"dependencies": [ "dependencies": [
"elements", "elements",
"ui", "ui",
"sdk" "sdk",
"data_grid"
], ],
"scripts": [ "scripts": [
"CSSOverviewController.js", "CSSOverviewController.js",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment