Bug 941862 - UITour: Support a callback to notify when the menu panel opens while the menu button is an info panel target. r=Unfocused
--- a/browser/modules/UITour.jsm
+++ b/browser/modules/UITour.jsm
@@ -66,17 +66,27 @@ this.UITour = {
let statusButton = aDocument.getElementById("PanelUI-fxa-status");
return aDocument.getAnonymousElementByAttribute(statusButton,
"class",
"toolbarbutton-icon");
},
widgetName: "PanelUI-fxa-status",
}],
["addons", {query: "#add-ons-button"}],
- ["appMenu", {query: "#PanelUI-button"}],
+ ["appMenu", {
+ addTargetListener: (aDocument, aCallback) => {
+ let panelPopup = aDocument.getElementById("PanelUI-popup");
+ panelPopup.addEventListener("popupshown", aCallback);
+ },
+ query: "#PanelUI-button",
+ removeTargetListener: (aDocument, aCallback) => {
+ let panelPopup = aDocument.getElementById("PanelUI-popup");
+ panelPopup.removeEventListener("popupshown", aCallback);
+ },
+ }],
["backForward", {
query: "#back-button",
widgetName: "urlbar-container",
}],
["bookmarks", {query: "#bookmarks-menu-button"}],
["customize", {
query: (aDocument) => {
let customizeButton = aDocument.getElementById("PanelUI-customize");
@@ -324,16 +334,18 @@ this.UITour = {
}
}
}
let infoOptions = {};
if (typeof data.closeButtonCallbackID == "string")
infoOptions.closeButtonCallbackID = data.closeButtonCallbackID;
+ if (typeof data.targetCallbackID == "string")
+ infoOptions.targetCallbackID = data.targetCallbackID;
this.showInfo(contentDocument, target, data.title, data.text, iconURL, buttons, infoOptions);
}).then(null, Cu.reportError);
break;
}
case "hideInfo": {
this.hideInfo(window);
@@ -668,26 +680,30 @@ this.UITour = {
deferred.reject("The specified target name is not in the allowed set");
return deferred.promise;
}
let targetQuery = targetObject.query;
aWindow.PanelUI.ensureReady().then(() => {
if (typeof targetQuery == "function") {
deferred.resolve({
+ addTargetListener: targetObject.addTargetListener,
+ node: targetQuery(aWindow.document),
+ removeTargetListener: targetObject.removeTargetListener,
targetName: aTargetName,
- node: targetQuery(aWindow.document),
widgetName: targetObject.widgetName,
});
return;
}
deferred.resolve({
+ addTargetListener: targetObject.addTargetListener,
+ node: aWindow.document.querySelector(targetQuery),
+ removeTargetListener: targetObject.removeTargetListener,
targetName: aTargetName,
- node: aWindow.document.querySelector(targetQuery),
widgetName: targetObject.widgetName,
});
}).then(null, Cu.reportError);
return deferred.promise;
},
targetIsInAppMenu: function(aTarget) {
let placement = CustomizableUI.getPlacementOfWidget(aTarget.widgetName || aTarget.node.id);
@@ -928,19 +944,34 @@ this.UITour = {
let tooltipClose = document.getElementById("UITourTooltipClose");
let closeButtonCallback = (event) => {
this.hideInfo(document.defaultView);
if (aOptions && aOptions.closeButtonCallbackID)
this.sendPageCallback(aContentDocument, aOptions.closeButtonCallbackID);
};
tooltipClose.addEventListener("command", closeButtonCallback);
+
+ let targetCallback = (event) => {
+ let details = {
+ target: aAnchor.targetName,
+ type: event.type,
+ };
+ this.sendPageCallback(aContentDocument, aOptions.targetCallbackID, details);
+ };
+ if (aOptions.targetCallbackID && aAnchor.addTargetListener) {
+ aAnchor.addTargetListener(document, targetCallback);
+ }
+
tooltip.addEventListener("popuphiding", function tooltipHiding(event) {
tooltip.removeEventListener("popuphiding", tooltipHiding);
tooltipClose.removeEventListener("command", closeButtonCallback);
+ if (aOptions.targetCallbackID && aAnchor.removeTargetListener) {
+ aAnchor.removeTargetListener(document, targetCallback);
+ }
});
tooltip.setAttribute("targetName", aAnchor.targetName);
tooltip.hidden = false;
let alignment = "bottomcenter topright";
this._addAnnotationPanelMutationObserver(tooltip);
tooltip.openPopup(aAnchorEl, alignment);
}
--- a/browser/modules/test/browser_UITour3.js
+++ b/browser/modules/test/browser_UITour3.js
@@ -133,10 +133,26 @@ let tests = [
executeSoon(function() {
is(gContentWindow.callbackResult, "closeButton", "Close button callback called");
done();
});
});
let infoOptions = gContentWindow.makeInfoOptions();
gContentAPI.showInfo("urlbar", "Close me", "X marks the spot", null, null, infoOptions);
- }
+ },
+
+ function test_info_target_callback(done) {
+ let popup = document.getElementById("UITourTooltip");
+ popup.addEventListener("popupshown", function onPopupShown() {
+ popup.removeEventListener("popupshown", onPopupShown);
+ PanelUI.show().then(() => {
+ is(gContentWindow.callbackResult, "target", "target callback called");
+ is(gContentWindow.callbackData.target, "appMenu", "target callback was from the appMenu");
+ is(gContentWindow.callbackData.type, "popupshown", "target callback was from the mousedown");
+ done();
+ });
+ });
+
+ let infoOptions = gContentWindow.makeInfoOptions();
+ gContentAPI.showInfo("appMenu", "I want to know when the target is clicked", "*click*", null, null, infoOptions);
+ },
];
--- a/browser/modules/test/uitour.html
+++ b/browser/modules/test/uitour.html
@@ -1,34 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>UITour test</title>
<script type="application/javascript" src="uitour.js">
</script>
<script type="application/javascript">
- var callbackResult;
+ var callbackResult, callbackData;
function makeCallback(name) {
- return (function() {
+ return (function(data) {
callbackResult = name;
+ callbackData = data;
});
}
// Defined in content to avoid weird issues when crossing between chrome/content.
function makeButtons() {
return [
{label: "Button 1", callback: makeCallback("button1")},
{label: "Button 2", callback: makeCallback("button2"), icon: "image.png"}
];
}
function makeInfoOptions() {
return {
- closeButtonCallback: makeCallback("closeButton")
+ closeButtonCallback: makeCallback("closeButton"),
+ targetCallback: makeCallback("target"),
};
}
</script>
</head>
<body>
<h1>UITour tests</h1>
<p>Because Firefox is...</p>
<p>Never gonna let you down</p>
--- a/browser/modules/test/uitour.js
+++ b/browser/modules/test/uitour.js
@@ -85,27 +85,30 @@ if (typeof Mozilla == 'undefined') {
label: buttons[i].label,
icon: buttons[i].icon,
style: buttons[i].style,
callbackID: _waitForCallback(buttons[i].callback)
});
}
}
- var closeButtonCallbackID;
+ var closeButtonCallbackID, targetCallbackID;
if (options && options.closeButtonCallback)
closeButtonCallbackID = _waitForCallback(options.closeButtonCallback);
+ if (options && options.targetCallback)
+ targetCallbackID = _waitForCallback(options.targetCallback);
_sendEvent('showInfo', {
target: target,
title: title,
text: text,
icon: icon,
buttons: buttonData,
- closeButtonCallbackID: closeButtonCallbackID
+ closeButtonCallbackID: closeButtonCallbackID,
+ targetCallbackID: targetCallbackID
});
};
Mozilla.UITour.hideInfo = function() {
_sendEvent('hideInfo');
};
Mozilla.UITour.previewTheme = function(theme) {