summaryrefslogtreecommitdiffstats
path: root/components/newtab
diff options
context:
space:
mode:
Diffstat (limited to 'components/newtab')
-rw-r--r--components/newtab/cells.js126
-rw-r--r--components/newtab/drag.js151
-rw-r--r--components/newtab/dragDataHelper.js22
-rw-r--r--components/newtab/drop.js150
-rw-r--r--components/newtab/dropPreview.js222
-rw-r--r--components/newtab/dropTargetShim.js232
-rw-r--r--components/newtab/grid.js175
-rw-r--r--components/newtab/jar.mn8
-rw-r--r--components/newtab/moz.build8
-rw-r--r--components/newtab/newTab.css349
-rw-r--r--components/newtab/newTab.js69
-rw-r--r--components/newtab/newTab.xhtml61
-rw-r--r--components/newtab/page.js244
-rw-r--r--components/newtab/search.js134
-rw-r--r--components/newtab/sites.js353
-rw-r--r--components/newtab/transformations.js270
-rw-r--r--components/newtab/undo.js116
-rw-r--r--components/newtab/updater.js177
18 files changed, 0 insertions, 2867 deletions
diff --git a/components/newtab/cells.js b/components/newtab/cells.js
deleted file mode 100644
index 47d4ef5..0000000
--- a/components/newtab/cells.js
+++ /dev/null
@@ -1,126 +0,0 @@
-#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 manages a cell's DOM node (not the actually cell content, a site).
- * It's mostly read-only, i.e. all manipulation of both position and content
- * aren't handled here.
- */
-function Cell(aGrid, aNode) {
- this._grid = aGrid;
- this._node = aNode;
- this._node._newtabCell = this;
-
- // Register drag-and-drop event handlers.
- ["dragenter", "dragover", "dragexit", "drop"].forEach(function (aType) {
- this._node.addEventListener(aType, this, false);
- }, this);
-}
-
-Cell.prototype = {
- /**
- * The grid.
- */
- _grid: null,
-
- /**
- * The cell's DOM node.
- */
- get node() { return this._node; },
-
- /**
- * The cell's offset in the grid.
- */
- get index() {
- let index = this._grid.cells.indexOf(this);
-
- // Cache this value, overwrite the getter.
- Object.defineProperty(this, "index", {value: index, enumerable: true});
-
- return index;
- },
-
- /**
- * The previous cell in the grid.
- */
- get previousSibling() {
- let prev = this.node.previousElementSibling;
- prev = prev && prev._newtabCell;
-
- // Cache this value, overwrite the getter.
- Object.defineProperty(this, "previousSibling", {value: prev, enumerable: true});
-
- return prev;
- },
-
- /**
- * The next cell in the grid.
- */
- get nextSibling() {
- let next = this.node.nextElementSibling;
- next = next && next._newtabCell;
-
- // Cache this value, overwrite the getter.
- Object.defineProperty(this, "nextSibling", {value: next, enumerable: true});
-
- return next;
- },
-
- /**
- * The site contained in the cell, if any.
- */
- get site() {
- let firstChild = this.node.firstElementChild;
- return firstChild && firstChild._newtabSite;
- },
-
- /**
- * Checks whether the cell contains a pinned site.
- * @return Whether the cell contains a pinned site.
- */
- containsPinnedSite: function Cell_containsPinnedSite() {
- let site = this.site;
- return site && site.isPinned();
- },
-
- /**
- * Checks whether the cell contains a site (is empty).
- * @return Whether the cell is empty.
- */
- isEmpty: function Cell_isEmpty() {
- return !this.site;
- },
-
- /**
- * Handles all cell events.
- */
- handleEvent: function Cell_handleEvent(aEvent) {
- // We're not responding to external drag/drop events
- // when our parent window is in private browsing mode.
- if (inPrivateBrowsingMode() && !gDrag.draggedSite)
- return;
-
- if (aEvent.type != "dragexit" && !gDrag.isValid(aEvent))
- return;
-
- switch (aEvent.type) {
- case "dragenter":
- aEvent.preventDefault();
- gDrop.enter(this, aEvent);
- break;
- case "dragover":
- aEvent.preventDefault();
- break;
- case "dragexit":
- gDrop.exit(this, aEvent);
- break;
- case "drop":
- aEvent.preventDefault();
- gDrop.drop(this, aEvent);
- break;
- }
- }
-};
diff --git a/components/newtab/drag.js b/components/newtab/drag.js
deleted file mode 100644
index e3928eb..0000000
--- a/components/newtab/drag.js
+++ /dev/null
@@ -1,151 +0,0 @@
-#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 singleton implements site dragging functionality.
- */
-var gDrag = {
- /**
- * The site offset to the drag start point.
- */
- _offsetX: null,
- _offsetY: null,
-
- /**
- * The site that is dragged.
- */
- _draggedSite: null,
- get draggedSite() { return this._draggedSite; },
-
- /**
- * The cell width/height at the point the drag started.
- */
- _cellWidth: null,
- _cellHeight: null,
- get cellWidth() { return this._cellWidth; },
- get cellHeight() { return this._cellHeight; },
-
- /**
- * Start a new drag operation.
- * @param aSite The site that's being dragged.
- * @param aEvent The 'dragstart' event.
- */
- start: function Drag_start(aSite, aEvent) {
- this._draggedSite = aSite;
-
- // Mark nodes as being dragged.
- let selector = ".newtab-site, .newtab-control, .newtab-thumbnail";
- let parentCell = aSite.node.parentNode;
- let nodes = parentCell.querySelectorAll(selector);
- for (let i = 0; i < nodes.length; i++)
- nodes[i].setAttribute("dragged", "true");
-
- parentCell.setAttribute("dragged", "true");
-
- this._setDragData(aSite, aEvent);
-
- // Store the cursor offset.
- let node = aSite.node;
- let rect = node.getBoundingClientRect();
- this._offsetX = aEvent.clientX - rect.left;
- this._offsetY = aEvent.clientY - rect.top;
-
- // Store the cell dimensions.
- let cellNode = aSite.cell.node;
- this._cellWidth = cellNode.offsetWidth;
- this._cellHeight = cellNode.offsetHeight;
-
- gTransformation.freezeSitePosition(aSite);
- },
-
- /**
- * Handles the 'drag' event.
- * @param aSite The site that's being dragged.
- * @param aEvent The 'drag' event.
- */
- drag: function Drag_drag(aSite, aEvent) {
- // Get the viewport size.
- let {clientWidth, clientHeight} = document.documentElement;
-
- // We'll want a padding of 5px.
- let border = 5;
-
- // Enforce minimum constraints to keep the drag image inside the window.
- let left = Math.max(scrollX + aEvent.clientX - this._offsetX, border);
- let top = Math.max(scrollY + aEvent.clientY - this._offsetY, border);
-
- // Enforce maximum constraints to keep the drag image inside the window.
- left = Math.min(left, scrollX + clientWidth - this.cellWidth - border);
- top = Math.min(top, scrollY + clientHeight - this.cellHeight - border);
-
- // Update the drag image's position.
- gTransformation.setSitePosition(aSite, {left: left, top: top});
- },
-
- /**
- * Ends the current drag operation.
- * @param aSite The site that's being dragged.
- * @param aEvent The 'dragend' event.
- */
- end: function Drag_end(aSite, aEvent) {
- let nodes = gGrid.node.querySelectorAll("[dragged]")
- for (let i = 0; i < nodes.length; i++)
- nodes[i].removeAttribute("dragged");
-
- // Slide the dragged site back into its cell (may be the old or the new cell).
- gTransformation.slideSiteTo(aSite, aSite.cell, {unfreeze: true});
-
- this._draggedSite = null;
- },
-
- /**
- * Checks whether we're responsible for a given drag event.
- * @param aEvent The drag event to check.
- * @return Whether we should handle this drag and drop operation.
- */
- isValid: function Drag_isValid(aEvent) {
- let link = gDragDataHelper.getLinkFromDragEvent(aEvent);
-
- // Check that the drag data is non-empty.
- // Can happen when dragging places folders.
- if (!link || !link.url) {
- return false;
- }
-
- // Check that we're not accepting URLs which would inherit the caller's
- // principal (such as javascript: or data:).
- return gLinkChecker.checkLoadURI(link.url);
- },
-
- /**
- * Initializes the drag data for the current drag operation.
- * @param aSite The site that's being dragged.
- * @param aEvent The 'dragstart' event.
- */
- _setDragData: function Drag_setDragData(aSite, aEvent) {
- let {url, title} = aSite;
-
- let dt = aEvent.dataTransfer;
- dt.mozCursor = "default";
- dt.effectAllowed = "move";
- dt.setData("text/plain", url);
- dt.setData("text/uri-list", url);
- dt.setData("text/x-moz-url", url + "\n" + title);
- dt.setData("text/html", "<a href=\"" + url + "\">" + url + "</a>");
-
- // Create and use an empty drag element. We don't want to use the default
- // drag image with its default opacity.
- let dragElement = document.createElementNS(HTML_NAMESPACE, "div");
- dragElement.classList.add("newtab-drag");
- let scrollbox = document.getElementById("newtab-vertical-margin");
- scrollbox.appendChild(dragElement);
- dt.setDragImage(dragElement, 0, 0);
-
- // After the 'dragstart' event has been processed we can remove the
- // temporary drag element from the DOM.
- setTimeout(() => scrollbox.removeChild(dragElement), 0);
- }
-};
diff --git a/components/newtab/dragDataHelper.js b/components/newtab/dragDataHelper.js
deleted file mode 100644
index 675ff26..0000000
--- a/components/newtab/dragDataHelper.js
+++ /dev/null
@@ -1,22 +0,0 @@
-#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
-
-var gDragDataHelper = {
- get mimeType() {
- return "text/x-moz-url";
- },
-
- getLinkFromDragEvent: function DragDataHelper_getLinkFromDragEvent(aEvent) {
- let dt = aEvent.dataTransfer;
- if (!dt || !dt.types.includes(this.mimeType)) {
- return null;
- }
-
- let data = dt.getData(this.mimeType) || "";
- let [url, title] = data.split(/[\r\n]+/);
- return {url: url, title: title};
- }
-};
diff --git a/components/newtab/drop.js b/components/newtab/drop.js
deleted file mode 100644
index 7486524..0000000
--- a/components/newtab/drop.js
+++ /dev/null
@@ -1,150 +0,0 @@
-#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
-
-// A little delay that prevents the grid from being too sensitive when dragging
-// sites around.
-const DELAY_REARRANGE_MS = 100;
-
-/**
- * This singleton implements site dropping functionality.
- */
-var gDrop = {
- /**
- * The last drop target.
- */
- _lastDropTarget: null,
-
- /**
- * Handles the 'dragenter' event.
- * @param aCell The drop target cell.
- */
- enter: function Drop_enter(aCell) {
- this._delayedRearrange(aCell);
- },
-
- /**
- * Handles the 'dragexit' event.
- * @param aCell The drop target cell.
- * @param aEvent The 'dragexit' event.
- */
- exit: function Drop_exit(aCell, aEvent) {
- if (aEvent.dataTransfer && !aEvent.dataTransfer.mozUserCancelled) {
- this._delayedRearrange();
- } else {
- // The drag operation has been cancelled.
- this._cancelDelayedArrange();
- this._rearrange();
- }
- },
-
- /**
- * Handles the 'drop' event.
- * @param aCell The drop target cell.
- * @param aEvent The 'dragexit' event.
- */
- drop: function Drop_drop(aCell, aEvent) {
- // The cell that is the drop target could contain a pinned site. We need
- // to find out where that site has gone and re-pin it there.
- if (aCell.containsPinnedSite())
- this._repinSitesAfterDrop(aCell);
-
- // Pin the dragged or insert the new site.
- this._pinDraggedSite(aCell, aEvent);
-
- this._cancelDelayedArrange();
-
- // Update the grid and move all sites to their new places.
- gUpdater.updateGrid();
- },
-
- /**
- * Re-pins all pinned sites in their (new) positions.
- * @param aCell The drop target cell.
- */
- _repinSitesAfterDrop: function Drop_repinSitesAfterDrop(aCell) {
- let sites = gDropPreview.rearrange(aCell);
-
- // Filter out pinned sites.
- let pinnedSites = sites.filter(function (aSite) {
- return aSite && aSite.isPinned();
- });
-
- // Re-pin all shifted pinned cells.
- pinnedSites.forEach(aSite => aSite.pin(sites.indexOf(aSite)));
- },
-
- /**
- * Pins the dragged site in its new place.
- * @param aCell The drop target cell.
- * @param aEvent The 'dragexit' event.
- */
- _pinDraggedSite: function Drop_pinDraggedSite(aCell, aEvent) {
- let index = aCell.index;
- let draggedSite = gDrag.draggedSite;
-
- if (draggedSite) {
- // Pin the dragged site at its new place.
- if (aCell != draggedSite.cell)
- draggedSite.pin(index);
- } else {
- let link = gDragDataHelper.getLinkFromDragEvent(aEvent);
- if (link) {
- // A new link was dragged onto the grid. Create it by pinning its URL.
- gPinnedLinks.pin(link, index);
-
- // Make sure the newly added link is not blocked.
- gBlockedLinks.unblock(link);
- }
- }
- },
-
- /**
- * Time a rearrange with a little delay.
- * @param aCell The drop target cell.
- */
- _delayedRearrange: function Drop_delayedRearrange(aCell) {
- // The last drop target didn't change so there's no need to re-arrange.
- if (this._lastDropTarget == aCell)
- return;
-
- let self = this;
-
- function callback() {
- self._rearrangeTimeout = null;
- self._rearrange(aCell);
- }
-
- this._cancelDelayedArrange();
- this._rearrangeTimeout = setTimeout(callback, DELAY_REARRANGE_MS);
-
- // Store the last drop target.
- this._lastDropTarget = aCell;
- },
-
- /**
- * Cancels a timed rearrange, if any.
- */
- _cancelDelayedArrange: function Drop_cancelDelayedArrange() {
- if (this._rearrangeTimeout) {
- clearTimeout(this._rearrangeTimeout);
- this._rearrangeTimeout = null;
- }
- },
-
- /**
- * Rearrange all sites in the grid depending on the current drop target.
- * @param aCell The drop target cell.
- */
- _rearrange: function Drop_rearrange(aCell) {
- let sites = gGrid.sites;
-
- // We need to rearrange the grid only if there's a current drop target.
- if (aCell)
- sites = gDropPreview.rearrange(aCell);
-
- gTransformation.rearrangeSites(sites, {unfreeze: !aCell});
- }
-};
diff --git a/components/newtab/dropPreview.js b/components/newtab/dropPreview.js
deleted file mode 100644
index fd7587a..0000000
--- a/components/newtab/dropPreview.js
+++ /dev/null
@@ -1,222 +0,0 @@
-#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 singleton provides the ability to re-arrange the current grid to
- * indicate the transformation that results from dropping a cell at a certain
- * position.
- */
-var gDropPreview = {
- /**
- * Rearranges the sites currently contained in the grid when a site would be
- * dropped onto the given cell.
- * @param aCell The drop target cell.
- * @return The re-arranged array of sites.
- */
- rearrange: function DropPreview_rearrange(aCell) {
- let sites = gGrid.sites;
-
- // Insert the dragged site into the current grid.
- this._insertDraggedSite(sites, aCell);
-
- // After the new site has been inserted we need to correct the positions
- // of all pinned tabs that have been moved around.
- this._repositionPinnedSites(sites, aCell);
-
- return sites;
- },
-
- /**
- * Inserts the currently dragged site into the given array of sites.
- * @param aSites The array of sites to insert into.
- * @param aCell The drop target cell.
- */
- _insertDraggedSite: function DropPreview_insertDraggedSite(aSites, aCell) {
- let dropIndex = aCell.index;
- let draggedSite = gDrag.draggedSite;
-
- // We're currently dragging a site.
- if (draggedSite) {
- let dragCell = draggedSite.cell;
- let dragIndex = dragCell.index;
-
- // Move the dragged site into its new position.
- if (dragIndex != dropIndex) {
- aSites.splice(dragIndex, 1);
- aSites.splice(dropIndex, 0, draggedSite);
- }
- // We're handling an external drag item.
- } else {
- aSites.splice(dropIndex, 0, null);
- }
- },
-
- /**
- * Correct the position of all pinned sites that might have been moved to
- * different positions after the dragged site has been inserted.
- * @param aSites The array of sites containing the dragged site.
- * @param aCell The drop target cell.
- */
- _repositionPinnedSites:
- function DropPreview_repositionPinnedSites(aSites, aCell) {
-
- // Collect all pinned sites.
- let pinnedSites = this._filterPinnedSites(aSites, aCell);
-
- // Correct pinned site positions.
- pinnedSites.forEach(function (aSite) {
- aSites[aSites.indexOf(aSite)] = aSites[aSite.cell.index];
- aSites[aSite.cell.index] = aSite;
- }, this);
-
- // There might be a pinned cell that got pushed out of the grid, try to
- // sneak it in by removing a lower-priority cell.
- if (this._hasOverflowedPinnedSite(aSites, aCell))
- this._repositionOverflowedPinnedSite(aSites, aCell);
- },
-
- /**
- * Filter pinned sites out of the grid that are still on their old positions
- * and have not moved.
- * @param aSites The array of sites to filter.
- * @param aCell The drop target cell.
- * @return The filtered array of sites.
- */
- _filterPinnedSites: function DropPreview_filterPinnedSites(aSites, aCell) {
- let draggedSite = gDrag.draggedSite;
-
- // When dropping on a cell that contains a pinned site make sure that all
- // pinned cells surrounding the drop target are moved as well.
- let range = this._getPinnedRange(aCell);
-
- return aSites.filter(function (aSite, aIndex) {
- // The site must be valid, pinned and not the dragged site.
- if (!aSite || aSite == draggedSite || !aSite.isPinned())
- return false;
-
- let index = aSite.cell.index;
-
- // If it's not in the 'pinned range' it's a valid pinned site.
- return (index > range.end || index < range.start);
- });
- },
-
- /**
- * Determines the range of pinned sites surrounding the drop target cell.
- * @param aCell The drop target cell.
- * @return The range of pinned cells.
- */
- _getPinnedRange: function DropPreview_getPinnedRange(aCell) {
- let dropIndex = aCell.index;
- let range = {start: dropIndex, end: dropIndex};
-
- // We need a pinned range only when dropping on a pinned site.
- if (aCell.containsPinnedSite()) {
- let links = gPinnedLinks.links;
-
- // Find all previous siblings of the drop target that are pinned as well.
- while (range.start && links[range.start - 1])
- range.start--;
-
- let maxEnd = links.length - 1;
-
- // Find all next siblings of the drop target that are pinned as well.
- while (range.end < maxEnd && links[range.end + 1])
- range.end++;
- }
-
- return range;
- },
-
- /**
- * Checks if the given array of sites contains a pinned site that has
- * been pushed out of the grid.
- * @param aSites The array of sites to check.
- * @param aCell The drop target cell.
- * @return Whether there is an overflowed pinned cell.
- */
- _hasOverflowedPinnedSite:
- function DropPreview_hasOverflowedPinnedSite(aSites, aCell) {
-
- // If the drop target isn't pinned there's no way a pinned site has been
- // pushed out of the grid so we can just exit here.
- if (!aCell.containsPinnedSite())
- return false;
-
- let cells = gGrid.cells;
-
- // No cells have been pushed out of the grid, nothing to do here.
- if (aSites.length <= cells.length)
- return false;
-
- let overflowedSite = aSites[cells.length];
-
- // Nothing to do if the site that got pushed out of the grid is not pinned.
- return (overflowedSite && overflowedSite.isPinned());
- },
-
- /**
- * We have a overflowed pinned site that we need to re-position so that it's
- * visible again. We try to find a lower-priority cell (empty or containing
- * an unpinned site) that we can move it to.
- * @param aSites The array of sites.
- * @param aCell The drop target cell.
- */
- _repositionOverflowedPinnedSite:
- function DropPreview_repositionOverflowedPinnedSite(aSites, aCell) {
-
- // Try to find a lower-priority cell (empty or containing an unpinned site).
- let index = this._indexOfLowerPrioritySite(aSites, aCell);
-
- if (index > -1) {
- let cells = gGrid.cells;
- let dropIndex = aCell.index;
-
- // Move all pinned cells to their new positions to let the overflowed
- // site fit into the grid.
- for (let i = index + 1, lastPosition = index; i < aSites.length; i++) {
- if (i != dropIndex) {
- aSites[lastPosition] = aSites[i];
- lastPosition = i;
- }
- }
-
- // Finally, remove the overflowed site from its previous position.
- aSites.splice(cells.length, 1);
- }
- },
-
- /**
- * Finds the index of the last cell that is empty or contains an unpinned
- * site. These are considered to be of a lower priority.
- * @param aSites The array of sites.
- * @param aCell The drop target cell.
- * @return The cell's index.
- */
- _indexOfLowerPrioritySite:
- function DropPreview_indexOfLowerPrioritySite(aSites, aCell) {
-
- let cells = gGrid.cells;
- let dropIndex = aCell.index;
-
- // Search (beginning with the last site in the grid) for a site that is
- // empty or unpinned (an thus lower-priority) and can be pushed out of the
- // grid instead of the pinned site.
- for (let i = cells.length - 1; i >= 0; i--) {
- // The cell that is our drop target is not a good choice.
- if (i == dropIndex)
- continue;
-
- let site = aSites[i];
-
- // We can use the cell only if it's empty or the site is un-pinned.
- if (!site || !site.isPinned())
- return i;
- }
-
- return -1;
- }
-};
diff --git a/components/newtab/dropTargetShim.js b/components/newtab/dropTargetShim.js
deleted file mode 100644
index 57a97fa..0000000
--- a/components/newtab/dropTargetShim.js
+++ /dev/null
@@ -1,232 +0,0 @@
-#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 singleton provides a custom drop target detection. We need this because
- * the default DnD target detection relies on the cursor's position. We want
- * to pick a drop target based on the dragged site's position.
- */
-var gDropTargetShim = {
- /**
- * Cache for the position of all cells, cleaned after drag finished.
- */
- _cellPositions: null,
-
- /**
- * The last drop target that was hovered.
- */
- _lastDropTarget: null,
-
- /**
- * Initializes the drop target shim.
- */
- init: function () {
- gGrid.node.addEventListener("dragstart", this, true);
- },
-
- /**
- * Add all event listeners needed during a drag operation.
- */
- _addEventListeners: function () {
- gGrid.node.addEventListener("dragend", this);
-
- let docElement = document.documentElement;
- docElement.addEventListener("dragover", this);
- docElement.addEventListener("dragenter", this);
- docElement.addEventListener("drop", this);
- },
-
- /**
- * Remove all event listeners that were needed during a drag operation.
- */
- _removeEventListeners: function () {
- gGrid.node.removeEventListener("dragend", this);
-
- let docElement = document.documentElement;
- docElement.removeEventListener("dragover", this);
- docElement.removeEventListener("dragenter", this);
- docElement.removeEventListener("drop", this);
- },
-
- /**
- * Handles all shim events.
- */
- handleEvent: function (aEvent) {
- switch (aEvent.type) {
- case "dragstart":
- this._dragstart(aEvent);
- break;
- case "dragenter":
- aEvent.preventDefault();
- break;
- case "dragover":
- this._dragover(aEvent);
- break;
- case "drop":
- this._drop(aEvent);
- break;
- case "dragend":
- this._dragend(aEvent);
- break;
- }
- },
-
- /**
- * Handles the 'dragstart' event.
- * @param aEvent The 'dragstart' event.
- */
- _dragstart: function (aEvent) {
- if (aEvent.target.classList.contains("newtab-link")) {
- gGrid.lock();
- this._addEventListeners();
- }
- },
-
- /**
- * Handles the 'dragover' event.
- * @param aEvent The 'dragover' event.
- */
- _dragover: function (aEvent) {
- // XXX bug 505521 - Use the dragover event to retrieve the
- // current mouse coordinates while dragging.
- let sourceNode = aEvent.dataTransfer.mozSourceNode.parentNode;
- gDrag.drag(sourceNode._newtabSite, aEvent);
-
- // Find the current drop target, if there's one.
- this._updateDropTarget(aEvent);
-
- // If we have a valid drop target,
- // let the drag-and-drop service know.
- if (this._lastDropTarget) {
- aEvent.preventDefault();
- }
- },
-
- /**
- * Handles the 'drop' event.
- * @param aEvent The 'drop' event.
- */
- _drop: function (aEvent) {
- // We're accepting all drops.
- aEvent.preventDefault();
-
- // remember that drop event was seen, this explicitly
- // assumes that drop event preceeds dragend event
- this._dropSeen = true;
-
- // Make sure to determine the current drop target
- // in case the dragover event hasn't been fired.
- this._updateDropTarget(aEvent);
-
- // A site was successfully dropped.
- this._dispatchEvent(aEvent, "drop", this._lastDropTarget);
- },
-
- /**
- * Handles the 'dragend' event.
- * @param aEvent The 'dragend' event.
- */
- _dragend: function (aEvent) {
- if (this._lastDropTarget) {
- if (aEvent.dataTransfer.mozUserCancelled || !this._dropSeen) {
- // The drag operation was cancelled or no drop event was generated
- this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
- this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget);
- }
-
- // Clean up.
- this._lastDropTarget = null;
- this._cellPositions = null;
- }
-
- this._dropSeen = false;
- gGrid.unlock();
- this._removeEventListeners();
- },
-
- /**
- * Tries to find the current drop target and will fire
- * appropriate dragenter, dragexit, and dragleave events.
- * @param aEvent The current drag event.
- */
- _updateDropTarget: function (aEvent) {
- // Let's see if we find a drop target.
- let target = this._findDropTarget(aEvent);
-
- if (target != this._lastDropTarget) {
- if (this._lastDropTarget)
- // We left the last drop target.
- this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
-
- if (target)
- // We're now hovering a (new) drop target.
- this._dispatchEvent(aEvent, "dragenter", target);
-
- if (this._lastDropTarget)
- // We left the last drop target.
- this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget);
-
- this._lastDropTarget = target;
- }
- },
-
- /**
- * Determines the current drop target by matching the dragged site's position
- * against all cells in the grid.
- * @return The currently hovered drop target or null.
- */
- _findDropTarget: function () {
- // These are the minimum intersection values - we want to use the cell if
- // the site is >= 50% hovering its position.
- let minWidth = gDrag.cellWidth / 2;
- let minHeight = gDrag.cellHeight / 2;
-
- let cellPositions = this._getCellPositions();
- let rect = gTransformation.getNodePosition(gDrag.draggedSite.node);
-
- // Compare each cell's position to the dragged site's position.
- for (let i = 0; i < cellPositions.length; i++) {
- let inter = rect.intersect(cellPositions[i].rect);
-
- // If the intersection is big enough we found a drop target.
- if (inter.width >= minWidth && inter.height >= minHeight)
- return cellPositions[i].cell;
- }
-
- // No drop target found.
- return null;
- },
-
- /**
- * Gets the positions of all cell nodes.
- * @return The (cached) cell positions.
- */
- _getCellPositions: function DropTargetShim_getCellPositions() {
- if (this._cellPositions)
- return this._cellPositions;
-
- return this._cellPositions = gGrid.cells.map(function (cell) {
- return {cell: cell, rect: gTransformation.getNodePosition(cell.node)};
- });
- },
-
- /**
- * Dispatches a custom DragEvent on the given target node.
- * @param aEvent The source event.
- * @param aType The event type.
- * @param aTarget The target node that receives the event.
- */
- _dispatchEvent: function (aEvent, aType, aTarget) {
- let node = aTarget.node;
- let event = document.createEvent("DragEvent");
-
- // The event should not bubble to prevent recursion.
- event.initDragEvent(aType, false, true, window, 0, 0, 0, 0, 0, false, false,
- false, false, 0, node, aEvent.dataTransfer);
-
- node.dispatchEvent(event);
- }
-};
diff --git a/components/newtab/grid.js b/components/newtab/grid.js
deleted file mode 100644
index e63ea54..0000000
--- a/components/newtab/grid.js
+++ /dev/null
@@ -1,175 +0,0 @@
-#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 singleton represents the grid that contains all sites.
- */
-var gGrid = {
- /**
- * The DOM node of the grid.
- */
- _node: null,
- _gridDefaultContent: null,
- get node() { return this._node; },
-
- /**
- * The cached DOM fragment for sites.
- */
- _siteFragment: null,
-
- /**
- * All cells contained in the grid.
- */
- _cells: [],
- get cells() { return this._cells; },
-
- /**
- * All sites contained in the grid's cells. Sites may be empty.
- */
- get sites() {
- // return [for (cell of this.cells) cell.site];
- let aSites = [];
- for (let cell of this.cells) {
- aSites.push(cell.site);
- }
- return aSites;
- },
-
- // Tells whether the grid has already been initialized.
- get ready() { return !!this._ready; },
-
- // Returns whether the page has finished loading yet.
- get isDocumentLoaded() { return document.readyState == "complete"; },
-
- /**
- * Initializes the grid.
- * @param aSelector The query selector of the grid.
- */
- init: function Grid_init() {
- this._node = document.getElementById("newtab-grid");
- this._gridDefaultContent = this._node.lastChild;
- this._createSiteFragment();
-
- gLinks.populateCache(() => {
- this._refreshGrid();
- this._ready = true;
- });
- },
-
- /**
- * Creates a new site in the grid.
- * @param aLink The new site's link.
- * @param aCell The cell that will contain the new site.
- * @return The newly created site.
- */
- createSite: function Grid_createSite(aLink, aCell) {
- let node = aCell.node;
- node.appendChild(this._siteFragment.cloneNode(true));
- return new Site(node.firstElementChild, aLink);
- },
-
- /**
- * Handles all grid events.
- */
- handleEvent: function Grid_handleEvent(aEvent) {
- // Any specific events should go here.
- },
-
- /**
- * Locks the grid to block all pointer events.
- */
- lock: function Grid_lock() {
- this.node.setAttribute("locked", "true");
- },
-
- /**
- * Unlocks the grid to allow all pointer events.
- */
- unlock: function Grid_unlock() {
- this.node.removeAttribute("locked");
- },
-
- /**
- * Renders the grid.
- */
- refresh() {
- this._refreshGrid();
- },
-
- /**
- * Renders the grid, including cells and sites.
- */
- _refreshGrid() {
- let row = document.createElementNS(HTML_NAMESPACE, "div");
- row.classList.add("newtab-row");
- let cell = document.createElementNS(HTML_NAMESPACE, "div");
- cell.classList.add("newtab-cell");
-
- // Clear the grid
- this._node.innerHTML = "";
-
- // Creates the structure of one row
- for (let i = 0; i < gGridPrefs.gridColumns; i++) {
- row.appendChild(cell.cloneNode(true));
- }
-
- // Creates the grid
- for (let j = 0; j < gGridPrefs.gridRows; j++) {
- this._node.appendChild(row.cloneNode(true));
- }
-
- // Create cell array.
- let cellElements = this.node.querySelectorAll(".newtab-cell");
- let cells = Array.from(cellElements, (cell) => new Cell(this, cell));
-
- // Fetch links.
- let links = gLinks.getLinks();
-
- // Create sites.
- let numLinks = Math.min(links.length, cells.length);
- for (let i = 0; i < numLinks; i++) {
- if (links[i]) {
- this.createSite(links[i], cells[i]);
- }
- }
-
- this._cells = cells;
- },
-
- /**
- * Creates the DOM fragment that is re-used when creating sites.
- */
- _createSiteFragment: function Grid_createSiteFragment() {
- let site = document.createElementNS(HTML_NAMESPACE, "div");
- site.classList.add("newtab-site");
- site.setAttribute("draggable", "true");
-
- // Create the site's inner HTML code.
- site.innerHTML =
- '<a class="newtab-link">' +
- ' <span class="newtab-thumbnail placeholder"/>' +
- ' <span class="newtab-thumbnail thumbnail"/>' +
- ' <span class="newtab-title"/>' +
- '</a>' +
- '<input type="button" title="' + newTabString("pin") + '"' +
- ' class="newtab-control newtab-control-pin"/>' +
- '<input type="button" title="' + newTabString("block") + '"' +
- ' class="newtab-control newtab-control-block"/>';
-
- this._siteFragment = document.createDocumentFragment();
- this._siteFragment.appendChild(site);
- },
-
- /**
- * Test a tile at a given position for being pinned or history
- * @param position Position in sites array
- */
- _isHistoricalTile: function Grid_isHistoricalTile(aPos) {
- let site = this.sites[aPos];
- return site && (site.isPinned() || site.link && site.link.type == "history");
- }
-
-};
diff --git a/components/newtab/jar.mn b/components/newtab/jar.mn
deleted file mode 100644
index 2d62914..0000000
--- a/components/newtab/jar.mn
+++ /dev/null
@@ -1,8 +0,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/.
-
-browser.jar:
- content/browser/newtab/newTab.xhtml
-* content/browser/newtab/newTab.js
- content/browser/newtab/newTab.css \ No newline at end of file
diff --git a/components/newtab/moz.build b/components/newtab/moz.build
deleted file mode 100644
index 2d64d50..0000000
--- a/components/newtab/moz.build
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-JAR_MANIFESTS += ['jar.mn']
-
diff --git a/components/newtab/newTab.css b/components/newtab/newTab.css
deleted file mode 100644
index 3c7cfa1..0000000
--- a/components/newtab/newTab.css
+++ /dev/null
@@ -1,349 +0,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/. */
-
-html {
- width: 100%;
- height: 100%;
-}
-
-body {
- font: message-box;
- width: 100%;
- height: 100%;
- padding: 0;
- margin: 0;
- background-color: #F9F9F9;
- display: -moz-box;
- position: relative;
- -moz-box-flex: 1;
- -moz-user-focus: normal;
- -moz-box-orient: vertical;
-}
-
-input {
- font: message-box;
- font-size: 16px;
-}
-
-input[type=button] {
- cursor: pointer;
-}
-
-/* UNDO */
-#newtab-undo-container {
- transition: opacity 100ms ease-out;
- -moz-box-align: center;
- -moz-box-pack: center;
-}
-
-#newtab-undo-container[undo-disabled] {
- opacity: 0;
- pointer-events: none;
-}
-
-/* TOGGLE */
-#newtab-toggle {
- position: absolute;
- top: 12px;
- right: 12px;
-}
-
-#newtab-toggle:-moz-locale-dir(rtl) {
- left: 12px;
- right: auto;
-}
-
-/* MARGINS */
-#newtab-vertical-margin {
- display: -moz-box;
- position: relative;
- -moz-box-flex: 1;
- -moz-box-orient: vertical;
-}
-
-#newtab-margin-undo-container {
- display: -moz-box;
- left: 6px;
- position: absolute;
- top: 6px;
- z-index: 1;
-}
-
-#newtab-margin-undo-container:dir(rtl) {
- left: auto;
- right: 6px;
-}
-
-#newtab-undo-close-button:dir(rtl) {
- float:left;
-}
-
-#newtab-horizontal-margin {
- display: -moz-box;
- -moz-box-flex: 5;
-}
-
-#newtab-margin-top {
- min-height: 10px;
- max-height: 30px;
- display: -moz-box;
- -moz-box-flex: 1;
- -moz-box-align: center;
- -moz-box-pack: center;
-}
-
-#newtab-margin-bottom {
- min-height: 40px;
- max-height: 80px;
- -moz-box-flex: 1;
-}
-
-.newtab-side-margin {
- min-width: 40px;
- max-width: 300px;
- -moz-box-flex: 1;
-}
-
-/* GRID */
-#newtab-grid {
- display: -moz-box;
- -moz-box-flex: 5;
- -moz-box-orient: vertical;
- min-width: 600px;
- min-height: 400px;
- transition: 175ms ease-out;
- transition-property: opacity;
-}
-
-#newtab-grid[page-disabled] {
- opacity: 0;
-}
-
-#newtab-grid[locked],
-#newtab-grid[page-disabled] {
- pointer-events: none;
-}
-
-/* ROWS */
-.newtab-row {
- display: -moz-box;
- -moz-box-orient: horizontal;
- -moz-box-direction: normal;
- -moz-box-flex: 1;
-}
-
-/*
- * Thumbnail image sizes are determined in the preferences:
- * toolkit.pageThumbs.minWidth
- * toolkit.pageThumbs.minHeight
- */
-/* CELLS */
-.newtab-cell {
- display: -moz-box;
- -moz-box-flex: 1;
-}
-
-/* SITES */
-.newtab-site {
- position: relative;
- -moz-box-flex: 1;
- transition: 150ms ease-out;
- transition-property: top, left, opacity;
-}
-
-.newtab-site[frozen] {
- position: absolute;
- pointer-events: none;
-}
-
-.newtab-site[dragged] {
- transition-property: none;
- z-index: 10;
-}
-
-/* LINK + THUMBNAILS */
-.newtab-link,
-.newtab-thumbnail {
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
-}
-
-/* TITLES */
-.newtab-title {
- overflow: hidden;
- position: absolute;
- right: 0;
- text-align: center;
-}
-
-.newtab-title {
- bottom: 0;
- white-space: nowrap;
- text-overflow: ellipsis;
- vertical-align: middle;
-}
-
-.newtab-title {
- left: 0;
- padding: 0 4px;
-}
-
-/* CONTROLS */
-.newtab-control {
- position: absolute;
- opacity: 0;
- transition: opacity 100ms ease-out;
-}
-
-.newtab-control:-moz-focusring,
-.newtab-cell:not([ignorehover]) > .newtab-site:hover > .newtab-control {
- opacity: 1;
-}
-
-.newtab-control[dragged] {
- opacity: 0 !important;
-}
-
-@media (-moz-touch-enabled) {
- .newtab-control {
- opacity: 1;
- }
-}
-
-/* DRAG & DROP */
-
-/*
- * This is just a temporary drag element used for dataTransfer.setDragImage()
- * so that we can use custom drag images and elements. It needs an opacity of
- * 0.01 so that the core code detects that it's in fact a visible element.
- */
-.newtab-drag {
- width: 1px;
- height: 1px;
- background-color: #fff;
- opacity: 0.01;
-}
-
-/* SEARCH */
-#searchContainer {
- display: -moz-box;
- position: relative;
- -moz-box-pack: center;
- margin: 10px 0 15px;
-}
-
-#searchContainer[page-disabled] {
- opacity: 0;
- pointer-events: none;
-}
-
-#searchForm {
- display: -moz-box;
- position: relative;
- height: 36px;
- -moz-box-flex: 1;
- max-width: 600px; /* 2 * (290 cell width + 10 cell margin) */
-}
-
-#searchEngineLogo {
- border: 1px transparent;
- padding: 2px 4px;
- margin: 0;
- width: 32px;
- height: 32px;
- position: absolute;
-}
-
-#searchText {
- -moz-box-flex: 1;
- padding-top: 6px;
- padding-bottom: 6px;
- padding-inline-start: 42px;
- padding-inline-end: 8px;
- background: hsla(0,0%,100%,.9) padding-box;
- border: 1px solid;
- border-spacing: 0;
- border-radius: 2px 0 0 2px;
- border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
- box-shadow: 0 1px 0 hsla(210,65%,9%,.02) inset,
- 0 0 2px hsla(210,65%,9%,.1) inset,
- 0 1px 0 hsla(0,0%,100%,.2);
- color: inherit;
- unicode-bidi: plaintext;
-}
-
-#searchText:dir(rtl) {
- border-radius: 0 2px 2px 0;
-}
-
-#searchText[aria-expanded="true"] {
- border-radius: 2px 0 0 0;
-}
-
-#searchText[aria-expanded="true"]:dir(rtl) {
- border-radius: 0 2px 0 0;
-}
-
-#searchText[keepfocus],
-#searchText:focus {
- border-color: hsla(216,100%,60%,.6) hsla(216,76%,52%,.6) hsla(214,100%,40%,.6);
-}
-
-#searchSubmit {
- margin-inline-start: -1px;
- padding: 0;
- border: 1px solid;
- background-color: #e0e0e0;
- color: black;
- border-color: hsla(220,54%,20%,.15) hsla(220,54%,20%,.17) hsla(220,54%,20%,.2);
- border-radius: 0 2px 2px 0;
- box-shadow: 0 0 2px hsla(0,0%,100%,.5) inset,
- 0 1px 0 hsla(0,0%,100%,.2);
- cursor: pointer;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
- width: 50px;
-}
-
-#searchSubmit:dir(rtl) {
- border-radius: 2px 0 0 2px;
-}
-
-#searchSubmit:hover {
- background-color: hsl(220,54%,20%);
- color: white;
-}
-
-#searchText:focus + #searchSubmit,
-#searchText + #searchSubmit:hover {
- border-color: #5985fc #4573e7 #3264d5;
-}
-
-#searchText:focus + #searchSubmit,
-#searchText[keepfocus] + #searchSubmit {
- box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
- 0 0 0 1px hsla(0,0%,100%,.1) inset,
- 0 1px 0 hsla(220,54%,20%,.03);
-}
-
-#searchText + #searchSubmit:hover {
- box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
- 0 0 0 1px hsla(0,0%,100%,.1) inset,
- 0 1px 0 hsla(220,54%,20%,.03),
- 0 0 4px hsla(216,100%,20%,.2);
-}
-
-#searchText + #searchSubmit:hover:active {
- box-shadow: 0 1px 1px hsla(221,79%,6%,.1) inset,
- 0 0 1px hsla(221,79%,6%,.2) inset;
- transition-duration: 0ms;
-}
-
-.contentSearchSuggestionTable {
- font: message-box;
- font-size: 16px;
-}
diff --git a/components/newtab/newTab.js b/components/newtab/newTab.js
deleted file mode 100644
index 0022f21..0000000
--- a/components/newtab/newTab.js
+++ /dev/null
@@ -1,69 +0,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/. */
-
-"use strict";
-
-var Cu = Components.utils;
-var Ci = Components.interfaces;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/PageThumbs.jsm");
-Cu.import("resource://gre/modules/BackgroundPageThumbs.jsm");
-Cu.import("resource://gre/modules/NewTabUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Rect",
- "resource://gre/modules/Geometry.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
- "resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-var {
- links: gLinks,
- allPages: gAllPages,
- linkChecker: gLinkChecker,
- pinnedLinks: gPinnedLinks,
- blockedLinks: gBlockedLinks,
- gridPrefs: gGridPrefs
-} = NewTabUtils;
-
-XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
- return Services.strings.
- createBundle("chrome://browser/locale/newTab.properties");
-});
-
-function newTabString(name, args) {
- let stringName = "newtab." + name;
- if (!args) {
- return gStringBundle.GetStringFromName(stringName);
- }
- return gStringBundle.formatStringFromName(stringName, args, args.length);
-}
-
-function inPrivateBrowsingMode() {
- return PrivateBrowsingUtils.isContentWindowPrivate(window);
-}
-
-const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
-const XUL_NAMESPACE = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-
-const TILES_EXPLAIN_LINK = "https://support.mozilla.org/kb/how-do-tiles-work-firefox";
-const TILES_INTRO_LINK = "https://www.mozilla.org/firefox/tiles/";
-const TILES_PRIVACY_LINK = "https://www.mozilla.org/privacy/";
-
-#include transformations.js
-#include page.js
-#include grid.js
-#include cells.js
-#include sites.js
-#include drag.js
-#include dragDataHelper.js
-#include drop.js
-#include dropTargetShim.js
-#include dropPreview.js
-#include updater.js
-#include undo.js
-#include search.js
-
-// Everything is loaded. Initialize the New Tab Page.
-gPage.init();
diff --git a/components/newtab/newTab.xhtml b/components/newtab/newTab.xhtml
deleted file mode 100644
index de000e7..0000000
--- a/components/newtab/newTab.xhtml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- 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/. -->
-
-<!DOCTYPE html [
- <!ENTITY % newTabDTD SYSTEM "chrome://browser/locale/newTab.dtd">
- %newTabDTD;
- <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
- %browserDTD;
- <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
-]>
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
- <title>&newtab.pageTitle;</title>
-
- <link rel="stylesheet" type="text/css" media="all" href="chrome://global/skin/" />
- <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/content/newtab/newTab.css" />
- <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/skin/newtab/newTab.css" />
-</head>
-
-<body dir="&locale.dir;">
- <div id="newtab-vertical-margin">
- <div id="newtab-margin-top"/>
-
- <div id="newtab-margin-undo-container">
- <div id="newtab-undo-container" undo-disabled="true">
- <label id="newtab-undo-label">&newtab.undo.removedLabel;</label>
- <button id="newtab-undo-button" tabindex="-1"
- class="newtab-undo-button">&newtab.undo.undoButton;</button>
- <button id="newtab-undo-restore-button" tabindex="-1"
- class="newtab-undo-button">&newtab.undo.restoreButton;</button>
- <button id="newtab-undo-close-button" tabindex="-1" title="&newtab.undo.closeTooltip;"/>
- </div>
- </div>
-
- <div id="searchContainer">
- <form name="searchForm" id="searchForm" onsubmit="onSearchSubmit(event)">
- <div id="searchLogoContainer"><img id="searchEngineLogo"/></div>
- <input type="text" name="q" value="" id="searchText" maxlength="256"/>
- <input id="searchSubmit" type="submit" value="&newtab.searchEngineButton.label;"/>
- </form>
- </div>
-
- <div id="newtab-horizontal-margin">
- <div class="newtab-side-margin"/>
- <div id="newtab-grid">
- <!-- site grid -->
- </div>
- <div class="newtab-side-margin"/>
- </div>
-
- <div id="newtab-margin-bottom"/>
- <input id="newtab-toggle" type="button"/>
- </div>
-</body>
-<script type="text/javascript;version=1.8" src="chrome://browser/content/newtab/newTab.js"/>
-</html>
diff --git a/components/newtab/page.js b/components/newtab/page.js
deleted file mode 100644
index 34387fd..0000000
--- a/components/newtab/page.js
+++ /dev/null
@@ -1,244 +0,0 @@
-#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
-
-// The amount of time we wait while coalescing updates for hidden pages.
-const SCHEDULE_UPDATE_TIMEOUT_MS = 1000;
-
-/**
- * This singleton represents the whole 'New Tab Page' and takes care of
- * initializing all its components.
- */
-var gPage = {
- /**
- * Initializes the page.
- */
- init: function Page_init() {
- // Add ourselves to the list of pages to receive notifications.
- gAllPages.register(this);
-
- // Listen for 'unload' to unregister this page.
- addEventListener("unload", this, false);
-
- // Listen for toggle button clicks.
- let button = document.getElementById("newtab-toggle");
- button.addEventListener("click", e => this.toggleEnabled(e));
-
- // XXX bug 991111 - Not all click events are correctly triggered when
- // listening from xhtml nodes -- in particular middle clicks on sites, so
- // listen from the xul window and filter then delegate
- addEventListener("click", this, false);
-
- // Check if the new tab feature is enabled.
- let enabled = gAllPages.enabled;
- if (enabled)
- this._init();
-
- this._updateAttributes(enabled);
- },
-
- /**
- * Listens for notifications specific to this page.
- */
- observe: function Page_observe(aSubject, aTopic, aData) {
- if (aTopic == "nsPref:changed") {
- let enabled = gAllPages.enabled;
- this._updateAttributes(enabled);
-
- // Initialize the whole page if we haven't done that, yet.
- if (enabled) {
- this._init();
- } else {
- gUndoDialog.hide();
- }
- } else if (aTopic == "page-thumbnail:create" && gGrid.ready) {
- for (let site of gGrid.sites) {
- if (site && site.url === aData) {
- site.refreshThumbnail();
- }
- }
- }
- },
-
- /**
- * Updates the page's grid right away for visible pages. If the page is
- * currently hidden, i.e. in a background tab or in the preloader, then we
- * batch multiple update requests and refresh the grid once after a short
- * delay. Accepts a single parameter the specifies the reason for requesting
- * a page update. The page may decide to delay or prevent a requested updated
- * based on the given reason.
- */
- update(reason = "") {
- // Update immediately if we're visible.
- if (!document.hidden) {
- // Ignore updates where reason=links-changed as those signal that the
- // provider's set of links changed. We don't want to update visible pages
- // in that case, it is ok to wait until the user opens the next tab.
- if (reason != "links-changed" && gGrid.ready) {
- gGrid.refresh();
- }
-
- return;
- }
-
- // Bail out if we scheduled before.
- if (this._scheduleUpdateTimeout) {
- return;
- }
-
- this._scheduleUpdateTimeout = setTimeout(() => {
- // Refresh if the grid is ready.
- if (gGrid.ready) {
- gGrid.refresh();
- }
-
- this._scheduleUpdateTimeout = null;
- }, SCHEDULE_UPDATE_TIMEOUT_MS);
- },
-
- /**
- * Internally initializes the page. This runs only when/if the feature
- * is/gets enabled.
- */
- _init: function Page_init() {
- if (this._initialized)
- return;
-
- this._initialized = true;
-
- // Set submit button label for when CSS background are disabled (e.g.
- // high contrast mode).
- document.getElementById("searchSubmit").value =
- document.body.getAttribute("dir") == "ltr" ? "\u25B6" : "\u25C0";
-
- if (document.hidden) {
- addEventListener("visibilitychange", this);
- } else {
- setTimeout(() => this.onPageFirstVisible());
- }
-
- // Initialize and render the grid.
- gGrid.init();
-
- // Initialize the drop target shim.
- gDropTargetShim.init();
-
-#ifdef XP_MACOSX
- // Workaround to prevent a delay on MacOSX due to a slow drop animation.
- document.addEventListener("dragover", this, false);
- document.addEventListener("drop", this, false);
-#endif
- },
-
- /**
- * Updates the 'page-disabled' attributes of the respective DOM nodes.
- * @param aValue Whether the New Tab Page is enabled or not.
- */
- _updateAttributes: function Page_updateAttributes(aValue) {
- // Set the nodes' states.
- let nodeSelector = "#newtab-grid, #searchContainer";
- for (let node of document.querySelectorAll(nodeSelector)) {
- if (aValue)
- node.removeAttribute("page-disabled");
- else
- node.setAttribute("page-disabled", "true");
- }
-
- // Enables/disables the control and link elements.
- let inputSelector = ".newtab-control, .newtab-link";
- for (let input of document.querySelectorAll(inputSelector)) {
- if (aValue)
- input.removeAttribute("tabindex");
- else
- input.setAttribute("tabindex", "-1");
- }
- },
-
- /**
- * Handles unload event
- */
- _handleUnloadEvent: function Page_handleUnloadEvent() {
- gAllPages.unregister(this);
- },
-
- /**
- * Handles all page events.
- */
- handleEvent: function Page_handleEvent(aEvent) {
- switch (aEvent.type) {
- case "load":
- this.onPageVisibleAndLoaded();
- break;
- case "unload":
- this._handleUnloadEvent();
- break;
- case "click":
- let {button, target} = aEvent;
- // Go up ancestors until we find a Site or not
- while (target) {
- if (target.hasOwnProperty("_newtabSite")) {
- target._newtabSite.onClick(aEvent);
- break;
- }
- target = target.parentNode;
- }
- break;
- case "dragover":
- if (gDrag.isValid(aEvent) && gDrag.draggedSite)
- aEvent.preventDefault();
- break;
- case "drop":
- if (gDrag.isValid(aEvent) && gDrag.draggedSite) {
- aEvent.preventDefault();
- aEvent.stopPropagation();
- }
- break;
- case "visibilitychange":
- // Cancel any delayed updates for hidden pages now that we're visible.
- if (this._scheduleUpdateTimeout) {
- clearTimeout(this._scheduleUpdateTimeout);
- this._scheduleUpdateTimeout = null;
-
- // An update was pending so force an update now.
- this.update();
- }
-
- setTimeout(() => this.onPageFirstVisible());
- removeEventListener("visibilitychange", this);
- break;
- }
- },
-
- onPageFirstVisible: function () {
- // Record another page impression.
- Services.telemetry.getHistogramById("NEWTAB_PAGE_SHOWN").add(true);
-
- for (let site of gGrid.sites) {
- if (site) {
- // The site may need to modify and/or re-render itself if
- // something changed after newtab was created by preloader.
- // For example, the suggested tile endTime may have passed.
- site.onFirstVisible();
- }
- }
-
- // save timestamp to compute page life-span delta
- this._firstVisibleTime = Date.now();
-
- if (document.readyState == "complete") {
- this.onPageVisibleAndLoaded();
- } else {
- addEventListener("load", this);
- }
- },
-
- onPageVisibleAndLoaded() {
- },
-
- toggleEnabled: function(aEvent) {
- gAllPages.enabled = !gAllPages.enabled;
- aEvent.stopPropagation();
- }
-};
diff --git a/components/newtab/search.js b/components/newtab/search.js
deleted file mode 100644
index 8bc959e..0000000
--- a/components/newtab/search.js
+++ /dev/null
@@ -1,134 +0,0 @@
-#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 SEARCH_ENGINES = {
- "DuckDuckGo": {
- image: "data:image/png;base64," +
- "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAACT1BMVEXvISn/////9/fvUlr3ra3/" +
- "zs7/7+/va2v/5+f/xsbvMTn/tbX/3t7/vb3vOUL3WmPvQkr/zgDvKTHvSlL3hIT3paX/1tbnISn3" +
- "c3v3e3v3a3P3jIz3nJz/tb33c3PvKSn3lJT39/cAc73vSkr3e4Tv7+/3Yxj3pa3/tQj3jJT3nKX3" +
- "Y2P/xs73hIzvQkL/vQjvQiHn5+f3hBD/ztbvMTH/vcb/3ucIc733lJz/pQilzufe7/fvMSHOzs73" +
- "//cQrUpKvVprxmP3Y2vvShiUzmvWlJRzzmMYtUrvOTnn7/davVrWra3v9//nY2PvISGUxudztd7e" +
- "3t7/76XvKSHea2v/xgDnOUK93vfW5/f/1t73Uhj/52ut3q2l3rXO784pjMZrrdb/rQjera3/5+/e" +
- "paWMxufO79aEazkYrUr/nAj3jBD3axj3lBD///fehIRKpd7/1hCEYzk5vVL3//8ptVLW77UxtVLn" +
- "SlLW1tZCvVp7vef/1gj/3invSkL//+fWtbXvpaX/3kr/97XvnJznWmMxjM5zvefOxsbWnKXWjIzG" +
- "3u/ea3Pn997O5/fnQkqExuf3Whit1u/nUlrnxs7v5+d7zmuU1pT3exDOSjFjrVL/987/pUoQe8b/" +
- "75T/3jFKxnO158bWKSl7zoRSxmtajEK1e0pzxlqcUjH/1iHOMSnOvb33cxDWnJx7td6EzmP/74xz" +
- "azlrcznec3Pe771jxlpzczne78YpvVqEvWPn99YxvWOtSjHee3vG787OOTE5lEK1QjHv9+drzmve" +
- "tbXO772q+r8wAAAFbUlEQVR4Xo2X84PzTBDHN3Zqu2fbemzbNl7atm3btvGHvTNJ2myuyd3NL2mT" +
- "zmdnvjM76RImyGQlH5dCHBeSmscNmQkyfwBrZMLEY2aRF5cMSDYPEx+LZpUlAYRQbVEpnuc1je/M" +
- "SbVwYoVFAbpE0IaLmiwqiVymmE3H84YuGs2mheCEhQH5qPUrje2ONxHKVIkXR2x2MxsMkDnLvftk" +
- "2fSTQNCzSAgngwCCipkXxHiU+BsnCDFE8f6AQgnwaTGhkmDLymW8jPsBeIsth8iCpha618El1wgo" +
- "4FOhWyWLWY+O8pbnAwTI29S1ElncJBmF4L0AGeJSdR4dUpt5w+DL0nAgoUuGGKKCBxDCOxrykaDb" +
- "+yFQjhUylLlXpAB5jGnIqV6uvvWUcAAhLmDBXIAMrkXRdHQ+cerUiWefq1hRrAgg8LikUgdkQUAx" +
- "6+2Ze0WLEO/1BQzrHCFNrAPAeDSD4q/Ln6R3p68MSYzDAUiwIEutJM0bHXE/gpEhJMxaAB3T6aT8" +
- "mfkm+QBiMlwKFqAHvrHu9tvTOLrEdX4hFAkJWQB42qbVyam75ruv3zvF+wBCKJ0MAAV6SAy5+raA" +
- "y+lb9tYBUw9sffKRJh+CDl2SAEAPquaC76swU1c+zlxbA9if/EIY78AcCBODDKjnVzDM0+sb57zq" +
- "N14gdpbg4nraBaxm3NWpIDKNgJIIDTxEAKMyVM9/VrFcpijK52PbNhmk0RQORCA8dhGhIkDA+qPV" +
- "Y/U8No2NHZsUfQCdzYTECSiRSRJKgxYAnK6+tnVrPYL7q2P7GNNnT0L3SQSS61AowK4BAExWq9XJ" +
- "OmDT5D4GtUab7p92W1aD6AFBOjUKcONNKMG2o9vmScmhd+v5SCTS91StDLBwmHR5q0iiM4yv3X5g" +
- "sD1i24tUHc0GQOrOihdw+ZV7drx+8I1IzfpaCQ1oSIGsbqEBdxy8KkLb8dYt7m7AFBpEJI8OUIAd" +
- "Hve+wX509IqYgzLqxKMi5X+r6737wgHfMrZBKGwpQMWP0PN8/8qLn15cSRosEQeI3coxGrzRVfE2" +
- "BEyTAMNpmbA3k2erPOyq+CUCPGvv3OmGykYBQhiYFbynDLu2uyW826qb7bSlv/VCe2R3vQqhIYQQ" +
- "nLmSGKUAT1AqXn7V6p72iUsTThsNuhKUAeKMNFaiW2nG08H90IF1m6DywVdsHgA4bPgRGgAqUgBr" +
- "DwxOtPcdv9RK6yklnaGKOXBMmN7RVCtJJMiUdG2s78dv9HbY7KrI9AQBOHwjaxaA6cKhRLXCHkpF" +
- "PrAJYBz1su7LtSBQIjzozgI5AJDWsQ7gTJxETTHuEh5yW8kR5+1fvQBT5PDdWgPokE6GSuK3Aaby" +
- "2KwNyGFIZ8/NfexVMAGXEfe8MA5QTVdrgGe2M9evev6FMwiAYr308nVzcx/SgHwSlswyLgDLHU0K" +
- "tX5UZwCwZsM1b7516J1333v/g2UAuJoCNMsmZkEDZBXujCoOIfVJxQKsvXnDshvWfrEcAV9RAoqY" +
- "rfdvHjY06R3tVmtjzQYsQ8ByC/C1O0dEzqkAGqELbiZ1W/RvBr51Ad9ZgO8dQCkh4/q5xvMC6hot" +
- "sBl7rP1QT+HHQz9RGoSHhkyMgqEBdNPFWSWMY+1nBPxy+MjvZ2aZxB9n/zz3FwKiOTZfotb3AhhF" +
- "xSUUNmGSjX+vWvPPYacVWJOkUilUT05ymEVb0JFHj9l/AVn+35b/jsx6YzNz8mja+iAEH7rYDntY" +
- "Gaz3dizW080KWaeICx77kiG7lTKG6EEoPb0Wu0lZ9OA5whFH8GxHQjOMQls5HSs5t/glHX2FYtT/" +
- "mGAs/fCtFU0vQJUSQYfvIBvVyukuLhbjuood/H6WCbD/AQSFvIO3JDxgAAAAAElFTkSuQmCC"
- }
-};
-
-// This global tracks if the page has been set up before, to prevent double inits
-var gInitialized = false;
-var gObserver = new MutationObserver(function (mutations) {
- for (let mutation of mutations) {
- if (mutation.attributeName == "searchEngineURL") {
- setupSearchEngine();
- if (!gInitialized) {
- gInitialized = true;
- }
- return;
- }
- }
-});
-
-window.addEventListener("pageshow", function () {
- window.gObserver.observe(document.documentElement, { attributes: true });
-});
-
-window.addEventListener("pagehide", function() {
- window.gObserver.disconnect();
-});
-
-function onSearchSubmit(aEvent) {
- let searchTerms = document.getElementById("searchText").value;
- let searchURL = document.documentElement.getAttribute("searchEngineURL");
-
- if (searchURL && searchTerms.length > 0) {
- const SEARCH_TOKEN = "_searchTerms_";
- let searchPostData = document.documentElement.getAttribute("searchEnginePostData");
- if (searchPostData) {
- // Check if a post form already exists. If so, remove it.
- const POST_FORM_NAME = "searchFormPost";
- let form = document.forms[POST_FORM_NAME];
- if (form) {
- form.parentNode.removeChild(form);
- }
-
- // Create a new post form.
- form = document.body.appendChild(document.createElement("form"));
- form.setAttribute("name", POST_FORM_NAME);
- // Set the URL to submit the form to.
- form.setAttribute("action", searchURL.replace(SEARCH_TOKEN, searchTerms));
- form.setAttribute("method", "post");
-
- // Create new <input type=hidden> elements for search param.
- searchPostData = searchPostData.split("&");
- for (let postVar of searchPostData) {
- let [name, value] = postVar.split("=");
- if (value == SEARCH_TOKEN) {
- value = searchTerms;
- }
- let input = document.createElement("input");
- input.setAttribute("type", "hidden");
- input.setAttribute("name", name);
- input.setAttribute("value", value);
- form.appendChild(input);
- }
- // Submit the form.
- form.submit();
- } else {
- searchURL = searchURL.replace(SEARCH_TOKEN, encodeURIComponent(searchTerms));
- window.location.href = searchURL;
- }
- }
-
- aEvent.preventDefault();
-}
-
-
-function setupSearchEngine() {
- let searchText = document.getElementById("searchText");
- let searchEngineName = document.documentElement.getAttribute("searchEngineName");
- let searchEngineInfo = SEARCH_ENGINES[searchEngineName];
- let logoElt = document.getElementById("searchEngineLogo");
-
- // Add search engine logo.
- if (searchEngineInfo && searchEngineInfo.image) {
- logoElt.parentNode.hidden = false;
- logoElt.src = searchEngineInfo.image;
- logoElt.alt = searchEngineName;
- searchText.placeholder = "";
- } else {
- logoElt.parentNode.hidden = true;
- searchText.placeholder = searchEngineName;
- }
-}
diff --git a/components/newtab/sites.js b/components/newtab/sites.js
deleted file mode 100644
index cb56752..0000000
--- a/components/newtab/sites.js
+++ /dev/null
@@ -1,353 +0,0 @@
-#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 THUMBNAIL_PLACEHOLDER_ENABLED =
- Services.prefs.getBoolPref("browser.newtabpage.thumbnailPlaceholder");
-
-/**
- * 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() { return this._node; },
-
- /**
- * The site's link.
- */
- get link() { return this._link; },
-
- /**
- * The url of the site's link.
- */
- get url() { return this.link.url; },
-
- /**
- * The title of the site's link.
- */
- get title() { return this.link.title || this.link.url; },
-
- /**
- * 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).
- * @return true if link changed type after pin
- */
- pin: function Site_pin(aIndex) {
- if (typeof aIndex == "undefined")
- aIndex = this.cell.index;
-
- this._updateAttributes(true);
- let changed = gPinnedLinks.pin(this._link, aIndex);
- if (changed) {
- // render site again
- this._render();
- }
- return changed;
- },
-
- /**
- * 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) {
- this.node.setAttribute("pinned", true);
- control.setAttribute("title", newTabString("unpin"));
- } else {
- this.node.removeAttribute("pinned");
- control.setAttribute("title", newTabString("pin"));
- }
- },
-
- _newTabString: function(str, substrArr) {
- let regExp = /%[0-9]\$S/g;
- let matches;
- while ((matches = regExp.exec(str))) {
- let match = matches[0];
- let index = match.charAt(1); // Get the digit in the regExp.
- str = str.replace(match, substrArr[index - 1]);
- }
- return str;
- },
-
- /**
- * Checks for and modifies link at campaign end time
- */
- _checkLinkEndTime: function Site_checkLinkEndTime() {
- if (this.link.endTime && this.link.endTime < Date.now()) {
- let oldUrl = this.url;
- // chop off the path part from url
- this.link.url = Services.io.newURI(this.url, null, null).resolve("/");
- // clear supplied images - this triggers thumbnail download for new url
- delete this.link.imageURI;
- // remove endTime to avoid further time checks
- delete this.link.endTime;
- gPinnedLinks.replace(oldUrl, this.link);
- }
- },
-
- /**
- * Renders the site's data (fills the HTML fragment).
- */
- _render: function Site_render() {
- // first check for end time, as it may modify the link
- this._checkLinkEndTime();
- // setup display variables
- let url = this.url;
- let title = this.link.type == "history" ? this.link.baseDomain :
- this.title;
- let tooltip = (this.title == url ? this.title : this.title + "\n" + url);
-
- let link = this._querySelector(".newtab-link");
- link.setAttribute("title", tooltip);
- link.setAttribute("href", url);
- this.node.setAttribute("type", this.link.type);
-
- let titleNode = this._querySelector(".newtab-title");
- titleNode.textContent = title;
- if (this.link.titleBgColor) {
- titleNode.style.backgroundColor = this.link.titleBgColor;
- }
-
- 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();
- },
-
- /**
- * Called when the site's tab becomes visible for the first time.
- * Since the newtab may be preloaded long before it's displayed,
- * check for changed conditions and re-render if needed
- */
- onFirstVisible: function Site_onFirstVisible() {
- if (this.link.endTime && this.link.endTime < Date.now()) {
- // site needs to change landing url and background image
- this._render();
- }
- else {
- this.captureIfMissing();
- }
- },
-
- /**
- * 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 (!document.hidden && !this.link.imageURI) {
- BackgroundPageThumbs.captureIfMissing(this.url);
- }
- },
-
- /**
- * Refreshes the thumbnail for the site.
- */
- refreshThumbnail: function Site_refreshThumbnail() {
- let link = this.link;
-
- let thumbnail = this._querySelector(".newtab-thumbnail.thumbnail");
- if (link.bgColor) {
- thumbnail.style.backgroundColor = link.bgColor;
- }
- let uri = link.imageURI || PageThumbs.getThumbnailURL(this.url);
- thumbnail.style.backgroundImage = 'url("' + uri + '")';
-
- if (THUMBNAIL_PLACEHOLDER_ENABLED &&
- link.type == "history" &&
- link.baseDomain) {
- let placeholder = this._querySelector(".newtab-thumbnail.placeholder");
- let charCodeSum = 0;
- for (let c of link.baseDomain) {
- charCodeSum += c.charCodeAt(0);
- }
- const COLORS = 16;
- let hue = Math.round((charCodeSum % COLORS) / COLORS * 360);
- placeholder.style.backgroundColor = "hsl(" + hue + ",80%,40%)";
- placeholder.textContent = link.baseDomain.substr(0,1).toUpperCase();
- }
- },
-
- _ignoreHoverEvents: function(element) {
- element.addEventListener("mouseover", () => {
- this.cell.node.setAttribute("ignorehover", "true");
- });
- element.addEventListener("mouseout", () => {
- this.cell.node.removeAttribute("ignorehover");
- });
- },
-
- /**
- * 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);
- },
-
- /**
- * 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);
- try {
- // This can throw for certain internal URLs, when they wind up in
- // about:newtab. Be sure not to propagate the error.
- sc.speculativeConnect(uri, null);
- } catch (e) {}
- },
-
- /**
- * 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);
- },
-
- _toggleLegalText: function(buttonClass, explanationTextClass) {
- let button = this._querySelector(buttonClass);
- if (button.hasAttribute("active")) {
- let explain = this._querySelector(explanationTextClass);
- explain.parentNode.removeChild(explain);
-
- button.removeAttribute("active");
- }
- },
-
- /**
- * Handles site click events.
- */
- onClick: function Site_onClick(aEvent) {
- let action;
- let pinned = this.isPinned();
- let tileIndex = this.cell.index;
- let {button, target} = aEvent;
-
- // Handle tile/thumbnail link click
- 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(tileIndex);
- action = "click";
- }
- }
- // Only handle primary clicks for the remaining targets
- else if (button == 0) {
- aEvent.preventDefault();
- if (target.classList.contains("newtab-control-block")) {
- this.block();
- action = "block";
- }
- else if (pinned && target.classList.contains("newtab-control-pin")) {
- this.unpin();
- action = "unpin";
- }
- else if (!pinned && target.classList.contains("newtab-control-pin")) {
- if (this.pin()) {
- // link has changed - update rest of the pages
- gAllPages.update(gPage);
- }
- action = "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;
- }
- }
-};
diff --git a/components/newtab/transformations.js b/components/newtab/transformations.js
deleted file mode 100644
index f7db0ad..0000000
--- a/components/newtab/transformations.js
+++ /dev/null
@@ -1,270 +0,0 @@
-#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 singleton allows to transform the grid by repositioning a site's node
- * in the DOM and by showing or hiding the node. It additionally provides
- * convenience methods to work with a site's DOM node.
- */
-var gTransformation = {
- /**
- * Returns the width of the left and top border of a cell. We need to take it
- * into account when measuring and comparing site and cell positions.
- */
- get _cellBorderWidths() {
- let cstyle = window.getComputedStyle(gGrid.cells[0].node, null);
- let widths = {
- left: parseInt(cstyle.getPropertyValue("border-left-width")),
- top: parseInt(cstyle.getPropertyValue("border-top-width"))
- };
-
- // Cache this value, overwrite the getter.
- Object.defineProperty(this, "_cellBorderWidths",
- {value: widths, enumerable: true});
-
- return widths;
- },
-
- /**
- * Gets a DOM node's position.
- * @param aNode The DOM node.
- * @return A Rect instance with the position.
- */
- getNodePosition: function Transformation_getNodePosition(aNode) {
- let {left, top, width, height} = aNode.getBoundingClientRect();
- return new Rect(left + scrollX, top + scrollY, width, height);
- },
-
- /**
- * Fades a given node from zero to full opacity.
- * @param aNode The node to fade.
- * @param aCallback The callback to call when finished.
- */
- fadeNodeIn: function Transformation_fadeNodeIn(aNode, aCallback) {
- this._setNodeOpacity(aNode, 1, function () {
- // Clear the style property.
- aNode.style.opacity = "";
-
- if (aCallback)
- aCallback();
- });
- },
-
- /**
- * Fades a given node from full to zero opacity.
- * @param aNode The node to fade.
- * @param aCallback The callback to call when finished.
- */
- fadeNodeOut: function Transformation_fadeNodeOut(aNode, aCallback) {
- this._setNodeOpacity(aNode, 0, aCallback);
- },
-
- /**
- * Fades a given site from zero to full opacity.
- * @param aSite The site to fade.
- * @param aCallback The callback to call when finished.
- */
- showSite: function Transformation_showSite(aSite, aCallback) {
- this.fadeNodeIn(aSite.node, aCallback);
- },
-
- /**
- * Fades a given site from full to zero opacity.
- * @param aSite The site to fade.
- * @param aCallback The callback to call when finished.
- */
- hideSite: function Transformation_hideSite(aSite, aCallback) {
- this.fadeNodeOut(aSite.node, aCallback);
- },
-
- /**
- * Allows to set a site's position.
- * @param aSite The site to re-position.
- * @param aPosition The desired position for the given site.
- */
- setSitePosition: function Transformation_setSitePosition(aSite, aPosition) {
- let style = aSite.node.style;
- let {top, left} = aPosition;
-
- style.top = top + "px";
- style.left = left + "px";
- },
-
- /**
- * Freezes a site in its current position by positioning it absolute.
- * @param aSite The site to freeze.
- */
- freezeSitePosition: function Transformation_freezeSitePosition(aSite) {
- if (this._isFrozen(aSite))
- return;
-
- let style = aSite.node.style;
- let comp = getComputedStyle(aSite.node, null);
- style.width = comp.getPropertyValue("width");
- style.height = comp.getPropertyValue("height");
-
- aSite.node.setAttribute("frozen", "true");
- this.setSitePosition(aSite, this.getNodePosition(aSite.node));
- },
-
- /**
- * Unfreezes a site by removing its absolute positioning.
- * @param aSite The site to unfreeze.
- */
- unfreezeSitePosition: function Transformation_unfreezeSitePosition(aSite) {
- if (!this._isFrozen(aSite))
- return;
-
- let style = aSite.node.style;
- style.left = style.top = style.width = style.height = "";
- aSite.node.removeAttribute("frozen");
- },
-
- /**
- * Slides the given site to the target node's position.
- * @param aSite The site to move.
- * @param aTarget The slide target.
- * @param aOptions Set of options (see below).
- * unfreeze - unfreeze the site after sliding
- * callback - the callback to call when finished
- */
- slideSiteTo: function Transformation_slideSiteTo(aSite, aTarget, aOptions) {
- let currentPosition = this.getNodePosition(aSite.node);
- let targetPosition = this.getNodePosition(aTarget.node)
- let callback = aOptions && aOptions.callback;
-
- let self = this;
-
- function finish() {
- if (aOptions && aOptions.unfreeze)
- self.unfreezeSitePosition(aSite);
-
- if (callback)
- callback();
- }
-
- // We need to take the width of a cell's border into account.
- targetPosition.left += this._cellBorderWidths.left;
- targetPosition.top += this._cellBorderWidths.top;
-
- // Nothing to do here if the positions already match.
- if (currentPosition.left == targetPosition.left &&
- currentPosition.top == targetPosition.top) {
- finish();
- } else {
- this.setSitePosition(aSite, targetPosition);
- this._whenTransitionEnded(aSite.node, ["left", "top"], finish);
- }
- },
-
- /**
- * Rearranges a given array of sites and moves them to their new positions or
- * fades in/out new/removed sites.
- * @param aSites An array of sites to rearrange.
- * @param aOptions Set of options (see below).
- * unfreeze - unfreeze the site after rearranging
- * callback - the callback to call when finished
- */
- rearrangeSites: function Transformation_rearrangeSites(aSites, aOptions) {
- let batch = [];
- let cells = gGrid.cells;
- let callback = aOptions && aOptions.callback;
- let unfreeze = aOptions && aOptions.unfreeze;
-
- aSites.forEach(function (aSite, aIndex) {
- // Do not re-arrange empty cells or the dragged site.
- if (!aSite || aSite == gDrag.draggedSite)
- return;
-
- batch.push(new Promise(resolve => {
- if (!cells[aIndex]) {
- // The site disappeared from the grid, hide it.
- this.hideSite(aSite, resolve);
- } else if (this._getNodeOpacity(aSite.node) != 1) {
- // The site disappeared before but is now back, show it.
- this.showSite(aSite, resolve);
- } else {
- // The site's position has changed, move it around.
- this._moveSite(aSite, aIndex, {unfreeze: unfreeze, callback: resolve});
- }
- }));
- }, this);
-
- if (callback) {
- Promise.all(batch).then(callback);
- }
- },
-
- /**
- * Listens for the 'transitionend' event on a given node and calls the given
- * callback.
- * @param aNode The node that is transitioned.
- * @param aProperties The properties we'll wait to be transitioned.
- * @param aCallback The callback to call when finished.
- */
- _whenTransitionEnded:
- function Transformation_whenTransitionEnded(aNode, aProperties, aCallback) {
-
- let props = new Set(aProperties);
- aNode.addEventListener("transitionend", function onEnd(e) {
- if (props.has(e.propertyName)) {
- aNode.removeEventListener("transitionend", onEnd);
- aCallback();
- }
- });
- },
-
- /**
- * Gets a given node's opacity value.
- * @param aNode The node to get the opacity value from.
- * @return The node's opacity value.
- */
- _getNodeOpacity: function Transformation_getNodeOpacity(aNode) {
- let cstyle = window.getComputedStyle(aNode, null);
- return cstyle.getPropertyValue("opacity");
- },
-
- /**
- * Sets a given node's opacity.
- * @param aNode The node to set the opacity value for.
- * @param aOpacity The opacity value to set.
- * @param aCallback The callback to call when finished.
- */
- _setNodeOpacity:
- function Transformation_setNodeOpacity(aNode, aOpacity, aCallback) {
-
- if (this._getNodeOpacity(aNode) == aOpacity) {
- if (aCallback)
- aCallback();
- } else {
- if (aCallback) {
- this._whenTransitionEnded(aNode, ["opacity"], aCallback);
- }
-
- aNode.style.opacity = aOpacity;
- }
- },
-
- /**
- * Moves a site to the cell with the given index.
- * @param aSite The site to move.
- * @param aIndex The target cell's index.
- * @param aOptions Options that are directly passed to slideSiteTo().
- */
- _moveSite: function Transformation_moveSite(aSite, aIndex, aOptions) {
- this.freezeSitePosition(aSite);
- this.slideSiteTo(aSite, gGrid.cells[aIndex], aOptions);
- },
-
- /**
- * Checks whether a site is currently frozen.
- * @param aSite The site to check.
- * @return Whether the given site is frozen.
- */
- _isFrozen: function Transformation_isFrozen(aSite) {
- return aSite.node.hasAttribute("frozen");
- }
-};
diff --git a/components/newtab/undo.js b/components/newtab/undo.js
deleted file mode 100644
index b856914..0000000
--- a/components/newtab/undo.js
+++ /dev/null
@@ -1,116 +0,0 @@
-#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
-
-/**
- * Dialog allowing to undo the removal of single site or to completely restore
- * the grid's original state.
- */
-var gUndoDialog = {
- /**
- * The undo dialog's timeout in miliseconds.
- */
- HIDE_TIMEOUT_MS: 15000,
-
- /**
- * Contains undo information.
- */
- _undoData: null,
-
- /**
- * Initializes the undo dialog.
- */
- init: function UndoDialog_init() {
- this._undoContainer = document.getElementById("newtab-undo-container");
- this._undoContainer.addEventListener("click", this, false);
- this._undoButton = document.getElementById("newtab-undo-button");
- this._undoCloseButton = document.getElementById("newtab-undo-close-button");
- this._undoRestoreButton = document.getElementById("newtab-undo-restore-button");
- },
-
- /**
- * Shows the undo dialog.
- * @param aSite The site that just got removed.
- */
- show: function UndoDialog_show(aSite) {
- if (this._undoData)
- clearTimeout(this._undoData.timeout);
-
- this._undoData = {
- index: aSite.cell.index,
- wasPinned: aSite.isPinned(),
- blockedLink: aSite.link,
- timeout: setTimeout(this.hide.bind(this), this.HIDE_TIMEOUT_MS)
- };
-
- this._undoContainer.removeAttribute("undo-disabled");
- this._undoButton.removeAttribute("tabindex");
- this._undoCloseButton.removeAttribute("tabindex");
- this._undoRestoreButton.removeAttribute("tabindex");
- },
-
- /**
- * Hides the undo dialog.
- */
- hide: function UndoDialog_hide() {
- if (!this._undoData)
- return;
-
- clearTimeout(this._undoData.timeout);
- this._undoData = null;
- this._undoContainer.setAttribute("undo-disabled", "true");
- this._undoButton.setAttribute("tabindex", "-1");
- this._undoCloseButton.setAttribute("tabindex", "-1");
- this._undoRestoreButton.setAttribute("tabindex", "-1");
- },
-
- /**
- * The undo dialog event handler.
- * @param aEvent The event to handle.
- */
- handleEvent: function UndoDialog_handleEvent(aEvent) {
- switch (aEvent.target.id) {
- case "newtab-undo-button":
- this._undo();
- break;
- case "newtab-undo-restore-button":
- this._undoAll();
- break;
- case "newtab-undo-close-button":
- this.hide();
- break;
- }
- },
-
- /**
- * Undo the last blocked site.
- */
- _undo: function UndoDialog_undo() {
- if (!this._undoData)
- return;
-
- let {index, wasPinned, blockedLink} = this._undoData;
- gBlockedLinks.unblock(blockedLink);
-
- if (wasPinned) {
- gPinnedLinks.pin(blockedLink, index);
- }
-
- gUpdater.updateGrid();
- this.hide();
- },
-
- /**
- * Undo all blocked sites.
- */
- _undoAll: function UndoDialog_undoAll() {
- NewTabUtils.undoAll(function() {
- gUpdater.updateGrid();
- this.hide();
- }.bind(this));
- }
-};
-
-gUndoDialog.init();
diff --git a/components/newtab/updater.js b/components/newtab/updater.js
deleted file mode 100644
index 2bab74d..0000000
--- a/components/newtab/updater.js
+++ /dev/null
@@ -1,177 +0,0 @@
-#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 singleton provides functionality to update the current grid to a new
- * set of pinned and blocked sites. It adds, moves and removes sites.
- */
-var gUpdater = {
- /**
- * Updates the current grid according to its pinned and blocked sites.
- * This removes old, moves existing and creates new sites to fill gaps.
- * @param aCallback The callback to call when finished.
- */
- updateGrid: function Updater_updateGrid(aCallback) {
- let links = gLinks.getLinks().slice(0, gGrid.cells.length);
-
- // Find all sites that remain in the grid.
- let sites = this._findRemainingSites(links);
-
- // Remove sites that are no longer in the grid.
- this._removeLegacySites(sites, () => {
- // Freeze all site positions so that we can move their DOM nodes around
- // without any visual impact.
- this._freezeSitePositions(sites);
-
- // Move the sites' DOM nodes to their new position in the DOM. This will
- // have no visual effect as all the sites have been frozen and will
- // remain in their current position.
- this._moveSiteNodes(sites);
-
- // Now it's time to animate the sites actually moving to their new
- // positions.
- this._rearrangeSites(sites, () => {
- // Try to fill empty cells and finish.
- this._fillEmptyCells(links, aCallback);
-
- // Update other pages that might be open to keep them synced.
- gAllPages.update(gPage);
- });
- });
- },
-
- /**
- * Takes an array of links and tries to correlate them to sites contained in
- * the current grid. If no corresponding site can be found (i.e. the link is
- * new and a site will be created) then just set it to null.
- * @param aLinks The array of links to find sites for.
- * @return Array of sites mapped to the given links (can contain null values).
- */
- _findRemainingSites: function Updater_findRemainingSites(aLinks) {
- let map = {};
-
- // Create a map to easily retrieve the site for a given URL.
- gGrid.sites.forEach(function (aSite) {
- if (aSite)
- map[aSite.url] = aSite;
- });
-
- // Map each link to its corresponding site, if any.
- return aLinks.map(function (aLink) {
- return aLink && (aLink.url in map) && map[aLink.url];
- });
- },
-
- /**
- * Freezes the given sites' positions.
- * @param aSites The array of sites to freeze.
- */
- _freezeSitePositions: function Updater_freezeSitePositions(aSites) {
- aSites.forEach(function (aSite) {
- if (aSite)
- gTransformation.freezeSitePosition(aSite);
- });
- },
-
- /**
- * Moves the given sites' DOM nodes to their new positions.
- * @param aSites The array of sites to move.
- */
- _moveSiteNodes: function Updater_moveSiteNodes(aSites) {
- let cells = gGrid.cells;
-
- // Truncate the given array of sites to not have more sites than cells.
- // This can happen when the user drags a bookmark (or any other new kind
- // of link) onto the grid.
- let sites = aSites.slice(0, cells.length);
-
- sites.forEach(function (aSite, aIndex) {
- let cell = cells[aIndex];
- let cellSite = cell.site;
-
- // The site's position didn't change.
- if (!aSite || cellSite != aSite) {
- let cellNode = cell.node;
-
- // Empty the cell if necessary.
- if (cellSite)
- cellNode.removeChild(cellSite.node);
-
- // Put the new site in place, if any.
- if (aSite)
- cellNode.appendChild(aSite.node);
- }
- }, this);
- },
-
- /**
- * Rearranges the given sites and slides them to their new positions.
- * @param aSites The array of sites to re-arrange.
- * @param aCallback The callback to call when finished.
- */
- _rearrangeSites: function Updater_rearrangeSites(aSites, aCallback) {
- let options = {callback: aCallback, unfreeze: true};
- gTransformation.rearrangeSites(aSites, options);
- },
-
- /**
- * Removes all sites from the grid that are not in the given links array or
- * exceed the grid.
- * @param aSites The array of sites remaining in the grid.
- * @param aCallback The callback to call when finished.
- */
- _removeLegacySites: function Updater_removeLegacySites(aSites, aCallback) {
- let batch = [];
-
- // Delete sites that were removed from the grid.
- gGrid.sites.forEach(function (aSite) {
- // The site must be valid and not in the current grid.
- if (!aSite || aSites.indexOf(aSite) != -1)
- return;
-
- batch.push(new Promise(resolve => {
- // Fade out the to-be-removed site.
- gTransformation.hideSite(aSite, function () {
- let node = aSite.node;
-
- // Remove the site from the DOM.
- node.parentNode.removeChild(node);
- resolve();
- });
- }));
- });
-
- Promise.all(batch).then(aCallback);
- },
-
- /**
- * Tries to fill empty cells with new links if available.
- * @param aLinks The array of links.
- * @param aCallback The callback to call when finished.
- */
- _fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) {
- let {cells, sites} = gGrid;
-
- // Find empty cells and fill them.
- Promise.all(sites.map((aSite, aIndex) => {
- if (aSite || !aLinks[aIndex])
- return null;
-
- return new Promise(resolve => {
- // Create the new site and fade it in.
- let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]);
-
- // Set the site's initial opacity to zero.
- site.node.style.opacity = 0;
-
- // Flush all style changes for the dynamically inserted site to make
- // the fade-in transition work.
- window.getComputedStyle(site.node).opacity;
- gTransformation.showSite(site, resolve);
- });
- })).then(aCallback).catch(console.exception);
- }
-};