Files
tubestation/browser/base/content/newtab/intro.js
2015-05-13 12:23:48 -04:00

308 lines
11 KiB
JavaScript

#ifdef 0
/* 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/. */
#endif
const PREF_INTRO_SHOWN = "browser.newtabpage.introShown";
const PREF_UPDATE_INTRO_SHOWN = "browser.newtabpage.updateIntroShown";
// These consts indicate the type of intro/onboarding we show.
const WELCOME = "welcome";
const UPDATE = "update";
// The maximum paragraph ID listed for 'newtab.intro.paragraph'
// strings in newTab.properties
const MAX_PARAGRAPH_ID = 9;
const NUM_INTRO_PAGES = 3;
let gIntro = {
_enUSStrings: {
"newtab.intro.paragraph2": "In order to provide this service, Mozilla collects and uses certain analytics information relating to your use of the tiles in accordance with our %1$S.",
"newtab.intro.paragraph4": "You can turn off this feature by clicking the gear (%1$S) button and selecting 'Show blank page' in the %2$S menu.",
"newtab.intro.paragraph5": "New Tab will show the sites you visit most frequently, along with sites we think might be of interest to you. To get started, you'll see several sites from Mozilla.",
"newtab.intro.paragraph6": "You can %1$S or %2$S any site by using the controls available on rollover.",
"newtab.intro.paragraph7": "Some of the sites you will see may be suggested by Mozilla and may be sponsored by a Mozilla partner. We'll always indicate which sites are sponsored.",
"newtab.intro.paragraph8": "Firefox will only show sites that most closely match your interests on the Web. %1$S",
"newtab.intro.paragraph9": "Now when you open New Tab, you'll also see sites we think might be interesting to you.",
"newtab.intro.controls": "New Tab Controls",
"newtab.learn.link2": "More about New Tab",
"newtab.privacy.link2": "About your privacy",
"newtab.intro.remove": "remove",
"newtab.intro.pin": "pin",
"newtab.intro.header.welcome": "Welcome to New Tab on %1$S",
"newtab.intro.header.update": "New Tab got an update!",
"newtab.intro.skip": "Skip this",
"newtab.intro.continue": "Continue tour",
"newtab.intro.back": "Back",
"newtab.intro.next": "Next",
"newtab.intro.gotit": "Got it!",
"newtab.intro.firefox": "Firefox!"
},
_nodeIDSuffixes: [
"panel",
"what",
"mask",
"modal",
"numerical-progress",
"text",
"buttons",
"image",
"header",
"footer"
],
_imageTypes: {
COG : "cog",
PIN_REMOVE : "pin-remove",
SUGGESTED : "suggested"
},
/**
* The paragraphs & buttons to show on each page in the intros.
*
* _introPages.welcome and _introPages.update contain an array of
* indices of paragraphs to be used to lookup text in _paragraphs
* for each page of the intro.
*
* Similarly, _introPages.buttons is used to lookup text for buttons
* on each page of the intro.
*/
_introPages: {
"welcome": [[0,1],[2,3],[4,5]],
"update": [[6,5],[4,3],[0,1]],
"buttons": [["skip", "continue"],["back", "next"],["back", "gotit"]],
"welcome-images": ["cog", "pin-remove", "suggested"],
"update-images": ["suggested", "pin-remove", "cog"]
},
_paragraphs: [],
_nodes: {},
_images: {},
init: function() {
for (let idSuffix of this._nodeIDSuffixes) {
this._nodes[idSuffix] = document.getElementById("newtab-intro-" + idSuffix);
}
if (DirectoryLinksProvider.locale != "en-US") {
this._nodes.what.style.display = "block";
this._nodes.panel.addEventListener("popupshowing", e => this._setUpPanel());
this._nodes.panel.addEventListener("popuphidden", e => this._hidePanel());
this._nodes.what.addEventListener("click", e => this.showPanel());
}
},
_setImage: function(imageType) {
// Remove previously existing images, if any.
let currImageHolder = this._nodes.image;
while (currImageHolder.firstChild) {
currImageHolder.removeChild(currImageHolder.firstChild);
}
this._nodes.image.appendChild(this._images[imageType]);
},
_goToPage: function(pageNum) {
this._currPage = pageNum;
this._nodes["numerical-progress"].innerHTML = `${this._bold(pageNum + 1)} / ${NUM_INTRO_PAGES}`;
this._nodes["numerical-progress"].setAttribute("page", pageNum);
// Set the page's image
let imageType = this._introPages[this._onboardingType + "-images"][pageNum];
this._setImage(imageType);
// Set the paragraphs
let paragraphNodes = this._nodes.text.getElementsByTagName("p");
let paragraphIDs = this._introPages[this._onboardingType][pageNum];
paragraphIDs.forEach((arg, index) => {
paragraphNodes[index].innerHTML = this._paragraphs[arg];
});
// Set the buttons
let buttonNodes = this._nodes.buttons.getElementsByTagName("input");
let buttonIDs = this._introPages.buttons[pageNum];
buttonIDs.forEach((arg, index) => {
buttonNodes[index].setAttribute("value", this._newTabString("intro." + arg));
});
},
_bold: function(str) {
return `<strong>${str}</strong>`
},
_link: function(url, text) {
return `<a href="${url}" target="_blank">${text}</a>`;
},
_span: function(text, className) {
return `<span class="${className}">${text}</span>`;
},
_exitIntro: function() {
this._nodes.mask.style.opacity = 0;
this._nodes.mask.addEventListener("transitionend", () => {
this._nodes.mask.style.display = "none";
});
},
_back: function() {
if (this._currPage == 0) {
// We're on the first page so 'back' means exit.
this._exitIntro();
return;
}
this._goToPage(this._currPage - 1);
},
_next: function() {
if (this._currPage == (NUM_INTRO_PAGES - 1)) {
// We're on the last page so 'next' means exit.
this._exitIntro();
return;
}
this._goToPage(this._currPage + 1);
},
_generateImages: function() {
Object.keys(this._imageTypes).forEach(type => {
let image = "";
let imageClass = "";
switch (this._imageTypes[type]) {
case this._imageTypes.COG:
image = document.getElementById("newtab-customize-panel2").cloneNode(true);
image.removeAttribute("hidden");
image.removeAttribute("type");
image.classList.add("newtab-intro-image-customize");
break;
case this._imageTypes.PIN_REMOVE:
imageClass = "-hover";
// fall-through
case this._imageTypes.SUGGESTED:
image = document.createElementNS(HTML_NAMESPACE, "div");
image.classList.add("newtab-intro-cell-wrapper");
// Create the cell's inner HTML code.
image.innerHTML =
'<div class="newtab-intro-cell' + imageClass + '">' +
' <div class="newtab-site newtab-intro-image-tile" type="sponsored">' +
' <a class="newtab-link">' +
' <span class="newtab-thumbnail"/>' +
' <span class="newtab-title">Example Title</span>' +
' </a>' +
' <input type="button" class="newtab-control newtab-control-pin"/>' +
' <input type="button" class="newtab-control newtab-control-block"/>' + (imageClass ? "" :
' <span class="newtab-sponsored">SUGGESTED</span>') +
' </div>' +
'</div>';
break;
}
this._images[this._imageTypes[type]] = image;
});
},
_generateParagraphs: function() {
let customizeIcon = '<input type="button" class="newtab-control newtab-customize"/>';
let substringMappings = {
"2": [this._link(TILES_PRIVACY_LINK, newTabString("privacy.link"))],
"4": [customizeIcon, this._bold(this._newTabString("intro.controls"))],
"6": [this._bold(this._newTabString("intro.remove")), this._bold(this._newTabString("intro.pin"))],
"7": [this._link(TILES_INTRO_LINK, newTabString("learn.link"))],
"8": [this._link(TILES_INTRO_LINK, newTabString("learn.link"))]
}
for (let i = 1; i <= MAX_PARAGRAPH_ID; i++) {
try {
this._paragraphs.push(this._newTabString("intro.paragraph" + i, substringMappings[i]))
} catch (ex) {
// Paragraph with this ID doesn't exist so continue
}
}
},
_newTabString: function(str, substrArr) {
let regExp = /%[0-9]\$S/g;
let paragraph = this._enUSStrings["newtab." + str];
if (!paragraph) {
throw new Error("Paragraph doesn't exist");
}
let matches;
while ((matches = regExp.exec(paragraph)) !== null) {
let match = matches[0];
let index = match.charAt(1); // Get the digit in the regExp.
paragraph = paragraph.replace(match, substrArr[index - 1]);
}
return paragraph;
},
showIfNecessary: function() {
if (!Services.prefs.getBoolPref(PREF_INTRO_SHOWN)) {
this._onboardingType = WELCOME;
this.showPanel();
} else if (!Services.prefs.getBoolPref(PREF_UPDATE_INTRO_SHOWN) && DirectoryLinksProvider.locale == "en-US") {
this._onboardingType = UPDATE;
this.showPanel();
}
Services.prefs.setBoolPref(PREF_INTRO_SHOWN, true);
Services.prefs.setBoolPref(PREF_UPDATE_INTRO_SHOWN, true);
},
showPanel: function() {
if (DirectoryLinksProvider.locale != "en-US") {
// Point the panel at the 'what' link
this._nodes.panel.hidden = false;
this._nodes.panel.openPopup(this._nodes.what);
return;
}
this._nodes.mask.style.display = "block";
this._nodes.mask.style.opacity = 1;
if (!this._paragraphs.length) {
// It's our first time showing the panel. Do some initial setup
this._generateParagraphs();
this._generateImages();
}
this._goToPage(0);
// Header text
let boldSubstr = this._onboardingType == WELCOME ? this._span(this._newTabString("intro.firefox"), "bold") : "";
this._nodes.header.innerHTML = this._newTabString("intro.header." + this._onboardingType, [boldSubstr]);
// Footer links
let footerLinkNodes = this._nodes.footer.getElementsByTagName("li");
[this._link(TILES_INTRO_LINK, this._newTabString("learn.link2")),
this._link(TILES_PRIVACY_LINK, this._newTabString("privacy.link2")),
].forEach((arg, index) => {
footerLinkNodes[index].innerHTML = arg;
});
},
_setUpPanel: function() {
// Build the panel if necessary
if (this._nodes.panel.childNodes.length == 1) {
['<a href="' + TILES_INTRO_LINK + '">' + newTabString("learn.link") + "</a>",
'<a href="' + TILES_PRIVACY_LINK + '">' + newTabString("privacy.link") + "</a>",
'<input type="button" class="newtab-customize"/>',
].forEach((arg, index) => {
let paragraph = document.createElementNS(HTML_NAMESPACE, "p");
this._nodes.panel.appendChild(paragraph);
paragraph.innerHTML = newTabString("intro.paragraph" + (index + 1), [arg]);
});
}
},
_hidePanel: function() {
this._nodes.panel.hidden = true;
}
};