mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-10 05:08:36 +02:00
MozReview-Commit-ID: 3lIF2XGAwlj Depends on D18102 Differential Revision: https://phabricator.services.mozilla.com/D18103 --HG-- extra : moz-landing-system : lando
219 lines
7.3 KiB
JavaScript
219 lines
7.3 KiB
JavaScript
/* globals log, catcher, onboardingHtml, onboardingCss, util, shooter, callBackground, assertIsTrusted, assertIsBlankDocument */
|
|
|
|
"use strict";
|
|
|
|
this.slides = (function() {
|
|
const exports = {};
|
|
|
|
const { watchFunction } = catcher;
|
|
|
|
let iframe;
|
|
let doc;
|
|
let currentSlide = 1;
|
|
let numberOfSlides;
|
|
let callbacks;
|
|
|
|
exports.display = function(addCallbacks) {
|
|
if (iframe) {
|
|
throw new Error("Attemted to call slides.display() twice");
|
|
}
|
|
return new Promise((resolve, reject) => {
|
|
callbacks = addCallbacks;
|
|
// FIXME: a lot of this iframe logic is in ui.js; maybe move to util.js
|
|
iframe = document.createElement("iframe");
|
|
iframe.src = browser.extension.getURL("blank.html");
|
|
iframe.id = "firefox-screenshots-onboarding-iframe";
|
|
iframe.style.zIndex = "99999999999";
|
|
iframe.style.display = "block";
|
|
iframe.style.border = "none";
|
|
iframe.style.position = "fixed";
|
|
iframe.style.top = "0";
|
|
iframe.style.left = "0";
|
|
iframe.style.margin = "0";
|
|
iframe.style.backgroundColor = "transparent";
|
|
iframe.scrolling = "no";
|
|
updateIframeSize();
|
|
let html = onboardingHtml.replace("<style></style>", `<style>${onboardingCss}</style>`);
|
|
html = html.replace(/MOZ_EXTENSION([^"]+)/g, (match, filename) => {
|
|
return browser.extension.getURL(filename);
|
|
});
|
|
iframe.addEventListener("load", catcher.watchFunction(() => {
|
|
doc = iframe.contentDocument;
|
|
assertIsBlankDocument(doc);
|
|
const parsedDom = (new DOMParser()).parseFromString(
|
|
html,
|
|
"text/html"
|
|
);
|
|
doc.replaceChild(
|
|
doc.adoptNode(parsedDom.documentElement),
|
|
doc.documentElement
|
|
);
|
|
doc.addEventListener("keyup", onKeyUp);
|
|
doc.documentElement.dir = browser.i18n.getMessage("@@bidi_dir");
|
|
doc.documentElement.lang = browser.i18n.getMessage("@@ui_locale");
|
|
localizeText(doc);
|
|
activateSlide(doc);
|
|
// Give the DOM a moment to settle before applying focus
|
|
setTimeout(() => {
|
|
iframe.contentWindow.focus();
|
|
});
|
|
resolve();
|
|
}), {once: true});
|
|
document.body.appendChild(iframe);
|
|
window.addEventListener("resize", onResize);
|
|
});
|
|
};
|
|
|
|
exports.remove = exports.unload = function() {
|
|
window.removeEventListener("resize", onResize);
|
|
if (doc) {
|
|
doc.removeEventListener("keyup", onKeyUp);
|
|
}
|
|
util.removeNode(iframe);
|
|
iframe = doc = null;
|
|
currentSlide = 1;
|
|
numberOfSlides = undefined;
|
|
callbacks = undefined;
|
|
};
|
|
|
|
function localizeText(doc) {
|
|
let els = doc.querySelectorAll("[data-l10n-id]");
|
|
for (const el of els) {
|
|
const id = el.getAttribute("data-l10n-id");
|
|
const text = browser.i18n.getMessage(id);
|
|
el.textContent = text;
|
|
}
|
|
els = doc.querySelectorAll("[data-l10n-label-id]");
|
|
for (const el of els) {
|
|
const id = el.getAttribute("data-l10n-label-id");
|
|
const text = browser.i18n.getMessage(id);
|
|
el.setAttribute("aria-label", text);
|
|
}
|
|
// termsAndPrivacyNoticeCloudServices is a more complicated substitution:
|
|
const termsContainer = doc.querySelector(".onboarding-legal-notice");
|
|
termsContainer.innerHTML = "";
|
|
const termsSentinel = "__TERMS__";
|
|
const privacySentinel = "__PRIVACY__";
|
|
const sentinelSplitter = "!!!";
|
|
const linkTexts = {
|
|
[termsSentinel]: browser.i18n.getMessage("termsAndPrivacyNoticeTermsLink"),
|
|
[privacySentinel]: browser.i18n.getMessage("termsAndPrivacyNoticyPrivacyLink"),
|
|
};
|
|
const linkUrls = {
|
|
[termsSentinel]: "https://www.mozilla.org/about/legal/terms/services/",
|
|
[privacySentinel]: "https://www.mozilla.org/privacy/firefox/",
|
|
};
|
|
const text = browser.i18n.getMessage(
|
|
"termsAndPrivacyNotice2",
|
|
[sentinelSplitter + termsSentinel + sentinelSplitter,
|
|
sentinelSplitter + privacySentinel + sentinelSplitter]);
|
|
const parts = text.split(sentinelSplitter);
|
|
for (const part of parts) {
|
|
let el;
|
|
if (part === termsSentinel || part === privacySentinel) {
|
|
el = doc.createElement("a");
|
|
el.href = linkUrls[part];
|
|
el.textContent = linkTexts[part];
|
|
el.target = "_blank";
|
|
el.id = (part === termsSentinel) ? "terms" : "privacy";
|
|
} else {
|
|
el = doc.createTextNode(part);
|
|
}
|
|
termsContainer.appendChild(el);
|
|
}
|
|
}
|
|
|
|
function activateSlide(doc) {
|
|
numberOfSlides = parseInt(doc.querySelector("[data-number-of-slides]").getAttribute("data-number-of-slides"), 10);
|
|
doc.querySelector("#next").addEventListener("click", watchFunction(assertIsTrusted(() => {
|
|
shooter.sendEvent("navigate-slide", "next");
|
|
next();
|
|
})));
|
|
doc.querySelector("#prev").addEventListener("click", watchFunction(assertIsTrusted(() => {
|
|
shooter.sendEvent("navigate-slide", "prev");
|
|
prev();
|
|
})));
|
|
for (const el of doc.querySelectorAll(".goto-slide")) {
|
|
el.addEventListener("click", watchFunction(assertIsTrusted((event) => {
|
|
shooter.sendEvent("navigate-slide", "goto");
|
|
const el = event.target;
|
|
const index = parseInt(el.getAttribute("data-number"), 10);
|
|
setSlide(index);
|
|
})));
|
|
}
|
|
doc.querySelector("#skip").addEventListener("click", watchFunction(assertIsTrusted((event) => {
|
|
shooter.sendEvent("cancel-slides", "skip");
|
|
callbacks.onEnd();
|
|
})));
|
|
doc.querySelector("#done").addEventListener("click", watchFunction(assertIsTrusted((event) => {
|
|
shooter.sendEvent("finish-slides", "done");
|
|
callbacks.onEnd();
|
|
})));
|
|
doc.querySelector("#slide-overlay").addEventListener("click", watchFunction(assertIsTrusted((event) => {
|
|
if (event.target === doc.querySelector("#slide-overlay")) {
|
|
shooter.sendEvent("cancel-slides", "background-click");
|
|
callbacks.onEnd();
|
|
}
|
|
})));
|
|
setSlide(1);
|
|
}
|
|
|
|
function next() {
|
|
setSlide(currentSlide + 1);
|
|
}
|
|
|
|
function prev() {
|
|
setSlide(currentSlide - 1);
|
|
}
|
|
|
|
const onResize = catcher.watchFunction(function() {
|
|
if (!iframe) {
|
|
log.warn("slides onResize called when iframe is not setup");
|
|
return;
|
|
}
|
|
updateIframeSize();
|
|
});
|
|
|
|
function updateIframeSize() {
|
|
iframe.style.height = window.innerHeight + "px";
|
|
iframe.style.width = window.innerWidth + "px";
|
|
}
|
|
|
|
const onKeyUp = catcher.watchFunction(assertIsTrusted(function(event) {
|
|
if ((event.key || event.code) === "Escape") {
|
|
shooter.sendEvent("cancel-slides", "keyboard-escape");
|
|
callbacks.onEnd();
|
|
}
|
|
if ((event.key || event.code) === "ArrowRight") {
|
|
shooter.sendEvent("navigate-slide", "keyboard-arrowright");
|
|
next();
|
|
}
|
|
if ((event.key || event.code) === "ArrowLeft") {
|
|
shooter.sendEvent("navigate-slide", "keyboard-arrowleft");
|
|
prev();
|
|
}
|
|
}));
|
|
|
|
function setSlide(index) {
|
|
if (index < 1) {
|
|
index = 1;
|
|
}
|
|
if (index > numberOfSlides) {
|
|
index = numberOfSlides;
|
|
}
|
|
shooter.sendEvent("visited-slide", `slide-${index}`);
|
|
currentSlide = index;
|
|
const slideEl = doc.querySelector("#slide-container");
|
|
for (let i = 1; i <= numberOfSlides; i++) {
|
|
const className = `active-slide-${i}`;
|
|
if (i === currentSlide) {
|
|
slideEl.classList.add(className);
|
|
} else {
|
|
slideEl.classList.remove(className);
|
|
}
|
|
}
|
|
}
|
|
|
|
return exports;
|
|
})();
|
|
null;
|