1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var EXPORTED_SYMBOLS = ["UrlbarContextualTip"];
// These are global listeners; all instances of the contextual tip will
// have click listeners executed when their button or link is clicked.
let clickListeners = new Map([["button", new Set()], ["link", new Set()]]);
/**
* Calls all the click listeners for the specified element.
*
* @param {string} element Either "button" or "link"
* Corresponds to the button or link on the contextual tip.
* @param {object} window The window
*/
function callClickListeners(element, window) {
for (let clickListener of clickListeners.get(element)) {
clickListener(window);
}
}
/**
* Consumers of this class can create, set, remove, and hide a contextual tip.
*/
class UrlbarContextualTip {
/**
* Creates the contextual tip and sets it in the urlbar's view.
*
* @param {object} view The urlbar's view
*/
constructor(view) {
this.document = view.document;
this.view = view;
this._create();
}
/**
* Creates an empty contextual tip in the DOM.
*/
_create() {
this._elements = {};
const fragment = this.document.createDocumentFragment();
this._elements.container = this.document.createElement("div");
this._elements.container.id = "urlbar-contextual-tip";
this._elements.icon = this.document.createElement("div");
this._elements.icon.id = "urlbar-contextual-tip-icon";
this._elements.title = this.document.createElement("div");
this._elements.title.id = "urlbar-contextual-tip-title";
this._elements.button = this.document.createElement("button");
this._elements.button.id = "urlbar-contextual-tip-button";
this._elements.link = this.document.createElement("a");
this._elements.link.id = "urlbar-contextual-tip-link";
this._elements.container.appendChild(this._elements.icon);
this._elements.container.appendChild(this._elements.title);
this._elements.container.appendChild(this._elements.button);
this._elements.container.appendChild(this._elements.link);
fragment.appendChild(this._elements.container);
this.view.panel.prepend(fragment);
this._elements.button.addEventListener("click", () => {
callClickListeners("button", this.document.ownerGlobal);
});
this._elements.link.addEventListener("click", () => {
callClickListeners("link", this.document.ownerGlobal);
});
}
/**
* Removes the contextual tip from the DOM.
*/
remove() {
this._elements.container.remove();
this._elements = null;
}
/**
* Sets the icon, title, button's title, and link's title
* for the contextual tip.
*
* @param {object} details
* @param {string} details.title
* Main title displayed by the contextual tip.
* @param {string} [details.buttonTitle]
* Title of the button on the contextual tip.
* If omitted then the button will be hidden.
* @param {string} [details.linkTitle]
* Title of the link on the contextual tip.
* If omitted then the link will be hidden.
* @param {string} [details.iconStyle]
* A non-empty string of styles to add to the icon's style attribute.
* These styles set CSS variables to URLs of images;
* the CSS variables responsible for the icon's background image are
* the variable names containing `--webextension-contextual-tip-icon`
* in `browser/base/content/browser.css`.
* If ommited, no changes are made to the icon.
*/
set(details) {
let { iconStyle, title, buttonTitle, linkTitle } = details;
if (iconStyle) {
this._elements.icon.setAttribute("style", iconStyle);
}
this._elements.title.textContent = title;
this._elements.button.textContent = buttonTitle;
this._elements.button.classList.toggle("hidden", !buttonTitle);
this._elements.link.textContent = linkTitle;
this._elements.link.classList.toggle("hidden", !linkTitle);
// If the contextual tip is not visible, then we'll make it visible
this._elements.container.classList.remove("hidden");
}
/**
* Hides the contextual tip.
*/
hide() {
if (!this._elements.container.classList.contains("hidden")) {
this._elements.container.classList.add("hidden");
}
}
/**
* Add a click listener to the specified element (either a button or link)
* on all windows (both existing and new windows).
*
* @param {string} element
* The clickListener will be added to the specified element.
* Must be either "button" or "link".
* @param {function} clickListener
* The click listener to add to the specified element.
*/
static addClickListener(element, clickListener) {
clickListeners.get(element).add(clickListener);
}
/**
* Remove a click listener from the specified element (either a button or
* link) on all windows (both existing and new windows).
*
* @param {string} element
* The clickListener will be removed from the specified element.
* Must be either "button" or "link".
* @param {function} clickListener
* The click listener to remove from the specified element.
*/
static removeClickListener(element, clickListener) {
clickListeners.get(element).delete(clickListener);
}
}
|