#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 /** * This class represents a site that is contained in a cell and can be pinned, * moved around or deleted. */ function Site(aNode, aLink) { this._node = aNode; this._node._newtabSite = this; this._link = aLink; this._render(); this._addEventHandlers(); } Site.prototype = { /** * The site's DOM node. */ get node() this._node, /** * The site's link. */ get link() this._link, /** * The url of the site's link. */ get url() this.link.url, /** * The title of the site's link. */ get title() this.link.title, /** * The site's parent cell. */ get cell() { let parentNode = this.node.parentNode; return parentNode && parentNode._newtabCell; }, /** * Pins the site on its current or a given index. * @param aIndex The pinned index (optional). */ pin: function Site_pin(aIndex) { if (typeof aIndex == "undefined") aIndex = this.cell.index; this._updateAttributes(true); gPinnedLinks.pin(this._link, aIndex); }, /** * Unpins the site and calls the given callback when done. */ unpin: function Site_unpin() { if (this.isPinned()) { this._updateAttributes(false); gPinnedLinks.unpin(this._link); gUpdater.updateGrid(); } }, /** * Checks whether this site is pinned. * @return Whether this site is pinned. */ isPinned: function Site_isPinned() { return gPinnedLinks.isPinned(this._link); }, /** * Blocks the site (removes it from the grid) and calls the given callback * when done. */ block: function Site_block() { if (!gBlockedLinks.isBlocked(this._link)) { gUndoDialog.show(this); gBlockedLinks.block(this._link); gUpdater.updateGrid(); } }, /** * Gets the DOM node specified by the given query selector. * @param aSelector The query selector. * @return The DOM node we found. */ _querySelector: function Site_querySelector(aSelector) { return this.node.querySelector(aSelector); }, /** * Updates attributes for all nodes which status depends on this site being * pinned or unpinned. * @param aPinned Whether this site is now pinned or unpinned. */ _updateAttributes: function (aPinned) { let control = this._querySelector(".newtab-control-pin"); if (aPinned) { control.setAttribute("pinned", true); control.setAttribute("title", newTabString("unpin")); } else { control.removeAttribute("pinned"); control.setAttribute("title", newTabString("pin")); } }, /** * Renders the site's data (fills the HTML fragment). */ _render: function Site_render() { let url = this.url; let title = this.title || url; let tooltip = (title == url ? title : title + "\n" + url); let link = this._querySelector(".newtab-link"); link.setAttribute("title", tooltip); link.setAttribute("href", url); this._querySelector(".newtab-title").textContent = title; this.node.setAttribute("type", this.link.type); if (this.isPinned()) this._updateAttributes(true); // Capture the page if the thumbnail is missing, which will cause page.js // to be notified and call our refreshThumbnail() method. this.captureIfMissing(); // but still display whatever thumbnail might be available now. this.refreshThumbnail(); }, /** * Captures the site's thumbnail in the background, but only if there's no * existing thumbnail and the page allows background captures. */ captureIfMissing: function Site_captureIfMissing() { if (gPage.allowBackgroundCaptures && !this.link.imageURI) { BackgroundPageThumbs.captureIfMissing(this.url); } }, /** * Refreshes the thumbnail for the site. */ refreshThumbnail: function Site_refreshThumbnail() { let thumbnail = this._querySelector(".newtab-thumbnail"); if (this.link.bgColor) { thumbnail.style.backgroundColor = this.link.bgColor; } let uri = this.link.imageURI || PageThumbs.getThumbnailURL(this.url); thumbnail.style.backgroundImage = "url(" + uri + ")"; }, /** * Adds event handlers for the site and its buttons. */ _addEventHandlers: function Site_addEventHandlers() { // Register drag-and-drop event handlers. this._node.addEventListener("dragstart", this, false); this._node.addEventListener("dragend", this, false); this._node.addEventListener("mouseover", this, false); // Specially treat the sponsored icon to prevent regular hover effects let sponsored = this._querySelector(".newtab-control-sponsored"); sponsored.addEventListener("mouseover", () => { this.cell.node.setAttribute("ignorehover", "true"); }); sponsored.addEventListener("mouseout", () => { this.cell.node.removeAttribute("ignorehover"); }); }, /** * Speculatively opens a connection to the current site. */ _speculativeConnect: function Site_speculativeConnect() { let sc = Services.io.QueryInterface(Ci.nsISpeculativeConnect); let uri = Services.io.newURI(this.url, null, null); sc.speculativeConnect(uri, null); }, /** * Record interaction with site using telemetry. */ _recordSiteClicked: function Site_recordSiteClicked(aIndex) { if (Services.prefs.prefHasUserValue("browser.newtabpage.rows") || Services.prefs.prefHasUserValue("browser.newtabpage.columns") || aIndex > 8) { // 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); // Specially count clicks on directory tiles let typeIndex = DirectoryLinksProvider.linkTypes.indexOf(this.link.type); if (typeIndex != -1) { Services.telemetry.getHistogramById("NEWTAB_PAGE_DIRECTORY_TYPE_CLICKED") .add(typeIndex); } }, /** * Handles site click events. */ onClick: function Site_onClick(aEvent) { let {button, target} = aEvent; if (target.classList.contains("newtab-link") || target.parentElement.classList.contains("newtab-link")) { // Record for primary and middle clicks if (button == 0 || button == 1) { this._recordSiteClicked(this.cell.index); } return; } // Only handle primary clicks for the remaining targets if (button != 0) { return; } aEvent.preventDefault(); if (aEvent.target.classList.contains("newtab-control-block")) this.block(); else if (target.classList.contains("newtab-control-sponsored")) gPage.showSponsoredPanel(target); else if (this.isPinned()) this.unpin(); else this.pin(); }, /** * Handles all site events. */ handleEvent: function Site_handleEvent(aEvent) { switch (aEvent.type) { case "mouseover": this._node.removeEventListener("mouseover", this, false); this._speculativeConnect(); break; case "dragstart": gDrag.start(this, aEvent); break; case "dragend": gDrag.end(this, aEvent); break; } } };