mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-06 15:58:39 +09:00
Issue #517 Part 1: Import newtab page from Basilisk (sans directory service provider module)
This commit is contained in:
parent
a179019413
commit
48cdeab201
20 changed files with 4821 additions and 314 deletions
|
|
@ -1056,11 +1056,18 @@ pref("browser.newtabpage.enabled", true);
|
|||
// XXX: Remove this when "enhanced" tiles are dead
|
||||
pref("browser.newtabpage.enhanced", false);
|
||||
|
||||
// enables showing basic placeholders for missing thumbnails
|
||||
pref("browser.newtabpage.thumbnailPlaceholder", false);
|
||||
|
||||
pref("browser.newtabpage.compact", false);
|
||||
|
||||
pref("privacy.usercontext.about_newtab_segregation.enabled", false);
|
||||
|
||||
// number of columns of newtab grid
|
||||
pref("browser.newtabpage.columns", 4);
|
||||
|
||||
// number of rows of newtab grid
|
||||
pref("browser.newtabpage.rows", 4);
|
||||
pref("browser.newtabpage.rows", 3);
|
||||
|
||||
// Enable the DOM fullscreen API.
|
||||
pref("full-screen-api.enabled", true);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"directory": [
|
||||
{
|
||||
"bgColor": "#ffffff",
|
||||
"directoryId": 10000000,
|
||||
"imageURI": "data:image/png;base64,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",
|
||||
"type": "affiliate",
|
||||
"title": "Google",
|
||||
"url": "https://www.google.com/"
|
||||
},
|
||||
{
|
||||
"bgColor": "#E62117",
|
||||
"directoryId": 10000001,
|
||||
"imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAACd0lEQVR4nO3av0tVYRzH8WOIBEVDUUIGCa32FwQ5OrS42NKeRUOTdGmoqUGiLVBqa5UG+7WUREGiEqhTDkVJEA2iYZBkxKvhHumo96o3uM9z0ucNZ7zn834+XO59znm+WZZIJBKJRCKRSGwCx3AWfbiIaxjEPYzgOd7gLWbwIb8WsFjjWrU9q3U+u1C4/0yeOZ47jOROg6jkrn25e3uji27NbzC9A9n/hWnVNbVut/hOTMZ1bSqT6Ky3+A58jOsXhE/o2Lj4FryILBaSF2gpFtAT2ygCPcUCHse2icDTtcW3YSW2TQRW0JahK7ZJRLoy9Ma2iEhvhoHYFhEZyDAU2yIiwxkeBgj6FSDjXxjN8CpA0A1cxucAWY0wkeFdgKBK/pe7H1fxNUDmTpjLMB8gqLJh631A9dF6IUD2Vsxn+BYgaF0BhSIO4WYgh1osZVgOEFSzgEIRh3EL3wO4FFnOAgVtWUChiKO4gx+BvJSqgEIRx3EXP5stVsoCCkWcxH1N3EeUuoBCEafwshlipS8AJzTxW1DaAnAEtzX5B7F0BeAgrmMphFhpClB9M3UFXwI5oQQFYB8u4H0gl3VE3QninOoxVyyWozwL4AxeB8jdjqWgT4M4jUcB8nbKfKj3AUN4gN8BshphLtQbobIyEeqdYFkZzTAc2yIiw+lcQDoZSmeDe/t0ON+gPIltE4Fnxa3pnp8QacFYbKOAjCnOCOUldKhOUO12Nk+JFUroxFRkwWYypd6cYKGEVvTbfZOil2w3KVqjjHZ047xqKRWbZ4XHVed2Z/2d5a0167vYgHC9z6/df9bWs8L9uXO3RmeFE4lEIpFIJPYKfwAcall+TY3q/wAAAABJRU5ErkJggg==",
|
||||
"type": "affiliate",
|
||||
"title": "YouTube",
|
||||
"url": "https://www.youtube.com/"
|
||||
},
|
||||
{
|
||||
"directoryId": 10000002,
|
||||
"imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAACT0lEQVR4nO3bzWsTQRgG8PlPHMVLqRVMoQiFehJyUBAFtRCFHspExaaSoFg8CMGPSg+R3kQhh3osIbOlMVrbGKtrsbYESTbB0gqNVGu1WCkWutnXg+ihQjqxi7Oz8w481533+V32iyGEEEIZ76Rho0SZ4ewOG+D3UMatXSx9nPwqb5ySPZC0dPMzhDJelD6IrDCjQijjtvRBJIWGeY3IHkJ2EED2ALKDALIHkB2lAJoujkIwnoNQwoQL96aha3AKQgkTTtyZhKM383D4+gQEoll/AQRiWbg1XILZ+VWwaw6IrE3bgZbejNoAe8+PwEC6DOsbm0Klt679lxQGCESzMD335Z+KKw+wrzcDpcVvOyqvNMCwubjj8soCnBx44Up5ZQGeFZf1BWi7/BhqjthtzpcAseRsQwVrjgNzS9/hZWUFJq3Pf6U5MqoWQHJ8Qbh8aqoKB688cWVfzwBMvP0kVN6srMCec+7t6xmAmfmvQgCRBzOu7usZgHJ1TQjgyI283gCHrj3VG6C9bwwBEAABEEAtgAPRR9A3VKibpdUfQgD9KWvba529+8pbAMF4TqicW+th/r3eAP0pS2+Anvtv9AY4dvu53gCtMfGfI74DWN+wG5rNdwDl6preAGOFj3oDJMcXvAfQHMlAKGHWTeWD2KPw1aFC3et0NPi9wDPvAq/fif0LDMZzru6LALKLIwACIAACIAACIAACIAACIAACIAACIAACIMD/BvDKwUkZAJRx2zNHZyUBFAntTp+WXV4iQCf5c3yecUsXAMq49bv8Txsl6ZCTabOAAAAAAElFTkSuQmCC",
|
||||
"title": "Facebook",
|
||||
"type": "affiliate",
|
||||
"url": "https://www.facebook.com/"
|
||||
},
|
||||
{
|
||||
"bgColor": "#ffffff",
|
||||
"directoryId": 10000003,
|
||||
"imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA/CAYAAABQHc7KAAAEyUlEQVRoge2abYhVRRjHf7veVqSFhIQwa7E3ojXNpSiNgl0S+tAHKUjohbQohUgqKKwMSXpbsATdqOgFU4zKpAzMioploxI/WFBZmhRlL/S2lbpsudvd24dzjve5c58558ycey9B84MB95x5/vM/d+bMzDNHCAQCgUAgEAgE/rf0AOd6lJmKVrdDfI8SfxawIKNcEscfa8TOzBFrlj6Aimd5XnmAbx01TD5xiL3IiH3Y8zm4DXgaGALGMip/DDwHDACXKQ9wA/AiMJyi8T3wAnCvEr841t9tiR2JY/uB443YC4BHgA3ApyntTxD90FuAlaaBU4EfLIHvKIZtnAT8ZtE5O6fGCiNuFJiTM7YNWKe0PQScmRV8ncX4+zkbT1hq0bkyZ/wyI+5ux/bPM+I/ACbnCSyhv8tloMvBQAnYr+h8mDP+PRHzGXCMQ9sA14j4ceAMl+A70HtvjaMJ22jqy4i70Kh/sWO7AO+K+Jdcg6cCh6k3/gfQ6aBTAr5UdN7OiHtL1H3NxXhMN9Fkl2jM89BgPXrv3eKoc71Fx2ZqvqhTJv+kKRkQGjs94gE4PTZgGt9DNMvmpQR8pehst9R/Q9TZ5OG7EzgkNK720DjKNvTeu9RRZ4miMUH9bnCeuH8EOMXD881C40egw0PjKL3oP8Cbjjq2FWGrUW+HuDfg6XmP0NA2W060GYKy97odtbQVoQzMiu+fL66PACd4+O0VGqPANA+NOm5CHwVPOeqUgH2Kzub4/uvi2gOeXrcU8GdlCtG7ZBr/C5juqHWtojMOXCX+HgaO8/B5YqyV6GjZpjf3oI+C+x11JgF7FZ1/xL/v9PS4WmgMempYsW2MfsdtYwTRsqT9mBXgANGIc6WD2lG60EMjk0fRTS931GkHPrdo3ejpbZHQ2B+30XC6iNZm0/Q3RBOcC7Yc4WRPb0NC43ZPjVxsRDe+yFHHHLJJWevhabaIP0z0ujaNWdQmGUn5yEPrPkVnBPe1+0kRv97DhzPb0UdBr6OObZv9kIOGnJzLRPlL0+lFN+6yPe5BH0kV4E/yD+PlIm6bQ/uF2Um98Qlgbs74V5V4WVbl0GgDvsB/BBbiCnTj2lG5yVyqvX+QaOSYOsNk7y8WiPo+c1Ah2tFPesbJTmFfEfX7qU2BZVmRoSPnkMU+D1EUW5L0WErMHKq9P0o149NeqZ+w7wq7qO77f02p11Qmo6/laWnoVlFvnbh+uaJTAW616Dwo6rjmIw3lLnTjminZ+38DM8Q92yv1HfUnOh3AL/H9I7hnpA1lKrXnb0nRkqSXxf0nFC3bK7XMqCdT6o2NeIiirEE3Lvfks6kesI6hf1m2nTt8TW2uIeeLhub8vsxAT5IOUB2+8qTm2RStlYqOnOV7xLXBRj5EUWxJ0hKic/2k98dJ367azh32Es0Tz4hrTcn5fZE9I8s+ajc6m20CgrUWrdVEK0yFJub8RRhEN56UMjk+TVO7xtuK6yFMS1hIuuk82+SETSk6h3A/hmsJ7egfPypEh555ej/hHOzZYktyfl9keiqLzzc+LUlqWc7vSyfRJ3Rpegw4zUOrj/ofoKU5vy/91Jp+vIDWLkPL/J9h/0mmAT9TXa58vvIkzKe6ydpQ3FogEAgEAoFAIBCI+Rf5q90lTPZHIwAAAABJRU5ErkJggg==",
|
||||
"title": "Wikipedia",
|
||||
"type": "affiliate",
|
||||
"url": "https://www.wikipedia.org/"
|
||||
},
|
||||
{
|
||||
"bgColor": "#400090",
|
||||
"directoryId": 10000004,
|
||||
"imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAD3ElEQVR4nO3bS4xecxjH8WmLBVVEx63JBIkEISkhJqURpAsZQioWqpeNSxraYlKpSwiDIRY0aSakqgS9qHRBIhKxYdFFFxWXIGkilYZEUCKj4zLzsfi/LN55zpiZc/lr+/6Ss3nfc57ze77n9r88/y7swxaswgLM7jpMhTlYiNWtnPd1Ga9RfIVtuB+L0J3b/FSFeejDQ9iBvRhrTzYCUKTv8RFewlrcgAtxQsYk5+Ii3IQHsBm78ONkk5oKgIn0Mz7BO3gBA7gHS3EtLsXZre1UnITj2pI5vvV7D85BL67DCvRjEJvwHj7HcBXGqwJwyKoDILeB3OoAyG0gt8oAGMYj0qdnJ17DY3i2vK1CPYmn8Cq2YwgP4rfpBix7BwwE3+aZ2F0ybqQPMSM439NlgpYFMILzAlO9glZXCf2F+cF5LsafZQJX8Q4oujKbK4j9j4aC+EdhT9nAVb0Ebw8MduNABbF/wMlB/LUVxK4MwE84JTC5uoLYK4O48/BrBbEr/Qy+XnCbfloi5h7MCuJurcSxagGMYWFg9qr/SbxQVTeEiq7Ym9OI9UYQ52ipJ1iZ6mgJ3h0Y7zG17usvOC2I01+12ToAHBCMIGHdFGKsCo4/QwJTqerqC2wMEjgGX0zi2KLH6JU6jNYFYBSXBElc/R/HjaE3OO4y1bYs/1WdvcFd4hbilgmOie6cGa1Ytaju7vDSIKHTxc9yUYtvWZ0G6wawH8cGSa0J9r0t2G92K0ZtamJA5PEgsfaOTNHjMlC3uSYADKMnSG6B9GIr6uqehYN1m2tqSGxre4KtJDdhfcF/O5ow1hSAMVweJNmNOcHvlbb3J1KTg6K7MTO62m3Jz1LBQMdk1fSo8IpJALizSUNNA/jWBNPvOFGahG1MOeYFnpgAwHNNm8kB4CDODJI/F380bSbXzNAzAYD1OYzkAjAYABjKYaQDIMdJxQDqnFMsVC4A6wIAgzmMdADkOKkYwKM5jOQCcFcAYCqjxpUpF4Bovu+IB3BfDiO5AIzrFWJlDiO5ACzpABgP4I4cRnIBWBwAWJLDSC4AfR0A4wHcksNILgCLAgB9OYzkAnDFkQ5gDZbj3ta2XCp5bVydYuncBnKrAyC3gdzqAMhtILfqBDCCb6SZ3velatGXsUFa5NC+vdjatrf2/QAfSyUyv9dlsgyAEXyGt/G8VBl+PS7A3PaGTllJCy7n40Zp8GQD3sWXSgCaDIBRqcBxGx7GYmll57hixlySaojPx83SuqW3pLXC0wKwX7oF+3GloILjUJE03X6NtAh8J76LAOzFRtwqKGY63CStX14mLen5+m9Vgqdbrd+9cgAAAABJRU5ErkJggg==",
|
||||
"title": "Yahoo!",
|
||||
"type": "affiliate",
|
||||
"url": "https://www.yahoo.com/"
|
||||
},
|
||||
{
|
||||
"directoryId": 10000005,
|
||||
"imageURI": "data:image/png;base64,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",
|
||||
"title": "Amazon",
|
||||
"type": "affiliate",
|
||||
"url": "https://www.amazon.com/"
|
||||
}
|
||||
]
|
||||
}
|
||||
124
application/palemoon/base/content/newtab/customize.js
Normal file
124
application/palemoon/base/content/newtab/customize.js
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
#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 gCustomize = {
|
||||
_nodeIDSuffixes: [
|
||||
"blank",
|
||||
"button",
|
||||
"classic",
|
||||
"enhanced",
|
||||
"panel",
|
||||
"overlay",
|
||||
"learn"
|
||||
],
|
||||
|
||||
_nodes: {},
|
||||
|
||||
init: function() {
|
||||
for (let idSuffix of this._nodeIDSuffixes) {
|
||||
this._nodes[idSuffix] = document.getElementById("newtab-customize-" + idSuffix);
|
||||
}
|
||||
|
||||
this._nodes.button.addEventListener("click", e => this.showPanel(e));
|
||||
this._nodes.blank.addEventListener("click", this);
|
||||
this._nodes.classic.addEventListener("click", this);
|
||||
this._nodes.learn.addEventListener("click", this);
|
||||
|
||||
this.updateSelected();
|
||||
},
|
||||
|
||||
hidePanel: function() {
|
||||
this._nodes.overlay.addEventListener("transitionend", function onTransitionEnd() {
|
||||
gCustomize._nodes.overlay.removeEventListener("transitionend", onTransitionEnd);
|
||||
gCustomize._nodes.overlay.style.display = "none";
|
||||
});
|
||||
this._nodes.overlay.style.opacity = 0;
|
||||
this._nodes.button.removeAttribute("active");
|
||||
this._nodes.panel.removeAttribute("open");
|
||||
document.removeEventListener("click", this);
|
||||
document.removeEventListener("keydown", this);
|
||||
},
|
||||
|
||||
showPanel: function(event) {
|
||||
if (this._nodes.panel.getAttribute("open") == "true") {
|
||||
return;
|
||||
}
|
||||
|
||||
let {panel, button, overlay} = this._nodes;
|
||||
overlay.style.display = "block";
|
||||
panel.setAttribute("open", "true");
|
||||
button.setAttribute("active", "true");
|
||||
setTimeout(() => {
|
||||
// Wait for display update to take place, then animate.
|
||||
overlay.style.opacity = 0.8;
|
||||
}, 0);
|
||||
|
||||
document.addEventListener("click", this);
|
||||
document.addEventListener("keydown", this);
|
||||
|
||||
// Stop the event propogation to prevent panel from immediately closing
|
||||
// via the document click event that we just added.
|
||||
event.stopPropagation();
|
||||
},
|
||||
|
||||
handleEvent: function(event) {
|
||||
switch (event.type) {
|
||||
case "click":
|
||||
this.onClick(event);
|
||||
break;
|
||||
case "keydown":
|
||||
this.onKeyDown(event);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onClick: function(event) {
|
||||
if (event.currentTarget == document) {
|
||||
if (!this._nodes.panel.contains(event.target)) {
|
||||
this.hidePanel();
|
||||
}
|
||||
}
|
||||
switch (event.currentTarget.id) {
|
||||
case "newtab-customize-blank":
|
||||
sendAsyncMessage("NewTab:Customize", {enabled: false, enhanced: false});
|
||||
break;
|
||||
case "newtab-customize-classic":
|
||||
sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: false});
|
||||
break;
|
||||
case "newtab-customize-enhanced":
|
||||
sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: !gAllPages.enhanced});
|
||||
break;
|
||||
case "newtab-customize-learn":
|
||||
this.showLearn();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onKeyDown: function(event) {
|
||||
if (event.keyCode == event.DOM_VK_ESCAPE) {
|
||||
this.hidePanel();
|
||||
}
|
||||
},
|
||||
|
||||
showLearn: function() {
|
||||
window.open(TILES_INTRO_LINK, 'new_window');
|
||||
this.hidePanel();
|
||||
},
|
||||
|
||||
updateSelected: function() {
|
||||
let {enabled} = gAllPages;
|
||||
let selected = enabled ? "classic" : "blank";
|
||||
["classic", "blank"].forEach(id => {
|
||||
let node = this._nodes[id];
|
||||
if (id == selected) {
|
||||
node.setAttribute("selected", true);
|
||||
}
|
||||
else {
|
||||
node.removeAttribute("selected");
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
@ -140,7 +140,7 @@ var gDrag = {
|
|||
// drag image with its default opacity.
|
||||
let dragElement = document.createElementNS(HTML_NAMESPACE, "div");
|
||||
dragElement.classList.add("newtab-drag");
|
||||
let scrollbox = document.getElementById("newtab-scrollbox");
|
||||
let scrollbox = document.getElementById("newtab-vertical-margin");
|
||||
scrollbox.appendChild(dragElement);
|
||||
dt.setDragImage(dragElement, 0, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ var gDragDataHelper = {
|
|||
|
||||
getLinkFromDragEvent: function DragDataHelper_getLinkFromDragEvent(aEvent) {
|
||||
let dt = aEvent.dataTransfer;
|
||||
if (!dt || !dt.types.contains(this.mimeType)) {
|
||||
if (!dt || !dt.types.includes(this.mimeType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,27 +23,53 @@ var gDropTargetShim = {
|
|||
/**
|
||||
* Initializes the drop target shim.
|
||||
*/
|
||||
init: function DropTargetShim_init() {
|
||||
let node = gGrid.node;
|
||||
init: function () {
|
||||
gGrid.node.addEventListener("dragstart", this, true);
|
||||
},
|
||||
|
||||
// Add drag event handlers.
|
||||
node.addEventListener("dragstart", this, true);
|
||||
node.addEventListener("dragend", 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 DropTargetShim_handleEvent(aEvent) {
|
||||
handleEvent: function (aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "dragstart":
|
||||
this._start(aEvent);
|
||||
this._dragstart(aEvent);
|
||||
break;
|
||||
case "dragenter":
|
||||
aEvent.preventDefault();
|
||||
break;
|
||||
case "dragover":
|
||||
this._dragover(aEvent);
|
||||
break;
|
||||
case "drop":
|
||||
this._drop(aEvent);
|
||||
break;
|
||||
case "dragend":
|
||||
this._end(aEvent);
|
||||
this._dragend(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
|
@ -52,20 +78,81 @@ var gDropTargetShim = {
|
|||
* Handles the 'dragstart' event.
|
||||
* @param aEvent The 'dragstart' event.
|
||||
*/
|
||||
_start: function DropTargetShim_start(aEvent) {
|
||||
_dragstart: function (aEvent) {
|
||||
if (aEvent.target.classList.contains("newtab-link")) {
|
||||
gGrid.lock();
|
||||
|
||||
// XXX bug 505521 - Listen for dragover on the document.
|
||||
document.documentElement.addEventListener("dragover", this, false);
|
||||
this._addEventListeners();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the 'drag' event and determines the current drop target.
|
||||
* @param aEvent The 'drag' event.
|
||||
* Handles the 'dragover' event.
|
||||
* @param aEvent The 'dragover' event.
|
||||
*/
|
||||
_drag: function DropTargetShim_drag(aEvent) {
|
||||
_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);
|
||||
|
||||
|
|
@ -86,54 +173,12 @@ var gDropTargetShim = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the 'dragover' event as long as bug 505521 isn't fixed to get
|
||||
* current mouse cursor coordinates while dragging.
|
||||
* @param aEvent The 'dragover' event.
|
||||
*/
|
||||
_dragover: function DropTargetShim_dragover(aEvent) {
|
||||
let sourceNode = aEvent.dataTransfer.mozSourceNode.parentNode;
|
||||
gDrag.drag(sourceNode._newtabSite, aEvent);
|
||||
|
||||
this._drag(aEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the 'dragend' event.
|
||||
* @param aEvent The 'dragend' event.
|
||||
*/
|
||||
_end: function DropTargetShim_end(aEvent) {
|
||||
// Make sure to determine the current drop target in case the dragenter
|
||||
// event hasn't been fired.
|
||||
this._drag(aEvent);
|
||||
|
||||
if (this._lastDropTarget) {
|
||||
if (aEvent.dataTransfer.mozUserCancelled) {
|
||||
// The drag operation was cancelled.
|
||||
this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
|
||||
this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget);
|
||||
} else {
|
||||
// A site was successfully dropped.
|
||||
this._dispatchEvent(aEvent, "drop", this._lastDropTarget);
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
this._lastDropTarget = null;
|
||||
this._cellPositions = null;
|
||||
}
|
||||
|
||||
gGrid.unlock();
|
||||
|
||||
// XXX bug 505521 - Remove the document's dragover listener.
|
||||
document.documentElement.removeEventListener("dragover", this, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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 DropTargetShim_findDropTarget() {
|
||||
_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;
|
||||
|
|
@ -174,13 +219,12 @@ var gDropTargetShim = {
|
|||
* @param aType The event type.
|
||||
* @param aTarget The target node that receives the event.
|
||||
*/
|
||||
_dispatchEvent:
|
||||
function DropTargetShim_dispatchEvent(aEvent, aType, aTarget) {
|
||||
|
||||
_dispatchEvent: function (aEvent, aType, aTarget) {
|
||||
let node = aTarget.node;
|
||||
let event = document.createEvent("DragEvents");
|
||||
let event = document.createEvent("DragEvent");
|
||||
|
||||
event.initDragEvent(aType, true, true, window, 0, 0, 0, 0, 0, false, false,
|
||||
// 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);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,13 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Define various fixed dimensions
|
||||
*/
|
||||
const GRID_BOTTOM_EXTRA = 7; // title's line-height extends 7px past the margin
|
||||
const GRID_WIDTH_EXTRA = 1; // provide 1px buffer to allow for rounding error
|
||||
const SPONSORED_TAG_BUFFER = 2; // 2px buffer to clip off top of sponsored tag
|
||||
|
||||
/**
|
||||
* This singleton represents the grid that contains all sites.
|
||||
*/
|
||||
|
|
@ -12,6 +19,7 @@ var gGrid = {
|
|||
* The DOM node of the grid.
|
||||
*/
|
||||
_node: null,
|
||||
_gridDefaultContent: null,
|
||||
get node() { return this._node; },
|
||||
|
||||
/**
|
||||
|
|
@ -22,7 +30,7 @@ var gGrid = {
|
|||
/**
|
||||
* All cells contained in the grid.
|
||||
*/
|
||||
_cells: null,
|
||||
_cells: [],
|
||||
get cells() { return this._cells; },
|
||||
|
||||
/**
|
||||
|
|
@ -31,7 +39,10 @@ var gGrid = {
|
|||
get sites() { return [for (cell of this.cells) cell.site]; },
|
||||
|
||||
// Tells whether the grid has already been initialized.
|
||||
get ready() { return !!this._node; },
|
||||
get ready() { return !!this._ready; },
|
||||
|
||||
// Returns whether the page has finished loading yet.
|
||||
get isDocumentLoaded() { return document.readyState == "complete"; },
|
||||
|
||||
/**
|
||||
* Initializes the grid.
|
||||
|
|
@ -39,8 +50,26 @@ var gGrid = {
|
|||
*/
|
||||
init: function Grid_init() {
|
||||
this._node = document.getElementById("newtab-grid");
|
||||
this._gridDefaultContent = this._node.lastChild;
|
||||
this._createSiteFragment();
|
||||
this._render();
|
||||
|
||||
gLinks.populateCache(() => {
|
||||
this._refreshGrid();
|
||||
this._ready = true;
|
||||
|
||||
// If fetching links took longer than loading the page itself then
|
||||
// we need to resize the grid as that was blocked until now.
|
||||
// We also want to resize now if the page was already loaded when
|
||||
// initializing the grid (the user toggled the page).
|
||||
this._resizeGrid();
|
||||
|
||||
addEventListener("resize", this);
|
||||
});
|
||||
|
||||
// Resize the grid as soon as the page loads.
|
||||
if (!this.isDocumentLoaded) {
|
||||
addEventListener("load", this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -56,25 +85,15 @@ var gGrid = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Refreshes the grid and re-creates all sites.
|
||||
* Handles all grid events.
|
||||
*/
|
||||
refresh: function Grid_refresh() {
|
||||
let cells = this.cells;
|
||||
if (!cells) {
|
||||
return;
|
||||
handleEvent: function Grid_handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "load":
|
||||
case "resize":
|
||||
this._resizeGrid();
|
||||
break;
|
||||
}
|
||||
|
||||
// Remove all sites.
|
||||
cells.forEach(function (cell) {
|
||||
let node = cell.node;
|
||||
let child = node.firstElementChild;
|
||||
|
||||
if (child)
|
||||
node.removeChild(child);
|
||||
}, this);
|
||||
|
||||
// Render the grid again.
|
||||
this._render();
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -92,34 +111,65 @@ var gGrid = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Creates the newtab grid.
|
||||
* Renders and resizes the gird. _resizeGrid() call is needed to ensure
|
||||
* that scrollbar disappears when the bottom row becomes empty following
|
||||
* the block action, or tile display is turmed off via cog menu
|
||||
*/
|
||||
_renderGrid: function Grid_renderGrid() {
|
||||
let row = document.createElementNS(HTML_NAMESPACE, "div");
|
||||
|
||||
refresh() {
|
||||
this._refreshGrid();
|
||||
this._resizeGrid();
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders the grid, including cells and sites.
|
||||
*/
|
||||
_refreshGrid() {
|
||||
let cell = document.createElementNS(HTML_NAMESPACE, "div");
|
||||
row.classList.add("newtab-row");
|
||||
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));
|
||||
// Creates all the cells up to the maximum
|
||||
let fragment = document.createDocumentFragment();
|
||||
for (let i = 0; i < gGridPrefs.gridColumns * gGridPrefs.gridRows; i++) {
|
||||
fragment.appendChild(cell.cloneNode(true));
|
||||
}
|
||||
|
||||
// (Re-)initialize all cells.
|
||||
let cellElements = this.node.querySelectorAll(".newtab-cell");
|
||||
// Tycho: this._cells = [new Cell(this, cell) for (cell of cellElements)];
|
||||
this._cells = [];
|
||||
|
||||
for (let cellItem of cellElements) {
|
||||
this._cells.push(new Cell(this, cellItem));
|
||||
// Create cells.
|
||||
let cells = Array.from(fragment.childNodes, (cell) => new Cell(this, cell));
|
||||
|
||||
// Fetch links.
|
||||
let links = gLinks.getLinks();
|
||||
|
||||
// Create sites.
|
||||
let numLinks = Math.min(links.length, cells.length);
|
||||
let hasHistoryTiles = false;
|
||||
for (let i = 0; i < numLinks; i++) {
|
||||
if (links[i]) {
|
||||
this.createSite(links[i], cells[i]);
|
||||
if (links[i].type == "history") {
|
||||
hasHistoryTiles = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._cells = cells;
|
||||
while (this._gridDefaultContent.nextSibling) {
|
||||
this._gridDefaultContent.nextSibling.remove();
|
||||
}
|
||||
this._node.appendChild(fragment);
|
||||
|
||||
document.getElementById("topsites-heading").textContent =
|
||||
hasHistoryTiles ? "Your Top Sites" : "Top Sites";
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculate the height for a number of rows up to the maximum rows
|
||||
* @param rows Number of rows defaulting to the max
|
||||
*/
|
||||
_computeHeight: function Grid_computeHeight(aRows) {
|
||||
let {gridRows} = gGridPrefs;
|
||||
aRows = aRows === undefined ? gridRows : Math.min(gridRows, aRows);
|
||||
return aRows * this._cellHeight + GRID_BOTTOM_EXTRA;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -132,50 +182,98 @@ var gGrid = {
|
|||
|
||||
// Create the site's inner HTML code.
|
||||
site.innerHTML =
|
||||
'<span class="newtab-sponsored">' + newTabString("sponsored.button") + '</span>' +
|
||||
'<a class="newtab-link">' +
|
||||
' <span class="newtab-thumbnail"/>' +
|
||||
' <span class="newtab-thumbnail placeholder"/>' +
|
||||
' <span class="newtab-thumbnail thumbnail"/>' +
|
||||
' <span class="newtab-thumbnail enhanced-content"/>' +
|
||||
' <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"/>';
|
||||
' class="newtab-control newtab-control-block"/>' +
|
||||
'<span class="newtab-suggested"/>';
|
||||
|
||||
this._siteFragment = document.createDocumentFragment();
|
||||
this._siteFragment.appendChild(site);
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders the sites, creates all sites and puts them into their cells.
|
||||
* Test a tile at a given position for being pinned or history
|
||||
* @param position Position in sites array
|
||||
*/
|
||||
_renderSites: function Grid_renderSites() {
|
||||
let cells = this.cells;
|
||||
// Put sites into the cells.
|
||||
let links = gLinks.getLinks();
|
||||
let length = Math.min(links.length, cells.length);
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (links[i])
|
||||
this.createSite(links[i], cells[i]);
|
||||
}
|
||||
_isHistoricalTile: function Grid_isHistoricalTile(aPos) {
|
||||
let site = this.sites[aPos];
|
||||
return site && (site.isPinned() || site.link && site.link.type == "history");
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders the grid.
|
||||
* Make sure the correct number of rows and columns are visible
|
||||
*/
|
||||
_render: function Grid_render() {
|
||||
if (this._shouldRenderGrid()) {
|
||||
this._renderGrid();
|
||||
_resizeGrid: function Grid_resizeGrid() {
|
||||
// If we're somehow called before the page has finished loading,
|
||||
// let's bail out to avoid caching zero heights and widths.
|
||||
// We'll be called again when DOMContentLoaded fires.
|
||||
// Same goes for the grid if that's not ready yet.
|
||||
if (!this.isDocumentLoaded || !this._ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._renderSites();
|
||||
},
|
||||
// Save the cell's computed height/width including margin and border
|
||||
if (this._cellHeight === undefined) {
|
||||
let refCell = document.querySelector(".newtab-cell");
|
||||
let style = getComputedStyle(refCell);
|
||||
this._cellHeight = refCell.offsetHeight +
|
||||
parseFloat(style.marginTop) + parseFloat(style.marginBottom);
|
||||
this._cellWidth = refCell.offsetWidth +
|
||||
parseFloat(style.marginLeft) + parseFloat(style.marginRight);
|
||||
}
|
||||
|
||||
_shouldRenderGrid : function Grid_shouldRenderGrid() {
|
||||
let rowsLength = this._node.querySelectorAll(".newtab-row").length;
|
||||
let cellsLength = this._node.querySelectorAll(".newtab-cell").length;
|
||||
let searchContainer = document.querySelector("#newtab-search-container");
|
||||
// Save search-container margin height
|
||||
if (this._searchContainerMargin === undefined) {
|
||||
let style = getComputedStyle(searchContainer);
|
||||
this._searchContainerMargin = parseFloat(style.marginBottom) +
|
||||
parseFloat(style.marginTop);
|
||||
}
|
||||
|
||||
return (rowsLength != gGridPrefs.gridRows ||
|
||||
cellsLength != (gGridPrefs.gridRows * gGridPrefs.gridColumns));
|
||||
// Find the number of rows we can place into view port
|
||||
let availHeight = document.documentElement.clientHeight -
|
||||
searchContainer.offsetHeight - this._searchContainerMargin;
|
||||
let visibleRows = Math.floor(availHeight / this._cellHeight);
|
||||
|
||||
// Find the number of columns that fit into view port
|
||||
let maxGridWidth = gGridPrefs.gridColumns * this._cellWidth + GRID_WIDTH_EXTRA;
|
||||
// available width is current grid width, but no greater than maxGridWidth
|
||||
let availWidth = Math.min(document.querySelector("#newtab-grid").clientWidth,
|
||||
maxGridWidth);
|
||||
// finally get the number of columns we can fit into view port
|
||||
let gridColumns = Math.floor(availWidth / this._cellWidth);
|
||||
// walk sites backwords until a pinned or history tile is found or visibleRows reached
|
||||
let tileIndex = Math.min(gGridPrefs.gridRows * gridColumns, this.sites.length) - 1;
|
||||
while (tileIndex >= visibleRows * gridColumns) {
|
||||
if (this._isHistoricalTile(tileIndex)) {
|
||||
break;
|
||||
}
|
||||
tileIndex--;
|
||||
}
|
||||
|
||||
// Compute the actual number of grid rows we will display (potentially
|
||||
// with a scroll bar). tileIndex now points to a historical tile with
|
||||
// heighest index or to the last index of the visible row, if none found
|
||||
// Dividing tileIndex by number of tiles in a column gives the rows
|
||||
let gridRows = Math.floor(tileIndex / gridColumns) + 1;
|
||||
|
||||
// we need to set grid width, for otherwise the scrollbar may shrink
|
||||
// the grid when shown and cause grid layout to be different from
|
||||
// what being computed above. This, in turn, may cause scrollbar shown
|
||||
// for directory tiles, and introduce jitter when grid width is aligned
|
||||
// exactly on the column boundary
|
||||
this._node.style.width = gridColumns * this._cellWidth + "px";
|
||||
this._node.style.maxWidth = gGridPrefs.gridColumns * this._cellWidth +
|
||||
GRID_WIDTH_EXTRA + "px";
|
||||
this._node.style.height = this._computeHeight() + "px";
|
||||
this._node.style.maxHeight = this._computeHeight(gridRows) - SPONSORED_TAG_BUFFER + "px";
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,26 +2,37 @@
|
|||
* 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;
|
||||
}
|
||||
|
||||
/* SCROLLBOX */
|
||||
#newtab-scrollbox {
|
||||
display: -moz-box;
|
||||
position: relative;
|
||||
-moz-box-flex: 1;
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
#newtab-scrollbox:not([page-disabled]) {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* UNDO */
|
||||
#newtab-undo-container {
|
||||
transition: opacity 100ms ease-out;
|
||||
display: -moz-box;
|
||||
-moz-box-align: center;
|
||||
-moz-box-pack: center;
|
||||
}
|
||||
|
|
@ -31,15 +42,16 @@ input[type=button] {
|
|||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* TOGGLE */
|
||||
#newtab-toggle {
|
||||
/* CUSTOMIZE */
|
||||
#newtab-customize-button {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
top: 10px;
|
||||
right: 20px;
|
||||
z-index: 101;
|
||||
}
|
||||
|
||||
#newtab-toggle:-moz-locale-dir(rtl) {
|
||||
left: 12px;
|
||||
#newtab-customize-button:dir(rtl) {
|
||||
left: 20px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
|
|
@ -51,39 +63,52 @@ input[type=button] {
|
|||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
#newtab-margin-top {
|
||||
min-height: 50px;
|
||||
max-height: 80px;
|
||||
#newtab-margin-undo-container {
|
||||
display: -moz-box;
|
||||
-moz-box-flex: 1;
|
||||
-moz-box-align: center;
|
||||
-moz-box-pack: center;
|
||||
left: 6px;
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#newtab-margin-bottom {
|
||||
min-height: 40px;
|
||||
max-height: 100px;
|
||||
-moz-box-flex: 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;
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
#newtab-margin-top,
|
||||
#newtab-margin-bottom {
|
||||
display: -moz-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#newtab-margin-top {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
#newtab-margin-bottom {
|
||||
-moz-box-flex: 2;
|
||||
}
|
||||
|
||||
.newtab-side-margin {
|
||||
min-width: 40px;
|
||||
max-width: 300px;
|
||||
min-width: 10px;
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
/* GRID */
|
||||
#newtab-grid {
|
||||
display: -moz-box;
|
||||
-moz-box-flex: 5;
|
||||
-moz-box-orient: vertical;
|
||||
min-width: 600px;
|
||||
min-height: 400px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
transition: 100ms ease-out;
|
||||
transition-property: opacity;
|
||||
}
|
||||
|
|
@ -97,18 +122,28 @@ input[type=button] {
|
|||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ROWS */
|
||||
.newtab-row {
|
||||
display: -moz-box;
|
||||
-moz-box-orient: horizontal;
|
||||
-moz-box-direction: normal;
|
||||
-moz-box-flex: 1;
|
||||
body:not(.compact) #topsites-heading {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* If you change the sizes here, make sure you
|
||||
* change the preferences:
|
||||
* toolkit.pageThumbs.minWidth
|
||||
* toolkit.pageThumbs.minHeight
|
||||
*/
|
||||
/* CELLS */
|
||||
.newtab-cell {
|
||||
display: -moz-box;
|
||||
-moz-box-flex: 1;
|
||||
height: 210px;
|
||||
margin: 20px 10px 35px;
|
||||
width: 290px;
|
||||
}
|
||||
|
||||
body.compact .newtab-cell {
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
/* SITES */
|
||||
|
|
@ -139,38 +174,130 @@ input[type=button] {
|
|||
bottom: 0;
|
||||
}
|
||||
|
||||
.newtab-thumbnail {
|
||||
opacity: .8;
|
||||
transition: opacity 100ms ease-out;
|
||||
}
|
||||
|
||||
.newtab-thumbnail[dragged],
|
||||
.newtab-link:-moz-focusring > .newtab-thumbnail,
|
||||
.newtab-site:hover > .newtab-link > .newtab-thumbnail {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* TITLES */
|
||||
.newtab-title {
|
||||
.newtab-sponsored,
|
||||
.newtab-title,
|
||||
.newtab-suggested {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.newtab-sponsored,
|
||||
.newtab-title {
|
||||
bottom: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.newtab-suggested {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2px;
|
||||
font-size: 12px;
|
||||
height: 17px;
|
||||
line-height: 17px;
|
||||
margin-bottom: -1px;
|
||||
padding: 2px 8px;
|
||||
display: none;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
top: 215px;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.newtab-suggested-bounds {
|
||||
max-height: 34px; /* 34 / 17 = 2 lines maximum */
|
||||
}
|
||||
|
||||
.newtab-title {
|
||||
left: 0;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.newtab-sponsored {
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #E2E2E2;
|
||||
border-radius: 3px;
|
||||
color: #4A4A4A;
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
font-family: Arial;
|
||||
font-size: 9px;
|
||||
height: 17px;
|
||||
left: 0;
|
||||
line-height: 6px;
|
||||
padding: 4px;
|
||||
right: auto;
|
||||
top: -15px;
|
||||
}
|
||||
|
||||
.newtab-site[suggested=true] > .newtab-sponsored {
|
||||
background-color: #E2E2E2;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.newtab-site > .newtab-sponsored:-moz-any(:hover, [active]) {
|
||||
background-color: #4A90E2;
|
||||
border: 0;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.newtab-site > .newtab-sponsored[active] {
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.newtab-sponsored:dir(rtl) {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
.newtab-site:-moz-any([type=enhanced], [type=sponsored], [suggested]) .newtab-sponsored {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.newtab-site[suggested] .newtab-suggested {
|
||||
display: table;
|
||||
}
|
||||
|
||||
.sponsored-explain,
|
||||
.sponsored-explain a,
|
||||
.suggested-explain,
|
||||
.suggested-explain a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.sponsored-explain,
|
||||
.suggested-explain {
|
||||
background-color: rgba(51, 51, 51, 0.95);
|
||||
bottom: 30px;
|
||||
line-height: 20px;
|
||||
padding: 15px 10px;
|
||||
position: absolute;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.sponsored-explain input,
|
||||
.suggested-explain input {
|
||||
background-size: 18px;
|
||||
height: 18px;
|
||||
opacity: 1;
|
||||
pointer-events: none;
|
||||
position: static;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
/* CONTROLS */
|
||||
.newtab-control {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
opacity: 0;
|
||||
transition: opacity 100ms ease-out;
|
||||
}
|
||||
|
||||
.newtab-control:-moz-focusring,
|
||||
.newtab-site:hover > .newtab-control {
|
||||
.newtab-cell:not([ignorehover]) > .newtab-site:hover > .newtab-control {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
|
@ -184,16 +311,6 @@ input[type=button] {
|
|||
}
|
||||
}
|
||||
|
||||
.newtab-control-pin:-moz-locale-dir(ltr),
|
||||
.newtab-control-block:-moz-locale-dir(rtl) {
|
||||
left: 4px;
|
||||
}
|
||||
|
||||
.newtab-control-block:-moz-locale-dir(ltr),
|
||||
.newtab-control-pin:-moz-locale-dir(rtl) {
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
/* DRAG & DROP */
|
||||
|
||||
/*
|
||||
|
|
@ -207,3 +324,331 @@ input[type=button] {
|
|||
background-color: #fff;
|
||||
opacity: 0.01;
|
||||
}
|
||||
|
||||
/* SEARCH */
|
||||
#newtab-search-container {
|
||||
display: -moz-box;
|
||||
position: relative;
|
||||
-moz-box-pack: center;
|
||||
margin: 40px 0 15px;
|
||||
}
|
||||
|
||||
body.compact #newtab-search-container {
|
||||
margin-top: 0;
|
||||
margin-bottom: 80px;
|
||||
}
|
||||
|
||||
#newtab-search-container[page-disabled] {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#newtab-search-form {
|
||||
display: -moz-box;
|
||||
position: relative;
|
||||
height: 36px;
|
||||
-moz-box-flex: 1;
|
||||
max-width: 600px; /* 2 * (290 cell width + 10 cell margin) */
|
||||
}
|
||||
|
||||
#newtab-search-icon {
|
||||
border: 1px transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background: url("chrome://browser/skin/search-indicator-magnifying-glass.svg") center center no-repeat;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#newtab-search-text {
|
||||
-moz-box-flex: 1;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
padding-inline-start: 34px;
|
||||
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;
|
||||
}
|
||||
|
||||
#newtab-search-text:dir(rtl) {
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
|
||||
#newtab-search-text[aria-expanded="true"] {
|
||||
border-radius: 2px 0 0 0;
|
||||
}
|
||||
|
||||
#newtab-search-text[aria-expanded="true"]:dir(rtl) {
|
||||
border-radius: 0 2px 0 0;
|
||||
}
|
||||
|
||||
#newtab-search-text[keepfocus],
|
||||
#newtab-search-text:focus,
|
||||
#newtab-search-text[autofocus] {
|
||||
border-color: hsla(206,100%,60%,.6) hsla(206,76%,52%,.6) hsla(204,100%,40%,.6);
|
||||
}
|
||||
|
||||
#newtab-search-submit {
|
||||
margin-inline-start: -1px;
|
||||
color: transparent;
|
||||
background: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go") center center no-repeat, linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.1)) padding-box;
|
||||
padding: 0;
|
||||
border: 1px solid;
|
||||
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
|
||||
border-radius: 0 2px 2px 0;
|
||||
border-inline-start: 1px solid transparent;
|
||||
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;
|
||||
}
|
||||
|
||||
#newtab-search-submit:dir(rtl) {
|
||||
border-radius: 2px 0 0 2px;
|
||||
background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-rtl"), linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.1));
|
||||
}
|
||||
|
||||
#newtab-search-text:focus + #newtab-search-submit,
|
||||
#newtab-search-text + #newtab-search-submit:hover,
|
||||
#newtab-search-text[autofocus] + #newtab-search-submit {
|
||||
border-color: #59b5fc #45a3e7 #3294d5;
|
||||
}
|
||||
|
||||
#newtab-search-text:focus + #newtab-search-submit,
|
||||
#newtab-search-text[keepfocus] + #newtab-search-submit,
|
||||
#newtab-search-text[autofocus] + #newtab-search-submit {
|
||||
background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-inverted"), linear-gradient(#4cb1ff, #1793e5);
|
||||
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(210,54%,20%,.03);
|
||||
}
|
||||
|
||||
#newtab-search-text + #newtab-search-submit:hover {
|
||||
background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-inverted"), linear-gradient(#4cb1ff, #1793e5);
|
||||
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(210,54%,20%,.03),
|
||||
0 0 4px hsla(206,100%,20%,.2);
|
||||
}
|
||||
|
||||
#newtab-search-text + #newtab-search-submit:hover:active {
|
||||
box-shadow: 0 1px 1px hsla(211,79%,6%,.1) inset,
|
||||
0 0 1px hsla(211,79%,6%,.2) inset;
|
||||
transition-duration: 0ms;
|
||||
}
|
||||
|
||||
#newtab-search-text:focus + #newtab-search-submit:dir(rtl),
|
||||
#newtab-search-text[keepfocus] + #newtab-search-submit:dir(rtl),
|
||||
#newtab-search-text[autofocus] + #newtab-search-submit:dir(rtl),
|
||||
#newtab-search-text + #newtab-search-submit:dir(rtl):hover {
|
||||
background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-rtl-inverted"), linear-gradient(#4cb1ff, #1793e5);
|
||||
}
|
||||
|
||||
/* CUSTOMIZE */
|
||||
#newtab-customize-overlay {
|
||||
opacity: 0;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #F9F9F9;
|
||||
z-index: 100;
|
||||
position: fixed;
|
||||
transition: opacity .07s linear;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-container {
|
||||
position: absolute;
|
||||
margin-right: 40px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-container:dir(rtl) {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#newtab-customize-panel {
|
||||
z-index: 999;
|
||||
margin-top: 55px;
|
||||
min-width: 270px;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: -25px;
|
||||
filter: drop-shadow(0 0 1px rgba(0,0,0,0.4)) drop-shadow(0 3px 4px rgba(0,0,0,0.4));
|
||||
transition: all 200ms ease-in-out;
|
||||
transform-origin: top right;
|
||||
transform: translate(-30px, -20px) scale(0) translate(30px, 20px);
|
||||
}
|
||||
|
||||
#newtab-customize-panel:dir(rtl) {
|
||||
transform-origin: 40px top 20px;
|
||||
}
|
||||
|
||||
#newtab-customize-panel:dir(rtl),
|
||||
#newtab-customize-panel-anchor:dir(rtl) {
|
||||
left: 15px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
#newtab-customize-panel[open="true"] {
|
||||
transform: translate(-30px, -20px) scale(1) translate(30px, 20px);
|
||||
}
|
||||
|
||||
#newtab-customize-panel-anchor {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-color: white;
|
||||
transform: rotate(45deg);
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
#newtab-customize-title {
|
||||
color: #7A7A7A;
|
||||
font-size: 14px;
|
||||
background-color: #FFFFFF;
|
||||
line-height: 25px;
|
||||
padding: 15px;
|
||||
font-weight: 600;
|
||||
cursor: default;
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
max-width: 300px;
|
||||
overflow: hidden;
|
||||
display: table-cell;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
#newtab-customize-panel-inner-wrapper {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#newtab-customize-title > label {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#newtab-customize-panel > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-item {
|
||||
line-height: 25px;
|
||||
padding: 15px;
|
||||
padding-inline-start: 40px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-item:not(:first-child) {
|
||||
border-top: 1px solid threedshadow;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-subitem > label,
|
||||
.newtab-customize-panel-item > label,
|
||||
.newtab-customize-complex-option {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-item,
|
||||
.newtab-customize-complex-option {
|
||||
display: block;
|
||||
text-align: start;
|
||||
background-color: #F9F9F9;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-item[selected]:-moz-locale-dir(rtl) {
|
||||
background-position: right 15px center;
|
||||
}
|
||||
|
||||
.newtab-customize-complex-option:hover > .selectable:not([selected]):-moz-locale-dir(rtl),
|
||||
.selectable:not([selected]):hover:-moz-locale-dir(rtl) {
|
||||
background-position: right 15px center;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-item:not([selected]),
|
||||
.newtab-customize-panel-subitem:not([selected]){
|
||||
color: #7A7A7A;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-item:not([selected]):hover {
|
||||
color: #FFFFFF;
|
||||
background-color: #4A90E2
|
||||
}
|
||||
|
||||
.newtab-customize-complex-option:hover > .selectable:not([selected]),
|
||||
.selectable:not([selected]):hover {
|
||||
background: url("chrome://global/skin/menu/shared-menu-check-hover.svg") no-repeat #FFFFFF;
|
||||
background-size: 16px 16px;
|
||||
background-position: 15px 15px;
|
||||
color: #171F26;
|
||||
}
|
||||
|
||||
.newtab-customize-complex-option:hover > .selectable:not([selected]) + .newtab-customize-panel-subitem {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-item[selected] {
|
||||
background: url("chrome://global/skin/menu/shared-menu-check-active.svg") no-repeat transparent;
|
||||
background-size: 16px 16px;
|
||||
background-position: 15px 15px;
|
||||
color: black;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-subitem > .checkbox {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-color: #FFFFFF;
|
||||
border: solid 1px threedshadow;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-subitem[selected] > .checkbox {
|
||||
background: url("chrome://global/skin/menu/shared-menu-check-black.svg") no-repeat #FFFFFF;
|
||||
background-size: 9px 9px;
|
||||
background-position: center;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-subitem {
|
||||
font-size: 12px;
|
||||
padding: 0px 15px 15px 15px;
|
||||
padding-inline-start: 40px;
|
||||
display: block;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-subitem > label {
|
||||
padding: 0px 10px;
|
||||
line-height: 20px;
|
||||
vertical-align: middle;
|
||||
max-width: 225px;
|
||||
}
|
||||
|
||||
.newtab-customize-panel-superitem {
|
||||
line-height: 20px;
|
||||
border-bottom: medium none !important;
|
||||
padding: 15px 15px 10px 15px;
|
||||
padding-inline-start: 40px;
|
||||
border-top: 1px solid threedshadow;
|
||||
}
|
||||
|
||||
.contentSearchSuggestionTable {
|
||||
font: message-box;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
|
|
|||
3209
application/palemoon/base/content/newtab/newTab.inadjacent.json
Normal file
3209
application/palemoon/base/content/newtab/newTab.inadjacent.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -10,6 +10,8 @@ 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:///modules/DirectoryLinksProvider.jsm");
|
||||
Cu.import("resource://gre/modules/NewTabUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Rect",
|
||||
|
|
@ -31,13 +33,24 @@ XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
|
|||
createBundle("chrome://browser/locale/newTab.properties");
|
||||
});
|
||||
|
||||
function newTabString(name) gStringBundle.GetStringFromName('newtab.' + name);
|
||||
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.isWindowPrivate(window);
|
||||
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
|
||||
|
|
@ -51,6 +64,8 @@ const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
|||
#include dropPreview.js
|
||||
#include updater.js
|
||||
#include undo.js
|
||||
#include search.js
|
||||
#include customize.js
|
||||
|
||||
// Everything is loaded. Initialize the New Tab Page.
|
||||
gPage.init();
|
||||
|
|
|
|||
89
application/palemoon/base/content/newtab/newTab.xhtml
Normal file
89
application/palemoon/base/content/newtab/newTab.xhtml
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
<?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/contentSearchUI.css" />
|
||||
<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-customize-overlay"></div>
|
||||
|
||||
<div class="newtab-customize-panel-container">
|
||||
<div id="newtab-customize-panel" orient="vertical">
|
||||
<div id="newtab-customize-panel-anchor"></div>
|
||||
<div id="newtab-customize-panel-inner-wrapper">
|
||||
<div id="newtab-customize-title" class="newtab-customize-panel-item">
|
||||
<label>&newtab.customize.cog.title2;</label>
|
||||
</div>
|
||||
<div id="newtab-customize-classic" class="newtab-customize-panel-item selectable">
|
||||
<label>&newtab.customize.classic;</label>
|
||||
</div>
|
||||
<div id="newtab-customize-blank" class="newtab-customize-panel-item selectable">
|
||||
<label>&newtab.customize.blank2;</label>
|
||||
</div>
|
||||
<div id="newtab-customize-learn" class="newtab-customize-panel-item">
|
||||
<label>&newtab.customize.cog.learn;</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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="newtab-search-container">
|
||||
<div id="newtab-search-form">
|
||||
<div id="newtab-search-icon"/>
|
||||
<input type="text" name="q" value="" id="newtab-search-text"
|
||||
aria-label="&contentSearchInput.label;" maxlength="256"/>
|
||||
<input id="newtab-search-submit" type="button"
|
||||
title="&contentSearchSubmit.tooltip;"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="newtab-horizontal-margin">
|
||||
<div class="newtab-side-margin"/>
|
||||
<div id="newtab-grid">
|
||||
<h1 id="topsites-heading"/>
|
||||
</div>
|
||||
<div class="newtab-side-margin"/>
|
||||
</div>
|
||||
|
||||
<div id="newtab-margin-bottom"/>
|
||||
</div>
|
||||
<input id="newtab-customize-button" type="button" dir="&locale.dir;"
|
||||
value="⚙"
|
||||
title="&newtab.customize.title;"/>
|
||||
</body>
|
||||
<script type="text/javascript;version=1.8" src="chrome://browser/content/contentSearchUI.js"/>
|
||||
<script type="text/javascript;version=1.8" src="chrome://browser/content/newtab/newTab.js"/>
|
||||
</html>
|
||||
|
|
@ -1,55 +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/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/newtab/newTab.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/newtab/newTab.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % newTabDTD SYSTEM "chrome://browser/locale/newTab.dtd">
|
||||
%newTabDTD;
|
||||
]>
|
||||
|
||||
<xul:window id="newtab-window" xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&newtab.pageTitle;">
|
||||
|
||||
<div id="newtab-scrollbox">
|
||||
|
||||
<div id="newtab-vertical-margin">
|
||||
<div id="newtab-margin-top">
|
||||
<div id="newtab-undo-container" undo-disabled="true">
|
||||
<xul:label id="newtab-undo-label"
|
||||
value="&newtab.undo.removedLabel;" />
|
||||
<xul:button id="newtab-undo-button" tabindex="-1"
|
||||
label="&newtab.undo.undoButton;"
|
||||
class="newtab-undo-button" />
|
||||
<xul:button id="newtab-undo-restore-button" tabindex="-1"
|
||||
label="&newtab.undo.restoreButton;"
|
||||
class="newtab-undo-button" />
|
||||
<xul:toolbarbutton id="newtab-undo-close-button" tabindex="-1"
|
||||
class="close-icon"
|
||||
tooltiptext="&newtab.undo.closeTooltip;" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="newtab-horizontal-margin">
|
||||
<div class="newtab-side-margin"/>
|
||||
|
||||
<div id="newtab-grid">
|
||||
</div>
|
||||
|
||||
<div class="newtab-side-margin"/>
|
||||
</div>
|
||||
|
||||
<div id="newtab-margin-bottom"/>
|
||||
</div>
|
||||
<input id="newtab-toggle" type="button"/>
|
||||
</div>
|
||||
|
||||
<xul:script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/newtab/newTab.js"/>
|
||||
</xul:window>
|
||||
|
|
@ -4,6 +4,9 @@
|
|||
* 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.
|
||||
|
|
@ -19,9 +22,10 @@ var gPage = {
|
|||
// 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", this, false);
|
||||
// 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;
|
||||
|
|
@ -29,31 +33,75 @@ var gPage = {
|
|||
this._init();
|
||||
|
||||
this._updateAttributes(enabled);
|
||||
|
||||
// Initialize customize controls.
|
||||
gCustomize.init();
|
||||
},
|
||||
|
||||
/**
|
||||
* Listens for notifications specific to this page.
|
||||
*/
|
||||
observe: function Page_observe() {
|
||||
let enabled = gAllPages.enabled;
|
||||
this._updateAttributes(enabled);
|
||||
observe: function Page_observe(aSubject, aTopic, aData) {
|
||||
if (aTopic == "nsPref:changed") {
|
||||
gCustomize.updateSelected();
|
||||
|
||||
// Initialize the whole page if we haven't done that, yet.
|
||||
if (enabled) {
|
||||
this._init();
|
||||
} else {
|
||||
gUndoDialog.hide();
|
||||
let enabled = gAllPages.enabled;
|
||||
this._updateAttributes(enabled);
|
||||
|
||||
// Update thumbnails to the new enhanced setting
|
||||
if (aData == "browser.newtabpage.enhanced") {
|
||||
this.update();
|
||||
}
|
||||
|
||||
// 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 whole page and the grid when the storage has changed.
|
||||
* 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: function Page_update() {
|
||||
// The grid might not be ready yet as we initialize it asynchronously.
|
||||
if (gGrid.ready) {
|
||||
gGrid.refresh();
|
||||
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);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -66,19 +114,35 @@ var gPage = {
|
|||
|
||||
this._initialized = true;
|
||||
|
||||
gLinks.populateCache(function () {
|
||||
// Initialize and render the grid.
|
||||
gGrid.init();
|
||||
// Set submit button label for when CSS background are disabled (e.g.
|
||||
// high contrast mode).
|
||||
document.getElementById("newtab-search-submit").value =
|
||||
document.body.getAttribute("dir") == "ltr" ? "\u25B6" : "\u25C0";
|
||||
|
||||
// Initialize the drop target shim.
|
||||
gDropTargetShim.init();
|
||||
if (Services.prefs.getBoolPref("browser.newtabpage.compact")) {
|
||||
document.body.classList.add("compact");
|
||||
}
|
||||
|
||||
// Initialize search.
|
||||
gSearch.init();
|
||||
|
||||
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);
|
||||
// Workaround to prevent a delay on MacOSX due to a slow drop animation.
|
||||
document.addEventListener("dragover", this, false);
|
||||
document.addEventListener("drop", this, false);
|
||||
#endif
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -87,7 +151,7 @@ var gPage = {
|
|||
*/
|
||||
_updateAttributes: function Page_updateAttributes(aValue) {
|
||||
// Set the nodes' states.
|
||||
let nodeSelector = "#newtab-scrollbox, #newtab-toggle, #newtab-grid";
|
||||
let nodeSelector = "#newtab-grid, #newtab-search-container";
|
||||
for (let node of document.querySelectorAll(nodeSelector)) {
|
||||
if (aValue)
|
||||
node.removeAttribute("page-disabled");
|
||||
|
|
@ -98,15 +162,28 @@ var gPage = {
|
|||
// Enables/disables the control and link elements.
|
||||
let inputSelector = ".newtab-control, .newtab-link";
|
||||
for (let input of document.querySelectorAll(inputSelector)) {
|
||||
if (aValue)
|
||||
if (aValue)
|
||||
input.removeAttribute("tabindex");
|
||||
else
|
||||
input.setAttribute("tabindex", "-1");
|
||||
}
|
||||
},
|
||||
|
||||
// Update the toggle button's title.
|
||||
let toggle = document.getElementById("newtab-toggle");
|
||||
toggle.setAttribute("title", newTabString(aValue ? "hide" : "show"));
|
||||
/**
|
||||
* Handles unload event
|
||||
*/
|
||||
_handleUnloadEvent: function Page_handleUnloadEvent() {
|
||||
gAllPages.unregister(this);
|
||||
// compute page life-span and send telemetry probe: using milli-seconds will leave
|
||||
// many low buckets empty. Instead we use half-second precision to make low end
|
||||
// of histogram linear and not lose the change in user attention
|
||||
let delta = Math.round((Date.now() - this._firstVisibleTime) / 500);
|
||||
if (this._suggestedTilePresent) {
|
||||
Services.telemetry.getHistogramById("NEWTAB_PAGE_LIFE_SPAN_SUGGESTED").add(delta);
|
||||
}
|
||||
else {
|
||||
Services.telemetry.getHistogramById("NEWTAB_PAGE_LIFE_SPAN").add(delta);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -114,11 +191,22 @@ var gPage = {
|
|||
*/
|
||||
handleEvent: function Page_handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "load":
|
||||
this.onPageVisibleAndLoaded();
|
||||
break;
|
||||
case "unload":
|
||||
gAllPages.unregister(this);
|
||||
this._handleUnloadEvent();
|
||||
break;
|
||||
case "click":
|
||||
gAllPages.enabled = !gAllPages.enabled;
|
||||
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)
|
||||
|
|
@ -130,6 +218,80 @@ var gPage = {
|
|||
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() {
|
||||
// Send the index of the last visible tile.
|
||||
this.reportLastVisibleTileIndex();
|
||||
// Maybe tell the user they can undo an initial automigration
|
||||
this.maybeShowAutoMigrationUndoNotification();
|
||||
},
|
||||
|
||||
reportLastVisibleTileIndex() {
|
||||
let cwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let rect = cwu.getBoundsWithoutFlushing(gGrid.node);
|
||||
let nodes = cwu.nodesFromRect(rect.left, rect.top, 0, rect.width,
|
||||
rect.height, 0, true, false);
|
||||
|
||||
let i = -1;
|
||||
let lastIndex = -1;
|
||||
let sites = gGrid.sites;
|
||||
|
||||
for (let node of nodes) {
|
||||
if (node.classList && node.classList.contains("newtab-cell")) {
|
||||
if (sites[++i]) {
|
||||
lastIndex = i;
|
||||
if (sites[i].link.targetedSite) {
|
||||
// record that suggested tile is shown to use suggested-tiles-histogram
|
||||
this._suggestedTilePresent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DirectoryLinksProvider.reportSitesAction(sites, "view", lastIndex);
|
||||
},
|
||||
|
||||
maybeShowAutoMigrationUndoNotification() {
|
||||
// sendAsyncMessage("NewTab:MaybeShowAutoMigrationUndoNotification");
|
||||
},
|
||||
};
|
||||
|
|
|
|||
13
application/palemoon/base/content/newtab/search.js
Normal file
13
application/palemoon/base/content/newtab/search.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#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 gSearch = {
|
||||
init: function () {
|
||||
document.getElementById("newtab-search-submit")
|
||||
.addEventListener("click", e => this._contentSearchController.search(e));
|
||||
let textbox = document.getElementById("newtab-search-text");
|
||||
},
|
||||
};
|
||||
|
|
@ -4,6 +4,9 @@
|
|||
* 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.
|
||||
|
|
@ -37,7 +40,7 @@ Site.prototype = {
|
|||
/**
|
||||
* The title of the site's link.
|
||||
*/
|
||||
get title() { return this.link.title; },
|
||||
get title() { return this.link.title || this.link.url; },
|
||||
|
||||
/**
|
||||
* The site's parent cell.
|
||||
|
|
@ -50,13 +53,19 @@ Site.prototype = {
|
|||
/**
|
||||
* 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);
|
||||
gPinnedLinks.pin(this._link, aIndex);
|
||||
let changed = gPinnedLinks.pin(this._link, aIndex);
|
||||
if (changed) {
|
||||
// render site again to remove suggested/sponsored tags
|
||||
this._render();
|
||||
}
|
||||
return changed;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -108,33 +117,175 @@ Site.prototype = {
|
|||
let control = this._querySelector(".newtab-control-pin");
|
||||
|
||||
if (aPinned) {
|
||||
control.setAttribute("pinned", true);
|
||||
this.node.setAttribute("pinned", true);
|
||||
control.setAttribute("title", newTabString("unpin"));
|
||||
} else {
|
||||
control.removeAttribute("pinned");
|
||||
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;
|
||||
},
|
||||
|
||||
_getSuggestedTileExplanation: function() {
|
||||
let targetedName = `<strong> ${this.link.targetedName} </strong>`;
|
||||
let targetedSite = `<strong> ${this.link.targetedSite} </strong>`;
|
||||
if (this.link.explanation) {
|
||||
return this._newTabString(this.link.explanation, [targetedName, targetedSite]);
|
||||
}
|
||||
return newTabString("suggested.button", [targetedName]);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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;
|
||||
delete this.link.enhancedImageURI;
|
||||
// remove endTime to avoid further time checks
|
||||
delete this.link.endTime;
|
||||
// clear enhanced-content image that may still exist in preloaded page
|
||||
this._querySelector(".enhanced-content").style.backgroundImage = "";
|
||||
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 enhanced = gAllPages.enhanced; // && DirectoryLinksProvider.getEnhancedLink(this.link);
|
||||
let url = this.url;
|
||||
let title = this.title || url;
|
||||
let tooltip = (title == url ? title : title + "\n" + url);
|
||||
let title = enhanced && enhanced.title ? enhanced.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._querySelector(".newtab-title").textContent = title;
|
||||
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;
|
||||
}
|
||||
|
||||
// remove "suggested" attribute to avoid showing "suggested" tag
|
||||
// after site was pinned or dropped
|
||||
this.node.removeAttribute("suggested");
|
||||
|
||||
if (this.link.targetedSite) {
|
||||
if (this.node.getAttribute("type") != "sponsored") {
|
||||
this._querySelector(".newtab-sponsored").textContent =
|
||||
newTabString("suggested.tag");
|
||||
}
|
||||
|
||||
this.node.setAttribute("suggested", true);
|
||||
let explanation = this._getSuggestedTileExplanation();
|
||||
this._querySelector(".newtab-suggested").innerHTML =
|
||||
`<div class='newtab-suggested-bounds'> ${explanation} </div>`;
|
||||
}
|
||||
|
||||
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();
|
||||
},
|
||||
|
||||
let thumbnailURL = PageThumbs.getThumbnailURL(this.url);
|
||||
let thumbnail = this._querySelector(".newtab-thumbnail");
|
||||
thumbnail.style.backgroundImage = "url(" + thumbnailURL + ")";
|
||||
/**
|
||||
* 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() {
|
||||
// Only enhance tiles if that feature is turned on
|
||||
let link = gAllPages.enhanced; // && DirectoryLinksProvider.getEnhancedLink(this.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();
|
||||
}
|
||||
|
||||
if (link.enhancedImageURI) {
|
||||
let enhanced = this._querySelector(".enhanced-content");
|
||||
enhanced.style.backgroundImage = 'url("' + link.enhancedImageURI + '")';
|
||||
|
||||
if (this.link.type != link.type) {
|
||||
this.node.setAttribute("type", "enhanced");
|
||||
this.enhancedId = link.directoryId;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_ignoreHoverEvents: function(element) {
|
||||
element.addEventListener("mouseover", () => {
|
||||
this.cell.node.setAttribute("ignorehover", "true");
|
||||
});
|
||||
element.addEventListener("mouseout", () => {
|
||||
this.cell.node.removeAttribute("ignorehover");
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -146,9 +297,12 @@ Site.prototype = {
|
|||
this._node.addEventListener("dragend", this, false);
|
||||
this._node.addEventListener("mouseover", this, false);
|
||||
|
||||
let controls = this.node.querySelectorAll(".newtab-control");
|
||||
for (let i = 0; i < controls.length; i++)
|
||||
controls[i].addEventListener("click", this, false);
|
||||
// Specially treat the sponsored icon & suggested explanation
|
||||
// text to prevent regular hover effects
|
||||
let sponsored = this._querySelector(".newtab-sponsored");
|
||||
let suggested = this._querySelector(".newtab-suggested");
|
||||
this._ignoreHoverEvents(sponsored);
|
||||
this._ignoreHoverEvents(suggested);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -157,7 +311,113 @@ Site.prototype = {
|
|||
_speculativeConnect: function Site_speculativeConnect() {
|
||||
let sc = Services.io.QueryInterface(Ci.nsISpeculativeConnect);
|
||||
let uri = Services.io.newURI(this.url, null, null);
|
||||
sc.speculativeConnect(uri, 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");
|
||||
}
|
||||
else {
|
||||
let explain = document.createElementNS(HTML_NAMESPACE, "div");
|
||||
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("suggested") && this.node.getAttribute("type") == "affiliate") ?
|
||||
"suggested" : this.node.getAttribute("type");
|
||||
let icon = '<input type="button" class="newtab-control newtab-' +
|
||||
(type == "enhanced" ? "customize" : "control-block") + '"/>';
|
||||
explain.innerHTML = newTabString(type + (type == "sponsored" ? ".explain2" : ".explain"), [icon, link]);
|
||||
|
||||
button.setAttribute("active", "true");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
// 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) {
|
||||
aEvent.preventDefault();
|
||||
if (target.classList.contains("newtab-control-block")) {
|
||||
// Notify DirectoryLinksProvider of suggested tile block, this may
|
||||
// affect if and how suggested tiles are recommended and needs to
|
||||
// be reported before pages are updated inside block() call
|
||||
if (this.link.targetedSite) {
|
||||
// DirectoryLinksProvider.handleSuggestedTileBlock();
|
||||
}
|
||||
this.block();
|
||||
action = "block";
|
||||
}
|
||||
else if (target.classList.contains("sponsored-explain") ||
|
||||
target.classList.contains("newtab-sponsored")) {
|
||||
this._toggleLegalText(".newtab-sponsored", ".sponsored-explain");
|
||||
action = "sponsored";
|
||||
}
|
||||
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()) {
|
||||
// suggested link has changed - update rest of the pages
|
||||
gAllPages.update(gPage);
|
||||
}
|
||||
action = "pin";
|
||||
}
|
||||
}
|
||||
|
||||
// Report all link click actions
|
||||
if (action) {
|
||||
// DirectoryLinksProvider.reportSitesAction(gGrid.sites, action, tileIndex);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -165,15 +425,6 @@ Site.prototype = {
|
|||
*/
|
||||
handleEvent: function Site_handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "click":
|
||||
aEvent.preventDefault();
|
||||
if (aEvent.target.classList.contains("newtab-control-block"))
|
||||
this.block();
|
||||
else if (this.isPinned())
|
||||
this.unpin();
|
||||
else
|
||||
this.pin();
|
||||
break;
|
||||
case "mouseover":
|
||||
this._node.removeEventListener("mouseover", this, false);
|
||||
this._speculativeConnect();
|
||||
|
|
@ -181,9 +432,6 @@ Site.prototype = {
|
|||
case "dragstart":
|
||||
gDrag.start(this, aEvent);
|
||||
break;
|
||||
case "drag":
|
||||
gDrag.drag(this, aEvent);
|
||||
break;
|
||||
case "dragend":
|
||||
gDrag.end(this, aEvent);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ var gTransformation = {
|
|||
finish();
|
||||
} else {
|
||||
this.setSitePosition(aSite, targetPosition);
|
||||
this._whenTransitionEnded(aSite.node, finish);
|
||||
this._whenTransitionEnded(aSite.node, ["left", "top"], finish);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -181,13 +181,13 @@ var gTransformation = {
|
|||
|
||||
batch.push(new Promise(resolve => {
|
||||
if (!cells[aIndex]) {
|
||||
// The site disappeared from the grid, hide it.
|
||||
// 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.
|
||||
// The site disappeared before but is now back, show it.
|
||||
this.showSite(aSite, resolve);
|
||||
} else {
|
||||
// The site's position has changed, move it around.
|
||||
// The site's position has changed, move it around.
|
||||
this._moveSite(aSite, aIndex, {unfreeze: unfreeze, callback: resolve});
|
||||
}
|
||||
}));
|
||||
|
|
@ -202,15 +202,19 @@ var gTransformation = {
|
|||
* 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, aCallback) {
|
||||
function Transformation_whenTransitionEnded(aNode, aProperties, aCallback) {
|
||||
|
||||
aNode.addEventListener("transitionend", function onEnd() {
|
||||
aNode.removeEventListener("transitionend", onEnd, false);
|
||||
aCallback();
|
||||
}, false);
|
||||
let props = new Set(aProperties);
|
||||
aNode.addEventListener("transitionend", function onEnd(e) {
|
||||
if (props.has(e.propertyName)) {
|
||||
aNode.removeEventListener("transitionend", onEnd);
|
||||
aCallback();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -236,8 +240,9 @@ var gTransformation = {
|
|||
if (aCallback)
|
||||
aCallback();
|
||||
} else {
|
||||
if (aCallback)
|
||||
this._whenTransitionEnded(aNode, aCallback);
|
||||
if (aCallback) {
|
||||
this._whenTransitionEnded(aNode, ["opacity"], aCallback);
|
||||
}
|
||||
|
||||
aNode.style.opacity = aOpacity;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,9 +69,11 @@ browser.jar:
|
|||
content/browser/padlock_classic_https.png (content/padlock_classic_https.png)
|
||||
content/browser/padlock_classic_low.png (content/padlock_classic_low.png)
|
||||
content/browser/padlock_classic_broken.png (content/padlock_classic_broken.png)
|
||||
content/browser/newtab/newTab.xul (content/newtab/newTab.xul)
|
||||
content/browser/newtab/newTab.xhtml (content/newtab/newTab.xhtml)
|
||||
* content/browser/newtab/newTab.js (content/newtab/newTab.js)
|
||||
content/browser/newtab/newTab.css (content/newtab/newTab.css)
|
||||
content/browser/newtab/newTab.inadjacent.json (content/newtab/newTab.inadjacent.json)
|
||||
content/browser/newtab/alternativeDefaultSites.json (content/newtab/alternativeDefaultSites.json)
|
||||
* content/browser/pageinfo/pageInfo.xul (content/pageinfo/pageInfo.xul)
|
||||
content/browser/pageinfo/pageInfo.js (content/pageinfo/pageInfo.js)
|
||||
content/browser/pageinfo/pageInfo.css (content/pageinfo/pageInfo.css)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ static RedirEntry kRedirMap[] = {
|
|||
nsIAboutModule::ALLOW_SCRIPT
|
||||
},
|
||||
{
|
||||
"newtab", "chrome://browser/content/newtab/newTab.xul",
|
||||
"newtab", "chrome://browser/content/newtab/newTab.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,21 @@
|
|||
|
||||
<!-- These strings are used in the about:newtab page -->
|
||||
<!ENTITY newtab.pageTitle "New Tab">
|
||||
<!ENTITY newtab.customize.classic "Show your top sites">
|
||||
<!ENTITY newtab.customize.cog.enhanced "Include suggested sites">
|
||||
<!ENTITY newtab.customize.cog.title2 "NEW TAB CONTROLS">
|
||||
<!ENTITY newtab.customize.cog.learn "Learn about New Tab">
|
||||
<!ENTITY newtab.customize.title "Customize your New Tab page">
|
||||
<!ENTITY newtab.customize.suggested "Show suggested and your top sites">
|
||||
<!ENTITY newtab.customize.topsites "Show your top sites">
|
||||
<!ENTITY newtab.customize.blank2 "Show blank page">
|
||||
<!ENTITY newtab.undo.removedLabel "Thumbnail removed.">
|
||||
<!ENTITY newtab.undo.undoButton "Undo.">
|
||||
<!ENTITY newtab.undo.restoreButton "Restore All.">
|
||||
<!ENTITY newtab.undo.closeTooltip "Hide">
|
||||
|
||||
<!-- LOCALIZATION NOTE (contentSearchInput.label):
|
||||
This is set as the aria-label attribute for the search input box in the
|
||||
in-content search UI, to be used by screen readers. -->
|
||||
<!ENTITY contentSearchInput.label "Search query">
|
||||
<!ENTITY contentSearchSubmit.tooltip "Submit search">
|
||||
|
|
|
|||
|
|
@ -5,5 +5,42 @@
|
|||
newtab.pin=Pin this site at its current position
|
||||
newtab.unpin=Unpin this site
|
||||
newtab.block=Remove this site
|
||||
newtab.show=Show the new tab page
|
||||
newtab.hide=Hide the new tab page
|
||||
# LOCALIZATION NOTE(newtab.sponsored.button): This text appears for sponsored
|
||||
# and enhanced tiles on the same line as the tile's title, so prefer short
|
||||
# strings to avoid overlap. This string should be uppercase.
|
||||
newtab.sponsored.button=SPONSORED
|
||||
# LOCALIZATION NOTE(newtab.suggested.button): This text appears for sponsored
|
||||
# and suggested tiles on the same line as the tile's title, so prefer short
|
||||
# strings to avoid overlap. This string should be uppercase.
|
||||
newtab.suggested.tag=SUGGESTED
|
||||
# LOCALIZATION NOTE(newtab.suggested.button): %1$S will be replaced inline by
|
||||
# one of the user's top 100 sites that triggered this suggested tile.
|
||||
# This text appears for suggested tiles under the tile's title, so prefer short
|
||||
# strings to avoid truncating important text.
|
||||
newtab.suggested.button=Suggested for %1$S visitors
|
||||
# LOCALIZATION NOTE(newtab.sponsored.explain): %1$S will be replaced inline by
|
||||
# the (X) block icon. %2$S will be replaced by an active link using string
|
||||
# newtab.learn.link as text.
|
||||
newtab.sponsored.explain=This tile is being shown to you on behalf of a Mozilla partner. You can remove it at any time by clicking the %1$S button. %2$S
|
||||
# LOCALIZATION NOTE(newtab.sponsored.explain2): %1$S will be replaced inline by
|
||||
# the (X) block icon. %2$S will be replaced by an active link using string
|
||||
# newtab.learn.link as text.
|
||||
newtab.sponsored.explain2=This site is suggested to you on behalf of a Mozilla partner. You can remove it at any time by clicking the %1$S button. %2$S
|
||||
# LOCALIZATION NOTE(newtab.suggested.explain): %1$S will be replaced inline by
|
||||
# the (X) block icon. %2$S will be replaced by an active link using string
|
||||
# newtab.learn.link as text.
|
||||
newtab.suggested.explain=This site is suggested to you by Mozilla. You can remove it at any time by clicking the %1$S button. %2$S
|
||||
# LOCALIZATION NOTE(newtab.enhanced.explain): %1$S will be replaced inline by
|
||||
# the gear icon used to customize the new tab window. %2$S will be replaced by
|
||||
# an active link using string newtab.learn.link as text.
|
||||
newtab.enhanced.explain=A Mozilla partner has visually enhanced this tile, replacing the screenshot. You can turn off enhanced tiles by clicking the %1$S button for your preferences. %2$S
|
||||
newtab.intro1.paragraph1=Now when you open New Tab, you’ll also see sites we think might be interesting to you. Some may be suggested by Mozilla or sponsored by one of our partners.
|
||||
# LOCALIZATION NOTE(newtab.intro1.paragraph2): %1$S will be replaced inline by
|
||||
# an active link using string newtab.privacy.link as text. %2$S will be replaced
|
||||
# inline by the gear icon used to customize the new tab window.
|
||||
newtab.intro1.paragraph2=In order to provide this service, some data is automatically sent back to us in accordance with our %1$S. You can turn this off by unchecking the option under the gear icon (%2$S).
|
||||
newtab.learn.link=Learn more…
|
||||
newtab.privacy.link=Privacy Notice
|
||||
newtab.learn.link2=More about New Tab
|
||||
newtab.intro.header.update=New Tab got an update!
|
||||
newtab.intro.gotit=Got it!
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue