1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * @fileoverview Nav dot
7 * This is the class for the navigation controls that appear along the bottom
11 cr.define('ntp4', function() {
15 * Creates a new navigation dot.
16 * @param {TilePage} page The associated TilePage.
17 * @param {string} title The title of the navigation dot.
18 * @param {bool} titleIsEditable If true, the title can be changed.
19 * @param {bool} animate If true, animates into existence.
21 * @extends {HTMLLIElement}
23 function NavDot(page, title, titleIsEditable, animate) {
24 var dot = cr.doc.createElement('li');
25 dot.__proto__ = NavDot.prototype;
26 dot.initialize(page, title, titleIsEditable, animate);
32 __proto__: HTMLLIElement.prototype,
34 initialize: function(page, title, titleIsEditable, animate) {
35 this.className = 'dot';
36 this.setAttribute('role', 'button');
40 var selectionBar = this.ownerDocument.createElement('div');
41 selectionBar.className = 'selection-bar';
42 this.appendChild(selectionBar);
44 // TODO(estade): should there be some limit to the number of characters?
45 this.input_ = this.ownerDocument.createElement('input');
46 this.input_.setAttribute('spellcheck', false);
47 this.input_.value = title;
48 // Take the input out of the tab-traversal focus order.
49 this.input_.disabled = true;
50 this.appendChild(this.input_);
52 this.displayTitle = title;
53 this.titleIsEditable_ = titleIsEditable;
55 this.addEventListener('keydown', this.onKeyDown_);
56 this.addEventListener('click', this.onClick_);
57 this.addEventListener('dblclick', this.onDoubleClick_);
58 this.dragWrapper_ = new cr.ui.DragWrapper(this, this);
59 this.addEventListener('webkitTransitionEnd', this.onTransitionEnd_);
61 this.input_.addEventListener('blur', this.onInputBlur_.bind(this));
62 this.input_.addEventListener('mousedown',
63 this.onInputMouseDown_.bind(this));
64 this.input_.addEventListener('keydown', this.onInputKeyDown_.bind(this));
67 this.classList.add('small');
69 window.setTimeout(function() {
70 self.classList.remove('small');
76 * Gets the associated TilePage.
84 * Sets/gets the display title.
85 * @type {String} title The display name for this nav dot.
90 set displayTitle(title) {
91 this.title = this.input_.value = title;
95 * Removes the dot from the page after transitioning to 0 width.
97 animateRemove: function() {
98 this.classList.add('small');
102 * Navigates the card slider to the page for this dot.
104 switchToPage: function() {
105 ntp4.getCardSlider().selectCardByValue(this.page_, true);
109 * Handler for keydown event on the dot.
110 * @param {Event} e The KeyboardEvent.
112 onKeyDown_: function(e) {
113 if (e.keyIdentifier == 'Enter') {
120 * Clicking causes the associated page to show.
121 * @param {Event} e The click event.
124 onClick_: function(e) {
126 // The explicit focus call is necessary because of overriding the default
127 // handling in onInputMouseDown_.
128 if (this.ownerDocument.activeElement != this.input_)
131 chrome.send('introMessageDismissed');
136 * Double clicks allow the user to edit the page title.
137 * @param {Event} e The click event.
140 onDoubleClick_: function(e) {
141 if (this.titleIsEditable_) {
142 this.input_.disabled = false;
144 this.input_.select();
149 * Prevent mouse down on the input from selecting it.
150 * @param {Event} e The click event.
153 onInputMouseDown_: function(e) {
154 if (this.ownerDocument.activeElement != this.input_)
159 * Handle keypresses on the input.
160 * @param {Event} e The click event.
163 onInputKeyDown_: function(e) {
164 switch (e.keyIdentifier) {
165 case 'U+001B': // Escape cancels edits.
166 this.input_.value = this.displayTitle;
167 case 'Enter': // Fall through.
174 * When the input blurs, commit the edited changes.
175 * @param {Event} e The blur event.
178 onInputBlur_: function(e) {
179 window.getSelection().removeAllRanges();
180 this.displayTitle = this.input_.value;
181 ntp4.saveAppPageName(this.page_, this.displayTitle);
182 this.input_.disabled = true;
185 shouldAcceptDrag: function(e) {
186 return this.page_.shouldAcceptDrag(e);
190 * A drag has entered the navigation dot. If the user hovers long enough,
191 * we will navigate to the relevant page.
192 * @param {Event} e The MouseOver event for the drag.
195 doDragEnter: function(e) {
197 function navPageClearTimeout() {
199 self.dragNavTimeout = null;
201 this.dragNavTimeout = window.setTimeout(navPageClearTimeout, 500);
207 * A dragged element has moved over the navigation dot. Show the correct
208 * indicator and prevent default handling so the <input> won't act as a drag
210 * @param {Event} e The MouseOver event for the drag.
213 doDragOver: function(e) {
216 if (!this.dragWrapper_.isCurrentDragTarget)
217 ntp4.setCurrentDropEffect(e.dataTransfer, 'none');
219 this.page_.setDropEffect(e.dataTransfer);
223 * A dragged element has been dropped on the navigation dot. Tell the page
225 * @param {Event} e The MouseOver event for the drag.
228 doDrop: function(e) {
230 var tile = ntp4.getCurrentlyDraggingTile();
231 if (tile && tile.tilePage != this.page_)
232 this.page_.appendDraggingTile();
233 // TODO(estade): handle non-tile drags.
235 this.cancelDelayedSwitch_();
239 * The drag has left the navigation dot.
240 * @param {Event} e The MouseOver event for the drag.
243 doDragLeave: function(e) {
244 this.cancelDelayedSwitch_();
248 * Cancels the timer for page switching.
251 cancelDelayedSwitch_: function() {
252 if (this.dragNavTimeout) {
253 window.clearTimeout(this.dragNavTimeout);
254 this.dragNavTimeout = null;
259 * A transition has ended.
260 * @param {Event} e The transition end event.
263 onTransitionEnd_: function(e) {
264 if (e.propertyName === 'max-width' && this.classList.contains('small'))
265 this.parentNode.removeChild(this);