| 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(); |
| 429 }, |
| 430 |
| 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 } |
| 418 }, | 446 }, |
| 419 | 447 |
| 420 /** | 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 |