From 647c857c5f9f3cc780b6c2decd3cc0e8421f2ad3 Mon Sep 17 00:00:00 2001 From: Nicolas Chevobbe Date: Fri, 14 Jan 2022 10:21:14 +0000 Subject: [PATCH] Bug 1749550 - [devtools] Add distinct style to event badge in markup view when an event listener is disabled. r=ochameau. Differential Revision: https://phabricator.services.mozilla.com/D135680 --- .../test/browser_markup_events_toggle.js | 41 ++++++++++++++++++- .../markup/views/element-container.js | 14 +++++++ .../widgets/tooltip/EventTooltipHelper.js | 15 ++++++- devtools/client/themes/badge.css | 9 ++++ 4 files changed, 76 insertions(+), 3 deletions(-) diff --git a/devtools/client/inspector/markup/test/browser_markup_events_toggle.js b/devtools/client/inspector/markup/test/browser_markup_events_toggle.js index 4900b7904178..3eca0a5b7444 100644 --- a/devtools/client/inspector/markup/test/browser_markup_events_toggle.js +++ b/devtools/client/inspector/markup/test/browser_markup_events_toggle.js @@ -58,6 +58,10 @@ add_task(async function() { ["click [x]", "mousedown [x]", "mouseup [x]"], "The expected events are displayed, all enabled" ); + ok( + !eventTooltipBadge.classList.contains("has-disabled-events"), + "The event badge does not have the has-disabled-events class" + ); const [ clickHeader, @@ -72,11 +76,36 @@ add_task(async function() { ["click [x]", "mousedown []", "mouseup [x]"], "mousedown checkbox was unchecked" ); + ok( + eventTooltipBadge.classList.contains("has-disabled-events"), + "Unchecking an event applied the has-disabled-events class to the badge" + ); await safeSynthesizeMouseEventAtCenterInContentPage("#target"); data = await getTargetElementHandledEventData(); is(data.click, 2, `target handled another "click" event…`); is(data.mousedown, 1, `… but not a mousedown one`); + info( + "Check that the event badge style is reset when re-enabling all disabled events" + ); + await toggleEventListenerCheckbox(tooltip, mousedownHeader); + Assert.deepEqual( + getAsciiHeadersViz(tooltip), + ["click [x]", "mousedown [x]", "mouseup [x]"], + "mousedown checkbox is checked again" + ); + ok( + !eventTooltipBadge.classList.contains("has-disabled-events"), + "The event badge does not have the has-disabled-events class after re-enabling disabled event" + ); + info("Disable mousedown again for the rest of the test"); + await toggleEventListenerCheckbox(tooltip, mousedownHeader); + Assert.deepEqual( + getAsciiHeadersViz(tooltip), + ["click [x]", "mousedown []", "mouseup [x]"], + "mousedown checkbox is unchecked again" + ); + info("Uncheck the click event checkbox"); await toggleEventListenerCheckbox(tooltip, clickHeader); Assert.deepEqual( @@ -84,6 +113,10 @@ add_task(async function() { ["click []", "mousedown []", "mouseup [x]"], "click checkbox was unchecked" ); + ok( + eventTooltipBadge.classList.contains("has-disabled-events"), + "event badge still has the has-disabled-events class" + ); await safeSynthesizeMouseEventAtCenterInContentPage("#target"); data = await getTargetElementHandledEventData(); is(data.click, 2, `click event listener was disabled`); @@ -124,6 +157,10 @@ add_task(async function() { ["click []", "mousedown [x]", "mouseup []"], "mousedown checkbox is checked again" ); + ok( + eventTooltipBadge.classList.contains("has-disabled-events"), + "event badge still has the has-disabled-events class" + ); await safeSynthesizeMouseEventAtCenterInContentPage("#target"); data = await getTargetElementHandledEventData(); is(data.click, 2, `no additional "click" event were handled`); @@ -229,7 +266,9 @@ function getHeaderCheckbox(headerEl) { } async function toggleEventListenerCheckbox(tooltip, headerEl) { - const onEventToggled = tooltip.once("event-tooltip-listener-toggled"); + const onEventToggled = tooltip.eventTooltip.once( + "event-tooltip-listener-toggled" + ); const checkbox = getHeaderCheckbox(headerEl); const previousValue = checkbox.checked; EventUtils.synthesizeMouseAtCenter( diff --git a/devtools/client/inspector/markup/views/element-container.js b/devtools/client/inspector/markup/views/element-container.js index d8eceea5f306..08bc1c15babc 100644 --- a/devtools/client/inspector/markup/views/element-container.js +++ b/devtools/client/inspector/markup/views/element-container.js @@ -82,6 +82,20 @@ MarkupElementContainer.prototype = extend(MarkupContainer.prototype, { this.node ); + // Add specific styling to the "event" badge when at least one event is disabled. + // The eventTooltip will take care of clearing the event listener when it's destroyed. + eventTooltip.on( + "event-tooltip-listener-toggled", + ({ hasDisabledEventListeners }) => { + const className = "has-disabled-events"; + if (hasDisabledEventListeners) { + this.editor._eventBadge.classList.add(className); + } else { + this.editor._eventBadge.classList.remove(className); + } + } + ); + // Disable the image preview tooltip while we display the event details this.markup._disableImagePreviewTooltip(); tooltip.once("hidden", () => { diff --git a/devtools/client/shared/widgets/tooltip/EventTooltipHelper.js b/devtools/client/shared/widgets/tooltip/EventTooltipHelper.js index 8d563e691752..974dfd8752f5 100644 --- a/devtools/client/shared/widgets/tooltip/EventTooltipHelper.js +++ b/devtools/client/shared/widgets/tooltip/EventTooltipHelper.js @@ -11,11 +11,12 @@ const L10N = new LocalizationHelper( const Editor = require("devtools/client/shared/sourceeditor/editor"); const beautify = require("devtools/shared/jsbeautify/beautify"); +const EventEmitter = require("devtools/shared/event-emitter"); const XHTML_NS = "http://www.w3.org/1999/xhtml"; const CONTAINER_WIDTH = 500; -class EventTooltip { +class EventTooltip extends EventEmitter { /** * Set the content of a provided HTMLTooltip instance to display a list of event * listeners, with their event type, capturing argument and a link to the code @@ -31,6 +32,8 @@ class EventTooltip { * The nodeFront we're displaying event listeners for. */ constructor(tooltip, eventListenerInfos, toolbox, nodeFront) { + super(); + this._tooltip = tooltip; this._toolbox = toolbox; this._eventEditors = new WeakMap(); @@ -313,7 +316,14 @@ class EventTooltip { } else { await this._nodeFront.disableEventListener(id); } - this._tooltip.emitForTests("event-tooltip-listener-toggled"); + this.emit("event-tooltip-listener-toggled", { + hasDisabledEventListeners: + // No need to query the other checkboxes if the handled checkbox is unchecked + !checkbox.checked || + this._tooltip.doc.querySelector( + `input.event-tooltip-listener-toggle-checkbox:not(:checked)` + ) !== null, + }); } /** @@ -358,6 +368,7 @@ class EventTooltip { this._tooltip.eventTooltip = null; } + this.clearEvents(); if (this._eventListenersAbortController) { this._eventListenersAbortController.abort(); this._eventListenersAbortController = null; diff --git a/devtools/client/themes/badge.css b/devtools/client/themes/badge.css index 6c38ef028508..7a809a106671 100644 --- a/devtools/client/themes/badge.css +++ b/devtools/client/themes/badge.css @@ -91,3 +91,12 @@ background-color: var(--badge-scrollable-active-background-color); color: var(--theme-selection-color); } + +.inspector-badge.has-disabled-events { + font-style: italic; +} + +.inspector-badge.has-disabled-events::before { + content: "*"; + padding-inline-end: 2px; +}