Commit 60a79cb6 authored by Kristi Park's avatar Kristi Park Committed by Commit Bot

[NTP] Move common functions into separate utils and animations files

Move the ripple animation handler to a new animations file, and move
common helper functions into a new utils file.

This enables us to add ripple animations to the edit custom link dialog
buttons.

Bug: 874201
Change-Id: I5e3d72bf3fa282faf0068122f1a660e8ad72bab3
Reviewed-on: https://chromium-review.googlesource.com/c/1347776
Commit-Queue: Kristi Park <kristipark@chromium.org>
Reviewed-by: default avatarRamya Nagarajan <ramyan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611227}
parent 27866045
/* Copyright 2018 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
.ripple-container {
height: 100%;
left: 0;
pointer-events: none;
position: absolute;
top: 0;
width: 100%;
z-index: 100;
}
.ripple-effect-mask {
height: 0;
left: 0;
overflow: hidden;
position: absolute;
top: 0;
width: 0;
}
.ripple-effect {
background-color: rgba(26, 115, 232, 0.1);
border-radius: 50%;
height: 1px;
pointer-events: none;
transition: width, height, margin, background-color 400ms 250ms;
transition-duration: 400ms;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
width: 1px;
}
/* Copyright 2018 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
/**
* Contains common animations used in the main NTP page and its iframes.
*/
let animations = {};
/**
* Enum for classnames.
* @enum {string}
* @const
*/
animations.CLASSES = {
RIPPLE: 'ripple',
RIPPLE_CONTAINER: 'ripple-container',
RIPPLE_EFFECT_MASK: 'ripple-effect-mask',
RIPPLE_EFFECT: 'ripple-effect',
};
/**
* The duration of the ripple animation.
* @type {number}
* @const
*/
animations.RIPPLE_DURATION_MS = 800;
/**
* The max size of the ripple animation.
* @type {number}
* @const
*/
animations.RIPPLE_MAX_RADIUS_PX = 300;
/**
* Enables ripple animations for elements with CLASSES.RIPPLE. The target
* element must have position relative or absolute.
*/
animations.addRippleAnimations = function() {
let ripple = (event) => {
let target = event.target;
const rect = target.getBoundingClientRect();
const x = Math.round(event.clientX - rect.left);
const y = Math.round(event.clientY - rect.top);
// Calculate radius
const corners = [
{x: 0, y: 0},
{x: rect.width, y: 0},
{x: 0, y: rect.height},
{x: rect.width, y: rect.height},
];
let distance = (x1, y1, x2, y2) => {
var xDelta = x1 - x2;
var yDelta = y1 - y2;
return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
};
let cornerDistances = corners.map(function(corner) {
return Math.round(distance(x, y, corner.x, corner.y));
});
const radius = Math.min(
animations.RIPPLE_MAX_RADIUS_PX, Math.max.apply(Math, cornerDistances));
let ripple = document.createElement('div');
let rippleMask = document.createElement('div');
let rippleContainer = document.createElement('div');
ripple.classList.add(animations.CLASSES.RIPPLE_EFFECT);
rippleMask.classList.add(animations.CLASSES.RIPPLE_EFFECT_MASK);
rippleContainer.classList.add(animations.CLASSES.RIPPLE_CONTAINER);
rippleMask.appendChild(ripple);
rippleContainer.appendChild(rippleMask);
target.appendChild(rippleContainer);
// Ripple start location
ripple.style.marginLeft = x + 'px';
ripple.style.marginTop = y + 'px';
rippleMask.style.width = target.offsetWidth + 'px';
rippleMask.style.height = target.offsetHeight + 'px';
rippleMask.style.borderRadius =
window.getComputedStyle(target).borderRadius;
// Start transition/ripple
ripple.style.width = radius * 2 + 'px';
ripple.style.height = radius * 2 + 'px';
ripple.style.marginLeft = x - radius + 'px';
ripple.style.marginTop = y - radius + 'px';
ripple.style.backgroundColor = 'rgba(0, 0, 0, 0)';
window.setTimeout(function() {
ripple.remove();
rippleMask.remove();
rippleContainer.remove();
}, animations.RIPPLE_DURATION_MS);
};
let rippleElements =
document.querySelectorAll('.' + animations.CLASSES.RIPPLE);
for (let i = 0; i < rippleElements.length; i++) {
rippleElements[i].addEventListener('mousedown', ripple);
}
};
......@@ -193,16 +193,6 @@ customBackgrounds.showErrorNotification;
*/
customBackgrounds.hideCustomLinkNotification;
/**
* Alias for document.getElementById.
* @param {string} id The ID of the element to find.
* @return {HTMLElement} The found element or null if not found.
*/
function $(id) {
// eslint-disable-next-line no-restricted-properties
return document.getElementById(id);
}
/**
* Sets the visibility of the settings menu and individual options depending on
* their respective features.
......
......@@ -144,6 +144,7 @@ button {
font-weight: 500;
height: 32px;
padding: 0 16px;
position: relative;
transition-duration: 200ms;
transition-property: background-color, color, box-shadow, border;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
......
......@@ -6,7 +6,10 @@
<head>
<base target="_top">
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="animations.css">
<link rel="stylesheet" type="text/css" href="edit.css">
<script src="utils.js"></script>
<script src="animations.js"></script>
<script src="edit.js"></script>
</head>
<body>
......@@ -32,11 +35,11 @@
</div>
<div class="buttons-container">
<span>
<button id="delete" class="secondary" type="button" tabindex="0"></button>
<button id="delete" class="secondary ripple" type="button" tabindex="0"></button>
</span>
<span>
<button id="cancel" class="secondary" type="button" tabindex="0"></button>
<button type="submit" id="done" class="primary" tabindex="0"></button>
<button id="cancel" class="secondary ripple" type="button" tabindex="0"></button>
<button type="submit" id="done" class="primary ripple" tabindex="0"></button>
</span>
</div>
</form>
......
......@@ -3,17 +3,6 @@
* found in the LICENSE file. */
/**
* Alias for document.getElementById.
* @param {string} id The ID of the element to find.
* @return {HTMLElement} The found element or null if not found.
*/
function $(id) {
// eslint-disable-next-line no-restricted-properties
return document.getElementById(id);
}
/**
* Enum for ids.
* @enum {string}
......@@ -244,22 +233,6 @@ function handlePostMessage(event) {
}
/**
* Disables the focus outline for |element| on mousedown.
* @param {Element} element The element to remove the focus outline from.
*/
function disableOutlineOnMouseClick(element) {
element.addEventListener('mousedown', (event) => {
element.classList.add('mouse-navigation');
let resetOutline = (event) => {
element.classList.remove('mouse-navigation');
element.removeEventListener('blur', resetOutline);
};
element.addEventListener('blur', resetOutline);
});
}
/**
* Does some initialization and shows the dialog window.
*/
......@@ -323,9 +296,11 @@ function init() {
};
$(IDS.TITLE_FIELD).onkeydown = finishEditOrClose;
$(IDS.URL_FIELD).onkeydown = finishEditOrClose;
disableOutlineOnMouseClick($(IDS.DELETE));
disableOutlineOnMouseClick($(IDS.CANCEL));
disableOutlineOnMouseClick($(IDS.DONE));
utils.disableOutlineOnMouseClick($(IDS.DELETE));
utils.disableOutlineOnMouseClick($(IDS.CANCEL));
utils.disableOutlineOnMouseClick($(IDS.DONE));
animations.addRippleAnimations();
// Change input field name to blue on input field focus.
let changeColor = (fieldTitle) => {
......
......@@ -731,36 +731,6 @@ html[dir=rtl] #attribution,
opacity: 0;
}
.ripple-container {
height: 100%;
left: 0;
pointer-events: none;
position: absolute;
top: 0;
width: 100%;
z-index: 100;
}
.ripple-effect-mask {
height: 0;
left: 0;
overflow: hidden;
position: absolute;
top: 0;
width: 0;
}
.ripple-effect {
background-color: rgba(26, 115, 232, 0.1);
border-radius: 50%;
height: 1px;
pointer-events: none;
transition: width, height, margin, background-color 400ms 250ms;
transition-duration: 400ms;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
width: 1px;
}
/* The box containing the slider */
.switch {
background-color: #fff;
......
......@@ -4,6 +4,7 @@
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<head>
<link rel="stylesheet" href="chrome-search://local-ntp/animations.css"></link>
<link rel="stylesheet" href="chrome-search://local-ntp/theme.css"></link>
<link rel="stylesheet" href="chrome-search://local-ntp/local-ntp.css"></link>
<link rel="stylesheet" href="chrome-search://local-ntp/voice.css"></link>
......@@ -12,6 +13,10 @@
content="{{CONTENT_SECURITY_POLICY}}">
<script src="chrome-search://local-ntp/config.js"
{{CONFIG_DATA_INTEGRITY}}></script>
<script src="chrome-search://local-ntp/utils.js"
{{UTILS_INTEGRITY}}></script>
<script src="chrome-search://local-ntp/animations.js"
{{ANIMATIONS_INTEGRITY}}></script>
<script src="chrome-search://local-ntp/custom-backgrounds.js"
{{LOCAL_NTP_CUSTOM_BG_INTEGRITY}}></script>
<script src="chrome-search://local-ntp/local-ntp.js"
......
......@@ -49,17 +49,6 @@ function disableIframesAndVoiceSearchForTesting() {
}
/**
* Alias for document.getElementById.
* @param {string} id The ID of the element to find.
* @return {HTMLElement} The found element or null if not found.
*/
function $(id) {
// eslint-disable-next-line no-restricted-properties
return document.getElementById(id);
}
/**
* Specifications for an NTP design (not comprehensive).
*
......@@ -98,11 +87,6 @@ var CLASSES = {
// link dialog is open.
// Applies float animations to the Most Visited notification
FLOAT_UP: 'float-up',
// Applies ripple animation to the element on click
RIPPLE: 'ripple',
RIPPLE_CONTAINER: 'ripple-container',
RIPPLE_EFFECT_MASK: 'ripple-effect-mask',
RIPPLE_EFFECT: 'ripple-effect',
// Applies drag focus style to the fakebox
FAKEBOX_DRAG_FOCUS: 'fakebox-drag-focused',
// Applies a different style to the error notification if a link is present.
......@@ -247,20 +231,6 @@ var KEYCODE = {ENTER: 13, SPACE: 32};
const NOTIFICATION_TIMEOUT = 10000;
/**
* The duration of the ripple animation.
* @type {number}
*/
const RIPPLE_DURATION_MS = 800;
/**
* The max size of the ripple animation.
* @type {number}
*/
const RIPPLE_MAX_RADIUS_PX = 300;
/**
* The last blacklisted tile rid if any, which by definition should not be
* filler.
......@@ -948,7 +918,7 @@ function enableMDIcons() {
$(IDS.MOST_VISITED).classList.add(CLASSES.MATERIAL_DESIGN_ICONS);
$(IDS.TILES).classList.add(CLASSES.MATERIAL_DESIGN_ICONS);
enableMD();
addRippleAnimations();
animations.addRippleAnimations();
}
......@@ -960,91 +930,6 @@ function enableMD() {
}
/**
* Enables ripple animations for elements with CLASSES.RIPPLE. The target
* element must have position relative or absolute.
* TODO(kristipark): Remove after migrating to WebUI.
*/
function addRippleAnimations() {
let ripple = (event) => {
let target = event.target;
const rect = target.getBoundingClientRect();
const x = Math.round(event.clientX - rect.left);
const y = Math.round(event.clientY - rect.top);
// Calculate radius
const corners = [
{x: 0, y: 0},
{x: rect.width, y: 0},
{x: 0, y: rect.height},
{x: rect.width, y: rect.height},
];
let distance = (x1, y1, x2, y2) => {
var xDelta = x1 - x2;
var yDelta = y1 - y2;
return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
};
let cornerDistances = corners.map(function(corner) {
return Math.round(distance(x, y, corner.x, corner.y));
});
const radius =
Math.min(RIPPLE_MAX_RADIUS_PX, Math.max.apply(Math, cornerDistances));
let ripple = document.createElement('div');
let rippleMask = document.createElement('div');
let rippleContainer = document.createElement('div');
ripple.classList.add(CLASSES.RIPPLE_EFFECT);
rippleMask.classList.add(CLASSES.RIPPLE_EFFECT_MASK);
rippleContainer.classList.add(CLASSES.RIPPLE_CONTAINER);
rippleMask.appendChild(ripple);
rippleContainer.appendChild(rippleMask);
target.appendChild(rippleContainer);
// Ripple start location
ripple.style.marginLeft = x + 'px';
ripple.style.marginTop = y + 'px';
rippleMask.style.width = target.offsetWidth + 'px';
rippleMask.style.height = target.offsetHeight + 'px';
rippleMask.style.borderRadius =
window.getComputedStyle(target).borderRadius;
// Start transition/ripple
ripple.style.width = radius * 2 + 'px';
ripple.style.height = radius * 2 + 'px';
ripple.style.marginLeft = x - radius + 'px';
ripple.style.marginTop = y - radius + 'px';
ripple.style.backgroundColor = 'rgba(0, 0, 0, 0)';
window.setTimeout(function() {
ripple.remove();
rippleMask.remove();
rippleContainer.remove();
}, RIPPLE_DURATION_MS);
};
let rippleElements = document.querySelectorAll('.' + CLASSES.RIPPLE);
for (let i = 0; i < rippleElements.length; i++) {
rippleElements[i].addEventListener('mousedown', ripple);
}
}
/**
* Disables the focus outline for |element| on mousedown.
* @param {Element} element The element to remove the focus outline from.
*/
function disableOutlineOnMouseClick(element) {
element.addEventListener('mousedown', (event) => {
element.classList.add('mouse-navigation');
let resetOutline = (event) => {
element.classList.remove('mouse-navigation');
element.removeEventListener('blur', resetOutline);
};
element.addEventListener('blur', resetOutline);
});
}
/**
* Prepares the New Tab Page by adding listeners, the most visited pages
* section, and Google-specific elements for a Google-provided page.
......@@ -1164,7 +1049,7 @@ function init() {
inputbox.ondragleave = function() {
setFakeboxDragFocus(false);
};
disableOutlineOnMouseClick($(IDS.FAKEBOX_MICROPHONE));
utils.disableOutlineOnMouseClick($(IDS.FAKEBOX_MICROPHONE));
// Update the fakebox style to match the current key capturing state.
setFakeboxFocus(searchboxApiHandle.isKeyCaptureEnabled);
......
......@@ -7,6 +7,7 @@
<base target="_top">
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="single.css">
<script src="utils.js"></script>
<script src="single.js"></script>
</head>
<body>
......
......@@ -7,17 +7,6 @@
'use strict';
/**
* Alias for document.getElementById.
* @param {string} id The ID of the element to find.
* @return {HTMLElement} The found element or null if not found.
*/
function $(id) {
// eslint-disable-next-line no-restricted-properties
return document.getElementById(id);
}
/**
* Enum for key codes.
* @enum {int}
......@@ -669,22 +658,6 @@ var isSchemeAllowed = function(url) {
};
/**
* Disables the focus outline for |element| on mousedown.
* @param {Element} element The element to remove the focus outline from.
*/
function disableOutlineOnMouseClick(element) {
element.addEventListener('mousedown', (event) => {
element.classList.add('mouse-navigation');
let resetOutline = (event) => {
element.classList.remove('mouse-navigation');
element.removeEventListener('blur', resetOutline);
};
element.addEventListener('blur', resetOutline);
});
}
/**
* Renders a MostVisited tile to the DOM.
* @param {object} data Object containing rid, url, title, favicon, thumbnail,
......@@ -916,7 +889,7 @@ function renderMaterialDesignTile(data) {
.focus();
}
});
disableOutlineOnMouseClick(mdTile);
utils.disableOutlineOnMouseClick(mdTile);
let mdTileInner = document.createElement('div');
mdTileInner.className = CLASSES.MD_TILE_INNER;
......@@ -1031,7 +1004,7 @@ function renderMaterialDesignTile(data) {
mdMenu.addEventListener('keydown', function(ev) {
event.stopPropagation();
});
disableOutlineOnMouseClick(mdMenu);
utils.disableOutlineOnMouseClick(mdMenu);
mdTileContainer.appendChild(mdMenu);
}
......
/* Copyright 2018 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
/**
* Alias for document.getElementById.
* @param {string} id The ID of the element to find.
* @return {HTMLElement} The found element or null if not found.
*/
function $(id) {
// eslint-disable-next-line no-restricted-properties
return document.getElementById(id);
}
/**
* Contains common functions used in the main NTP page and its iframes.
*/
let utils = {};
/**
* Disables the focus outline for |element| on mousedown.
* @param {Element} element The element to remove the focus outline from.
*/
utils.disableOutlineOnMouseClick = function(element) {
element.addEventListener('mousedown', () => {
element.classList.add('mouse-navigation');
element.addEventListener('blur', () => {
element.classList.remove('mouse-navigation');
}, {once: true});
});
};
......@@ -16,6 +16,9 @@
<include name="IDR_LOCAL_NTP_VOICE_JS" file="local_ntp\voice.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_LOCAL_NTP_CUSTOM_BACKGROUNDS_CSS" file="local_ntp\custom_backgrounds.css" flattenhtml="true" type="BINDATA" />
<include name="IDR_LOCAL_NTP_CUSTOM_BACKGROUNDS_JS" file="local_ntp\custom_backgrounds.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_LOCAL_NTP_ANIMATIONS_CSS" file="local_ntp\animations.css" flattenhtml="true" type="BINDATA" />
<include name="IDR_LOCAL_NTP_ANIMATIONS_JS" file="local_ntp\animations.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_LOCAL_NTP_UTILS_JS" file="local_ntp\utils.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_MOST_VISITED_IFRAME_CSS" file="local_ntp\most_visited_iframe.css" type="BINDATA" />
<include name="IDR_MOST_VISITED_TITLE_HTML" file="local_ntp\most_visited_title.html" type="BINDATA" />
<include name="IDR_MOST_VISITED_TITLE_CSS" file="local_ntp\most_visited_title.css" type="BINDATA" />
......
......@@ -10,11 +10,15 @@ action("local_ntp_code_generate") {
local_ntp_js = local_ntp_resources + "/local_ntp.js"
voice_js = local_ntp_resources + "/voice.js"
custom_bg_js = local_ntp_resources + "/custom_backgrounds.js"
utils_js = local_ntp_resources + "/utils.js"
animations_js = local_ntp_resources + "/animations.js"
inputs = [
local_ntp_js,
voice_js,
custom_bg_js,
utils_js,
animations_js,
]
outputs = [
......@@ -26,6 +30,8 @@ action("local_ntp_code_generate") {
rebase_path(local_ntp_js, root_build_dir),
rebase_path(voice_js, root_build_dir),
rebase_path(custom_bg_js, root_build_dir),
rebase_path(utils_js, root_build_dir),
rebase_path(animations_js, root_build_dir),
]
}
......
......@@ -100,12 +100,15 @@ const struct Resource{
{"voice.js", IDR_LOCAL_NTP_VOICE_JS, "application/javascript"},
{"custom-backgrounds.js", IDR_LOCAL_NTP_CUSTOM_BACKGROUNDS_JS,
"application/javascript"},
{"animations.js", IDR_LOCAL_NTP_ANIMATIONS_JS, "application/javascript"},
{"utils.js", IDR_LOCAL_NTP_UTILS_JS, "application/javascript"},
{kConfigDataFilename, kLocalResource, "application/javascript"},
{kThemeCSSFilename, kLocalResource, "text/css"},
{"local-ntp.css", IDR_LOCAL_NTP_CSS, "text/css"},
{"voice.css", IDR_LOCAL_NTP_VOICE_CSS, "text/css"},
{"custom-backgrounds.css", IDR_LOCAL_NTP_CUSTOM_BACKGROUNDS_CSS,
"text/css"},
{"animations.css", IDR_LOCAL_NTP_ANIMATIONS_CSS, "text/css"},
{"images/close_3_mask.png", IDR_CLOSE_3_MASK, "image/png"},
{"images/ntp_default_favicon.png", IDR_NTP_DEFAULT_FAVICON, "image/png"},
{kNtpBackgroundCollectionScriptFilename, kLocalResource, "text/javascript"},
......@@ -855,6 +858,16 @@ void LocalNtpSource::StartDataRequest(
"{{LOCAL_NTP_CUSTOM_BG_INTEGRITY}}",
local_ntp_custom_bg_integrity);
std::string utils_integrity =
base::StringPrintf(kIntegrityFormat, UTILS_JS_INTEGRITY);
base::ReplaceFirstSubstringAfterOffset(&html, 0, "{{UTILS_INTEGRITY}}",
utils_integrity);
std::string animations_integrity =
base::StringPrintf(kIntegrityFormat, ANIMATIONS_JS_INTEGRITY);
base::ReplaceFirstSubstringAfterOffset(&html, 0, "{{ANIMATIONS_INTEGRITY}}",
animations_integrity);
std::string config_data_integrity = base::StringPrintf(
kIntegrityFormat,
search_config_provider_->config_data_integrity().c_str());
......@@ -952,9 +965,10 @@ std::string LocalNtpSource::GetContentSecurityPolicy() const {
// 'strict-dynamic' allows those scripts to load dependencies not listed here.
std::string script_src_csp = base::StringPrintf(
"script-src 'strict-dynamic' 'sha256-%s' 'sha256-%s' 'sha256-%s' "
"'sha256-%s';",
"'sha256-%s' 'sha256-%s' 'sha256-%s';",
LOCAL_NTP_JS_INTEGRITY, VOICE_JS_INTEGRITY,
CUSTOM_BACKGROUNDS_JS_INTEGRITY,
CUSTOM_BACKGROUNDS_JS_INTEGRITY, UTILS_JS_INTEGRITY,
ANIMATIONS_JS_INTEGRITY,
search_config_provider_->config_data_integrity().c_str());
return GetContentSecurityPolicyObjectSrc() +
......
......@@ -35,6 +35,11 @@ const char kEditJSPath[] = "/edit.js";
const char kAddSvgPath[] = "/add_link.svg";
const char kEditMenuSvgPath[] = "/edit_menu.svg";
// Used in the single-iframe version and the edit custom links dialog iframe.
const char kAnimationsCSSPath[] = "/animations.css";
const char kAnimationsJSPath[] = "/animations.js";
const char kLocalNTPUtilsJSPath[] = "/utils.js";
} // namespace
MostVisitedIframeSource::MostVisitedIframeSource() = default;
......@@ -96,6 +101,12 @@ void MostVisitedIframeSource::StartDataRequest(
SendResource(IDR_CUSTOM_LINKS_ADD_SVG, callback);
} else if (path == kEditMenuSvgPath) {
SendResource(IDR_CUSTOM_LINKS_EDIT_MENU_SVG, callback);
} else if (path == kAnimationsCSSPath) {
SendResource(IDR_LOCAL_NTP_ANIMATIONS_CSS, callback);
} else if (path == kAnimationsJSPath) {
SendResource(IDR_LOCAL_NTP_ANIMATIONS_JS, callback);
} else if (path == kLocalNTPUtilsJSPath) {
SendResource(IDR_LOCAL_NTP_UTILS_JS, callback);
} else {
callback.Run(nullptr);
}
......@@ -107,5 +118,6 @@ bool MostVisitedIframeSource::ServesPath(const std::string& path) const {
path == kTitleCSSPath || path == kTitleJSPath || path == kUtilJSPath ||
path == kCommonCSSPath || path == kEditHTMLPath ||
path == kEditCSSPath || path == kEditJSPath || path == kAddSvgPath ||
path == kEditMenuSvgPath;
path == kEditMenuSvgPath || path == kAnimationsCSSPath ||
path == kAnimationsJSPath || path == kLocalNTPUtilsJSPath;
}
......@@ -5,18 +5,24 @@
found in the LICENSE file. -->
<head>
<script>window.localNTPUnitTest = true;</script>
<link rel="stylesheet" href="chrome-search://local-ntp/animations.css"></link>
<link rel="stylesheet" href="chrome-search://local-ntp/local-ntp.css"></link>
<link rel="stylesheet" href="chrome-search://local-ntp/voice.css"></link>
<link rel="stylesheet" href="chrome-search://local-ntp/custom-backgrounds.css"></link>
<script src="chrome-search://local-ntp/local-ntp.js" charset="utf-8"></script>
<script src="chrome-search://local-ntp/voice.js" charset="utf-8"></script>
<script src="chrome-search://local-ntp/config.js" charset="utf-8"></script>
<script src="chrome-search://local-ntp/utils.js" charset="utf-8"></script>
<script src="chrome-search://local-ntp/animations.js" charset="utf-8"></script>
<script src="chrome-search://local-ntp/custom-backgrounds.js" charset="utf-8"></script>
<script src="test_utils.js" charset="utf-8"></script>
<script src="local_ntp_browsertest.js" charset="utf-8"></script>
<script src="custom_backgrounds_browsertest.js" charset="utf-8"></script>
<template id="local-ntp-template">
<div id="custom-bg"></div>
<!-- Container for the OneGoogleBar HTML. -->
<div id="one-google" class="hidden"></div>
<div id="ntp-contents">
<div id="logo">
<!-- The logo that is displayed in the absence of a doodle. -->
......@@ -26,9 +32,9 @@
<!-- A doodle, if any: its link and image. -->
<div id="logo-doodle">
<button id="logo-doodle-button">
<img id="logo-doodle-image"></img>
<img id="logo-doodle-image" tabindex="-1"></img>
</button>
<iframe id="logo-doodle-iframe"></iframe>
<iframe id="logo-doodle-iframe" scrolling="no"></iframe>
<!-- A spinner, visible on dark-themed NTPs, prompting the doodle -->
<button id="logo-doodle-notifier">
<div class="outer ball0"><div class="inner"></div></div>
......@@ -70,47 +76,47 @@
<div id="error-notice-container">
<div id="error-notice" class="notice-hide" role="alert">
<span id="error-notice-icon-container">
<div id="error-notice-icon"></div>
</span>
<span id="error-notice-icon"></span>
<span id="error-notice-msg"></span>
<span id="error-notice-link" class="ripple" tabindex="0" role="button"></span>
</div>
</div>
<div id="edit-bg" hidden>
<button id="edit-bg-gear"></button>
<div id="edit-bg" tabindex="0" hidden>
<div id="edit-bg-gear" tabindex="-1" role="button"></div>
</div>
<div id="custom-bg-attr"></div>
</div>
<dialog div id="edit-bg-dialog">
<div id="edit-bg-title"></div>
<div id="edit-bg-default-wallpapers" class="bg-option" tabindex="0">
<div class="bg-option-img"></div>
<div id="edit-bg-default-wallpapers-text" class="bg-option-text">
<div id="edit-bg-menu">
<div id="edit-bg-title"></div>
<div id="edit-bg-default-wallpapers" class="bg-option" tabindex="0">
<div class="bg-option-img"></div>
<div id="edit-bg-default-wallpapers-text" class="bg-option-text">
</div>
</div>
<div id="edit-bg-upload-image" class="bg-option" tabindex="0">
<div class="bg-option-img"></div>
<div id="edit-bg-upload-image-text" class="bg-option-text"></div>
</div>
<div id="edit-bg-divider"></div>
<div id="custom-links-restore-default" class="bg-option bg-option-disabled" tabindex="0">
<div class="bg-option-img"></div>
<div id="custom-links-restore-default-text" class="bg-option-text"></div>
</div>
<div id="edit-bg-restore-default" class="bg-option bg-option-disabled" tabindex="0">
<div class="bg-option-img"></div>
<div id="edit-bg-restore-default-text" class="bg-option-text"></div>
</div>
</div>
<div id="edit-bg-upload-image" class="bg-option" tabindex="0">
<div class="bg-option-img"></div>
<div id="edit-bg-upload-image-text" class="bg-option-text"></div>
</div>
<div id="edit-bg-divider"></div>
<div id="custom-links-restore-default" class="bg-option bg-option-disabled" tabindex="0">
<div class="bg-option-img"></div>
<div id="custom-links-restore-default-text" class="bg-option-text"></div>
</div>
<div id="edit-bg-restore-default" class="bg-option bg-option-disabled" tabindex="0">
<div class="bg-option-img"></div>
<div id="edit-bg-restore-default-text" class="bg-option-text"></div>
</div>
</dialog>
<dialog id="bg-sel-menu">
<div id="bg-sel-title-bar">
<div id="bg-sel-back-circle">
<button id="bg-sel-back" tabindex="0"></button>
<div id="bg-sel-back-circle" tabindex="0" role="button">
<div id="bg-sel-back"></div>
</div>
<div id="bg-sel-title"></div>
</div>
......@@ -121,8 +127,8 @@
<span class="toggle"></span>
</label>
<div id="bg-sel-refresh-text"></div>
<div id="bg-sel-footer-cancel" class="bg-sel-footer-button ripple" tabindex="0"></div>
<div id="bg-sel-footer-done" class="bg-sel-footer-button ripple" tabindex="-1"></div>
<button id="bg-sel-footer-cancel" class="bg-sel-footer-button ripple" tabindex="0"></button>
<button id="bg-sel-footer-done" class="bg-sel-footer-button ripple" tabindex="-1"></button>
</div>
</dialog>
......@@ -157,6 +163,7 @@
</div>
</dialog>
<div id="one-google-end-of-body"></div>
</template>
</head>
<body>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment