/* 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/. */ /* eslint valid-jsdoc: ["error", { "requireReturn": false }] */ // create namespace if (typeof Mozilla == "undefined") { var Mozilla = {}; } (function($) { "use strict"; // create namespace if (typeof Mozilla.UITour == "undefined") { /** * Library that exposes an event-based Web API for communicating with the * desktop browser chrome. It can be used for tasks such as opening menu * panels and highlighting the position of buttons in the toolbar. * *
For security/privacy reasons `Mozilla.UITour` will only work on a list of allowed * secure origins. The list of allowed origins can be found in * {@link https://dxr.mozilla.org/mozilla-central/source/browser/app/permissions| * browser/app/permissions}.
* * @since 29 * @namespace */ Mozilla.UITour = {}; } var themeIntervalId = null; function _stopCyclingThemes() { if (themeIntervalId) { clearInterval(themeIntervalId); themeIntervalId = null; } } function _sendEvent(action, data) { var event = new CustomEvent("mozUITour", { bubbles: true, detail: { action, data: data || {} } }); document.dispatchEvent(event); } function _generateCallbackID() { return Math.random().toString(36).replace(/[^a-z]+/g, ""); } function _waitForCallback(callback) { var id = _generateCallbackID(); function listener(event) { if (typeof event.detail != "object") return; if (event.detail.callbackID != id) return; document.removeEventListener("mozUITourResponse", listener); callback(event.detail.data); } document.addEventListener("mozUITourResponse", listener); return id; } var notificationListener = null; function _notificationListener(event) { if (typeof event.detail != "object") return; if (typeof notificationListener != "function") return; notificationListener(event.detail.event, event.detail.params); } Mozilla.UITour.DEFAULT_THEME_CYCLE_DELAY = 10 * 1000; Mozilla.UITour.CONFIGNAME_SYNC = "sync"; Mozilla.UITour.CONFIGNAME_AVAILABLETARGETS = "availableTargets"; /** * @typedef {String} Mozilla.UITour.Target * * @summary Not all targets are available at all times because they may not be visible * or UITour doesn't not how to automatically make them visible. Use *`Mozilla.UITour.getConfiguration('availableTargets', callback)` to determine
* which ones are available at a given time.
* @see Mozilla.UITour.getConfiguration
* @see Mozilla.UITour.showHighlight
* @see Mozilla.UITour.showInfo
*
* @description Valid values:`[...UITour.targets.keys()].join("\n* <li>")`
*/
/**
* Ensure the browser is ready to handle this document as a tour.
*
* @param {Function} [callback] Callback to call if UITour is working for the document.
* @since 35
*/
Mozilla.UITour.ping = function(callback) {
var data = {};
if (callback) {
data.callbackID = _waitForCallback(callback);
}
_sendEvent("ping", data);
};
/**
* @summary Register a listener to observe all UITour notifications.
*
* @description There can only be one observer per tour tab so calling this a second time will
* replace any previous `listener`.
* To remove an observer, call the method with `null` as the first argument.
*
* @param {?Function} listener - Called when any UITour notification occurs.
* @param {Function} [callback] - Called when the browser acknowledges the observer.
*/
Mozilla.UITour.observe = function(listener, callback) {
notificationListener = listener;
if (listener) {
document.addEventListener("mozUITourNotification",
_notificationListener);
Mozilla.UITour.ping(callback);
} else {
document.removeEventListener("mozUITourNotification",
_notificationListener);
}
};
/**
* Register an identifier to use in
* {@link https://wiki.mozilla.org/Telemetry|Telemetry}. `pageID` must be a
* string unique to the page/tour.
*
* @example
* Mozilla.UITour.registerPageID('firstrun-page-firefox-29');
*
* @param {string} pageID Unique identifier for the page/tour.
* @memberof Mozilla.UITour
*/
Mozilla.UITour.registerPageID = function(pageID) {
_sendEvent("registerPageID", {
pageID
});
};
/**
* @typedef {String} Mozilla.UITour.HighlightEffect
*
* Specifies the effect/animation to use when highlighting UI elements.
* @description Valid values:[...UITour.highlightEffects].join("\n* <li>")
* @see Mozilla.UITour.showHighlight
*/
/**
* Visually highlight a UI widget.
*
* @see Mozilla.UITour.hideHighlight
* @example Mozilla.UITour.showHighlight('appMenu', 'wobble');
*
* @param {Mozilla.UITour.Target} target - Identifier of the UI widget to show a highlight on.
* @param {Mozilla.UITour.HighlightEffect} [effect="none"] - Name of the effect to use when highlighting.
*/
Mozilla.UITour.showHighlight = function(target, effect) {
_sendEvent("showHighlight", {
target,
effect
});
};
/**
* Hide any visible UI highlight.
* @see Mozilla.UITour.showHighlight
*/
Mozilla.UITour.hideHighlight = function() {
_sendEvent("hideHighlight");
};
/**
* Show an arrow panel with optional images and buttons anchored at a specific UI target.
*
* @see Mozilla.UITour.hideInfo
*
* @param {Mozilla.UITour.Target} target - Identifier of the UI widget to anchor the panel at.
* @param {String} title - Title text to be shown as the heading of the panel.
* @param {String} text - Body text of the panel.
* @param {String} [icon=null] - URL of a 48x48px (96px @ 2dppx) image (which will be resolved
* relative to the tab's URI) to display in the panel.
* @param {Object[]} [buttons=[]] - Array of objects describing buttons.
* @param {String} buttons[].label - Button label
* @param {String} buttons[].icon - Button icon URL
* @param {String} buttons[].style - Button style ("primary" or "link")
* @param {Function} buttons[].callback - Called when the button is clicked
* @param {Object} [options={}] - Advanced options
* @param {Function} options.closeButtonCallback - Called when the panel's close button is clicked.
*
* @example
* var buttons = [
* {
* label: 'Cancel',
* style: 'link',
* callback: cancelBtnCallback
* },
* {
* label: 'Confirm',
* style: 'primary',
* callback: confirmBtnCallback
* }
* ];
*
* var icon = '//mozorg.cdn.mozilla.net/media/img/firefox/australis/logo.png';
*
* var options = {
* closeButtonCallback: closeBtnCallback
* };
*
* Mozilla.UITour.showInfo('appMenu', 'my title', 'my text', icon, buttons, options);
*/
Mozilla.UITour.showInfo = function(target, title, text, icon, buttons, options) {
var buttonData = [];
if (Array.isArray(buttons)) {
for (var i = 0; i < buttons.length; i++) {
buttonData.push({
label: buttons[i].label,
icon: buttons[i].icon,
style: buttons[i].style,
callbackID: _waitForCallback(buttons[i].callback)
});
}
}
var closeButtonCallbackID, targetCallbackID;
if (options && options.closeButtonCallback)
closeButtonCallbackID = _waitForCallback(options.closeButtonCallback);
if (options && options.targetCallback)
targetCallbackID = _waitForCallback(options.targetCallback);
_sendEvent("showInfo", {
target,
title,
text,
icon,
buttons: buttonData,
closeButtonCallbackID,
targetCallbackID
});
};
/**
* Hide any visible info panels.
* @see Mozilla.UITour.showInfo
*/
Mozilla.UITour.hideInfo = function() {
_sendEvent("hideInfo");
};
/**
* Preview a lightweight-theme applied to the browser UI.
*
* @see Mozilla.UITour.cycleThemes
* @see Mozilla.UITour.resetTheme
*
* @param {Object} theme - Theme object format expected by `LightweightThemeManager.previewTheme`
* @example
* var theme = {
* …
* "iconURL": "https://addons.mozilla.org/_files/…/preview_small.jpg",
* "headerURL": "https://addons.mozilla.org/_files/….jpg",
* "name": "My cool theme",
* "author": "Mozilla",
* "footer": "https://addons.mozilla.org/_files/….jpg",
* "previewURL": "https://addons.mozilla.org/_files/…/preview.jpg",
* "updateURL": "https://versioncheck.addons.mozilla.org/…",
* "accentcolor": "#000000",
* "header": "https://addons.mozilla.org/_files/….jpg",
* "version": "1.0",
* "detailURL": "https://addons.mozilla.org/firefox/addon/…",
* "textcolor": "#ffffff",
* "id": "18066",
* "description": "My awesome theme.",
* …
* };
*
* Mozilla.UITour.previewTheme(theme);
*/
Mozilla.UITour.previewTheme = function(theme) {
_stopCyclingThemes();
_sendEvent("previewTheme", {
theme: JSON.stringify(theme)
});
};
/**
* Stop previewing and cycling themes, returning to the user's previous theme.
* @see Mozilla.UITour.cycleThemes
* @see Mozilla.UITour.previewTheme
*/
Mozilla.UITour.resetTheme = function() {
_stopCyclingThemes();
_sendEvent("resetTheme");
};
/**
* Cycle between an array of themes using the given delay.
*
* @see Mozilla.UITour.previewTheme
* @see Mozilla.UITour.resetTheme
*
* @param {Object[]} themes - Array of themes
* @param {Number} [delay=Mozilla.UITour.DEFAULT_THEME_CYCLE_DELAY]
* - Time in milliseconds between rotating themes
* @param {Function} callback - Function called at each rotation
*/
Mozilla.UITour.cycleThemes = function(themes, delay, callback) {
_stopCyclingThemes();
if (!delay) {
delay = Mozilla.UITour.DEFAULT_THEME_CYCLE_DELAY;
}
function nextTheme() {
var theme = themes.shift();
themes.push(theme);
_sendEvent("previewTheme", {
theme: JSON.stringify(theme),
state: true
});
callback(theme);
}
themeIntervalId = setInterval(nextTheme, delay);
nextTheme();
};
/**
* @typedef {String} Mozilla.UITour.MenuName
* Valid values:Valid configuration names: