Bug 729878 - Part 1 - New layout implementation; r=dietrich,dao ui-r=shorlander
This commit is contained in:
@@ -15,16 +15,14 @@ function Cell(aGrid, aNode) {
|
||||
this._node._newtabCell = this;
|
||||
|
||||
// Register drag-and-drop event handlers.
|
||||
["DragEnter", "DragOver", "DragExit", "Drop"].forEach(function (aType) {
|
||||
let method = "on" + aType;
|
||||
this[method] = this[method].bind(this);
|
||||
this._node.addEventListener(aType.toLowerCase(), this[method], false);
|
||||
["dragenter", "dragover", "dragexit", "drop"].forEach(function (aType) {
|
||||
this._node.addEventListener(aType, this, false);
|
||||
}, this);
|
||||
}
|
||||
|
||||
Cell.prototype = {
|
||||
/**
|
||||
*
|
||||
* The grid.
|
||||
*/
|
||||
_grid: null,
|
||||
|
||||
@@ -97,41 +95,27 @@ Cell.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for the 'dragenter' event.
|
||||
* @param aEvent The dragenter event.
|
||||
* Handles all cell events.
|
||||
*/
|
||||
onDragEnter: function Cell_onDragEnter(aEvent) {
|
||||
if (gDrag.isValid(aEvent)) {
|
||||
aEvent.preventDefault();
|
||||
gDrop.enter(this, aEvent);
|
||||
}
|
||||
},
|
||||
handleEvent: function Cell_handleEvent(aEvent) {
|
||||
if (aEvent.type != "dragexit" && !gDrag.isValid(aEvent))
|
||||
return;
|
||||
|
||||
/**
|
||||
* Event handler for the 'dragover' event.
|
||||
* @param aEvent The dragover event.
|
||||
*/
|
||||
onDragOver: function Cell_onDragOver(aEvent) {
|
||||
if (gDrag.isValid(aEvent))
|
||||
aEvent.preventDefault();
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for the 'dragexit' event.
|
||||
* @param aEvent The dragexit event.
|
||||
*/
|
||||
onDragExit: function Cell_onDragExit(aEvent) {
|
||||
gDrop.exit(this, aEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for the 'drop' event.
|
||||
* @param aEvent The drop event.
|
||||
*/
|
||||
onDrop: function Cell_onDrop(aEvent) {
|
||||
if (gDrag.isValid(aEvent)) {
|
||||
aEvent.preventDefault();
|
||||
gDrop.drop(this, aEvent);
|
||||
switch (aEvent.type) {
|
||||
case "dragenter":
|
||||
aEvent.preventDefault();
|
||||
gDrop.enter(this, aEvent);
|
||||
break;
|
||||
case "dragover":
|
||||
aEvent.preventDefault();
|
||||
break;
|
||||
case "dragexit":
|
||||
gDrop.exit(this, aEvent);
|
||||
break;
|
||||
case "drop":
|
||||
aEvent.preventDefault();
|
||||
gDrop.drop(this, aEvent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,11 +36,11 @@ let gDrag = {
|
||||
start: function Drag_start(aSite, aEvent) {
|
||||
this._draggedSite = aSite;
|
||||
|
||||
// Prevent moz-transform for left, top.
|
||||
aSite.node.setAttribute("dragged", "true");
|
||||
|
||||
// Make sure the dragged site is floating above the grid.
|
||||
aSite.node.setAttribute("ontop", "true");
|
||||
// Mark nodes as being dragged.
|
||||
let selector = ".newtab-site, .newtab-control, .newtab-thumbnail";
|
||||
let nodes = aSite.node.parentNode.querySelectorAll(selector);
|
||||
for (let i = 0; i < nodes.length; i++)
|
||||
nodes[i].setAttribute("dragged", "true");
|
||||
|
||||
this._setDragData(aSite, aEvent);
|
||||
|
||||
@@ -88,13 +88,12 @@ let gDrag = {
|
||||
* @param aEvent The 'dragend' event.
|
||||
*/
|
||||
end: function Drag_end(aSite, aEvent) {
|
||||
aSite.node.removeAttribute("dragged");
|
||||
let nodes = aSite.node.parentNode.querySelectorAll("[dragged]");
|
||||
for (let i = 0; i < nodes.length; i++)
|
||||
nodes[i].removeAttribute("dragged");
|
||||
|
||||
// Slide the dragged site back into its cell (may be the old or the new cell).
|
||||
gTransformation.slideSiteTo(aSite, aSite.cell, {
|
||||
unfreeze: true,
|
||||
callback: function () aSite.node.removeAttribute("ontop")
|
||||
});
|
||||
gTransformation.slideSiteTo(aSite, aSite.cell, {unfreeze: true});
|
||||
|
||||
this._draggedSite = null;
|
||||
},
|
||||
@@ -132,13 +131,13 @@ let gDrag = {
|
||||
// Create and use an empty drag element. We don't want to use the default
|
||||
// drag image with its default opacity.
|
||||
let dragElement = document.createElementNS(HTML_NAMESPACE, "div");
|
||||
dragElement.classList.add("drag-element");
|
||||
let body = document.getElementById("body");
|
||||
body.appendChild(dragElement);
|
||||
dragElement.classList.add("newtab-drag");
|
||||
let scrollbox = document.getElementById("newtab-scrollbox");
|
||||
scrollbox.appendChild(dragElement);
|
||||
dt.setDragImage(dragElement, 0, 0);
|
||||
|
||||
// After the 'dragstart' event has been processed we can remove the
|
||||
// temporary drag element from the DOM.
|
||||
setTimeout(function () body.removeChild(dragElement), 0);
|
||||
setTimeout(function () scrollbox.removeChild(dragElement), 0);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -26,13 +26,26 @@ let gDropTargetShim = {
|
||||
init: function DropTargetShim_init() {
|
||||
let node = gGrid.node;
|
||||
|
||||
this._dragover = this._dragover.bind(this);
|
||||
|
||||
// Add drag event handlers.
|
||||
node.addEventListener("dragstart", this._start.bind(this), true);
|
||||
// XXX bug 505521 - Don't listen for drag, it's useless at the moment.
|
||||
//node.addEventListener("drag", this._drag.bind(this), false);
|
||||
node.addEventListener("dragend", this._end.bind(this), true);
|
||||
node.addEventListener("dragstart", this, true);
|
||||
node.addEventListener("dragend", this, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles all shim events.
|
||||
*/
|
||||
handleEvent: function DropTargetShim_handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "dragstart":
|
||||
this._start(aEvent);
|
||||
break;
|
||||
case "dragover":
|
||||
this._dragover(aEvent);
|
||||
break;
|
||||
case "dragend":
|
||||
this._end(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -40,11 +53,11 @@ let gDropTargetShim = {
|
||||
* @param aEvent The 'dragstart' event.
|
||||
*/
|
||||
_start: function DropTargetShim_start(aEvent) {
|
||||
if (aEvent.target.classList.contains("site")) {
|
||||
if (aEvent.target.classList.contains("newtab-link")) {
|
||||
gGrid.lock();
|
||||
|
||||
// XXX bug 505521 - Listen for dragover on the document.
|
||||
document.documentElement.addEventListener("dragover", this._dragover, false);
|
||||
document.documentElement.addEventListener("dragover", this, false);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -56,12 +69,7 @@ let gDropTargetShim = {
|
||||
// Let's see if we find a drop target.
|
||||
let target = this._findDropTarget(aEvent);
|
||||
|
||||
if (target == this._lastDropTarget) {
|
||||
// XXX bug 505521 - Don't fire dragover for now (causes recursion).
|
||||
/*if (target)
|
||||
// The last drop target is valid and didn't change.
|
||||
this._dispatchEvent(aEvent, "dragover", target);*/
|
||||
} else {
|
||||
if (target != this._lastDropTarget) {
|
||||
if (this._lastDropTarget)
|
||||
// We left the last drop target.
|
||||
this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
|
||||
@@ -84,7 +92,7 @@ let gDropTargetShim = {
|
||||
* @param aEvent The 'dragover' event.
|
||||
*/
|
||||
_dragover: function DropTargetShim_dragover(aEvent) {
|
||||
let sourceNode = aEvent.dataTransfer.mozSourceNode;
|
||||
let sourceNode = aEvent.dataTransfer.mozSourceNode.parentNode;
|
||||
gDrag.drag(sourceNode._newtabSite, aEvent);
|
||||
|
||||
this._drag(aEvent);
|
||||
@@ -117,7 +125,7 @@ let gDropTargetShim = {
|
||||
gGrid.unlock();
|
||||
|
||||
// XXX bug 505521 - Remove the document's dragover listener.
|
||||
document.documentElement.removeEventListener("dragover", this._dragover, false);
|
||||
document.documentElement.removeEventListener("dragover", this, false);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,7 @@ let gGrid = {
|
||||
*/
|
||||
get cells() {
|
||||
let cells = [];
|
||||
let children = this.node.querySelectorAll("li");
|
||||
let children = this.node.querySelectorAll(".newtab-cell");
|
||||
for (let i = 0; i < children.length; i++)
|
||||
cells.push(new Cell(this, children[i]));
|
||||
|
||||
@@ -43,8 +43,8 @@ let gGrid = {
|
||||
* Initializes the grid.
|
||||
* @param aSelector The query selector of the grid.
|
||||
*/
|
||||
init: function Grid_init(aSelector) {
|
||||
this._node = document.querySelector(aSelector);
|
||||
init: function Grid_init() {
|
||||
this._node = document.getElementById("newtab-grid");
|
||||
this._createSiteFragment();
|
||||
this._draw();
|
||||
},
|
||||
@@ -96,21 +96,20 @@ let gGrid = {
|
||||
* Creates the DOM fragment that is re-used when creating sites.
|
||||
*/
|
||||
_createSiteFragment: function Grid_createSiteFragment() {
|
||||
let site = document.createElementNS(HTML_NAMESPACE, "a");
|
||||
site.classList.add("site");
|
||||
let site = document.createElementNS(HTML_NAMESPACE, "div");
|
||||
site.classList.add("newtab-site");
|
||||
site.setAttribute("draggable", "true");
|
||||
|
||||
// Create the site's inner HTML code.
|
||||
site.innerHTML =
|
||||
'<img class="site-img" width="' + THUMB_WIDTH +'" ' +
|
||||
' height="' + THUMB_HEIGHT + '" alt=""/>' +
|
||||
'<span class="site-title"/>' +
|
||||
'<span class="site-strip">' +
|
||||
' <input class="button strip-button strip-button-pin" type="button"' +
|
||||
' tabindex="-1" title="' + newTabString("pin") + '"/>' +
|
||||
' <input class="button strip-button strip-button-block" type="button"' +
|
||||
' tabindex="-1" title="' + newTabString("block") + '"/>' +
|
||||
'</span>';
|
||||
'<a class="newtab-link">' +
|
||||
' <span class="newtab-thumbnail"/>' +
|
||||
' <span class="newtab-title"/>' +
|
||||
'</a>' +
|
||||
'<input type="button" title="' + newTabString("pin") + '"' +
|
||||
' class="newtab-control newtab-control-pin"/>' +
|
||||
'<input type="button" title="' + newTabString("block") + '"' +
|
||||
' class="newtab-control newtab-control-block"/>';
|
||||
|
||||
this._siteFragment = document.createDocumentFragment();
|
||||
this._siteFragment.appendChild(site);
|
||||
|
||||
@@ -1,161 +1,174 @@
|
||||
:root {
|
||||
-moz-appearance: none;
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
#scrollbox:not([page-disabled]) {
|
||||
input[type=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* SCROLLBOX */
|
||||
#newtab-scrollbox {
|
||||
display: -moz-box;
|
||||
position: relative;
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
#newtab-scrollbox:not([page-disabled]) {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#body {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
min-width: 675px;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* TOOLBAR */
|
||||
#toolbar {
|
||||
/* TOGGLE */
|
||||
#newtab-toggle {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
}
|
||||
|
||||
#toolbar[page-disabled] {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#toolbar:-moz-locale-dir(rtl) {
|
||||
left: 8px;
|
||||
#newtab-toggle:-moz-locale-dir(rtl) {
|
||||
left: 12px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.toolbar-button {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
-moz-transition: opacity 200ms ease-out;
|
||||
/* MARGINS */
|
||||
#newtab-vertical-margin {
|
||||
display: -moz-box;
|
||||
position: relative;
|
||||
-moz-box-flex: 1;
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
#toolbar-button-show,
|
||||
#toolbar-button-reset {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
#newtab-margin-top {
|
||||
min-height: 50px;
|
||||
max-height: 80px;
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
#toolbar-button-reset[modified],
|
||||
#toolbar-button-show[page-disabled] {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
#newtab-margin-bottom {
|
||||
min-height: 40px;
|
||||
max-height: 100px;
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
#toolbar-button-hide[page-disabled],
|
||||
#toolbar-button-reset[page-disabled] {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
#newtab-horizontal-margin {
|
||||
display: -moz-box;
|
||||
-moz-box-flex: 5;
|
||||
}
|
||||
|
||||
.newtab-side-margin {
|
||||
min-width: 40px;
|
||||
max-width: 300px;
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
/* GRID */
|
||||
#grid {
|
||||
width: 637px;
|
||||
height: 411px;
|
||||
overflow: hidden;
|
||||
list-style-type: none;
|
||||
-moz-transition: opacity 200ms ease-out;
|
||||
#newtab-grid {
|
||||
display: -moz-box;
|
||||
-moz-box-flex: 5;
|
||||
-moz-box-orient: vertical;
|
||||
min-width: 600px;
|
||||
min-height: 400px;
|
||||
-moz-transition: 100ms ease-out;
|
||||
-moz-transition-property: opacity;
|
||||
}
|
||||
|
||||
#grid[page-disabled] {
|
||||
#newtab-grid[page-disabled] {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#grid[page-disabled],
|
||||
#grid[locked] {
|
||||
#newtab-grid[locked],
|
||||
#newtab-grid[page-disabled] {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ROWS */
|
||||
.newtab-row {
|
||||
display: -moz-box;
|
||||
-moz-box-orient: horizontal;
|
||||
-moz-box-direction: normal;
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
/* CELLS */
|
||||
.cell {
|
||||
float: left;
|
||||
width: 201px;
|
||||
height: 127px;
|
||||
margin-bottom: 15px;
|
||||
-moz-margin-end: 16px;
|
||||
}
|
||||
|
||||
.cell:-moz-locale-dir(rtl) {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.cell:nth-child(3n+3) {
|
||||
-moz-margin-end: 0;
|
||||
.newtab-cell {
|
||||
display: -moz-box;
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
/* SITES */
|
||||
.site {
|
||||
display: block;
|
||||
.newtab-site {
|
||||
position: relative;
|
||||
width: 201px;
|
||||
height: 127px;
|
||||
-moz-box-flex: 1;
|
||||
-moz-transition: 100ms ease-out;
|
||||
-moz-transition-property: top, left, opacity;
|
||||
}
|
||||
|
||||
.site[frozen] {
|
||||
.newtab-site[frozen] {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.site[ontop] {
|
||||
.newtab-site[dragged] {
|
||||
-moz-transition-property: none;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* SITE IMAGE */
|
||||
.site-img {
|
||||
display: block;
|
||||
opacity: 0.75;
|
||||
-moz-transition: opacity 200ms ease-out;
|
||||
}
|
||||
|
||||
.site:hover > .site-img,
|
||||
.site[ontop] > .site-img,
|
||||
.site:-moz-focusring > .site-img {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.site-img[loading] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* SITE TITLE */
|
||||
.site-title {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* SITE STRIP */
|
||||
.site-strip {
|
||||
/* LINK + THUMBNAILS */
|
||||
.newtab-link,
|
||||
.newtab-thumbnail {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 195px;
|
||||
height: 17px;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
-moz-transition: opacity 200ms ease-out;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.site:hover:not([frozen]) > .site-strip {
|
||||
.newtab-thumbnail {
|
||||
opacity: .8;
|
||||
-moz-transition: opacity 100ms ease-out;
|
||||
}
|
||||
|
||||
.newtab-thumbnail[dragged],
|
||||
.newtab-link:-moz-focusring > .newtab-thumbnail,
|
||||
.newtab-site:hover > .newtab-link > .newtab-thumbnail {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.strip-button-pin,
|
||||
.strip-button-block:-moz-locale-dir(rtl) {
|
||||
float: left;
|
||||
/* TITLES */
|
||||
.newtab-title {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.strip-button-block,
|
||||
.strip-button-pin:-moz-locale-dir(rtl) {
|
||||
float: right;
|
||||
/* CONTROLS */
|
||||
.newtab-control {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
opacity: 0;
|
||||
-moz-transition: opacity 100ms ease-out;
|
||||
}
|
||||
|
||||
.newtab-control:-moz-focusring,
|
||||
.newtab-site:hover > .newtab-control {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.newtab-control[dragged] {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
.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 */
|
||||
@@ -165,7 +178,7 @@
|
||||
* so that we can use custom drag images and elements. It needs an opacity of
|
||||
* 0.01 so that the core code detects that it's in fact a visible element.
|
||||
*/
|
||||
.drag-element {
|
||||
.newtab-drag {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
background-color: #fff;
|
||||
|
||||
@@ -30,13 +30,10 @@ XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
|
||||
function newTabString(name) gStringBundle.GetStringFromName('newtab.' + name);
|
||||
|
||||
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
||||
const THUMB_WIDTH = 201;
|
||||
const THUMB_HEIGHT = 127;
|
||||
|
||||
#include batch.js
|
||||
#include transformations.js
|
||||
#include page.js
|
||||
#include toolbar.js
|
||||
#include grid.js
|
||||
#include cells.js
|
||||
#include sites.js
|
||||
@@ -47,4 +44,4 @@ const THUMB_HEIGHT = 127;
|
||||
#include updater.js
|
||||
|
||||
// Everything is loaded. Initialize the New Tab Page.
|
||||
gPage.init("#toolbar", "#grid");
|
||||
gPage.init();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# 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/global.css"?>
|
||||
<?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"?>
|
||||
|
||||
@@ -13,28 +13,44 @@
|
||||
%newTabDTD;
|
||||
]>
|
||||
|
||||
<xul:window xmlns="http://www.w3.org/1999/xhtml"
|
||||
<xul:window id="newtab-window" xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
disablefastfind="true" title="&newtab.pageTitle;">
|
||||
<xul:vbox id="scrollbox" flex="1" title=" ">
|
||||
<body id="body">
|
||||
<div id="toolbar">
|
||||
<input class="button toolbar-button" id="toolbar-button-show"
|
||||
type="button" title="&newtab.show;"/>
|
||||
<input class="button toolbar-button" id="toolbar-button-hide"
|
||||
type="button" title="&newtab.hide;"/>
|
||||
<input class="button toolbar-button" id="toolbar-button-reset"
|
||||
type="button" title="&newtab.reset;"/>
|
||||
xul:disablefastfind="true" xul:title="&newtab.pageTitle;">
|
||||
|
||||
<div id="newtab-scrollbox">
|
||||
|
||||
<div id="newtab-vertical-margin">
|
||||
<div id="newtab-margin-top"/>
|
||||
|
||||
<div id="newtab-horizontal-margin">
|
||||
<div class="newtab-side-margin"/>
|
||||
|
||||
<div id="newtab-grid">
|
||||
<div class="newtab-row">
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
</div>
|
||||
<div class="newtab-row">
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
</div>
|
||||
<div class="newtab-row">
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
<div class="newtab-cell"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="newtab-side-margin"/>
|
||||
</div>
|
||||
|
||||
<ul id="grid">
|
||||
<li class="cell"/><li class="cell"/><li class="cell"/>
|
||||
<li class="cell"/><li class="cell"/><li class="cell"/>
|
||||
<li class="cell"/><li class="cell"/><li class="cell"/>
|
||||
</ul>
|
||||
<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"/>
|
||||
</body>
|
||||
</xul:vbox>
|
||||
<xul:script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/newtab/newTab.js"/>
|
||||
</xul:window>
|
||||
|
||||
@@ -11,25 +11,24 @@
|
||||
let gPage = {
|
||||
/**
|
||||
* Initializes the page.
|
||||
* @param aToolbarSelector The query selector for the page toolbar.
|
||||
* @param aGridSelector The query selector for the grid.
|
||||
*/
|
||||
init: function Page_init(aToolbarSelector, aGridSelector) {
|
||||
gToolbar.init(aToolbarSelector);
|
||||
this._gridSelector = aGridSelector;
|
||||
|
||||
init: function Page_init() {
|
||||
// Add ourselves to the list of pages to receive notifications.
|
||||
gAllPages.register(this);
|
||||
|
||||
// Listen for 'unload' to unregister this page.
|
||||
function unload() { gAllPages.unregister(this); }
|
||||
addEventListener("unload", unload.bind(this), false);
|
||||
addEventListener("unload", this, false);
|
||||
|
||||
// Listen for toggle button clicks.
|
||||
let button = document.getElementById("newtab-toggle");
|
||||
button.addEventListener("click", this, false);
|
||||
|
||||
// Check if the new tab feature is enabled.
|
||||
if (gAllPages.enabled)
|
||||
let enabled = gAllPages.enabled;
|
||||
if (enabled)
|
||||
this._init();
|
||||
else
|
||||
this._updateAttributes(false);
|
||||
|
||||
this._updateAttributes(enabled);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -48,25 +47,9 @@ let gPage = {
|
||||
* Updates the whole page and the grid when the storage has changed.
|
||||
*/
|
||||
update: function Page_update() {
|
||||
this.updateModifiedFlag();
|
||||
gGrid.refresh();
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if the page is modified and sets the CSS class accordingly
|
||||
*/
|
||||
updateModifiedFlag: function Page_updateModifiedFlag() {
|
||||
let node = document.getElementById("toolbar-button-reset");
|
||||
let modified = this._isModified();
|
||||
|
||||
if (modified)
|
||||
node.setAttribute("modified", "true");
|
||||
else
|
||||
node.removeAttribute("modified");
|
||||
|
||||
this._updateTabIndices(gAllPages.enabled, modified);
|
||||
},
|
||||
|
||||
/**
|
||||
* Internally initializes the page. This runs only when/if the feature
|
||||
* is/gets enabled.
|
||||
@@ -78,29 +61,27 @@ let gPage = {
|
||||
this._initialized = true;
|
||||
|
||||
gLinks.populateCache(function () {
|
||||
// Check if the grid is modified.
|
||||
this.updateModifiedFlag();
|
||||
|
||||
// Initialize and render the grid.
|
||||
gGrid.init(this._gridSelector);
|
||||
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.onDragOver, false);
|
||||
document.addEventListener("drop", this.onDrop, false);
|
||||
document.addEventListener("dragover", this, false);
|
||||
document.addEventListener("drop", this, false);
|
||||
#endif
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the 'page-disabled' attributes of the respective DOM nodes.
|
||||
* @param aValue Whether to set or remove attributes.
|
||||
* @param aValue Whether the New Tab Page is enabled or not.
|
||||
*/
|
||||
_updateAttributes: function Page_updateAttributes(aValue) {
|
||||
let nodes = document.querySelectorAll("#grid, #scrollbox, #toolbar, .toolbar-button");
|
||||
let selector = "#newtab-scrollbox, #newtab-toggle, #newtab-grid";
|
||||
let nodes = document.querySelectorAll(selector);
|
||||
|
||||
// Set the nodes' states.
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
@@ -111,64 +92,32 @@ let gPage = {
|
||||
node.setAttribute("page-disabled", "true");
|
||||
}
|
||||
|
||||
this._updateTabIndices(aValue, this._isModified());
|
||||
// Update the toggle button's title.
|
||||
let toggle = document.getElementById("newtab-toggle");
|
||||
toggle.setAttribute("title", newTabString(aValue ? "hide" : "show"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether the page is modified.
|
||||
* @return Whether the page is modified or not.
|
||||
* Handles all page events.
|
||||
*/
|
||||
_isModified: function Page_isModified() {
|
||||
// The page is considered modified only if sites have been removed.
|
||||
return !gBlockedLinks.isEmpty();
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the tab indices of focusable elements.
|
||||
* @param aEnabled Whether the page is currently enabled.
|
||||
* @param aModified Whether the page is currently modified.
|
||||
*/
|
||||
_updateTabIndices: function Page_updateTabIndices(aEnabled, aModified) {
|
||||
function setFocusable(aNode, aFocusable) {
|
||||
if (aFocusable)
|
||||
aNode.removeAttribute("tabindex");
|
||||
else
|
||||
aNode.setAttribute("tabindex", "-1");
|
||||
}
|
||||
|
||||
// Sites and the 'hide' button are always focusable when the grid is shown.
|
||||
let nodes = document.querySelectorAll(".site, #toolbar-button-hide");
|
||||
for (let i = 0; i < nodes.length; i++)
|
||||
setFocusable(nodes[i], aEnabled);
|
||||
|
||||
// The 'show' button is focusable when the grid is hidden.
|
||||
let btnShow = document.getElementById("toolbar-button-show");
|
||||
setFocusable(btnShow, !aEnabled);
|
||||
|
||||
// The 'reset' button is focusable when the grid is shown and modified.
|
||||
let btnReset = document.getElementById("toolbar-button-reset");
|
||||
setFocusable(btnReset, aEnabled && aModified);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the 'dragover' event. Workaround to prevent a delay on MacOSX
|
||||
* due to a slow drop animation.
|
||||
* @param aEvent The 'dragover' event.
|
||||
*/
|
||||
onDragOver: function Page_onDragOver(aEvent) {
|
||||
if (gDrag.isValid(aEvent) && gDrag.draggedSite)
|
||||
aEvent.preventDefault();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the 'drop' event. Workaround to prevent a delay on MacOSX due to
|
||||
* a slow drop animation.
|
||||
* @param aEvent The 'drop' event.
|
||||
*/
|
||||
onDrop: function Page_onDrop(aEvent) {
|
||||
if (gDrag.isValid(aEvent) && gDrag.draggedSite) {
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
handleEvent: function Page_handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "unload":
|
||||
gAllPages.unregister(this);
|
||||
break;
|
||||
case "click":
|
||||
gAllPages.enabled = !gAllPages.enabled;
|
||||
break;
|
||||
case "dragover":
|
||||
if (gDrag.isValid(aEvent) && gDrag.draggedSite)
|
||||
aEvent.preventDefault();
|
||||
break;
|
||||
case "drop":
|
||||
if (gDrag.isValid(aEvent) && gDrag.draggedSite) {
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,7 +91,6 @@ Site.prototype = {
|
||||
} else {
|
||||
gBlockedLinks.block(this._link);
|
||||
gUpdater.updateGrid(aCallback);
|
||||
gPage.updateModifiedFlag();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -110,14 +109,14 @@ Site.prototype = {
|
||||
* @param aPinned Whether this site is now pinned or unpinned.
|
||||
*/
|
||||
_updateAttributes: function (aPinned) {
|
||||
let buttonPin = this._querySelector(".strip-button-pin");
|
||||
let control = this._querySelector(".newtab-control-pin");
|
||||
|
||||
if (aPinned) {
|
||||
this.node.setAttribute("pinned", true);
|
||||
buttonPin.setAttribute("title", newTabString("unpin"));
|
||||
control.setAttribute("pinned", true);
|
||||
control.setAttribute("title", newTabString("unpin"));
|
||||
} else {
|
||||
this.node.removeAttribute("pinned");
|
||||
buttonPin.setAttribute("title", newTabString("pin"));
|
||||
control.removeAttribute("pinned");
|
||||
control.setAttribute("title", newTabString("pin"));
|
||||
}
|
||||
},
|
||||
|
||||
@@ -126,32 +125,17 @@ Site.prototype = {
|
||||
*/
|
||||
_render: function Site_render() {
|
||||
let title = this.title || this.url;
|
||||
this.node.setAttribute("title", title);
|
||||
this.node.setAttribute("href", this.url);
|
||||
this._querySelector(".site-title").textContent = title;
|
||||
let link = this._querySelector(".newtab-link");
|
||||
link.setAttribute("title", title);
|
||||
link.setAttribute("href", this.url);
|
||||
this._querySelector(".newtab-title").textContent = title;
|
||||
|
||||
if (this.isPinned())
|
||||
this._updateAttributes(true);
|
||||
|
||||
this._renderThumbnail();
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders the site's thumbnail.
|
||||
*/
|
||||
_renderThumbnail: function Site_renderThumbnail() {
|
||||
let img = this._querySelector(".site-img")
|
||||
img.setAttribute("alt", this.title || this.url);
|
||||
img.setAttribute("loading", "true");
|
||||
|
||||
// Wait until the image has loaded.
|
||||
img.addEventListener("load", function onLoad() {
|
||||
img.removeEventListener("load", onLoad, false);
|
||||
img.removeAttribute("loading");
|
||||
}, false);
|
||||
|
||||
// Set the thumbnail url.
|
||||
img.setAttribute("src", PageThumbs.getThumbnailURL(this.url));
|
||||
let thumbnailURL = PageThumbs.getThumbnailURL(this.url);
|
||||
let thumbnail = this._querySelector(".newtab-thumbnail");
|
||||
thumbnail.style.backgroundImage = "url(" + thumbnailURL + ")";
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -159,56 +143,37 @@ Site.prototype = {
|
||||
*/
|
||||
_addEventHandlers: function Site_addEventHandlers() {
|
||||
// Register drag-and-drop event handlers.
|
||||
["DragStart", /*"Drag",*/ "DragEnd"].forEach(function (aType) {
|
||||
let method = "_on" + aType;
|
||||
this[method] = this[method].bind(this);
|
||||
this._node.addEventListener(aType.toLowerCase(), this[method], false);
|
||||
}, this);
|
||||
this._node.addEventListener("dragstart", this, false);
|
||||
this._node.addEventListener("dragend", this, false);
|
||||
|
||||
let self = this;
|
||||
|
||||
function pin(aEvent) {
|
||||
if (aEvent)
|
||||
aEvent.preventDefault();
|
||||
|
||||
if (self.isPinned())
|
||||
self.unpin();
|
||||
else
|
||||
self.pin();
|
||||
}
|
||||
|
||||
function block(aEvent) {
|
||||
if (aEvent)
|
||||
aEvent.preventDefault();
|
||||
|
||||
self.block();
|
||||
}
|
||||
|
||||
this._querySelector(".strip-button-pin").addEventListener("click", pin, false);
|
||||
this._querySelector(".strip-button-block").addEventListener("click", block, false);
|
||||
let controls = this.node.querySelectorAll(".newtab-control");
|
||||
for (let i = 0; i < controls.length; i++)
|
||||
controls[i].addEventListener("click", this, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for the 'dragstart' event.
|
||||
* @param aEvent The drag event.
|
||||
* Handles all site events.
|
||||
*/
|
||||
_onDragStart: function Site_onDragStart(aEvent) {
|
||||
gDrag.start(this, aEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for the 'drag' event.
|
||||
* @param aEvent The drag event.
|
||||
*/
|
||||
_onDrag: function Site_onDrag(aEvent) {
|
||||
gDrag.drag(this, aEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for the 'dragend' event.
|
||||
* @param aEvent The drag event.
|
||||
*/
|
||||
_onDragEnd: function Site_onDragEnd(aEvent) {
|
||||
gDrag.end(this, aEvent);
|
||||
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 "dragstart":
|
||||
gDrag.start(this, aEvent);
|
||||
break;
|
||||
case "drag":
|
||||
gDrag.drag(this, aEvent);
|
||||
break;
|
||||
case "dragend":
|
||||
gDrag.end(this, aEvent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
#ifdef 0
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This singleton represents the page's toolbar that allows to enable/disable
|
||||
* the 'New Tab Page' feature and to reset the whole page.
|
||||
*/
|
||||
let gToolbar = {
|
||||
/**
|
||||
* Initializes the toolbar.
|
||||
* @param aSelector The query selector of the toolbar.
|
||||
*/
|
||||
init: function Toolbar_init(aSelector) {
|
||||
this._node = document.querySelector(aSelector);
|
||||
let buttons = this._node.querySelectorAll("input");
|
||||
|
||||
// Listen for 'click' events on the toolbar buttons.
|
||||
["show", "hide", "reset"].forEach(function (aType, aIndex) {
|
||||
let self = this;
|
||||
let button = buttons[aIndex];
|
||||
let handler = function () self[aType]();
|
||||
|
||||
button.addEventListener("click", handler, false);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Per default buttons lose focus after being clicked on Mac OS X.
|
||||
// So when the URL bar has focus and a toolbar button is clicked the
|
||||
// URL bar regains focus and the history pops up. We need to prevent
|
||||
// that by explicitly removing its focus.
|
||||
button.addEventListener("mousedown", function () {
|
||||
window.focus();
|
||||
}, false);
|
||||
#endif
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables the 'New Tab Page' feature.
|
||||
*/
|
||||
show: function Toolbar_show() {
|
||||
this._passButtonFocus("show", "hide");
|
||||
gAllPages.enabled = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Disables the 'New Tab Page' feature.
|
||||
*/
|
||||
hide: function Toolbar_hide() {
|
||||
this._passButtonFocus("hide", "show");
|
||||
gAllPages.enabled = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets the whole page and forces it to re-render its content.
|
||||
* @param aCallback The callback to call when the page has been reset.
|
||||
*/
|
||||
reset: function Toolbar_reset(aCallback) {
|
||||
this._passButtonFocus("reset", "hide");
|
||||
let node = gGrid.node;
|
||||
|
||||
// animate the page reset
|
||||
gTransformation.fadeNodeOut(node, function () {
|
||||
NewTabUtils.reset();
|
||||
|
||||
gLinks.populateCache(function () {
|
||||
gAllPages.update();
|
||||
|
||||
// Without the setTimeout() we have a strange flicker.
|
||||
setTimeout(function () gTransformation.fadeNodeIn(node, aCallback));
|
||||
}, true);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Passes the focus from the current button to the next.
|
||||
* @param aCurrent The button that currently has focus.
|
||||
* @param aNext The button that is focused next.
|
||||
*/
|
||||
_passButtonFocus: function Toolbar_passButtonFocus(aCurrent, aNext) {
|
||||
if (document.querySelector("#toolbar-button-" + aCurrent + ":-moz-focusring"))
|
||||
document.getElementById("toolbar-button-" + aNext).focus();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,6 +10,24 @@
|
||||
* convenience methods to work with a site's DOM node.
|
||||
*/
|
||||
let gTransformation = {
|
||||
/**
|
||||
* Returns the width of the left and top border of a cell. We need to take it
|
||||
* into account when measuring and comparing site and cell positions.
|
||||
*/
|
||||
get _cellBorderWidths() {
|
||||
let cstyle = window.getComputedStyle(gGrid.cells[0].node, null);
|
||||
let widths = {
|
||||
left: parseInt(cstyle.getPropertyValue("border-left-width")),
|
||||
top: parseInt(cstyle.getPropertyValue("border-top-width"))
|
||||
};
|
||||
|
||||
// Cache this value, overwrite the getter.
|
||||
Object.defineProperty(this, "_cellBorderWidths",
|
||||
{value: widths, enumerable: true});
|
||||
|
||||
return widths;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a DOM node's position.
|
||||
* @param aNode The DOM node.
|
||||
@@ -80,6 +98,14 @@ let gTransformation = {
|
||||
* @param aSite The site to freeze.
|
||||
*/
|
||||
freezeSitePosition: function Transformation_freezeSitePosition(aSite) {
|
||||
if (this._isFrozen(aSite))
|
||||
return;
|
||||
|
||||
let style = aSite.node.style;
|
||||
let comp = getComputedStyle(aSite.node, null);
|
||||
style.width = comp.getPropertyValue("width")
|
||||
style.height = comp.getPropertyValue("height");
|
||||
|
||||
aSite.node.setAttribute("frozen", "true");
|
||||
this.setSitePosition(aSite, this.getNodePosition(aSite.node));
|
||||
},
|
||||
@@ -89,8 +115,11 @@ let gTransformation = {
|
||||
* @param aSite The site to unfreeze.
|
||||
*/
|
||||
unfreezeSitePosition: function Transformation_unfreezeSitePosition(aSite) {
|
||||
if (!this._isFrozen(aSite))
|
||||
return;
|
||||
|
||||
let style = aSite.node.style;
|
||||
style.left = style.top = "";
|
||||
style.left = style.top = style.width = style.height = "";
|
||||
aSite.node.removeAttribute("frozen");
|
||||
},
|
||||
|
||||
@@ -117,8 +146,13 @@ let gTransformation = {
|
||||
callback();
|
||||
}
|
||||
|
||||
// We need to take the width of a cell's border into account.
|
||||
targetPosition.left += this._cellBorderWidths.left;
|
||||
targetPosition.top += this._cellBorderWidths.top;
|
||||
|
||||
// Nothing to do here if the positions already match.
|
||||
if (currentPosition.equals(targetPosition)) {
|
||||
if (currentPosition.left == targetPosition.left &&
|
||||
currentPosition.top == targetPosition.top) {
|
||||
finish();
|
||||
} else {
|
||||
this.setSitePosition(aSite, targetPosition);
|
||||
@@ -222,5 +256,14 @@ let gTransformation = {
|
||||
_moveSite: function Transformation_moveSite(aSite, aIndex, aOptions) {
|
||||
this.freezeSitePosition(aSite);
|
||||
this.slideSiteTo(aSite, gGrid.cells[aIndex], aOptions);
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether a site is currently frozen.
|
||||
* @param aSite The site to check.
|
||||
* @return Whether the given site is frozen.
|
||||
*/
|
||||
_isFrozen: function Transformation_isFrozen(aSite) {
|
||||
return aSite.node.hasAttribute("frozen");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@ const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
|
||||
* Hint: This is the default value because the 'New Tab Page' is the only
|
||||
* client for now.
|
||||
*/
|
||||
const THUMBNAIL_WIDTH = 201;
|
||||
const THUMBNAIL_WIDTH = 400;
|
||||
|
||||
/**
|
||||
* The default height for page thumbnails.
|
||||
@@ -26,7 +26,7 @@ const THUMBNAIL_WIDTH = 201;
|
||||
* Hint: This is the default value because the 'New Tab Page' is the only
|
||||
* client for now.
|
||||
*/
|
||||
const THUMBNAIL_HEIGHT = 127;
|
||||
const THUMBNAIL_HEIGHT = 225;
|
||||
|
||||
/**
|
||||
* The default background color for page thumbnails.
|
||||
|
||||
@@ -1,6 +1,2 @@
|
||||
<!-- These strings are used in the about:newtab page -->
|
||||
<!ENTITY newtab.pageTitle "New Tab">
|
||||
|
||||
<!ENTITY newtab.show "Show the New Tab Page">
|
||||
<!ENTITY newtab.hide "Hide the New Tab Page">
|
||||
<!ENTITY newtab.reset "Reset the New Tab Page">
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
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
|
||||
|
||||
@@ -1,148 +1,131 @@
|
||||
#scrollbox {
|
||||
padding-bottom: 18px;
|
||||
background-color: #fff;
|
||||
:root {
|
||||
-moz-appearance: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#body {
|
||||
padding-top: 106px;
|
||||
font-family: sans-serif;
|
||||
/* SCROLLBOX */
|
||||
#newtab-scrollbox:not([page-disabled]) {
|
||||
background-color: rgb(229,229,229);
|
||||
background-image: url(chrome://browser/skin/newtab/noise.png),
|
||||
-moz-linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,.2));
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.button {
|
||||
/* TOGGLE */
|
||||
#newtab-toggle {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
padding: 0;
|
||||
border: 0 none;
|
||||
border: none;
|
||||
background: -216px 0 transparent url(chrome://browser/skin/newtab/controls.png);
|
||||
}
|
||||
|
||||
/* TOOLBAR */
|
||||
#toolbar {
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
width: 13px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
#newtab-toggle[page-disabled] {
|
||||
background-position: -232px 0;
|
||||
}
|
||||
|
||||
.toolbar-button {
|
||||
background: transparent url(chrome://browser/skin/newtab/toolbar.png);
|
||||
/* ROWS */
|
||||
.newtab-row {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#toolbar-button-show {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
background-position: -10px 0;
|
||||
}
|
||||
|
||||
#toolbar-button-show:hover {
|
||||
background-position: -10px -12px;
|
||||
}
|
||||
|
||||
#toolbar-button-show:active {
|
||||
background-position: -10px -24px;
|
||||
}
|
||||
|
||||
#toolbar-button-hide {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
#toolbar-button-hide:hover {
|
||||
background-position: 0 -12px;
|
||||
}
|
||||
|
||||
#toolbar-button-hide:active {
|
||||
background-position: 0 -24px;
|
||||
}
|
||||
|
||||
#toolbar-button-reset {
|
||||
top: 17px;
|
||||
width: 11px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
#toolbar-button-reset {
|
||||
background-position: -21px 0;
|
||||
}
|
||||
|
||||
#toolbar-button-reset:hover {
|
||||
background-position: -21px -12px;
|
||||
}
|
||||
|
||||
#toolbar-button-reset:active {
|
||||
background-position: -21px -24px;
|
||||
}
|
||||
|
||||
/* GRID */
|
||||
#grid {
|
||||
padding: 1px;
|
||||
margin: 0 auto;
|
||||
.newtab-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* CELLS */
|
||||
.cell {
|
||||
outline: 1px dashed #ccc;
|
||||
outline-offset: -1px;
|
||||
.newtab-cell {
|
||||
-moz-margin-end: 20px;
|
||||
background-color: rgba(255,255,255,.2);
|
||||
border: 1px solid;
|
||||
border-color: rgba(8,22,37,.12) rgba(8,22,37,.14) rgba(8,22,37,.16);
|
||||
border-radius: 1px;
|
||||
-moz-transition: border-color 100ms ease-out;
|
||||
}
|
||||
|
||||
.newtab-cell:empty {
|
||||
border: 1px dashed;
|
||||
border-color: rgba(8,22,37,.15) rgba(8,22,37,.17) rgba(8,22,37,.19);
|
||||
}
|
||||
|
||||
.newtab-cell:last-child {
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
|
||||
.newtab-cell:hover:not(:empty) {
|
||||
border-color: rgba(8,22,37,.25) rgba(8,22,37,.27) rgba(8,22,37,.3);
|
||||
}
|
||||
|
||||
/* SITES */
|
||||
.site {
|
||||
background-color: #ececec;
|
||||
-moz-transition: 200ms ease-out;
|
||||
-moz-transition-property: top, left, box-shadow, opacity;
|
||||
}
|
||||
|
||||
.site[dragged] {
|
||||
-moz-transition-property: box-shadow;
|
||||
}
|
||||
|
||||
.site[ontop] {
|
||||
box-shadow: 0 1px 4px #000;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* SITE TITLE */
|
||||
.site-title {
|
||||
height: 2.4em;
|
||||
width: 189px;
|
||||
padding: 0 6px;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
border: solid transparent;
|
||||
border-width: 6px 0;
|
||||
color: #fff;
|
||||
.newtab-site {
|
||||
text-decoration: none;
|
||||
line-height: 1.2em;
|
||||
font-weight: 700;
|
||||
-moz-transition-property: top, left, opacity, box-shadow, background-color;
|
||||
}
|
||||
|
||||
/* SITE STRIP */
|
||||
.site-strip {
|
||||
padding: 4px 3px;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
.newtab-site:hover,
|
||||
.newtab-site[dragged] {
|
||||
box-shadow: 0 0 10px rgba(8,22,37,.3);
|
||||
}
|
||||
|
||||
.strip-button {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
background: transparent url(chrome://browser/skin/newtab/strip.png);
|
||||
.newtab-site[dragged] {
|
||||
-moz-transition-property: box-shadow, background-color;
|
||||
background-color: rgb(242,242,242);
|
||||
}
|
||||
|
||||
.strip-button-pin:hover {
|
||||
background-position: 0 -17px;
|
||||
/* THUMBNAILS */
|
||||
.newtab-thumbnail {
|
||||
background-origin: padding-box;
|
||||
background-clip: padding-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.strip-button-pin:active,
|
||||
.site[pinned] .strip-button-pin {
|
||||
background-position: 0 -34px;
|
||||
/* TITLES */
|
||||
.newtab-title {
|
||||
padding: 0 8px;
|
||||
background-color: rgba(248,249,251,.95);
|
||||
color: #1f364c;
|
||||
font-size: 12px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.strip-button-block {
|
||||
background-position: -17px 0;
|
||||
/* CONTROLS */
|
||||
.newtab-control {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 1px 2px 3px;
|
||||
border: none;
|
||||
background: transparent url(chrome://browser/skin/newtab/controls.png);
|
||||
}
|
||||
|
||||
.strip-button-block:hover {
|
||||
background-position: -17px -17px;
|
||||
.newtab-control-pin:hover {
|
||||
background-position: -24px 0;
|
||||
}
|
||||
|
||||
.strip-button-block:active {
|
||||
background-position: -17px -34px;
|
||||
.newtab-control-pin:active {
|
||||
background-position: -48px 0;
|
||||
}
|
||||
|
||||
.newtab-control-pin[pinned] {
|
||||
background-position: -72px 0;
|
||||
}
|
||||
|
||||
.newtab-control-pin[pinned]:hover {
|
||||
background-position: -96px 0;
|
||||
}
|
||||
|
||||
.newtab-control-pin[pinned]:active {
|
||||
background-position: -120px 0;
|
||||
}
|
||||
|
||||
.newtab-control-block {
|
||||
background-position: -144px 0;
|
||||
}
|
||||
|
||||
.newtab-control-block:hover {
|
||||
background-position: -168px 0;
|
||||
}
|
||||
|
||||
.newtab-control-block:active {
|
||||
background-position: -192px 0;
|
||||
}
|
||||
|
||||
@@ -1,147 +1,131 @@
|
||||
#scrollbox {
|
||||
padding-bottom: 18px;
|
||||
background-color: #fff;
|
||||
:root {
|
||||
-moz-appearance: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#body {
|
||||
padding-top: 106px;
|
||||
font-family: sans-serif;
|
||||
/* SCROLLBOX */
|
||||
#newtab-scrollbox:not([page-disabled]) {
|
||||
background-color: rgb(229,229,229);
|
||||
background-image: url(chrome://browser/skin/newtab/noise.png),
|
||||
-moz-linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,.2));
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.button {
|
||||
/* TOGGLE */
|
||||
#newtab-toggle {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
padding: 0;
|
||||
border: 0 none;
|
||||
border: none;
|
||||
background: -216px 0 transparent url(chrome://browser/skin/newtab/controls.png);
|
||||
}
|
||||
|
||||
/* TOOLBAR */
|
||||
#toolbar {
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
width: 13px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
#newtab-toggle[page-disabled] {
|
||||
background-position: -232px 0;
|
||||
}
|
||||
|
||||
.toolbar-button {
|
||||
background: transparent url(chrome://browser/skin/newtab/toolbar.png);
|
||||
/* ROWS */
|
||||
.newtab-row {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#toolbar-button-show {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
background-position: -10px 0;
|
||||
}
|
||||
|
||||
#toolbar-button-show:hover {
|
||||
background-position: -10px -12px;
|
||||
}
|
||||
|
||||
#toolbar-button-show:active {
|
||||
background-position: -10px -24px;
|
||||
}
|
||||
|
||||
#toolbar-button-hide {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
#toolbar-button-hide:hover {
|
||||
background-position: 0 -12px;
|
||||
}
|
||||
|
||||
#toolbar-button-hide:active {
|
||||
background-position: 0 -24px;
|
||||
}
|
||||
|
||||
#toolbar-button-reset {
|
||||
top: 17px;
|
||||
width: 11px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
#toolbar-button-reset {
|
||||
background-position: -21px 0;
|
||||
}
|
||||
|
||||
#toolbar-button-reset:hover {
|
||||
background-position: -21px -12px;
|
||||
}
|
||||
|
||||
#toolbar-button-reset:active {
|
||||
background-position: -21px -24px;
|
||||
}
|
||||
|
||||
/* GRID */
|
||||
#grid {
|
||||
padding: 1px;
|
||||
margin: 0 auto;
|
||||
.newtab-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* CELLS */
|
||||
.cell {
|
||||
outline: 1px dashed #ccc;
|
||||
outline-offset: -1px;
|
||||
.newtab-cell {
|
||||
-moz-margin-end: 20px;
|
||||
background-color: rgba(255,255,255,.2);
|
||||
border: 1px solid;
|
||||
border-color: rgba(8,22,37,.12) rgba(8,22,37,.14) rgba(8,22,37,.16);
|
||||
border-radius: 1px;
|
||||
-moz-transition: border-color 100ms ease-out;
|
||||
}
|
||||
|
||||
.newtab-cell:empty {
|
||||
border: 1px dashed;
|
||||
border-color: rgba(8,22,37,.15) rgba(8,22,37,.17) rgba(8,22,37,.19);
|
||||
}
|
||||
|
||||
.newtab-cell:last-child {
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
|
||||
.newtab-cell:hover:not(:empty) {
|
||||
border-color: rgba(8,22,37,.25) rgba(8,22,37,.27) rgba(8,22,37,.3);
|
||||
}
|
||||
|
||||
/* SITES */
|
||||
.site {
|
||||
background-color: #ececec;
|
||||
-moz-transition: 200ms ease-out;
|
||||
-moz-transition-property: top, left, box-shadow, opacity;
|
||||
}
|
||||
|
||||
.site[dragged] {
|
||||
-moz-transition-property: box-shadow;
|
||||
}
|
||||
|
||||
.site[ontop] {
|
||||
box-shadow: 0 1px 4px #000;
|
||||
}
|
||||
|
||||
/* SITE TITLE */
|
||||
.site-title {
|
||||
height: 2.4em;
|
||||
width: 189px;
|
||||
padding: 0 6px;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
border: solid transparent;
|
||||
border-width: 6px 0;
|
||||
color: #fff;
|
||||
.newtab-site {
|
||||
text-decoration: none;
|
||||
line-height: 1.2em;
|
||||
font-weight: 700;
|
||||
-moz-transition-property: top, left, opacity, box-shadow, background-color;
|
||||
}
|
||||
|
||||
/* SITE STRIP */
|
||||
.site-strip {
|
||||
padding: 4px 3px;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
.newtab-site:hover,
|
||||
.newtab-site[dragged] {
|
||||
box-shadow: 0 0 10px rgba(8,22,37,.3);
|
||||
}
|
||||
|
||||
.strip-button {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
background: transparent url(chrome://browser/skin/newtab/strip.png);
|
||||
.newtab-site[dragged] {
|
||||
-moz-transition-property: box-shadow, background-color;
|
||||
background-color: rgb(242,242,242);
|
||||
}
|
||||
|
||||
.strip-button-pin:hover {
|
||||
background-position: 0 -17px;
|
||||
/* THUMBNAILS */
|
||||
.newtab-thumbnail {
|
||||
background-origin: padding-box;
|
||||
background-clip: padding-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.strip-button-pin:active,
|
||||
.site[pinned] .strip-button-pin {
|
||||
background-position: 0 -34px;
|
||||
/* TITLES */
|
||||
.newtab-title {
|
||||
padding: 0 8px;
|
||||
background-color: rgba(248,249,251,.95);
|
||||
color: #1f364c;
|
||||
font-size: 12px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.strip-button-block {
|
||||
background-position: -17px 0;
|
||||
/* CONTROLS */
|
||||
.newtab-control {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 1px 2px 3px;
|
||||
border: none;
|
||||
background: transparent url(chrome://browser/skin/newtab/controls.png);
|
||||
}
|
||||
|
||||
.strip-button-block:hover {
|
||||
background-position: -17px -17px;
|
||||
.newtab-control-pin:hover {
|
||||
background-position: -24px 0;
|
||||
}
|
||||
|
||||
.strip-button-block:active {
|
||||
background-position: -17px -34px;
|
||||
.newtab-control-pin:active {
|
||||
background-position: -48px 0;
|
||||
}
|
||||
|
||||
.newtab-control-pin[pinned] {
|
||||
background-position: -72px 0;
|
||||
}
|
||||
|
||||
.newtab-control-pin[pinned]:hover {
|
||||
background-position: -96px 0;
|
||||
}
|
||||
|
||||
.newtab-control-pin[pinned]:active {
|
||||
background-position: -120px 0;
|
||||
}
|
||||
|
||||
.newtab-control-block {
|
||||
background-position: -144px 0;
|
||||
}
|
||||
|
||||
.newtab-control-block:hover {
|
||||
background-position: -168px 0;
|
||||
}
|
||||
|
||||
.newtab-control-block:active {
|
||||
background-position: -192px 0;
|
||||
}
|
||||
|
||||
@@ -1,148 +1,131 @@
|
||||
#scrollbox {
|
||||
padding-bottom: 18px;
|
||||
background-color: #fff;
|
||||
:root {
|
||||
-moz-appearance: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#body {
|
||||
padding-top: 106px;
|
||||
font-family: sans-serif;
|
||||
/* SCROLLBOX */
|
||||
#newtab-scrollbox:not([page-disabled]) {
|
||||
background-color: rgb(229,229,229);
|
||||
background-image: url(chrome://browser/skin/newtab/noise.png),
|
||||
-moz-linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,.2));
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.button {
|
||||
/* TOGGLE */
|
||||
#newtab-toggle {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
padding: 0;
|
||||
border: 0 none;
|
||||
border: none;
|
||||
background: -216px 0 transparent url(chrome://browser/skin/newtab/controls.png);
|
||||
}
|
||||
|
||||
/* TOOLBAR */
|
||||
#toolbar {
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
width: 13px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
#newtab-toggle[page-disabled] {
|
||||
background-position: -232px 0;
|
||||
}
|
||||
|
||||
.toolbar-button {
|
||||
background: transparent url(chrome://browser/skin/newtab/toolbar.png);
|
||||
/* ROWS */
|
||||
.newtab-row {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#toolbar-button-show {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
background-position: -10px 0;
|
||||
}
|
||||
|
||||
#toolbar-button-show:hover {
|
||||
background-position: -10px -12px;
|
||||
}
|
||||
|
||||
#toolbar-button-show:active {
|
||||
background-position: -10px -24px;
|
||||
}
|
||||
|
||||
#toolbar-button-hide {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
#toolbar-button-hide:hover {
|
||||
background-position: 0 -12px;
|
||||
}
|
||||
|
||||
#toolbar-button-hide:active {
|
||||
background-position: 0 -24px;
|
||||
}
|
||||
|
||||
#toolbar-button-reset {
|
||||
top: 17px;
|
||||
width: 11px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
#toolbar-button-reset {
|
||||
background-position: -21px 0;
|
||||
}
|
||||
|
||||
#toolbar-button-reset:hover {
|
||||
background-position: -21px -12px;
|
||||
}
|
||||
|
||||
#toolbar-button-reset:active {
|
||||
background-position: -21px -24px;
|
||||
}
|
||||
|
||||
/* GRID */
|
||||
#grid {
|
||||
padding: 1px;
|
||||
margin: 0 auto;
|
||||
.newtab-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* CELLS */
|
||||
.cell {
|
||||
outline: 1px dashed #ccc;
|
||||
outline-offset: -1px;
|
||||
.newtab-cell {
|
||||
-moz-margin-end: 20px;
|
||||
background-color: rgba(255,255,255,.2);
|
||||
border: 1px solid;
|
||||
border-color: rgba(8,22,37,.12) rgba(8,22,37,.14) rgba(8,22,37,.16);
|
||||
border-radius: 1px;
|
||||
-moz-transition: border-color 100ms ease-out;
|
||||
}
|
||||
|
||||
.newtab-cell:empty {
|
||||
border: 1px dashed;
|
||||
border-color: rgba(8,22,37,.15) rgba(8,22,37,.17) rgba(8,22,37,.19);
|
||||
}
|
||||
|
||||
.newtab-cell:last-child {
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
|
||||
.newtab-cell:hover:not(:empty) {
|
||||
border-color: rgba(8,22,37,.25) rgba(8,22,37,.27) rgba(8,22,37,.3);
|
||||
}
|
||||
|
||||
/* SITES */
|
||||
.site {
|
||||
background-color: #ececec;
|
||||
-moz-transition: 200ms ease-out;
|
||||
-moz-transition-property: top, left, box-shadow, opacity;
|
||||
}
|
||||
|
||||
.site[dragged] {
|
||||
-moz-transition-property: box-shadow;
|
||||
}
|
||||
|
||||
.site[ontop] {
|
||||
box-shadow: 0 1px 4px #000;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* SITE TITLE */
|
||||
.site-title {
|
||||
height: 2.4em;
|
||||
width: 189px;
|
||||
padding: 0 6px;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
border: solid transparent;
|
||||
border-width: 6px 0;
|
||||
color: #fff;
|
||||
.newtab-site {
|
||||
text-decoration: none;
|
||||
line-height: 1.2em;
|
||||
font-weight: 700;
|
||||
-moz-transition-property: top, left, opacity, box-shadow, background-color;
|
||||
}
|
||||
|
||||
/* SITE STRIP */
|
||||
.site-strip {
|
||||
padding: 4px 3px;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
.newtab-site:hover,
|
||||
.newtab-site[dragged] {
|
||||
box-shadow: 0 0 10px rgba(8,22,37,.3);
|
||||
}
|
||||
|
||||
.strip-button {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
background: transparent url(chrome://browser/skin/newtab/strip.png);
|
||||
.newtab-site[dragged] {
|
||||
-moz-transition-property: box-shadow, background-color;
|
||||
background-color: rgb(242,242,242);
|
||||
}
|
||||
|
||||
.strip-button-pin:hover {
|
||||
background-position: 0 -17px;
|
||||
/* THUMBNAILS */
|
||||
.newtab-thumbnail {
|
||||
background-origin: padding-box;
|
||||
background-clip: padding-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.strip-button-pin:active,
|
||||
.site[pinned] .strip-button-pin {
|
||||
background-position: 0 -34px;
|
||||
/* TITLES */
|
||||
.newtab-title {
|
||||
padding: 0 8px;
|
||||
background-color: rgba(248,249,251,.95);
|
||||
color: #1f364c;
|
||||
font-size: 12px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.strip-button-block {
|
||||
background-position: -17px 0;
|
||||
/* CONTROLS */
|
||||
.newtab-control {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 1px 2px 3px;
|
||||
border: none;
|
||||
background: transparent url(chrome://browser/skin/newtab/controls.png);
|
||||
}
|
||||
|
||||
.strip-button-block:hover {
|
||||
background-position: -17px -17px;
|
||||
.newtab-control-pin:hover {
|
||||
background-position: -24px 0;
|
||||
}
|
||||
|
||||
.strip-button-block:active {
|
||||
background-position: -17px -34px;
|
||||
.newtab-control-pin:active {
|
||||
background-position: -48px 0;
|
||||
}
|
||||
|
||||
.newtab-control-pin[pinned] {
|
||||
background-position: -72px 0;
|
||||
}
|
||||
|
||||
.newtab-control-pin[pinned]:hover {
|
||||
background-position: -96px 0;
|
||||
}
|
||||
|
||||
.newtab-control-pin[pinned]:active {
|
||||
background-position: -120px 0;
|
||||
}
|
||||
|
||||
.newtab-control-block {
|
||||
background-position: -144px 0;
|
||||
}
|
||||
|
||||
.newtab-control-block:hover {
|
||||
background-position: -168px 0;
|
||||
}
|
||||
|
||||
.newtab-control-block:active {
|
||||
background-position: -192px 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user