// Copyright (c) 2012 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. /** * @fileoverview Page switcher * This is the class for the left and right navigation arrows that switch * between pages. */ cr.define('ntp', function() { /** * @constructor * @extends {HTMLButtonElement} */ function PageSwitcher() {} PageSwitcher.prototype = { __proto__: HTMLButtonElement.prototype, decorate: function(el) { el.__proto__ = PageSwitcher.prototype; el.addEventListener('click', el.activate_); el.direction_ = el.id == 'page-switcher-start' ? -1 : 1; el.dragWrapper_ = new cr.ui.DragWrapper(el, el); }, /** * Activate the switcher (go to the next card). * @private */ activate_: function() { ntp.getCardSlider().selectCard(this.nextCardIndex_(), true); }, /** * Calculate the index of the card that this button will switch to. * @private */ nextCardIndex_: function() { const cardSlider = ntp.getCardSlider(); const index = cardSlider.currentCard + this.direction_; const numCards = cardSlider.cardCount - 1; return Math.max(0, Math.min(index, numCards)); }, /** * Update the accessible label attribute of this button, based on the * current position in the card slider and the names of the cards. * @param {NodeList} dots The dot elements which display the names of the * cards. */ updateButtonAccessibleLabel: function(dots) { const currentIndex = ntp.getCardSlider().currentCard; const nextCardIndex = this.nextCardIndex_(); if (nextCardIndex == currentIndex) { this.setAttribute('aria-label', ''); // No next card. return; } const currentDot = dots[currentIndex]; const nextDot = dots[nextCardIndex]; if (!currentDot || !nextDot) { this.setAttribute('aria-label', ''); // Dots not initialised yet. return; } const currentPageTitle = currentDot.displayTitle; const nextPageTitle = nextDot.displayTitle; const msgName = (currentPageTitle == nextPageTitle) ? 'page_switcher_same_title' : 'page_switcher_change_title'; const ariaLabel = loadTimeData.getStringF(msgName, nextPageTitle); this.setAttribute('aria-label', ariaLabel); }, shouldAcceptDrag: function(e) { // Only allow page switching when a drop could happen on the page being // switched to. const nextPage = ntp.getCardSlider().getCardAtIndex(this.nextCardIndex_()); return nextPage.shouldAcceptDrag(e); }, doDragEnter: function(e) { this.scheduleDelayedSwitch_(e); this.doDragOver(e); }, doDragLeave: function(e) { this.cancelDelayedSwitch_(); }, doDragOver: function(e) { e.preventDefault(); const targetPage = ntp.getCardSlider().currentCardValue; if (targetPage.shouldAcceptDrag(e)) { targetPage.setDropEffect(e.dataTransfer); } }, doDrop: function(e) { e.stopPropagation(); this.cancelDelayedSwitch_(); const tile = ntp.getCurrentlyDraggingTile(); if (!tile) { return; } const sourcePage = tile.tilePage; const targetPage = ntp.getCardSlider().currentCardValue; if (targetPage == sourcePage || !targetPage.shouldAcceptDrag(e)) { return; } targetPage.appendDraggingTile(); }, /** * Starts a timer to activate the switcher. The timer repeats until * cancelled by cancelDelayedSwitch_. * @private */ scheduleDelayedSwitch_: function(e) { // Stop switching when the next page can't be dropped onto. const nextPage = ntp.getCardSlider().getCardAtIndex(this.nextCardIndex_()); if (!nextPage.shouldAcceptDrag(e)) { return; } const self = this; function navPageClearTimeout() { self.activate_(); self.dragNavTimeout_ = null; self.scheduleDelayedSwitch_(e); } this.dragNavTimeout_ = window.setTimeout(navPageClearTimeout, 500); }, /** * Cancels the timer that activates the switcher while dragging. * @private */ cancelDelayedSwitch_: function() { if (this.dragNavTimeout_) { window.clearTimeout(this.dragNavTimeout_); this.dragNavTimeout_ = null; } }, }; /** @const */ const initializePageSwitcher = PageSwitcher.prototype.decorate; return { initializePageSwitcher: initializePageSwitcher, PageSwitcher: PageSwitcher }; });