OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview User pod row implementation. | 6 * @fileoverview User pod row implementation. |
7 */ | 7 */ |
8 | 8 |
9 cr.define('login', function() { | 9 cr.define('login', function() { |
10 // Pod width. 170px Pod + 10px padding + 10px margin on both sides. | 10 // Pod width. 170px Pod + 10px padding + 10px margin on both sides. |
(...skipping 20 matching lines...) Expand all Loading... |
31 */ | 31 */ |
32 var UserPod = cr.ui.define(function() { | 32 var UserPod = cr.ui.define(function() { |
33 return $('user-pod-template').cloneNode(true); | 33 return $('user-pod-template').cloneNode(true); |
34 }); | 34 }); |
35 | 35 |
36 UserPod.prototype = { | 36 UserPod.prototype = { |
37 __proto__: HTMLDivElement.prototype, | 37 __proto__: HTMLDivElement.prototype, |
38 | 38 |
39 /** @inheritDoc */ | 39 /** @inheritDoc */ |
40 decorate: function() { | 40 decorate: function() { |
41 this.addEventListener('click', this.handleClick_.bind(this)); | 41 // Make this focusable |
| 42 if (!this.hasAttribute('tabindex')) |
| 43 this.tabIndex = 0; |
| 44 |
| 45 this.addEventListener('mousedown', this.handleMouseDown_.bind(this)); |
| 46 |
42 this.enterButtonElement.addEventListener('click', | 47 this.enterButtonElement.addEventListener('click', |
43 this.activate.bind(this)); | 48 this.activate.bind(this)); |
44 this.removeUserButtonElement.addEventListener('click', | |
45 this.handleRemoveUserClick_.bind(this)); | |
46 }, | 49 }, |
47 | 50 |
48 /** | 51 /** |
49 * Initializes the pod after its properties set and added to a pod row. | 52 * Initializes the pod after its properties set and added to a pod row. |
50 */ | 53 */ |
51 initialize: function() { | 54 initialize: function() { |
52 if (!this.isGuest) { | 55 if (!this.isGuest) { |
53 this.passwordElement.addEventListener('keydown', | 56 this.passwordElement.addEventListener('keydown', |
54 this.parentNode.handleKeyDown.bind(this.parentNode)); | 57 this.parentNode.handleKeyDown.bind(this.parentNode)); |
55 } | 58 } |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 * @param {boolean} takeFocus True to take focus. | 172 * @param {boolean} takeFocus True to take focus. |
170 */ | 173 */ |
171 reset: function(takeFocus) { | 174 reset: function(takeFocus) { |
172 this.passwordElement.value = ''; | 175 this.passwordElement.value = ''; |
173 | 176 |
174 if (takeFocus) | 177 if (takeFocus) |
175 this.mainInput.focus(); | 178 this.mainInput.focus(); |
176 }, | 179 }, |
177 | 180 |
178 /** | 181 /** |
179 * Handles click event on remove user button. | 182 * Handles mousedown event. |
180 * @private | |
181 */ | 183 */ |
182 handleRemoveUserClick_: function(e) { | 184 handleMouseDown_: function(e) { |
183 chrome.send('removeUser', [this.email]); | 185 if (e.target == this.removeUserButtonElement) { |
184 this.parentNode.removeChild(this); | 186 chrome.send('removeUser', [this.user.emailAddress]); |
185 }, | |
186 | 187 |
187 /** | 188 // Prevent default so that we don't trigger 'focus' event. |
188 * Handles click event. | 189 e.preventDefault(); |
189 */ | 190 } |
190 handleClick_: function(e) { | |
191 this.parentNode.focusPod(this); | |
192 e.stopPropagation(); | |
193 } | 191 } |
194 }; | 192 }; |
195 | 193 |
196 | 194 |
197 /** | 195 /** |
198 * Creates a new pod row element. | 196 * Creates a new pod row element. |
199 * @constructor | 197 * @constructor |
200 * @extends {HTMLDivElement} | 198 * @extends {HTMLDivElement} |
201 */ | 199 */ |
202 var PodRow = cr.ui.define('podrow'); | 200 var PodRow = cr.ui.define('podrow'); |
203 | 201 |
204 PodRow.prototype = { | 202 PodRow.prototype = { |
205 __proto__: HTMLDivElement.prototype, | 203 __proto__: HTMLDivElement.prototype, |
206 | 204 |
207 // Focused pod. | 205 // Focused pod. |
208 focusedPod_ : undefined, | 206 focusedPod_ : undefined, |
209 | 207 |
210 // Acitvated pod, i.e. the pod of current login attempt. | 208 // Acitvated pod, i.e. the pod of current login attempt. |
211 activatedPod_: undefined, | 209 activatedPod_: undefined, |
212 | 210 |
213 /** @inheritDoc */ | 211 /** @inheritDoc */ |
214 decorate: function() { | 212 decorate: function() { |
215 // Make this focusable | 213 this.style.left = 0; |
216 if (!this.hasAttribute('tabindex')) | |
217 this.tabIndex = 0; | |
218 | 214 |
219 this.style.left = 0; | 215 this.ownerDocument.addEventListener('focus', |
| 216 this.handleFocus_.bind(this), true); |
220 | 217 |
221 this.ownerDocument.addEventListener('click', | 218 this.ownerDocument.addEventListener('click', |
222 this.handleClick_.bind(this)); | 219 this.handleClick_.bind(this)); |
223 this.ownerDocument.addEventListener('keydown', | 220 this.ownerDocument.addEventListener('keydown', |
224 this.handleKeyDown.bind(this)); | 221 this.handleKeyDown.bind(this)); |
225 }, | 222 }, |
226 | 223 |
227 /** | 224 /** |
228 * Returns all the pods in this pod row. | 225 * Returns all the pods in this pod row. |
229 */ | 226 */ |
230 get pods() { | 227 get pods() { |
231 return this.children; | 228 return this.children; |
232 }, | 229 }, |
233 | 230 |
234 /** | 231 /** |
235 * Creates a user pod from given email. | 232 * Creates a user pod from given email. |
236 * @param {string} email User's email. | 233 * @param {string} email User's email. |
237 */ | 234 */ |
238 createUserPod: function(user) { | 235 createUserPod: function(user) { |
239 var userPod = new UserPod({user: user}); | 236 var userPod = new UserPod({user: user}); |
240 userPod.hidden = false; | 237 userPod.hidden = false; |
241 return userPod; | 238 return userPod; |
242 }, | 239 }, |
243 | 240 |
244 /** | 241 /** |
245 * Add an existing user pod to this pod row. | 242 * Add an existing user pod to this pod row. |
246 * @param {!Object} user User info dictionary. | 243 * @param {!Object} user User info dictionary. |
| 244 * @param {boolean} animated Whether to use init animation. |
247 */ | 245 */ |
248 addUserPod: function(user) { | 246 addUserPod: function(user, animated) { |
249 var userPod = this.createUserPod(user); | 247 var userPod = this.createUserPod(user); |
| 248 if (animated) { |
| 249 userPod.classList.add('init'); |
| 250 userPod.nameElement.classList.add('init'); |
| 251 } |
| 252 |
250 this.appendChild(userPod); | 253 this.appendChild(userPod); |
251 userPod.initialize(); | 254 userPod.initialize(); |
252 }, | 255 }, |
253 | 256 |
254 /** | 257 /** |
255 * Ensures the given pod is visible. | 258 * Ensures the given pod is visible. |
256 * @param {UserPod} pod Pod to scroll into view. | 259 * @param {UserPod} pod Pod to scroll into view. |
257 */ | 260 */ |
258 scrollPodIntoView: function(pod) { | 261 scrollPodIntoView: function(pod) { |
259 var podIndex = this.findIndex_(pod); | 262 var podIndex = this.findIndex_(pod); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 this.pods[i], 'init'); | 301 this.pods[i], 'init'); |
299 window.setTimeout(removeClass, 700 + i * 70, | 302 window.setTimeout(removeClass, 700 + i * 70, |
300 this.pods[i].nameElement, 'init'); | 303 this.pods[i].nameElement, 'init'); |
301 } | 304 } |
302 }, | 305 }, |
303 | 306 |
304 /** | 307 /** |
305 * Populates pod row with given existing users and | 308 * Populates pod row with given existing users and |
306 * kick start init animiation. | 309 * kick start init animiation. |
307 * @param {array} users Array of existing user emails. | 310 * @param {array} users Array of existing user emails. |
| 311 * @param {boolean} animated Whether to use init animation. |
308 */ | 312 */ |
309 loadPods: function(users) { | 313 loadPods: function(users, animated) { |
310 // Clear existing pods. | 314 // Clear existing pods. |
311 this.innerHTML = ''; | 315 this.innerHTML = ''; |
312 this.focusedPod_ = undefined; | 316 this.focusedPod_ = undefined; |
| 317 this.activatedPod_ = undefined; |
313 | 318 |
314 // Popoulate the pod row. | 319 // Popoulate the pod row. |
315 for (var i = 0; i < users.length; ++i) { | 320 for (var i = 0; i < users.length; ++i) { |
316 this.addUserPod(users[i]); | 321 this.addUserPod(users[i], animated); |
317 } | 322 } |
318 }, | 323 }, |
319 | 324 |
320 /** | 325 /** |
321 * Focuses a given user pod or clear focus when given null. | 326 * Focuses a given user pod or clear focus when given null. |
322 * @param {UserPod} pod User pod to focus or null to clear focus. | 327 * @param {UserPod} pod User pod to focus or null to clear focus. |
323 */ | 328 */ |
324 focusPod: function(pod) { | 329 focusPod: function(pod) { |
325 for (var i = 0; i < this.pods.length; ++i) { | 330 if (this.focusedPod_ == pod) |
326 this.pods[i].classList.remove('focused'); | 331 return; |
327 this.pods[i].classList.add('faded'); | |
328 } | |
329 | 332 |
330 if (pod) { | 333 if (pod) { |
331 if (pod.isGuest || | 334 if (pod.isGuest || |
332 localStrings.getString('authType') != 'ext' || | 335 localStrings.getString('authType') != 'ext' || |
333 pod.user.oauthTokenStatus == OAUTH_TOKEN_STATUS_VALID) { | 336 pod.user.oauthTokenStatus == OAUTH_TOKEN_STATUS_VALID) { |
334 // Focus current pod if it is guest pod, or | 337 // Focus current pod if it is guest pod, or |
335 // we are not using gaia ext for signin or | 338 // we are not using gaia ext for signin or |
336 // the user has a valid oauth token. | 339 // the user has a valid oauth token. |
337 pod.classList.remove("faded"); | 340 for (var i = 0; i < this.pods.length; ++i) { |
338 pod.classList.add("focused"); | 341 if (this.pods[i] == pod) { |
| 342 pod.classList.remove("faded"); |
| 343 pod.classList.add("focused"); |
| 344 } else { |
| 345 this.pods[i].classList.remove('focused'); |
| 346 this.pods[i].classList.add('faded'); |
| 347 } |
| 348 } |
339 pod.focusInput(); | 349 pod.focusInput(); |
340 | 350 |
341 this.focusedPod_ = pod; | 351 this.focusedPod_ = pod; |
342 this.scrollPodIntoView(pod); | 352 this.scrollPodIntoView(pod); |
343 } else { | 353 } else { |
344 // Otherwise, switch to Gaia signin. | 354 // Otherwise, switch to Gaia signin. |
345 Oobe.showSigninUI(pod.user.emailAddress); | 355 Oobe.showSigninUI(pod.user.emailAddress); |
| 356 this.focusPod(); // Clears current focus. |
346 } | 357 } |
347 } else { | 358 } else { |
348 for (var i = 0; i < this.pods.length; ++i) { | 359 for (var i = 0; i < this.pods.length; ++i) { |
| 360 this.pods[i].classList.remove('focused'); |
349 this.pods[i].classList.remove('faded'); | 361 this.pods[i].classList.remove('faded'); |
350 } | 362 } |
351 this.focusedPod_ = undefined; | 363 this.focusedPod_ = undefined; |
352 } | 364 } |
353 | |
354 // TODO(xiyuan): Put this in a proper place. | |
355 $('bubble').hide(); | |
356 }, | 365 }, |
357 | 366 |
358 /** | 367 /** |
359 * Returns the currently activated pod. | 368 * Returns the currently activated pod. |
360 */ | 369 */ |
361 get activated() { | 370 get activated() { |
362 return this.activatedPod_; | 371 return this.activatedPod_; |
363 }, | 372 }, |
364 | 373 |
365 /** | 374 /** |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 | 415 |
407 if (this.activatedPod_) | 416 if (this.activatedPod_) |
408 this.activatedPod_.reset(takeFocus); | 417 this.activatedPod_.reset(takeFocus); |
409 }, | 418 }, |
410 | 419 |
411 /** | 420 /** |
412 * Handler of click event. | 421 * Handler of click event. |
413 * @private | 422 * @private |
414 */ | 423 */ |
415 handleClick_: function(e) { | 424 handleClick_: function(e) { |
416 // Clears focus. | 425 // Clears focus if not clicked on a pod. |
417 this.focusPod(); | 426 if (e.target.parentNode != this && |
| 427 e.target.parentNode.parentNode != this) |
| 428 this.focusPod(); |
418 }, | 429 }, |
419 | 430 |
420 /** | 431 /** |
| 432 * Handles focus event. |
| 433 */ |
| 434 handleFocus_: function(e) { |
| 435 if (e.target.parentNode == this) { |
| 436 // Focus on a pod |
| 437 if (e.target.classList.contains('focused')) |
| 438 e.target.focusInput(); |
| 439 else |
| 440 this.focusPod(e.target); |
| 441 } else if (e.target.parentNode.parentNode != this) { |
| 442 // Clears pod focus when we reach here. It means new focus is neither |
| 443 // on a pod nor on a button/input for a pod. |
| 444 this.focusPod(); |
| 445 } |
| 446 }, |
| 447 |
| 448 /** |
421 * Handler of keydown event. | 449 * Handler of keydown event. |
422 * @public | 450 * @public |
423 */ | 451 */ |
424 handleKeyDown: function(e) { | 452 handleKeyDown: function(e) { |
425 var editing = false; | 453 var editing = false; |
426 if (e.target.tagName == 'INPUT' && e.target.value) | 454 if (e.target.tagName == 'INPUT' && e.target.value) |
427 editing = true; | 455 editing = true; |
428 | 456 |
429 // TODO(xiyuan): Put this in a proper place. | |
430 $('bubble').hide(); | |
431 | |
432 switch (e.keyIdentifier) { | 457 switch (e.keyIdentifier) { |
433 case 'Left': | 458 case 'Left': |
434 if (!editing) { | 459 if (!editing) { |
435 if (this.focusedPod_ && this.focusedPod_.previousElementSibling) | 460 if (this.focusedPod_ && this.focusedPod_.previousElementSibling) |
436 this.focusPod(this.focusedPod_.previousElementSibling); | 461 this.focusPod(this.focusedPod_.previousElementSibling); |
437 else | 462 else |
438 this.focusPod(this.lastElementChild); | 463 this.focusPod(this.lastElementChild); |
439 | 464 |
440 e.stopPropagation(); | 465 e.stopPropagation(); |
441 } | 466 } |
442 break; | 467 break; |
443 case 'Right': | 468 case 'Right': |
444 if (!editing) { | 469 if (!editing) { |
445 if (this.focusedPod_ && this.focusedPod_.nextElementSibling) | 470 if (this.focusedPod_ && this.focusedPod_.nextElementSibling) |
446 this.focusPod(this.focusedPod_.nextElementSibling); | 471 this.focusPod(this.focusedPod_.nextElementSibling); |
447 else | 472 else |
448 this.focusPod(this.firstElementChild); | 473 this.focusPod(this.firstElementChild); |
449 | 474 |
450 e.stopPropagation(); | 475 e.stopPropagation(); |
451 } | 476 } |
452 break; | 477 break; |
453 case 'Enter': | 478 case 'Enter': |
454 this.activatePod(this.focusedPod_); | 479 if (this.focusedPod_) { |
455 e.stopPropagation(); | 480 this.activatePod(this.focusedPod_); |
| 481 e.stopPropagation(); |
| 482 } |
456 break; | 483 break; |
457 } | 484 } |
458 } | 485 } |
459 }; | 486 }; |
460 | 487 |
461 return { | 488 return { |
462 PodRow: PodRow | 489 PodRow: PodRow |
463 }; | 490 }; |
464 }); | 491 }); |
OLD | NEW |