Bug 1143797 - Allow clicking on suggested explanation text to see overlay explaining the suggested tile. r=adw, a=sylvestre
authorMarina Samuel <msamuel@mozilla.com>
Thu, 26 Mar 2015 17:05:44 -0400
changeset 258194 65f2aa5f2dd7
parent 258193 56763fc69140
child 258195 745269d59b33
push id4619
push useredilee@gmail.com
push date2015-04-02 05:50 +0000
treeherdermozilla-beta@daf8a9291a9b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersadw, sylvestre
bugs1143797
milestone38.0
Bug 1143797 - Allow clicking on suggested explanation text to see overlay explaining the suggested tile. r=adw, a=sylvestre
browser/base/content/newtab/newTab.css
browser/base/content/newtab/sites.js
browser/modules/DirectoryLinksProvider.jsm
browser/modules/test/xpcshell/test_DirectoryLinksProvider.js
browser/themes/shared/newtab/newTab.inc.css
--- a/browser/base/content/newtab/newTab.css
+++ b/browser/base/content/newtab/newTab.css
@@ -257,38 +257,42 @@ input[type=button] {
   left: 0;
   right: auto;
 }
 
 .newtab-site:-moz-any([type=enhanced], [type=sponsored]) .newtab-sponsored {
   display: block;
 }
 
-.newtab-site[type=related] .newtab-suggested {
+.newtab-site[type=suggested] .newtab-suggested {
   display: table;
 }
 
 .sponsored-explain,
-.sponsored-explain a {
+.sponsored-explain a,
+.suggested-explain,
+.suggested-explain a {
   color: white;
 }
 
-.sponsored-explain {
+.sponsored-explain,
+.suggested-explain {
   background-color: rgba(51, 51, 51, 0.95);
   border-bottom-left-radius: 6px;
   border-bottom-right-radius: 6px;
   bottom: 0px;
   line-height: 20px;
   padding: 15px 10px;
   position: absolute;
   text-align: start;
 }
 
 #newtab-intro-panel input,
-.sponsored-explain input {
+.sponsored-explain input,
+.suggested-explain input {
   background-size: 18px;
   height: 18px;
   opacity: 1;
   pointer-events: none;
   position: static;
   width: 18px;
 }
 
--- a/browser/base/content/newtab/sites.js
+++ b/browser/base/content/newtab/sites.js
@@ -228,35 +228,40 @@ Site.prototype = {
       // We only want to get indices for the default configuration, everything
       // else goes in the same bucket.
       aIndex = 9;
     }
     Services.telemetry.getHistogramById("NEWTAB_PAGE_SITE_CLICKED")
                       .add(aIndex);
   },
 
-  _toggleSponsored: function() {
-    let button = this._querySelector(".newtab-sponsored");
+  _toggleLegalText: function(buttonClass, explanationTextClass) {
+    let button = this._querySelector(buttonClass);
     if (button.hasAttribute("active")) {
-      let explain = this._querySelector(".sponsored-explain");
+      let explain = this._querySelector(explanationTextClass);
       explain.parentNode.removeChild(explain);
 
       button.removeAttribute("active");
     }
     else {
       let explain = document.createElementNS(HTML_NAMESPACE, "div");
-      explain.className = "sponsored-explain";
+      explain.className = explanationTextClass.slice(1); // Slice off the first character, '.'
       this.node.appendChild(explain);
 
       let link = '<a href="' + TILES_EXPLAIN_LINK + '">' +
                  newTabString("learn.link") + "</a>";
       let type = this.node.getAttribute("type");
       let icon = '<input type="button" class="newtab-control newtab-' +
-                 (type == "sponsored" ? "control-block" : "customize") + '"/>';
-      explain.innerHTML = newTabString(type + ".explain", [icon, link]);
+                 (type == "enhanced" ? "customize" : "control-block") + '"/>';
+
+      if (type == "suggested") {
+        explain.innerHTML = `This site is suggested to you by Mozilla. You can remove it at any time by clicking the ${icon} button. ${link}`;
+      } else {
+        explain.innerHTML = newTabString(type + ".explain", [icon, link]);
+      }
 
       button.setAttribute("active", "true");
     }
   },
 
   /**
    * Handles site click events.
    */
@@ -274,34 +279,38 @@ Site.prototype = {
         this._recordSiteClicked(tileIndex);
         action = "click";
       }
     }
     // Handle sponsored explanation link click
     else if (target.parentElement.classList.contains("sponsored-explain")) {
       action = "sponsored_link";
     }
+    else if (target.parentElement.classList.contains("suggested-explain")) {
+      action = "suggested_link";
+    }
     // Only handle primary clicks for the remaining targets
     else if (button == 0) {
-      if (target.parentElement.classList.contains("newtab-suggested") ||
-          target.classList.contains("newtab-suggested")) {
-        // Suggested explanation text should do nothing when clicked and
-        // the link in the suggested explanation should act as default.
-        return;
-      }
       aEvent.preventDefault();
       if (target.classList.contains("newtab-control-block")) {
         this.block();
         action = "block";
       }
       else if (target.classList.contains("sponsored-explain") ||
                target.classList.contains("newtab-sponsored")) {
-        this._toggleSponsored();
+        this._toggleLegalText(".newtab-sponsored", ".sponsored-explain");
         action = "sponsored";
       }
+      else if (target.classList.contains("suggested-explain") ||
+               target.classList.contains("newtab-suggested-bounds") ||
+               target.parentElement.classList.contains("newtab-suggested-bounds") ||
+               target.classList.contains("newtab-suggested")) {
+        this._toggleLegalText(".newtab-suggested", ".suggested-explain");
+        action = "suggested";
+      }
       else if (pinned) {
         this.unpin();
         action = "unpin";
       }
       else {
         this.pin();
         action = "pin";
       }
--- a/browser/modules/DirectoryLinksProvider.jsm
+++ b/browser/modules/DirectoryLinksProvider.jsm
@@ -197,17 +197,17 @@ let DirectoryLinksProvider = {
   _removePrefsObserver: function DirectoryLinksProvider_removeObserver() {
     for (let pref in this._observedPrefs) {
       let prefName = this._observedPrefs[pref];
       Services.prefs.removeObserver(prefName, this);
     }
   },
 
   _cacheRelatedLinks: function(link) {
-    for (let relatedSite of link.related) {
+    for (let relatedSite of link.suggested) {
       let relatedMap = this._relatedLinks.get(relatedSite) || new Map();
       relatedMap.set(link.url, link);
       this._relatedLinks.set(relatedSite, relatedMap);
     }
   },
 
   _fetchAndCacheLinks: function DirectoryLinksProvider_fetchAndCacheLinks(uri) {
     // Replace with the same display locale used for selecting links data
@@ -425,17 +425,17 @@ let DirectoryLinksProvider = {
         // Stash the enhanced image for the site
         if (link.enhancedImageURI) {
           this._enhancedLinks.set(NewTabUtils.extractSite(link.url), link);
         }
         link.lastVisitDate = rawLinks.length - position;
 
         // We cache related tiles here but do not push any of them in the links list yet.
         // The decision for which related tile to include will be made separately.
-        if ("related" == link.type) {
+        if ("suggested" == link.type) {
           this._cacheRelatedLinks(link);
           return;
         }
         link.frecency = DIRECTORY_FRECENCY;
         links.push(link);
       });
       return links;
     }).catch(ex => {
@@ -537,22 +537,22 @@ let DirectoryLinksProvider = {
       return;
     }
 
     // Delete the current related tile, if one exists.
     let initialLength = sortedLinks.length;
     this.maxNumLinks = initialLength;
     if (initialLength) {
       let mostFrecentLink = sortedLinks[0];
-      if ("related" == mostFrecentLink.type) {
+      if ("suggested" == mostFrecentLink.type) {
         this._callObservers("onLinkChanged", {
           url: mostFrecentLink.url,
           frecency: 0,
           lastVisitDate: mostFrecentLink.lastVisitDate,
-          type: "related",
+          type: "suggested",
         }, 0, true);
       }
     }
 
     if (this._topSitesWithRelatedLinks.size == 0) {
       // There are no potential related links we can show.
       return;
     }
@@ -584,17 +584,17 @@ let DirectoryLinksProvider = {
     let chosenRelatedLink = flattenedLinks[relatedIndex];
 
     // Show the new directory tile.
     this._callObservers("onLinkChanged", {
       url: chosenRelatedLink.url,
       title: chosenRelatedLink.title,
       frecency: RELATED_FRECENCY,
       lastVisitDate: chosenRelatedLink.lastVisitDate,
-      type: "related",
+      type: "suggested",
 
       // Choose the first site a user has visited as the target. In the future,
       // this should be the site with the highest frecency. However, we currently
       // store frecency by URL not by site.
       targetedSite: targetedSites.get(chosenRelatedLink.url).length ?
         targetedSites.get(chosenRelatedLink.url)[0] : null
     });
     return chosenRelatedLink;
--- a/browser/modules/test/xpcshell/test_DirectoryLinksProvider.js
+++ b/browser/modules/test/xpcshell/test_DirectoryLinksProvider.js
@@ -58,41 +58,41 @@ kHttpHandlerData[kExamplePath] = {"en-US
 const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
                               "nsIBinaryInputStream",
                               "setInputStream");
 
 let gLastRequestPath;
 
 let relatedTile1 = {
   url: "http://turbotax.com",
-  type: "related",
+  type: "suggested",
   lastVisitDate: 4,
-  related: [
+  suggested: [
     "taxact.com",
     "hrblock.com",
     "1040.com",
     "taxslayer.com"
   ]
 };
 let relatedTile2 = {
   url: "http://irs.gov",
-  type: "related",
+  type: "suggested",
   lastVisitDate: 3,
-  related: [
+  suggested: [
     "taxact.com",
     "hrblock.com",
     "freetaxusa.com",
     "taxslayer.com"
   ]
 };
 let relatedTile3 = {
   url: "http://hrblock.com",
-  type: "related",
+  type: "suggested",
   lastVisitDate: 2,
-  related: [
+  suggested: [
     "taxact.com",
     "freetaxusa.com",
     "1040.com",
     "taxslayer.com"
   ]
 };
 let someOtherSite = {url: "http://someothersite.com", title: "Not_A_Related_Site"};
 
@@ -243,31 +243,31 @@ add_task(function test_updateRelatedTile
     this.promise = new Promise(resolve => {
       this.onLinkChanged = (directoryLinksProvider, link) => {
         links.unshift(link);
         let possibleLinks = [relatedTile1.url, relatedTile2.url, relatedTile3.url];
 
         isIdentical([...DirectoryLinksProvider._topSitesWithRelatedLinks], ["hrblock.com", "1040.com", "freetaxusa.com"]);
         do_check_true(possibleLinks.indexOf(link.url) > -1);
         do_check_eq(link.frecency, Infinity);
-        do_check_eq(link.type, "related");
+        do_check_eq(link.type, "suggested");
         resolve();
       };
     });
   }
 
   function TestChangingRelatedTile() {
     this.count = 0;
     this.promise = new Promise(resolve => {
       this.onLinkChanged = (directoryLinksProvider, link) => {
         this.count++;
         let possibleLinks = [relatedTile1.url, relatedTile2.url, relatedTile3.url];
 
         do_check_true(possibleLinks.indexOf(link.url) > -1);
-        do_check_eq(link.type, "related");
+        do_check_eq(link.type, "suggested");
         do_check_true(this.count <= 2);
 
         if (this.count == 1) {
           // The removed related link is the one we added initially.
           do_check_eq(link.url, links.shift().url);
           do_check_eq(link.frecency, 0);
         } else {
           links.unshift(link);
@@ -280,17 +280,17 @@ add_task(function test_updateRelatedTile
   }
 
   function TestRemovingRelatedTile() {
     this.count = 0;
     this.promise = new Promise(resolve => {
       this.onLinkChanged = (directoryLinksProvider, link) => {
         this.count++;
 
-        do_check_eq(link.type, "related");
+        do_check_eq(link.type, "suggested");
         do_check_eq(this.count, 1);
         do_check_eq(link.frecency, 0);
         do_check_eq(link.url, links.shift().url);
         isIdentical([...DirectoryLinksProvider._topSitesWithRelatedLinks], []);
         resolve();
       }
     });
   }
--- a/browser/themes/shared/newtab/newTab.inc.css
+++ b/browser/themes/shared/newtab/newTab.inc.css
@@ -137,16 +137,27 @@
 /* TITLES */
 #newtab-intro-what,
 .newtab-sponsored,
 .newtab-title,
 .newtab-suggested  {
   color: #5c5c5c;
 }
 
+.newtab-suggested:hover {
+  color: #588FE4;
+  border: 1px solid #588FE4;
+}
+
+.newtab-suggested[active] {
+  background-color: rgba(51, 51, 51, 0.95);
+  border: 0;
+  color: white;
+}
+
 .newtab-suggested {
   background-color: white;
 }
 
 .newtab-site:hover .newtab-title {
   color: #222;
 }