1 // Copyright (c) 2012 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('ntp', 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 * @return {TilePage} The associated TilePage.
83 * Sets/gets the display title.
84 * @type {string} title The display name for this nav dot.
89 set displayTitle(title
) {
90 this.title
= this.input_
.value
= title
;
94 * Removes the dot from the page. If |opt_animate| is truthy, we first
95 * transition the element to 0 width.
96 * @param {boolean=} opt_animate Whether to animate the removal or not.
98 remove: function(opt_animate
) {
100 this.classList
.add('small');
102 this.parentNode
.removeChild(this);
106 * Navigates the card slider to the page for this dot.
108 switchToPage: function() {
109 ntp
.getCardSlider().selectCardByValue(this.page_
, true);
113 * Handler for keydown event on the dot.
114 * @param {Event} e The KeyboardEvent.
116 onKeyDown_: function(e
) {
117 if (e
.keyIdentifier
== 'Enter') {
124 * Clicking causes the associated page to show.
125 * @param {Event} e The click event.
128 onClick_: function(e
) {
130 // The explicit focus call is necessary because of overriding the default
131 // handling in onInputMouseDown_.
132 if (this.ownerDocument
.activeElement
!= this.input_
)
135 chrome
.send('introMessageDismissed');
140 * Double clicks allow the user to edit the page title.
141 * @param {Event} e The click event.
144 onDoubleClick_: function(e
) {
145 if (this.titleIsEditable_
) {
146 this.input_
.disabled
= false;
148 this.input_
.select();
153 * Prevent mouse down on the input from selecting it.
154 * @param {Event} e The click event.
157 onInputMouseDown_: function(e
) {
158 if (this.ownerDocument
.activeElement
!= this.input_
)
163 * Handle keypresses on the input.
164 * @param {Event} e The click event.
167 onInputKeyDown_: function(e
) {
168 switch (e
.keyIdentifier
) {
169 case 'U+001B': // Escape cancels edits.
170 this.input_
.value
= this.displayTitle
;
171 case 'Enter': // Fall through.
178 * When the input blurs, commit the edited changes.
179 * @param {Event} e The blur event.
182 onInputBlur_: function(e
) {
183 window
.getSelection().removeAllRanges();
184 this.displayTitle
= this.input_
.value
;
185 ntp
.saveAppPageName(this.page_
, this.displayTitle
);
186 this.input_
.disabled
= true;
189 shouldAcceptDrag: function(e
) {
190 return this.page_
.shouldAcceptDrag(e
);
194 * A drag has entered the navigation dot. If the user hovers long enough,
195 * we will navigate to the relevant page.
196 * @param {Event} e The MouseOver event for the drag.
199 doDragEnter: function(e
) {
201 function navPageClearTimeout() {
203 self
.dragNavTimeout
= null;
205 this.dragNavTimeout
= window
.setTimeout(navPageClearTimeout
, 500);
211 * A dragged element has moved over the navigation dot. Show the correct
212 * indicator and prevent default handling so the <input> won't act as a drag
214 * @param {Event} e The MouseOver event for the drag.
217 doDragOver: function(e
) {
220 if (!this.dragWrapper_
.isCurrentDragTarget
)
221 ntp
.setCurrentDropEffect(e
.dataTransfer
, 'none');
223 this.page_
.setDropEffect(e
.dataTransfer
);
227 * A dragged element has been dropped on the navigation dot. Tell the page
229 * @param {Event} e The MouseOver event for the drag.
232 doDrop: function(e
) {
234 var tile
= ntp
.getCurrentlyDraggingTile();
235 if (tile
&& tile
.tilePage
!= this.page_
)
236 this.page_
.appendDraggingTile();
237 // TODO(estade): handle non-tile drags.
239 this.cancelDelayedSwitch_();
243 * The drag has left the navigation dot.
244 * @param {Event} e The MouseOver event for the drag.
247 doDragLeave: function(e
) {
248 this.cancelDelayedSwitch_();
252 * Cancels the timer for page switching.
255 cancelDelayedSwitch_: function() {
256 if (this.dragNavTimeout
) {
257 window
.clearTimeout(this.dragNavTimeout
);
258 this.dragNavTimeout
= null;
263 * A transition has ended.
264 * @param {Event} e The transition end event.
267 onTransitionEnd_: function(e
) {
268 if (e
.propertyName
=== 'max-width' && this.classList
.contains('small'))
269 this.parentNode
.removeChild(this);