Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: chrome/browser/resources/chromeos/login/screen_supervised_user_creation.js

Issue 2944703004: Run clang-format on .js files in c/b/r/chromeos (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 Legacy supervised user creation flow screen. 6 * @fileoverview Legacy supervised user creation flow screen.
7 */ 7 */
8 8
9 login.createScreen('SupervisedUserCreationScreen', 9 login.createScreen(
10 'supervised-user-creation', function() { 10 'SupervisedUserCreationScreen', 'supervised-user-creation', function() {
11 var MAX_NAME_LENGTH = 50; 11 var MAX_NAME_LENGTH = 50;
12 var UserImagesGrid = options.UserImagesGrid; 12 var UserImagesGrid = options.UserImagesGrid;
13 var ButtonImages = UserImagesGrid.ButtonImages; 13 var ButtonImages = UserImagesGrid.ButtonImages;
14 14
15 var ManagerPod = cr.ui.define(function() { 15 var ManagerPod = cr.ui.define(function() {
16 var node = $('supervised-user-creation-manager-template').cloneNode(true); 16 var node =
17 node.removeAttribute('id'); 17 $('supervised-user-creation-manager-template').cloneNode(true);
18 node.removeAttribute('hidden'); 18 node.removeAttribute('id');
19 return node; 19 node.removeAttribute('hidden');
20 }); 20 return node;
21 21 });
22 ManagerPod.userImageSalt_ = {}; 22
23 23 ManagerPod.userImageSalt_ = {};
24 /** 24
25 * UI element for displaying single account in list of possible managers for 25 /**
26 * new supervised user. 26 * UI element for displaying single account in list of possible managers
27 * @type {Object} 27 * for new supervised user.
28 */ 28 * @type {Object}
29 ManagerPod.prototype = { 29 */
30 __proto__: HTMLDivElement.prototype, 30 ManagerPod.prototype = {
31 31 __proto__: HTMLDivElement.prototype,
32 /** @override */ 32
33 decorate: function() { 33 /** @override */
34 // Mousedown has to be used instead of click to be able to prevent 'focus' 34 decorate: function() {
35 // event later. 35 // Mousedown has to be used instead of click to be able to prevent
36 this.addEventListener('mousedown', 36 // 'focus' event later.
37 this.handleMouseDown_.bind(this)); 37 this.addEventListener('mousedown', this.handleMouseDown_.bind(this));
38 var screen = $('supervised-user-creation'); 38 var screen = $('supervised-user-creation');
39 var managerPod = this; 39 var managerPod = this;
40 var managerPodList = screen.managerList_; 40 var managerPodList = screen.managerList_;
41 var hideManagerPasswordError = function(element) { 41 var hideManagerPasswordError = function(element) {
42 managerPod.passwordElement.classList.remove('password-error'); 42 managerPod.passwordElement.classList.remove('password-error');
43 $('bubble').hide(); 43 $('bubble').hide();
44 };
45
46 screen.configureTextInput(
47 this.passwordElement,
48 screen.updateNextButtonForManager_.bind(screen),
49 screen.validIfNotEmpty_.bind(screen), function(element) {
50 screen.getScreenButton('next').focus();
51 }, hideManagerPasswordError);
52
53 this.passwordElement.addEventListener('keydown', function(e) {
54 switch (e.key) {
55 case 'ArrowUp':
56 managerPodList.selectNextPod(-1);
57 e.stopPropagation();
58 break;
59 case 'ArrowDown':
60 managerPodList.selectNextPod(+1);
61 e.stopPropagation();
62 break;
63 }
64 });
65 },
66
67 /**
68 * Updates UI elements from user data.
69 */
70 update: function() {
71 this.imageElement.src = 'chrome://userimage/' + this.user.username +
72 '?id=' + ManagerPod.userImageSalt_[this.user.username];
73
74 this.nameElement.textContent = this.user.displayName;
75 this.emailElement.textContent = this.user.emailAddress;
76 },
77
78 showPasswordError: function() {
79 this.passwordElement.classList.add('password-error');
80 $('bubble').showTextForElement(
81 this.passwordElement,
82 loadTimeData.getString(
83 'createSupervisedUserWrongManagerPasswordText'),
84 cr.ui.Bubble.Attachment.BOTTOM, 24, 4);
85 },
86
87 /**
88 * Brings focus to password field.
89 */
90 focusInput: function() {
91 this.passwordElement.focus();
92 },
93
94 /**
95 * Gets image element.
96 * @type {!HTMLImageElement}
97 */
98 get imageElement() {
99 return this.querySelector('.supervised-user-creation-manager-image');
100 },
101
102 /**
103 * Gets name element.
104 * @type {!HTMLDivElement}
105 */
106 get nameElement() {
107 return this.querySelector('.supervised-user-creation-manager-name');
108 },
109
110 /**
111 * Gets e-mail element.
112 * @type {!HTMLDivElement}
113 */
114 get emailElement() {
115 return this.querySelector('.supervised-user-creation-manager-email');
116 },
117
118 /**
119 * Gets password element.
120 * @type {!HTMLDivElement}
121 */
122 get passwordElement() {
123 return this.querySelector(
124 '.supervised-user-creation-manager-password');
125 },
126
127 /**
128 * Gets password enclosing block.
129 * @type {!HTMLDivElement}
130 */
131 get passwordBlock() {
132 return this.querySelector('.password-block');
133 },
134
135 /** @override */
136 handleMouseDown_: function(e) {
137 this.parentNode.selectPod(this);
138 // Prevent default so that we don't trigger 'focus' event.
139 e.preventDefault();
140 },
141
142 /**
143 * The user that this pod represents.
144 * @type {!Object}
145 */
146 user_: undefined,
147 get user() {
148 return this.user_;
149 },
150 set user(userDict) {
151 this.user_ = userDict;
152 this.update();
153 },
44 }; 154 };
45 155
46 screen.configureTextInput( 156 var ManagerPodList = cr.ui.define('div');
47 this.passwordElement, 157
48 screen.updateNextButtonForManager_.bind(screen), 158 /**
49 screen.validIfNotEmpty_.bind(screen), 159 * UI element for selecting manager account for new supervised user.
50 function(element) { 160 * @type {Object}
51 screen.getScreenButton('next').focus(); 161 */
52 }, 162 ManagerPodList.prototype = {
53 hideManagerPasswordError); 163 __proto__: HTMLDivElement.prototype,
54 164
55 this.passwordElement.addEventListener('keydown', function(e) { 165 selectedPod_: null,
56 switch (e.key) { 166
57 case 'ArrowUp': 167 /** @override */
58 managerPodList.selectNextPod(-1); 168 decorate: function() {},
59 e.stopPropagation(); 169
60 break; 170 /**
61 case 'ArrowDown': 171 * Returns all the pods in this pod list.
62 managerPodList.selectNextPod(+1); 172 * @type {NodeList}
63 e.stopPropagation(); 173 */
64 break; 174 get pods() {
65 } 175 return this.children;
66 }); 176 },
67 }, 177
68 178 addPod: function(manager) {
69 /** 179 var managerPod = new ManagerPod({user: manager});
70 * Updates UI elements from user data. 180 this.appendChild(managerPod);
71 */ 181 managerPod.update();
72 update: function() { 182 },
73 this.imageElement.src = 'chrome://userimage/' + this.user.username + 183
74 '?id=' + ManagerPod.userImageSalt_[this.user.username]; 184 clearPods: function() {
75 185 this.innerHTML = '';
76 this.nameElement.textContent = this.user.displayName; 186 this.selectedPod_ = null;
77 this.emailElement.textContent = this.user.emailAddress; 187 },
78 }, 188
79 189 selectPod: function(podToSelect) {
80 showPasswordError: function() { 190 if ((this.selectedPod_ == podToSelect) && !!podToSelect) {
81 this.passwordElement.classList.add('password-error'); 191 podToSelect.focusInput();
82 $('bubble').showTextForElement( 192 return;
83 this.passwordElement, 193 }
84 loadTimeData.getString( 194 this.selectedPod_ = podToSelect;
85 'createSupervisedUserWrongManagerPasswordText'), 195 for (var i = 0, pod; pod = this.pods[i]; ++i) {
86 cr.ui.Bubble.Attachment.BOTTOM, 196 if (pod != podToSelect) {
87 24, 4); 197 pod.classList.remove('focused');
88 }, 198 pod.passwordElement.value = '';
89 199 pod.passwordBlock.hidden = true;
90 /** 200 }
91 * Brings focus to password field. 201 }
92 */ 202 if (!podToSelect)
93 focusInput: function() { 203 return;
94 this.passwordElement.focus(); 204 podToSelect.classList.add('focused');
95 }, 205 podToSelect.passwordBlock.hidden = false;
96 206 podToSelect.passwordElement.value = '';
97 /** 207 podToSelect.focusInput();
98 * Gets image element. 208 chrome.send(
99 * @type {!HTMLImageElement} 209 'managerSelectedOnSupervisedUserCreationFlow',
100 */ 210 [podToSelect.user.username]);
101 get imageElement() { 211 },
102 return this.querySelector('.supervised-user-creation-manager-image'); 212
103 }, 213 /**
104 214 * Select pod next to currently selected one in given |direction|.
105 /** 215 * @param {integer} direction - +1 for selecting pod below current, -1 f or
106 * Gets name element. 216 * selecting pod above current.
107 * @type {!HTMLDivElement} 217 * @type {boolean} returns if selected pod has changed.
108 */ 218 */
109 get nameElement() { 219 selectNextPod: function(direction) {
110 return this.querySelector('.supervised-user-creation-manager-name'); 220 if (!this.selectedPod_)
111 }, 221 return false;
112 222 var index = -1;
113 /** 223 for (var i = 0, pod; pod = this.pods[i]; ++i) {
114 * Gets e-mail element. 224 if (pod == this.selectedPod_) {
115 * @type {!HTMLDivElement} 225 index = i;
116 */ 226 break;
117 get emailElement() { 227 }
118 return this.querySelector('.supervised-user-creation-manager-email'); 228 }
119 }, 229 if (-1 == index)
120 230 return false;
121 /** 231 index = index + direction;
122 * Gets password element. 232 if (index < 0 || index >= this.pods.length)
123 * @type {!HTMLDivElement} 233 return false;
124 */ 234 this.selectPod(this.pods[index]);
125 get passwordElement() {
126 return this.querySelector('.supervised-user-creation-manager-password');
127 },
128
129 /**
130 * Gets password enclosing block.
131 * @type {!HTMLDivElement}
132 */
133 get passwordBlock() {
134 return this.querySelector('.password-block');
135 },
136
137 /** @override */
138 handleMouseDown_: function(e) {
139 this.parentNode.selectPod(this);
140 // Prevent default so that we don't trigger 'focus' event.
141 e.preventDefault();
142 },
143
144 /**
145 * The user that this pod represents.
146 * @type {!Object}
147 */
148 user_: undefined,
149 get user() {
150 return this.user_;
151 },
152 set user(userDict) {
153 this.user_ = userDict;
154 this.update();
155 },
156 };
157
158 var ManagerPodList = cr.ui.define('div');
159
160 /**
161 * UI element for selecting manager account for new supervised user.
162 * @type {Object}
163 */
164 ManagerPodList.prototype = {
165 __proto__: HTMLDivElement.prototype,
166
167 selectedPod_: null,
168
169 /** @override */
170 decorate: function() {
171 },
172
173 /**
174 * Returns all the pods in this pod list.
175 * @type {NodeList}
176 */
177 get pods() {
178 return this.children;
179 },
180
181 addPod: function(manager) {
182 var managerPod = new ManagerPod({user: manager});
183 this.appendChild(managerPod);
184 managerPod.update();
185 },
186
187 clearPods: function() {
188 this.innerHTML = '';
189 this.selectedPod_ = null;
190 },
191
192 selectPod: function(podToSelect) {
193 if ((this.selectedPod_ == podToSelect) && !!podToSelect) {
194 podToSelect.focusInput();
195 return;
196 }
197 this.selectedPod_ = podToSelect;
198 for (var i = 0, pod; pod = this.pods[i]; ++i) {
199 if (pod != podToSelect) {
200 pod.classList.remove('focused');
201 pod.passwordElement.value = '';
202 pod.passwordBlock.hidden = true;
203 }
204 }
205 if (!podToSelect)
206 return;
207 podToSelect.classList.add('focused');
208 podToSelect.passwordBlock.hidden = false;
209 podToSelect.passwordElement.value = '';
210 podToSelect.focusInput();
211 chrome.send('managerSelectedOnSupervisedUserCreationFlow',
212 [podToSelect.user.username]);
213 },
214
215 /**
216 * Select pod next to currently selected one in given |direction|.
217 * @param {integer} direction - +1 for selecting pod below current, -1 for
218 * selecting pod above current.
219 * @type {boolean} returns if selected pod has changed.
220 */
221 selectNextPod: function(direction) {
222 if (!this.selectedPod_)
223 return false;
224 var index = -1;
225 for (var i = 0, pod; pod = this.pods[i]; ++i) {
226 if (pod == this.selectedPod_) {
227 index = i;
228 break;
229 }
230 }
231 if (-1 == index)
232 return false;
233 index = index + direction;
234 if (index < 0 || index >= this.pods.length)
235 return false;
236 this.selectPod(this.pods[index]);
237 return true;
238 }
239 };
240
241 var ImportPod = cr.ui.define(function() {
242 var node = $('supervised-user-creation-import-template').cloneNode(true);
243 node.removeAttribute('id');
244 node.removeAttribute('hidden');
245 return node;
246 });
247
248 /**
249 * UI element for displaying single supervised user in list of possible users
250 * for importing existing users.
251 * @type {Object}
252 */
253 ImportPod.prototype = {
254 __proto__: HTMLDivElement.prototype,
255
256 /** @override */
257 decorate: function() {
258 // Mousedown has to be used instead of click to be able to prevent 'focus'
259 // event later.
260 this.addEventListener('mousedown', this.handleMouseDown_.bind(this));
261 var screen = $('supervised-user-creation');
262 var importList = screen.importList_;
263 },
264
265 /**
266 * Updates UI elements from user data.
267 */
268 update: function() {
269 this.imageElement.src = this.user.avatarurl;
270 this.nameElement.textContent = this.user.name;
271 if (this.user.exists) {
272 if (this.user.conflict == 'imported') {
273 this.nameElement.textContent =
274 loadTimeData.getStringF('importUserExists', this.user.name);
275 } else {
276 this.nameElement.textContent =
277 loadTimeData.getStringF('importUsernameExists', this.user.name);
278 }
279 }
280 this.classList.toggle('imported', this.user.exists);
281 },
282
283 /**
284 * Gets image element.
285 * @type {!HTMLImageElement}
286 */
287 get imageElement() {
288 return this.querySelector('.import-pod-image');
289 },
290
291 /**
292 * Gets name element.
293 * @type {!HTMLDivElement}
294 */
295 get nameElement() {
296 return this.querySelector('.import-pod-name');
297 },
298
299 /** @override */
300 handleMouseDown_: function(e) {
301 this.parentNode.selectPod(this);
302 // Prevent default so that we don't trigger 'focus' event.
303 e.preventDefault();
304 },
305
306 /**
307 * The user that this pod represents.
308 * @type {Object}
309 */
310 user_: undefined,
311
312 get user() {
313 return this.user_;
314 },
315
316 set user(userDict) {
317 this.user_ = userDict;
318 this.update();
319 },
320 };
321
322 var ImportPodList = cr.ui.define('div');
323
324 /**
325 * UI element for selecting existing supervised user for import.
326 * @type {Object}
327 */
328 ImportPodList.prototype = {
329 __proto__: HTMLDivElement.prototype,
330
331 selectedPod_: null,
332
333 /** @override */
334 decorate: function() {
335 this.setAttribute('tabIndex', 0);
336 this.classList.add('nofocus');
337 var importList = this;
338 var screen = $('supervised-user-creation');
339
340 this.addEventListener('focus', function(e) {
341 if (importList.selectedPod_ == null) {
342 if (importList.pods.length > 0)
343 importList.selectPod(importList.pods[0]);
344 }
345 });
346
347 this.addEventListener('keydown', function(e) {
348 switch (e.key) {
349 case 'ArrowUp':
350 importList.selectNextPod(-1);
351 e.stopPropagation();
352 break;
353 case 'Enter':
354 if (importList.selectedPod_ != null)
355 screen.importSupervisedUser_();
356 e.stopPropagation();
357 break;
358 case 'ArrowDown':
359 importList.selectNextPod(+1);
360 e.stopPropagation();
361 break;
362 }
363 });
364 },
365
366 /**
367 * Returns all the pods in this pod list.
368 * @type {NodeList}
369 */
370 get pods() {
371 return this.children;
372 },
373
374 /**
375 * Returns selected pod.
376 * @type {Node}
377 */
378 get selectedPod() {
379 return this.selectedPod_;
380 },
381
382 addPod: function(user) {
383 var importPod = new ImportPod({user: user});
384 this.appendChild(importPod);
385 importPod.update();
386 },
387
388 clearPods: function() {
389 this.innerHTML = '';
390 this.selectedPod_ = null;
391 },
392
393 scrollIntoView: function(pod) {
394 scroller = this.parentNode;
395 var itemHeight = pod.getBoundingClientRect().height;
396 var scrollTop = scroller.scrollTop;
397 var top = pod.offsetTop - scroller.offsetTop;
398 var clientHeight = scroller.clientHeight;
399
400 var self = scroller;
401
402 // Function to adjust the tops of viewport and row.
403 function scrollToAdjustTop() {
404 self.scrollTop = top;
405 return true;
406 }
407 // Function to adjust the bottoms of viewport and row.
408 function scrollToAdjustBottom() {
409 var cs = getComputedStyle(self);
410 var paddingY = parseInt(cs.paddingTop, 10) +
411 parseInt(cs.paddingBottom, 10);
412
413 if (top + itemHeight > scrollTop + clientHeight - paddingY) {
414 self.scrollTop = top + itemHeight - clientHeight + paddingY;
415 return true; 235 return true;
416 } 236 }
417 return false;
418 }
419
420 // Check if the entire of given indexed row can be shown in the viewport.
421 if (itemHeight <= clientHeight) {
422 if (top < scrollTop)
423 return scrollToAdjustTop();
424 if (scrollTop + clientHeight < top + itemHeight)
425 return scrollToAdjustBottom();
426 } else {
427 if (scrollTop < top)
428 return scrollToAdjustTop();
429 if (top + itemHeight < scrollTop + clientHeight)
430 return scrollToAdjustBottom();
431 }
432 return false;
433 },
434
435 /**
436 * @param {Element} podToSelect - pod to select, can be null.
437 */
438 selectPod: function(podToSelect) {
439 if ((this.selectedPod_ == podToSelect) && !!podToSelect) {
440 return;
441 }
442 this.selectedPod_ = podToSelect;
443 for (var i = 0; i < this.pods.length; i++) {
444 var pod = this.pods[i];
445 if (pod != podToSelect)
446 pod.classList.remove('focused');
447 }
448 if (!podToSelect)
449 return;
450 podToSelect.classList.add('focused');
451 podToSelect.focus();
452 var screen = $('supervised-user-creation');
453 if (!this.selectedPod_) {
454 screen.getScreenButton('import').disabled = true;
455 } else {
456 screen.getScreenButton('import').disabled =
457 this.selectedPod_.user.exists;
458 if (!this.selectedPod_.user.exists) {
459 chrome.send('userSelectedForImportInSupervisedUserCreationFlow',
460 [podToSelect.user.id]);
461 }
462 }
463 },
464
465 selectNextPod: function(direction) {
466 if (!this.selectedPod_)
467 return false;
468 var index = -1;
469 for (var i = 0, pod; pod = this.pods[i]; ++i) {
470 if (pod == this.selectedPod_) {
471 index = i;
472 break;
473 }
474 }
475 if (-1 == index)
476 return false;
477 index = index + direction;
478 if (index < 0 || index >= this.pods.length)
479 return false;
480 this.selectPod(this.pods[index]);
481 return true;
482 },
483
484 selectUser: function(user_id) {
485 for (var i = 0, pod; pod = this.pods[i]; ++i) {
486 if (pod.user.id == user_id) {
487 this.selectPod(pod);
488 this.scrollIntoView(pod);
489 break;
490 }
491 }
492 },
493 };
494
495 return {
496 EXTERNAL_API: [
497 'loadManagers',
498 'setCameraPresent',
499 'setDefaultImages',
500 'setExistingSupervisedUsers',
501 'showErrorPage',
502 'showIntroPage',
503 'showManagerPage',
504 'showManagerPasswordError',
505 'showPage',
506 'showPasswordError',
507 'showProgress',
508 'showStatusError',
509 'showTutorialPage',
510 'showUsernamePage',
511 'supervisedUserNameError',
512 'supervisedUserNameOk',
513 'supervisedUserSuggestImport',
514 ],
515
516 lastVerifiedName_: null,
517 lastIncorrectUserName_: null,
518 managerList_: null,
519 importList_: null,
520
521 currentPage_: null,
522 imagesRequested_: false,
523
524 // Contains data that can be auto-shared with handler.
525 context_: {},
526
527 /** @override */
528 decorate: function() {
529 this.managerList_ = new ManagerPodList();
530 $('supervised-user-creation-managers-pane').appendChild(
531 this.managerList_);
532
533 this.importList_ = new ImportPodList();
534 $('supervised-user-creation-import-pane').appendChild(this.importList_);
535
536 var userNameField = $('supervised-user-creation-name');
537 var passwordField = $('supervised-user-creation-password');
538 var password2Field = $('supervised-user-creation-password-confirm');
539
540 var creationScreen = this;
541
542 var hideUserPasswordError = function(element) {
543 $('bubble').hide();
544 $('supervised-user-creation-password').classList.remove(
545 'password-error');
546 }; 237 };
547 238
548 this.configureTextInput(userNameField, 239 var ImportPod = cr.ui.define(function() {
549 this.checkUserName_.bind(this), 240 var node =
550 this.validIfNotEmpty_.bind(this), 241 $('supervised-user-creation-import-template').cloneNode(true);
551 function(element) { 242 node.removeAttribute('id');
552 passwordField.focus(); 243 node.removeAttribute('hidden');
553 }, 244 return node;
554 this.clearUserNameError_.bind(this));
555 this.configureTextInput(passwordField,
556 this.updateNextButtonForUser_.bind(this),
557 this.validIfNotEmpty_.bind(this),
558 function(element) {
559 password2Field.focus();
560 },
561 hideUserPasswordError);
562 this.configureTextInput(password2Field,
563 this.updateNextButtonForUser_.bind(this),
564 this.validIfNotEmpty_.bind(this),
565 function(element) {
566 creationScreen.getScreenButton('next').focus();
567 },
568 hideUserPasswordError);
569
570 this.getScreenButton('error').addEventListener('click', function(e) {
571 creationScreen.handleErrorButtonPressed_();
572 e.stopPropagation();
573 }); 245 });
574 246
575 /* 247 /**
576 TODO(antrim) : this is an explicit code duplications with UserImageScreen. 248 * UI element for displaying single supervised user in list of possible
577 It should be removed by issue 251179. 249 * users for importing existing users.
578 */ 250 * @type {Object}
579 var imageGrid = this.getScreenElement('image-grid'); 251 */
580 UserImagesGrid.decorate(imageGrid); 252 ImportPod.prototype = {
581 253 __proto__: HTMLDivElement.prototype,
582 // Preview image will track the selected item's URL. 254
583 var previewElement = this.getScreenElement('image-preview'); 255 /** @override */
584 previewElement.oncontextmenu = function(e) { e.preventDefault(); }; 256 decorate: function() {
585 257 // Mousedown has to be used instead of click to be able to prevent
586 imageGrid.previewElement = previewElement; 258 // 'focus' event later.
587 imageGrid.selectionType = 'default'; 259 this.addEventListener('mousedown', this.handleMouseDown_.bind(this));
588 imageGrid.flipPhotoElement = this.getScreenElement('flip-photo'); 260 var screen = $('supervised-user-creation');
589 261 var importList = screen.importList_;
590 imageGrid.addEventListener('activate', 262 },
591 this.handleActivate_.bind(this)); 263
592 imageGrid.addEventListener('select', 264 /**
593 this.handleSelect_.bind(this)); 265 * Updates UI elements from user data.
594 imageGrid.addEventListener('phototaken', 266 */
595 this.handlePhotoTaken_.bind(this)); 267 update: function() {
596 imageGrid.addEventListener('photoupdated', 268 this.imageElement.src = this.user.avatarurl;
597 this.handlePhotoUpdated_.bind(this)); 269 this.nameElement.textContent = this.user.name;
598 // Set the title for camera item in the grid. 270 if (this.user.exists) {
599 imageGrid.setCameraTitles( 271 if (this.user.conflict == 'imported') {
600 loadTimeData.getString('takePhoto'), 272 this.nameElement.textContent =
601 loadTimeData.getString('photoFromCamera')); 273 loadTimeData.getStringF('importUserExists', this.user.name);
602 274 } else {
603 this.getScreenElement('take-photo').addEventListener( 275 this.nameElement.textContent = loadTimeData.getStringF(
604 'click', this.handleTakePhoto_.bind(this)); 276 'importUsernameExists', this.user.name);
605 this.getScreenElement('discard-photo').addEventListener( 277 }
606 'click', this.handleDiscardPhoto_.bind(this)); 278 }
607 279 this.classList.toggle('imported', this.user.exists);
608 // Toggle 'animation' class for the duration of WebKit transition. 280 },
609 this.getScreenElement('flip-photo').addEventListener( 281
610 'click', this.handleFlipPhoto_.bind(this)); 282 /**
611 this.getScreenElement('image-stream-crop').addEventListener( 283 * Gets image element.
612 'transitionend', function(e) { 284 * @type {!HTMLImageElement}
613 previewElement.classList.remove('animation'); 285 */
286 get imageElement() {
287 return this.querySelector('.import-pod-image');
288 },
289
290 /**
291 * Gets name element.
292 * @type {!HTMLDivElement}
293 */
294 get nameElement() {
295 return this.querySelector('.import-pod-name');
296 },
297
298 /** @override */
299 handleMouseDown_: function(e) {
300 this.parentNode.selectPod(this);
301 // Prevent default so that we don't trigger 'focus' event.
302 e.preventDefault();
303 },
304
305 /**
306 * The user that this pod represents.
307 * @type {Object}
308 */
309 user_: undefined,
310
311 get user() {
312 return this.user_;
313 },
314
315 set user(userDict) {
316 this.user_ = userDict;
317 this.update();
318 },
319 };
320
321 var ImportPodList = cr.ui.define('div');
322
323 /**
324 * UI element for selecting existing supervised user for import.
325 * @type {Object}
326 */
327 ImportPodList.prototype = {
328 __proto__: HTMLDivElement.prototype,
329
330 selectedPod_: null,
331
332 /** @override */
333 decorate: function() {
334 this.setAttribute('tabIndex', 0);
335 this.classList.add('nofocus');
336 var importList = this;
337 var screen = $('supervised-user-creation');
338
339 this.addEventListener('focus', function(e) {
340 if (importList.selectedPod_ == null) {
341 if (importList.pods.length > 0)
342 importList.selectPod(importList.pods[0]);
343 }
614 }); 344 });
615 this.getScreenElement('image-preview-img').addEventListener( 345
616 'transitionend', function(e) { 346 this.addEventListener('keydown', function(e) {
617 previewElement.classList.remove('animation'); 347 switch (e.key) {
348 case 'ArrowUp':
349 importList.selectNextPod(-1);
350 e.stopPropagation();
351 break;
352 case 'Enter':
353 if (importList.selectedPod_ != null)
354 screen.importSupervisedUser_();
355 e.stopPropagation();
356 break;
357 case 'ArrowDown':
358 importList.selectNextPod(+1);
359 e.stopPropagation();
360 break;
361 }
618 }); 362 });
619 363 },
620 $('supervised-user-creation-navigation').addEventListener('close', 364
621 this.cancel.bind(this)); 365 /**
622 }, 366 * Returns all the pods in this pod list.
623 367 * @type {NodeList}
624 buttonIds: [], 368 */
625 369 get pods() {
626 /** 370 return this.children;
627 * Creates button for adding to controls. 371 },
628 * @param {string} buttonId -- id for button, have to be unique within 372
629 * screen. Actual id will be prefixed with screen name and appended with 373 /**
630 * '-button'. Use getScreenButton(buttonId) to find it later. 374 * Returns selected pod.
631 * @param {string} i18nPrefix -- screen prefix for i18n values. 375 * @type {Node}
632 * @param {function} callback -- will be called on button press with 376 */
633 * buttonId parameter. 377 get selectedPod() {
634 * @param {array} pages -- list of pages where this button should be 378 return this.selectedPod_;
635 * displayed. 379 },
636 * @param {array} classes -- list of additional CSS classes for button. 380
637 */ 381 addPod: function(user) {
638 makeButton: function(buttonId, i18nPrefix, callback, pages, classes) { 382 var importPod = new ImportPod({user: user});
639 var capitalizedId = buttonId.charAt(0).toUpperCase() + buttonId.slice(1); 383 this.appendChild(importPod);
640 this.buttonIds.push(buttonId); 384 importPod.update();
641 var result = this.ownerDocument.createElement('button'); 385 },
642 result.id = this.name() + '-' + buttonId + '-button'; 386
643 result.classList.add('screen-control-button'); 387 clearPods: function() {
644 for (var i = 0; i < classes.length; i++) { 388 this.innerHTML = '';
645 result.classList.add(classes[i]); 389 this.selectedPod_ = null;
646 } 390 },
647 result.textContent = loadTimeData. 391
648 getString(i18nPrefix + capitalizedId + 'ButtonTitle'); 392 scrollIntoView: function(pod) {
649 result.addEventListener('click', function(e) { 393 scroller = this.parentNode;
650 callback(buttonId); 394 var itemHeight = pod.getBoundingClientRect().height;
651 e.stopPropagation(); 395 var scrollTop = scroller.scrollTop;
652 }); 396 var top = pod.offsetTop - scroller.offsetTop;
653 result.pages = pages; 397 var clientHeight = scroller.clientHeight;
654 return result; 398
655 }, 399 var self = scroller;
656 400
657 /** 401 // Function to adjust the tops of viewport and row.
658 * Simple validator for |configureTextInput|. 402 function scrollToAdjustTop() {
659 * Element is considered valid if it has any text. 403 self.scrollTop = top;
660 * @param {Element} element - element to be validated. 404 return true;
661 * @return {boolean} - true, if element has any text. 405 }
662 */ 406 // Function to adjust the bottoms of viewport and row.
663 validIfNotEmpty_: function(element) { 407 function scrollToAdjustBottom() {
664 return (element.value.length > 0); 408 var cs = getComputedStyle(self);
665 }, 409 var paddingY =
666 410 parseInt(cs.paddingTop, 10) + parseInt(cs.paddingBottom, 10);
667 /** 411
668 * Configure text-input |element|. 412 if (top + itemHeight > scrollTop + clientHeight - paddingY) {
669 * @param {Element} element - element to be configured. 413 self.scrollTop = top + itemHeight - clientHeight + paddingY;
670 * @param {function(element)} inputChangeListener - function that will be 414 return true;
671 * called upon any button press/release. 415 }
672 * @param {function(element)} validator - function that will be called when 416 return false;
673 * Enter is pressed. If it returns |true| then advance to next element. 417 }
674 * @param {function(element)} moveFocus - function that will determine next 418
675 * element and move focus to it. 419 // Check if the entire of given indexed row can be shown in the
676 * @param {function(element)} errorHider - function that is called upon 420 // viewport.
677 * every button press, so that any associated error can be hidden. 421 if (itemHeight <= clientHeight) {
678 */ 422 if (top < scrollTop)
679 configureTextInput: function(element, 423 return scrollToAdjustTop();
680 inputChangeListener, 424 if (scrollTop + clientHeight < top + itemHeight)
681 validator, 425 return scrollToAdjustBottom();
682 moveFocus,
683 errorHider) {
684 element.addEventListener('keydown', function(e) {
685 if (e.key == 'Enter') {
686 var dataValid = true;
687 if (validator)
688 dataValid = validator(element);
689 if (!dataValid) {
690 element.focus();
691 } else { 426 } else {
692 if (moveFocus) 427 if (scrollTop < top)
693 moveFocus(element); 428 return scrollToAdjustTop();
694 } 429 if (top + itemHeight < scrollTop + clientHeight)
695 e.stopPropagation(); 430 return scrollToAdjustBottom();
696 return; 431 }
697 } 432 return false;
698 if (errorHider) 433 },
699 errorHider(element); 434
700 if (inputChangeListener) 435 /**
701 inputChangeListener(element); 436 * @param {Element} podToSelect - pod to select, can be null.
702 }); 437 */
703 element.addEventListener('keyup', function(e) { 438 selectPod: function(podToSelect) {
704 if (inputChangeListener) 439 if ((this.selectedPod_ == podToSelect) && !!podToSelect) {
705 inputChangeListener(element); 440 return;
706 }); 441 }
707 }, 442 this.selectedPod_ = podToSelect;
708 443 for (var i = 0; i < this.pods.length; i++) {
709 /** 444 var pod = this.pods[i];
710 * Makes element from template. 445 if (pod != podToSelect)
711 * @param {string} templateId -- template will be looked up within screen 446 pod.classList.remove('focused');
712 * by class with name "template-<templateId>". 447 }
713 * @param {string} elementId -- id for result, uinque within screen. Actual 448 if (!podToSelect)
714 * id will be prefixed with screen name. Use getScreenElement(id) to find 449 return;
715 * it later. 450 podToSelect.classList.add('focused');
716 */ 451 podToSelect.focus();
717 makeFromTemplate: function(templateId, elementId) { 452 var screen = $('supervised-user-creation');
718 var templateClassName = 'template-' + templateId; 453 if (!this.selectedPod_) {
719 var templateNode = this.querySelector('.' + templateClassName); 454 screen.getScreenButton('import').disabled = true;
720 var screenPrefix = this.name() + '-'; 455 } else {
721 var result = templateNode.cloneNode(true); 456 screen.getScreenButton('import').disabled =
722 result.classList.remove(templateClassName); 457 this.selectedPod_.user.exists;
723 result.id = screenPrefix + elementId; 458 if (!this.selectedPod_.user.exists) {
724 return result; 459 chrome.send(
725 }, 460 'userSelectedForImportInSupervisedUserCreationFlow',
726 461 [podToSelect.user.id]);
727 /** 462 }
728 * @param {string} buttonId -- id of button to be found, 463 }
729 * @return {Element} button created by makeButton with given buttonId. 464 },
730 */ 465
731 getScreenButton: function(buttonId) { 466 selectNextPod: function(direction) {
732 var fullId = this.name() + '-' + buttonId + '-button'; 467 if (!this.selectedPod_)
733 return this.getScreenElement(buttonId + '-button'); 468 return false;
734 }, 469 var index = -1;
735 470 for (var i = 0, pod; pod = this.pods[i]; ++i) {
736 /** 471 if (pod == this.selectedPod_) {
737 * @param {string} elementId -- id of element to be found, 472 index = i;
738 * @return {Element} button created by makeFromTemplate with elementId. 473 break;
739 */ 474 }
740 getScreenElement: function(elementId) { 475 }
741 var fullId = this.name() + '-' + elementId; 476 if (-1 == index)
742 return $(fullId); 477 return false;
743 }, 478 index = index + direction;
744 479 if (index < 0 || index >= this.pods.length)
745 /** 480 return false;
746 * Screen controls. 481 this.selectPod(this.pods[index]);
747 * @type {!Array} Array of Buttons. 482 return true;
748 */ 483 },
749 get buttons() { 484
750 var links = this.ownerDocument.createElement('div'); 485 selectUser: function(user_id) {
751 var buttons = this.ownerDocument.createElement('div'); 486 for (var i = 0, pod; pod = this.pods[i]; ++i) {
752 links.classList.add('controls-links'); 487 if (pod.user.id == user_id) {
753 buttons.classList.add('controls-buttons'); 488 this.selectPod(pod);
754 489 this.scrollIntoView(pod);
755 var importLink = this.makeFromTemplate('import-supervised-user-link', 490 break;
756 'import-link'); 491 }
757 importLink.hidden = true; 492 }
758 links.appendChild(importLink); 493 },
759 494 };
760 var linkElement = importLink.querySelector('.signin-link'); 495
761 linkElement.addEventListener('click', 496 return {
762 this.importLinkPressed_.bind(this)); 497 EXTERNAL_API: [
763 498 'loadManagers',
764 var createLink = this.makeFromTemplate('create-supervised-user-link', 499 'setCameraPresent',
765 'create-link'); 500 'setDefaultImages',
766 createLink.hidden = true; 501 'setExistingSupervisedUsers',
767 links.appendChild(createLink); 502 'showErrorPage',
768 503 'showIntroPage',
769 var status = this.makeFromTemplate('status-container', 'status'); 504 'showManagerPage',
770 buttons.appendChild(status); 505 'showManagerPasswordError',
771 506 'showPage',
772 linkElement = createLink.querySelector('.signin-link'); 507 'showPasswordError',
773 linkElement.addEventListener('click', 508 'showProgress',
774 this.createLinkPressed_.bind(this)); 509 'showStatusError',
775 510 'showTutorialPage',
776 buttons.appendChild(this.makeButton( 511 'showUsernamePage',
777 'start', 512 'supervisedUserNameError',
778 'supervisedUserCreationFlow', 513 'supervisedUserNameOk',
779 this.startButtonPressed_.bind(this), 514 'supervisedUserSuggestImport',
780 ['intro'], 515 ],
781 ['custom-appearance', 'button-fancy', 'button-blue'])); 516
782 517 lastVerifiedName_: null,
783 buttons.appendChild(this.makeButton( 518 lastIncorrectUserName_: null,
784 'prev', 519 managerList_: null,
785 'supervisedUserCreationFlow', 520 importList_: null,
786 this.prevButtonPressed_.bind(this), 521
787 ['manager'], 522 currentPage_: null,
788 [])); 523 imagesRequested_: false,
789 524
790 buttons.appendChild(this.makeButton( 525 // Contains data that can be auto-shared with handler.
791 'next', 526 context_: {},
792 'supervisedUserCreationFlow', 527
793 this.nextButtonPressed_.bind(this), 528 /** @override */
794 ['manager', 'username'], 529 decorate: function() {
795 [])); 530 this.managerList_ = new ManagerPodList();
796 531 $('supervised-user-creation-managers-pane')
797 buttons.appendChild(this.makeButton( 532 .appendChild(this.managerList_);
798 'import', 533
799 'supervisedUserCreationFlow', 534 this.importList_ = new ImportPodList();
800 this.importButtonPressed_.bind(this), 535 $('supervised-user-creation-import-pane')
801 ['import', 'import-password'], 536 .appendChild(this.importList_);
802 [])); 537
803 538 var userNameField = $('supervised-user-creation-name');
804 buttons.appendChild(this.makeButton( 539 var passwordField = $('supervised-user-creation-password');
805 'gotit', 540 var password2Field = $('supervised-user-creation-password-confirm');
806 'supervisedUserCreationFlow', 541
807 this.gotItButtonPressed_.bind(this), 542 var creationScreen = this;
808 ['created'], 543
809 ['custom-appearance', 'button-fancy', 'button-blue'])); 544 var hideUserPasswordError = function(element) {
810 return [links, buttons]; 545 $('bubble').hide();
811 }, 546 $('supervised-user-creation-password')
812 547 .classList.remove('password-error');
813 /** 548 };
814 * Does sanity check and calls backend with current user name/password pair 549
815 * to authenticate manager. May result in showManagerPasswordError. 550 this.configureTextInput(
816 * @private 551 userNameField, this.checkUserName_.bind(this),
817 */ 552 this.validIfNotEmpty_.bind(this), function(element) {
818 validateAndLogInAsManager_: function() { 553 passwordField.focus();
819 var selectedPod = this.managerList_.selectedPod_; 554 }, this.clearUserNameError_.bind(this));
820 if (null == selectedPod) 555 this.configureTextInput(
821 return; 556 passwordField, this.updateNextButtonForUser_.bind(this),
822 557 this.validIfNotEmpty_.bind(this), function(element) {
823 var managerId = selectedPod.user.username; 558 password2Field.focus();
824 var managerDisplayId = selectedPod.user.emailAddress; 559 }, hideUserPasswordError);
825 var managerPassword = selectedPod.passwordElement.value; 560 this.configureTextInput(
826 if (managerPassword.length == 0) 561 password2Field, this.updateNextButtonForUser_.bind(this),
827 return; 562 this.validIfNotEmpty_.bind(this), function(element) {
828 if (this.disabled) 563 creationScreen.getScreenButton('next').focus();
829 return; 564 }, hideUserPasswordError);
830 this.disabled = true; 565
831 this.context_.managerId = managerId; 566 this.getScreenButton('error').addEventListener('click', function(e) {
832 this.context_.managerDisplayId = managerDisplayId; 567 creationScreen.handleErrorButtonPressed_();
833 this.context_.managerName = selectedPod.user.displayName; 568 e.stopPropagation();
834 chrome.send('authenticateManagerInSupervisedUserCreationFlow', 569 });
835 [managerId, managerPassword]); 570
836 }, 571 /*
837 572 TODO(antrim) : this is an explicit code duplications with
838 /** 573 UserImageScreen. It should be removed by issue 251179.
839 * Does sanity check and calls backend with user display name/password pair 574 */
840 * to create a user. 575 var imageGrid = this.getScreenElement('image-grid');
841 * @private 576 UserImagesGrid.decorate(imageGrid);
842 */ 577
843 validateAndCreateSupervisedUser_: function() { 578 // Preview image will track the selected item's URL.
844 var firstPassword = $('supervised-user-creation-password').value; 579 var previewElement = this.getScreenElement('image-preview');
845 var secondPassword = 580 previewElement.oncontextmenu = function(e) {
846 $('supervised-user-creation-password-confirm').value; 581 e.preventDefault();
847 var userName = $('supervised-user-creation-name').value; 582 };
848 if (firstPassword != secondPassword) { 583
849 this.showPasswordError(loadTimeData.getString( 584 imageGrid.previewElement = previewElement;
850 'createSupervisedUserPasswordMismatchError')); 585 imageGrid.selectionType = 'default';
851 return; 586 imageGrid.flipPhotoElement = this.getScreenElement('flip-photo');
852 } 587
853 if (this.disabled) 588 imageGrid.addEventListener(
854 return; 589 'activate', this.handleActivate_.bind(this));
855 this.disabled = true; 590 imageGrid.addEventListener('select', this.handleSelect_.bind(this));
856 591 imageGrid.addEventListener(
857 this.context_.supervisedName = userName; 592 'phototaken', this.handlePhotoTaken_.bind(this));
858 chrome.send('specifySupervisedUserCreationFlowUserData', 593 imageGrid.addEventListener(
859 [userName, firstPassword]); 594 'photoupdated', this.handlePhotoUpdated_.bind(this));
860 }, 595 // Set the title for camera item in the grid.
861 596 imageGrid.setCameraTitles(
862 /** 597 loadTimeData.getString('takePhoto'),
863 * Does sanity check and calls backend with selected existing supervised 598 loadTimeData.getString('photoFromCamera'));
864 * user id to import user. 599
865 * @private 600 this.getScreenElement('take-photo')
866 */ 601 .addEventListener('click', this.handleTakePhoto_.bind(this));
867 importSupervisedUser_: function() { 602 this.getScreenElement('discard-photo')
868 if (this.disabled) 603 .addEventListener('click', this.handleDiscardPhoto_.bind(this));
869 return; 604
870 if (this.currentPage_ == 'import-password') { 605 // Toggle 'animation' class for the duration of WebKit transition.
871 var firstPassword = this.getScreenElement('password').value; 606 this.getScreenElement('flip-photo')
872 var secondPassword = this.getScreenElement('password-confirm').value; 607 .addEventListener('click', this.handleFlipPhoto_.bind(this));
873 if (firstPassword != secondPassword) { 608 this.getScreenElement('image-stream-crop')
874 this.showPasswordError(loadTimeData.getString( 609 .addEventListener('transitionend', function(e) {
875 'createSupervisedUserPasswordMismatchError')); 610 previewElement.classList.remove('animation');
876 return; 611 });
877 } 612 this.getScreenElement('image-preview-img')
878 var userId = this.context_.importUserId; 613 .addEventListener('transitionend', function(e) {
879 this.disabled = true; 614 previewElement.classList.remove('animation');
880 chrome.send('importSupervisedUserWithPassword', 615 });
881 [userId, firstPassword]); 616
882 return; 617 $('supervised-user-creation-navigation')
883 } else { 618 .addEventListener('close', this.cancel.bind(this));
884 var selectedPod = this.importList_.selectedPod_; 619 },
885 if (!selectedPod) 620
886 return; 621 buttonIds: [],
887 var user = selectedPod.user; 622
888 var userId = user.id; 623 /**
889 624 * Creates button for adding to controls.
890 this.context_.importUserId = userId; 625 * @param {string} buttonId -- id for button, have to be unique within
891 this.context_.supervisedName = user.name; 626 * screen. Actual id will be prefixed with screen name and appended
892 this.context_.selectedImageUrl = user.avatarurl; 627 * with
893 if (!user.needPassword) { 628 * '-button'. Use getScreenButton(buttonId) to find it later.
629 * @param {string} i18nPrefix -- screen prefix for i18n values.
630 * @param {function} callback -- will be called on button press with
631 * buttonId parameter.
632 * @param {array} pages -- list of pages where this button should be
633 * displayed.
634 * @param {array} classes -- list of additional CSS classes for button.
635 */
636 makeButton: function(buttonId, i18nPrefix, callback, pages, classes) {
637 var capitalizedId =
638 buttonId.charAt(0).toUpperCase() + buttonId.slice(1);
639 this.buttonIds.push(buttonId);
640 var result = this.ownerDocument.createElement('button');
641 result.id = this.name() + '-' + buttonId + '-button';
642 result.classList.add('screen-control-button');
643 for (var i = 0; i < classes.length; i++) {
644 result.classList.add(classes[i]);
645 }
646 result.textContent = loadTimeData.getString(
647 i18nPrefix + capitalizedId + 'ButtonTitle');
648 result.addEventListener('click', function(e) {
649 callback(buttonId);
650 e.stopPropagation();
651 });
652 result.pages = pages;
653 return result;
654 },
655
656 /**
657 * Simple validator for |configureTextInput|.
658 * Element is considered valid if it has any text.
659 * @param {Element} element - element to be validated.
660 * @return {boolean} - true, if element has any text.
661 */
662 validIfNotEmpty_: function(element) {
663 return (element.value.length > 0);
664 },
665
666 /**
667 * Configure text-input |element|.
668 * @param {Element} element - element to be configured.
669 * @param {function(element)} inputChangeListener - function that will b e
670 * called upon any button press/release.
671 * @param {function(element)} validator - function that will be called w hen
672 * Enter is pressed. If it returns |true| then advance to next
673 * element.
674 * @param {function(element)} moveFocus - function that will determine n ext
675 * element and move focus to it.
676 * @param {function(element)} errorHider - function that is called upon
677 * every button press, so that any associated error can be hidden.
678 */
679 configureTextInput: function(
680 element, inputChangeListener, validator, moveFocus, errorHider) {
681 element.addEventListener('keydown', function(e) {
682 if (e.key == 'Enter') {
683 var dataValid = true;
684 if (validator)
685 dataValid = validator(element);
686 if (!dataValid) {
687 element.focus();
688 } else {
689 if (moveFocus)
690 moveFocus(element);
691 }
692 e.stopPropagation();
693 return;
694 }
695 if (errorHider)
696 errorHider(element);
697 if (inputChangeListener)
698 inputChangeListener(element);
699 });
700 element.addEventListener('keyup', function(e) {
701 if (inputChangeListener)
702 inputChangeListener(element);
703 });
704 },
705
706 /**
707 * Makes element from template.
708 * @param {string} templateId -- template will be looked up within scree n
709 * by class with name "template-<templateId>".
710 * @param {string} elementId -- id for result, uinque within screen. Act ual
711 * id will be prefixed with screen name. Use getScreenElement(id) to
712 * find it later.
713 */
714 makeFromTemplate: function(templateId, elementId) {
715 var templateClassName = 'template-' + templateId;
716 var templateNode = this.querySelector('.' + templateClassName);
717 var screenPrefix = this.name() + '-';
718 var result = templateNode.cloneNode(true);
719 result.classList.remove(templateClassName);
720 result.id = screenPrefix + elementId;
721 return result;
722 },
723
724 /**
725 * @param {string} buttonId -- id of button to be found,
726 * @return {Element} button created by makeButton with given buttonId.
727 */
728 getScreenButton: function(buttonId) {
729 var fullId = this.name() + '-' + buttonId + '-button';
730 return this.getScreenElement(buttonId + '-button');
731 },
732
733 /**
734 * @param {string} elementId -- id of element to be found,
735 * @return {Element} button created by makeFromTemplate with elementId.
736 */
737 getScreenElement: function(elementId) {
738 var fullId = this.name() + '-' + elementId;
739 return $(fullId);
740 },
741
742 /**
743 * Screen controls.
744 * @type {!Array} Array of Buttons.
745 */
746 get buttons() {
747 var links = this.ownerDocument.createElement('div');
748 var buttons = this.ownerDocument.createElement('div');
749 links.classList.add('controls-links');
750 buttons.classList.add('controls-buttons');
751
752 var importLink = this.makeFromTemplate(
753 'import-supervised-user-link', 'import-link');
754 importLink.hidden = true;
755 links.appendChild(importLink);
756
757 var linkElement = importLink.querySelector('.signin-link');
758 linkElement.addEventListener(
759 'click', this.importLinkPressed_.bind(this));
760
761 var createLink = this.makeFromTemplate(
762 'create-supervised-user-link', 'create-link');
763 createLink.hidden = true;
764 links.appendChild(createLink);
765
766 var status = this.makeFromTemplate('status-container', 'status');
767 buttons.appendChild(status);
768
769 linkElement = createLink.querySelector('.signin-link');
770 linkElement.addEventListener(
771 'click', this.createLinkPressed_.bind(this));
772
773 buttons.appendChild(this.makeButton(
774 'start', 'supervisedUserCreationFlow',
775 this.startButtonPressed_.bind(this), ['intro'],
776 ['custom-appearance', 'button-fancy', 'button-blue']));
777
778 buttons.appendChild(this.makeButton(
779 'prev', 'supervisedUserCreationFlow',
780 this.prevButtonPressed_.bind(this), ['manager'], []));
781
782 buttons.appendChild(this.makeButton(
783 'next', 'supervisedUserCreationFlow',
784 this.nextButtonPressed_.bind(this), ['manager', 'username'], []));
785
786 buttons.appendChild(this.makeButton(
787 'import', 'supervisedUserCreationFlow',
788 this.importButtonPressed_.bind(this),
789 ['import', 'import-password'], []));
790
791 buttons.appendChild(this.makeButton(
792 'gotit', 'supervisedUserCreationFlow',
793 this.gotItButtonPressed_.bind(this), ['created'],
794 ['custom-appearance', 'button-fancy', 'button-blue']));
795 return [links, buttons];
796 },
797
798 /**
799 * Does sanity check and calls backend with current user name/password
800 * pair to authenticate manager. May result in showManagerPasswordError.
801 * @private
802 */
803 validateAndLogInAsManager_: function() {
804 var selectedPod = this.managerList_.selectedPod_;
805 if (null == selectedPod)
806 return;
807
808 var managerId = selectedPod.user.username;
809 var managerDisplayId = selectedPod.user.emailAddress;
810 var managerPassword = selectedPod.passwordElement.value;
811 if (managerPassword.length == 0)
812 return;
813 if (this.disabled)
814 return;
894 this.disabled = true; 815 this.disabled = true;
895 chrome.send('importSupervisedUser', [userId]); 816 this.context_.managerId = managerId;
896 } else { 817 this.context_.managerDisplayId = managerDisplayId;
897 this.setVisiblePage_('import-password'); 818 this.context_.managerName = selectedPod.user.displayName;
898 } 819 chrome.send(
899 } 820 'authenticateManagerInSupervisedUserCreationFlow',
900 }, 821 [managerId, managerPassword]);
901 822 },
902 /** 823
903 * Calls backend part to check if current user name is valid/not taken. 824 /**
904 * Results in a call to either supervisedUserNameOk or 825 * Does sanity check and calls backend with user display name/password
905 * supervisedUserNameError. 826 * pair to create a user.
906 * @private 827 * @private
907 */ 828 */
908 checkUserName_: function() { 829 validateAndCreateSupervisedUser_: function() {
909 var userName = this.getScreenElement('name').value; 830 var firstPassword = $('supervised-user-creation-password').value;
910 831 var secondPassword =
911 // Avoid flickering 832 $('supervised-user-creation-password-confirm').value;
912 if (userName == this.lastIncorrectUserName_ || 833 var userName = $('supervised-user-creation-name').value;
913 userName == this.lastVerifiedName_) { 834 if (firstPassword != secondPassword) {
914 return; 835 this.showPasswordError(loadTimeData.getString(
915 } 836 'createSupervisedUserPasswordMismatchError'));
916 if (userName.length > 0) { 837 return;
917 chrome.send('checkSupervisedUserName', [userName]); 838 }
918 } else { 839 if (this.disabled)
919 this.nameErrorVisible = false; 840 return;
920 this.lastVerifiedName_ = null; 841 this.disabled = true;
921 this.lastIncorrectUserName_ = null; 842
922 this.updateNextButtonForUser_(); 843 this.context_.supervisedName = userName;
923 } 844 chrome.send(
924 }, 845 'specifySupervisedUserCreationFlowUserData',
925 846 [userName, firstPassword]);
926 /** 847 },
927 * Called by backend part in case of successful name validation. 848
928 * @param {string} name - name that was validated. 849 /**
929 */ 850 * Does sanity check and calls backend with selected existing supervised
930 supervisedUserNameOk: function(name) { 851 * user id to import user.
931 this.lastVerifiedName_ = name; 852 * @private
932 this.lastIncorrectUserName_ = null; 853 */
933 if ($('supervised-user-creation-name').value == name) 854 importSupervisedUser_: function() {
934 this.clearUserNameError_(); 855 if (this.disabled)
935 this.updateNextButtonForUser_(); 856 return;
936 }, 857 if (this.currentPage_ == 'import-password') {
937 858 var firstPassword = this.getScreenElement('password').value;
938 /** 859 var secondPassword =
939 * Called by backend part in case of name validation failure. 860 this.getScreenElement('password-confirm').value;
940 * @param {string} name - name that was validated. 861 if (firstPassword != secondPassword) {
941 * @param {string} errorText - reason why this name is invalid. 862 this.showPasswordError(loadTimeData.getString(
942 */ 863 'createSupervisedUserPasswordMismatchError'));
943 supervisedUserNameError: function(name, errorText) { 864 return;
944 this.disabled = false; 865 }
945 this.lastIncorrectUserName_ = name; 866 var userId = this.context_.importUserId;
946 this.lastVerifiedName_ = null; 867 this.disabled = true;
947 868 chrome.send(
948 var userNameField = $('supervised-user-creation-name'); 869 'importSupervisedUserWithPassword', [userId, firstPassword]);
949 if (userNameField.value == this.lastIncorrectUserName_) { 870 return;
950 this.nameErrorVisible = true; 871 } else {
951 $('bubble').showTextForElement( 872 var selectedPod = this.importList_.selectedPod_;
952 $('supervised-user-creation-name'), 873 if (!selectedPod)
953 errorText, 874 return;
954 cr.ui.Bubble.Attachment.RIGHT, 875 var user = selectedPod.user;
955 12, 4); 876 var userId = user.id;
956 this.setButtonDisabledStatus('next', true); 877
957 } 878 this.context_.importUserId = userId;
958 }, 879 this.context_.supervisedName = user.name;
959 880 this.context_.selectedImageUrl = user.avatarurl;
960 supervisedUserSuggestImport: function(name, user_id) { 881 if (!user.needPassword) {
961 this.disabled = false; 882 this.disabled = true;
962 this.lastIncorrectUserName_ = name; 883 chrome.send('importSupervisedUser', [userId]);
963 this.lastVerifiedName_ = null; 884 } else {
964 885 this.setVisiblePage_('import-password');
965 var userNameField = $('supervised-user-creation-name'); 886 }
966 var creationScreen = this; 887 }
967 888 },
968 if (userNameField.value == this.lastIncorrectUserName_) { 889
969 this.nameErrorVisible = true; 890 /**
970 var link = this.ownerDocument.createElement('div'); 891 * Calls backend part to check if current user name is valid/not taken.
971 link.innerHTML = loadTimeData.getStringF( 892 * Results in a call to either supervisedUserNameOk or
972 'importBubbleText', 893 * supervisedUserNameError.
973 '<a class="signin-link" href="#">', 894 * @private
974 name, 895 */
975 '</a>'); 896 checkUserName_: function() {
976 link.querySelector('.signin-link').addEventListener('click', 897 var userName = this.getScreenElement('name').value;
977 function(e) { 898
978 creationScreen.handleSuggestImport_(user_id); 899 // Avoid flickering
979 e.stopPropagation(); 900 if (userName == this.lastIncorrectUserName_ ||
980 }); 901 userName == this.lastVerifiedName_) {
981 $('bubble').showContentForElement( 902 return;
982 $('supervised-user-creation-name'), 903 }
983 cr.ui.Bubble.Attachment.RIGHT, 904 if (userName.length > 0) {
984 link, 905 chrome.send('checkSupervisedUserName', [userName]);
985 12, 4); 906 } else {
986 this.setButtonDisabledStatus('next', true); 907 this.nameErrorVisible = false;
987 } 908 this.lastVerifiedName_ = null;
988 }, 909 this.lastIncorrectUserName_ = null;
989 910 this.updateNextButtonForUser_();
990 /** 911 }
991 * Clears user name error, if name is no more guaranteed to be invalid. 912 },
992 * @private 913
993 */ 914 /**
994 clearUserNameError_: function() { 915 * Called by backend part in case of successful name validation.
995 // Avoid flickering 916 * @param {string} name - name that was validated.
996 if ($('supervised-user-creation-name').value == 917 */
918 supervisedUserNameOk: function(name) {
919 this.lastVerifiedName_ = name;
920 this.lastIncorrectUserName_ = null;
921 if ($('supervised-user-creation-name').value == name)
922 this.clearUserNameError_();
923 this.updateNextButtonForUser_();
924 },
925
926 /**
927 * Called by backend part in case of name validation failure.
928 * @param {string} name - name that was validated.
929 * @param {string} errorText - reason why this name is invalid.
930 */
931 supervisedUserNameError: function(name, errorText) {
932 this.disabled = false;
933 this.lastIncorrectUserName_ = name;
934 this.lastVerifiedName_ = null;
935
936 var userNameField = $('supervised-user-creation-name');
937 if (userNameField.value == this.lastIncorrectUserName_) {
938 this.nameErrorVisible = true;
939 $('bubble').showTextForElement(
940 $('supervised-user-creation-name'), errorText,
941 cr.ui.Bubble.Attachment.RIGHT, 12, 4);
942 this.setButtonDisabledStatus('next', true);
943 }
944 },
945
946 supervisedUserSuggestImport: function(name, user_id) {
947 this.disabled = false;
948 this.lastIncorrectUserName_ = name;
949 this.lastVerifiedName_ = null;
950
951 var userNameField = $('supervised-user-creation-name');
952 var creationScreen = this;
953
954 if (userNameField.value == this.lastIncorrectUserName_) {
955 this.nameErrorVisible = true;
956 var link = this.ownerDocument.createElement('div');
957 link.innerHTML = loadTimeData.getStringF(
958 'importBubbleText', '<a class="signin-link" href="#">', name,
959 '</a>');
960 link.querySelector('.signin-link')
961 .addEventListener('click', function(e) {
962 creationScreen.handleSuggestImport_(user_id);
963 e.stopPropagation();
964 });
965 $('bubble').showContentForElement(
966 $('supervised-user-creation-name'),
967 cr.ui.Bubble.Attachment.RIGHT, link, 12, 4);
968 this.setButtonDisabledStatus('next', true);
969 }
970 },
971
972 /**
973 * Clears user name error, if name is no more guaranteed to be invalid.
974 * @private
975 */
976 clearUserNameError_: function() {
977 // Avoid flickering
978 if ($('supervised-user-creation-name').value ==
997 this.lastIncorrectUserName_) { 979 this.lastIncorrectUserName_) {
998 return; 980 return;
999 } 981 }
1000 this.nameErrorVisible = false; 982 this.nameErrorVisible = false;
1001 }, 983 },
1002 984
1003 /** 985 /**
1004 * Called by backend part in case of password validation failure. 986 * Called by backend part in case of password validation failure.
1005 * @param {string} errorText - reason why this password is invalid. 987 * @param {string} errorText - reason why this password is invalid.
1006 */ 988 */
1007 showPasswordError: function(errorText) { 989 showPasswordError: function(errorText) {
1008 $('bubble').showTextForElement( 990 $('bubble').showTextForElement(
1009 $('supervised-user-creation-password'), 991 $('supervised-user-creation-password'), errorText,
1010 errorText, 992 cr.ui.Bubble.Attachment.RIGHT, 12, 4);
1011 cr.ui.Bubble.Attachment.RIGHT, 993 $('supervised-user-creation-password')
1012 12, 4); 994 .classList.add('password-error');
1013 $('supervised-user-creation-password').classList.add('password-error'); 995 $('supervised-user-creation-password').focus();
1014 $('supervised-user-creation-password').focus(); 996 this.disabled = false;
1015 this.disabled = false; 997 this.setButtonDisabledStatus('next', true);
1016 this.setButtonDisabledStatus('next', true); 998 },
1017 }, 999
1018 1000 /**
1019 /** 1001 * True if user name error should be displayed.
1020 * True if user name error should be displayed. 1002 * @type {boolean}
1021 * @type {boolean} 1003 */
1022 */ 1004 set nameErrorVisible(value) {
1023 set nameErrorVisible(value) { 1005 $('supervised-user-creation-name')
1024 $('supervised-user-creation-name'). 1006 .classList.toggle('duplicate-name', value);
1025 classList.toggle('duplicate-name', value); 1007 if (!value)
1026 if (!value) 1008 $('bubble').hide();
1027 $('bubble').hide(); 1009 },
1028 }, 1010
1029 1011 /**
1030 /** 1012 * Updates state of Continue button after minimal checks.
1031 * Updates state of Continue button after minimal checks. 1013 * @return {boolean} true, if form seems to be valid.
1032 * @return {boolean} true, if form seems to be valid. 1014 * @private
1033 * @private 1015 */
1034 */ 1016 updateNextButtonForManager_: function() {
1035 updateNextButtonForManager_: function() { 1017 var selectedPod = this.managerList_.selectedPod_;
1036 var selectedPod = this.managerList_.selectedPod_; 1018 canProceed = null != selectedPod &&
1037 canProceed = null != selectedPod && 1019 selectedPod.passwordElement.value.length > 0;
1038 selectedPod.passwordElement.value.length > 0; 1020
1039 1021 this.setButtonDisabledStatus('next', !canProceed);
1040 this.setButtonDisabledStatus('next', !canProceed); 1022 return canProceed;
1041 return canProceed; 1023 },
1042 }, 1024
1043 1025 /**
1044 /** 1026 * Updates state of Continue button after minimal checks.
1045 * Updates state of Continue button after minimal checks. 1027 * @return {boolean} true, if form seems to be valid.
1046 * @return {boolean} true, if form seems to be valid. 1028 * @private
1047 * @private 1029 */
1048 */ 1030 updateNextButtonForUser_: function() {
1049 updateNextButtonForUser_: function() { 1031 var firstPassword = this.getScreenElement('password').value;
1050 var firstPassword = this.getScreenElement('password').value; 1032 var secondPassword = this.getScreenElement('password-confirm').value;
1051 var secondPassword = this.getScreenElement('password-confirm').value; 1033 var userName = this.getScreenElement('name').value;
1052 var userName = this.getScreenElement('name').value; 1034
1053 1035 var passwordOk = (firstPassword.length > 0) &&
1054 var passwordOk = (firstPassword.length > 0) && 1036 (firstPassword.length == secondPassword.length);
1055 (firstPassword.length == secondPassword.length); 1037
1056 1038 if (this.currentPage_ == 'import-password') {
1057 if (this.currentPage_ == 'import-password') { 1039 this.setButtonDisabledStatus('import', !passwordOk);
1058 this.setButtonDisabledStatus('import', !passwordOk); 1040 return passwordOk;
1059 return passwordOk; 1041 }
1060 } 1042 var imageGrid = this.getScreenElement('image-grid');
1061 var imageGrid = this.getScreenElement('image-grid'); 1043 var imageChosen =
1062 var imageChosen = !(imageGrid.selectionType == 'camera' && 1044 !(imageGrid.selectionType == 'camera' && imageGrid.cameraLive);
1063 imageGrid.cameraLive); 1045 var canProceed = passwordOk && (userName.length > 0) &&
1064 var canProceed = 1046 this.lastVerifiedName_ && (userName == this.lastVerifiedName_) &&
1065 passwordOk && 1047 imageChosen;
1066 (userName.length > 0) && 1048
1067 this.lastVerifiedName_ && 1049 this.setButtonDisabledStatus('next', !canProceed);
1068 (userName == this.lastVerifiedName_) && 1050 return canProceed;
1069 imageChosen; 1051 },
1070 1052
1071 this.setButtonDisabledStatus('next', !canProceed); 1053 showSelectedManagerPasswordError_: function() {
1072 return canProceed; 1054 var selectedPod = this.managerList_.selectedPod_;
1073 }, 1055 selectedPod.showPasswordError();
1074 1056 selectedPod.passwordElement.value = '';
1075 showSelectedManagerPasswordError_: function() { 1057 selectedPod.focusInput();
1076 var selectedPod = this.managerList_.selectedPod_; 1058 this.updateNextButtonForManager_();
1077 selectedPod.showPasswordError(); 1059 },
1078 selectedPod.passwordElement.value = ''; 1060
1079 selectedPod.focusInput(); 1061 /**
1080 this.updateNextButtonForManager_(); 1062 * Enables one particular subpage and hides the rest.
1081 }, 1063 * @param {string} visiblePage - name of subpage.
1082 1064 * @private
1083 /** 1065 */
1084 * Enables one particular subpage and hides the rest. 1066 setVisiblePage_: function(visiblePage) {
1085 * @param {string} visiblePage - name of subpage. 1067 this.disabled = false;
1086 * @private 1068 this.updateText_();
1087 */ 1069 $('bubble').hide();
1088 setVisiblePage_: function(visiblePage) { 1070 if (!this.imagesRequested_) {
1089 this.disabled = false; 1071 chrome.send('supervisedUserGetImages');
1090 this.updateText_(); 1072 this.imagesRequested_ = true;
1091 $('bubble').hide(); 1073 }
1092 if (!this.imagesRequested_) { 1074 var pageNames =
1093 chrome.send('supervisedUserGetImages'); 1075 ['intro', 'manager', 'username', 'import', 'created', 'error'];
1094 this.imagesRequested_ = true; 1076 var pageButtons = {
1095 } 1077 'intro': 'start',
1096 var pageNames = ['intro', 1078 'error': 'error',
1097 'manager', 1079 'import': 'import',
1098 'username', 1080 'import-password': 'import',
1099 'import', 1081 'created': 'gotit'
1100 'created', 1082 };
1101 'error']; 1083 this.hideStatus_();
1102 var pageButtons = {'intro' : 'start', 1084 var pageToDisplay = visiblePage;
1103 'error' : 'error', 1085 if (visiblePage == 'import-password')
1104 'import' : 'import', 1086 pageToDisplay = 'username';
1105 'import-password' : 'import', 1087
1106 'created' : 'gotit'}; 1088 for (i in pageNames) {
1107 this.hideStatus_(); 1089 var pageName = pageNames[i];
1108 var pageToDisplay = visiblePage; 1090 var page = $('supervised-user-creation-' + pageName);
1109 if (visiblePage == 'import-password') 1091 page.hidden = (pageName != pageToDisplay);
1110 pageToDisplay = 'username'; 1092 if (pageName == pageToDisplay)
1111 1093 $('step-logo').hidden = page.classList.contains('step-no-logo');
1112 for (i in pageNames) { 1094 }
1113 var pageName = pageNames[i]; 1095
1114 var page = $('supervised-user-creation-' + pageName); 1096 for (i in this.buttonIds) {
1115 page.hidden = (pageName != pageToDisplay); 1097 var button = this.getScreenButton(this.buttonIds[i]);
1116 if (pageName == pageToDisplay) 1098 button.hidden = button.pages.indexOf(visiblePage) < 0;
1117 $('step-logo').hidden = page.classList.contains('step-no-logo'); 1099 button.disabled = false;
1118 } 1100 }
1119 1101
1120 for (i in this.buttonIds) { 1102 this.getScreenElement('import-link').hidden = true;
1121 var button = this.getScreenButton(this.buttonIds[i]); 1103 this.getScreenElement('create-link').hidden = true;
1122 button.hidden = button.pages.indexOf(visiblePage) < 0; 1104
1123 button.disabled = false; 1105 if (pageButtons[visiblePage])
1124 } 1106 this.getScreenButton(pageButtons[visiblePage]).focus();
1125 1107
1126 this.getScreenElement('import-link').hidden = true; 1108 this.currentPage_ = visiblePage;
1127 this.getScreenElement('create-link').hidden = true; 1109
1128 1110 if (visiblePage == 'manager' || visiblePage == 'intro') {
1129 if (pageButtons[visiblePage]) 1111 $('supervised-user-creation-password')
1130 this.getScreenButton(pageButtons[visiblePage]).focus(); 1112 .classList.remove('password-error');
1131 1113 if (this.managerList_.pods.length > 0)
1132 this.currentPage_ = visiblePage; 1114 this.managerList_.selectPod(this.managerList_.pods[0]);
1133 1115 $('login-header-bar').updateUI_();
1134 if (visiblePage == 'manager' || visiblePage == 'intro') { 1116 }
1135 $('supervised-user-creation-password').classList.remove( 1117
1136 'password-error'); 1118 if (visiblePage == 'username' || visiblePage == 'import-password') {
1137 if (this.managerList_.pods.length > 0) 1119 var elements = this.getScreenElement(pageToDisplay)
1138 this.managerList_.selectPod(this.managerList_.pods[0]); 1120 .querySelectorAll('.hide-on-import');
1139 $('login-header-bar').updateUI_(); 1121 for (var i = 0; i < elements.length; i++) {
1140 } 1122 elements[i].classList.toggle(
1141 1123 'hidden-on-import', visiblePage == 'import-password');
1142 if (visiblePage == 'username' || visiblePage == 'import-password') { 1124 }
1143 var elements = this.getScreenElement(pageToDisplay). 1125 }
1144 querySelectorAll('.hide-on-import'); 1126 if (visiblePage == 'username') {
1145 for (var i = 0; i < elements.length; i++) { 1127 var imageGrid = this.getScreenElement('image-grid');
1146 elements[i].classList.toggle('hidden-on-import', 1128 // select some image.
1147 visiblePage == 'import-password'); 1129 var selected = this.imagesData_[Math.floor(
1148 } 1130 Math.random() * this.imagesData_.length)];
1149 } 1131 this.context_.selectedImageUrl = selected.url;
1150 if (visiblePage == 'username') { 1132 imageGrid.selectedItemUrl = selected.url;
1151 var imageGrid = this.getScreenElement('image-grid'); 1133 chrome.send('supervisedUserSelectImage', [selected.url, 'default']);
1152 // select some image. 1134 this.getScreenElement('image-grid').redraw();
1153 var selected = this.imagesData_[ 1135 this.checkUserName_();
1154 Math.floor(Math.random() * this.imagesData_.length)]; 1136 this.updateNextButtonForUser_();
1155 this.context_.selectedImageUrl = selected.url; 1137 this.getScreenElement('name').focus();
1156 imageGrid.selectedItemUrl = selected.url; 1138 this.getScreenElement('import-link').hidden =
1157 chrome.send('supervisedUserSelectImage', 1139 this.importList_.pods.length == 0;
1158 [selected.url, 'default']); 1140 } else if (visiblePage == 'import-password') {
1159 this.getScreenElement('image-grid').redraw(); 1141 var imageGrid = this.getScreenElement('image-grid');
1160 this.checkUserName_(); 1142 var selected;
1161 this.updateNextButtonForUser_(); 1143 if ('selectedImageUrl' in this.context_) {
1162 this.getScreenElement('name').focus(); 1144 selected = this.context_.selectedImageUrl;
1163 this.getScreenElement('import-link').hidden = 1145 } else {
1164 this.importList_.pods.length == 0; 1146 // select some image.
1165 } else if (visiblePage == 'import-password') { 1147 selected =
1166 var imageGrid = this.getScreenElement('image-grid'); 1148 this.imagesData_[Math.floor(
1167 var selected; 1149 Math.random() * this.imagesData_.length)]
1168 if ('selectedImageUrl' in this.context_) { 1150 .url;
1169 selected = this.context_.selectedImageUrl; 1151 chrome.send('supervisedUserSelectImage', [selected, 'default']);
1170 } else { 1152 }
1171 // select some image. 1153 imageGrid.selectedItemUrl = selected;
1172 selected = this.imagesData_[ 1154 this.getScreenElement('image-grid').redraw();
1173 Math.floor(Math.random() * this.imagesData_.length)].url; 1155
1174 chrome.send('supervisedUserSelectImage', 1156 this.updateNextButtonForUser_();
1175 [selected, 'default']); 1157
1176 } 1158 this.getScreenElement('password').focus();
1177 imageGrid.selectedItemUrl = selected; 1159 this.getScreenElement('import-link').hidden = true;
1178 this.getScreenElement('image-grid').redraw(); 1160 } else {
1179 1161 this.getScreenElement('image-grid').stopCamera();
1180 this.updateNextButtonForUser_(); 1162 }
1181 1163 if (visiblePage == 'import') {
1182 this.getScreenElement('password').focus(); 1164 this.getScreenElement('create-link').hidden = false;
1183 this.getScreenElement('import-link').hidden = true; 1165 this.getScreenButton('import').disabled =
1184 } else { 1166 !this.importList_.selectedPod_ ||
1185 this.getScreenElement('image-grid').stopCamera(); 1167 this.importList_.selectedPod_.user.exists;
1186 } 1168 }
1187 if (visiblePage == 'import') { 1169 $('supervised-user-creation-navigation').closeVisible =
1188 this.getScreenElement('create-link').hidden = false; 1170 (visiblePage != 'created');
1189 this.getScreenButton('import').disabled = 1171
1190 !this.importList_.selectedPod_ || 1172 chrome.send('currentSupervisedUserPage', [this.currentPage_]);
1191 this.importList_.selectedPod_.user.exists; 1173 },
1192 } 1174
1193 $('supervised-user-creation-navigation').closeVisible = 1175 setButtonDisabledStatus: function(buttonName, status) {
1194 (visiblePage != 'created'); 1176 var button = $('supervised-user-creation-' + buttonName + '-button');
1195 1177 button.disabled = status;
1196 chrome.send('currentSupervisedUserPage', [this.currentPage_]); 1178 },
1197 }, 1179
1198 1180 gotItButtonPressed_: function() {
1199 setButtonDisabledStatus: function(buttonName, status) { 1181 chrome.send('finishLocalSupervisedUserCreation');
1200 var button = $('supervised-user-creation-' + buttonName + '-button'); 1182 },
1201 button.disabled = status; 1183
1202 }, 1184 handleErrorButtonPressed_: function() {
1203 1185 chrome.send('abortLocalSupervisedUserCreation');
1204 gotItButtonPressed_: function() { 1186 },
1205 chrome.send('finishLocalSupervisedUserCreation'); 1187
1206 }, 1188 startButtonPressed_: function() {
1207 1189 this.setVisiblePage_('manager');
1208 handleErrorButtonPressed_: function() { 1190 this.setButtonDisabledStatus('next', true);
1209 chrome.send('abortLocalSupervisedUserCreation'); 1191 },
1210 }, 1192
1211 1193 nextButtonPressed_: function() {
1212 startButtonPressed_: function() { 1194 if (this.currentPage_ == 'manager') {
1213 this.setVisiblePage_('manager'); 1195 this.validateAndLogInAsManager_();
1214 this.setButtonDisabledStatus('next', true); 1196 return;
1215 }, 1197 }
1216 1198 if (this.currentPage_ == 'username') {
1217 nextButtonPressed_: function() { 1199 this.validateAndCreateSupervisedUser_();
1218 if (this.currentPage_ == 'manager') { 1200 }
1219 this.validateAndLogInAsManager_(); 1201 },
1220 return; 1202
1221 } 1203 importButtonPressed_: function() {
1222 if (this.currentPage_ == 'username') { 1204 this.importSupervisedUser_();
1223 this.validateAndCreateSupervisedUser_(); 1205 },
1224 } 1206
1225 }, 1207 importLinkPressed_: function() {
1226 1208 this.setVisiblePage_('import');
1227 importButtonPressed_: function() { 1209 },
1228 this.importSupervisedUser_(); 1210
1229 }, 1211 handleSuggestImport_: function(user_id) {
1230 1212 this.setVisiblePage_('import');
1231 importLinkPressed_: function() { 1213 this.importList_.selectUser(user_id);
1232 this.setVisiblePage_('import'); 1214 },
1233 }, 1215
1234 1216 createLinkPressed_: function() {
1235 handleSuggestImport_: function(user_id) { 1217 this.setVisiblePage_('username');
1236 this.setVisiblePage_('import'); 1218 this.lastIncorrectUserName_ = null;
1237 this.importList_.selectUser(user_id); 1219 this.lastVerifiedName_ = null;
1238 }, 1220 this.checkUserName_();
1239 1221 },
1240 createLinkPressed_: function() { 1222
1241 this.setVisiblePage_('username'); 1223 prevButtonPressed_: function() {
1242 this.lastIncorrectUserName_ = null; 1224 this.setVisiblePage_('intro');
1243 this.lastVerifiedName_ = null; 1225 },
1244 this.checkUserName_(); 1226
1245 }, 1227 showProgress: function(text) {
1246 1228 var status = this.getScreenElement('status');
1247 prevButtonPressed_: function() { 1229 var statusText = status.querySelector('.id-text');
1248 this.setVisiblePage_('intro'); 1230 statusText.textContent = text;
1249 }, 1231 statusText.classList.remove('error');
1250 1232 status.querySelector('.id-spinner').hidden = false;
1251 showProgress: function(text) { 1233 status.hidden = false;
1252 var status = this.getScreenElement('status'); 1234 this.getScreenElement('import-link').hidden = true;
1253 var statusText = status.querySelector('.id-text'); 1235 this.getScreenElement('create-link').hidden = true;
1254 statusText.textContent = text; 1236 },
1255 statusText.classList.remove('error'); 1237
1256 status.querySelector('.id-spinner').hidden = false; 1238 showStatusError: function(text) {
1257 status.hidden = false; 1239 var status = this.getScreenElement('status');
1258 this.getScreenElement('import-link').hidden = true; 1240 var statusText = status.querySelector('.id-text');
1259 this.getScreenElement('create-link').hidden = true; 1241 statusText.textContent = text;
1260 }, 1242 statusText.classList.add('error');
1261 1243 status.querySelector('.id-spinner').hidden = true;
1262 showStatusError: function(text) { 1244 status.hidden = false;
1263 var status = this.getScreenElement('status'); 1245 this.getScreenElement('import-link').hidden = true;
1264 var statusText = status.querySelector('.id-text'); 1246 this.getScreenElement('create-link').hidden = true;
1265 statusText.textContent = text; 1247 },
1266 statusText.classList.add('error'); 1248
1267 status.querySelector('.id-spinner').hidden = true; 1249 hideStatus_: function() {
1268 status.hidden = false; 1250 var status = this.getScreenElement('status');
1269 this.getScreenElement('import-link').hidden = true; 1251 status.hidden = true;
1270 this.getScreenElement('create-link').hidden = true; 1252 },
1271 }, 1253
1272 1254 /**
1273 hideStatus_: function() { 1255 * Updates state of login header so that necessary buttons are
1274 var status = this.getScreenElement('status'); 1256 * displayed.
1275 status.hidden = true; 1257 */
1276 }, 1258 onBeforeShow: function(data) {
1277 1259 $('login-header-bar').signinUIState =
1278 /** 1260 SIGNIN_UI_STATE.SUPERVISED_USER_CREATION_FLOW;
1279 * Updates state of login header so that necessary buttons are displayed. 1261 if (data['managers']) {
1280 */ 1262 this.loadManagers(data['managers']);
1281 onBeforeShow: function(data) { 1263 }
1282 $('login-header-bar').signinUIState = 1264 var imageGrid = this.getScreenElement('image-grid');
1283 SIGNIN_UI_STATE.SUPERVISED_USER_CREATION_FLOW; 1265 imageGrid.updateAndFocus();
1284 if (data['managers']) { 1266 },
1285 this.loadManagers(data['managers']); 1267
1286 } 1268 /**
1287 var imageGrid = this.getScreenElement('image-grid'); 1269 * Update state of login header so that necessary buttons are displayed.
1288 imageGrid.updateAndFocus(); 1270 */
1289 }, 1271 onBeforeHide: function() {
1290 1272 $('login-header-bar').signinUIState = SIGNIN_UI_STATE.HIDDEN;
1291 /** 1273 this.getScreenElement('image-grid').stopCamera();
1292 * Update state of login header so that necessary buttons are displayed. 1274 },
1293 */ 1275
1294 onBeforeHide: function() { 1276 /**
1295 $('login-header-bar').signinUIState = SIGNIN_UI_STATE.HIDDEN; 1277 * Returns a control which should receive an initial focus.
1296 this.getScreenElement('image-grid').stopCamera(); 1278 */
1297 }, 1279 get defaultControl() {
1298 1280 return $('supervised-user-creation-name');
1299 /** 1281 },
1300 * Returns a control which should receive an initial focus. 1282
1301 */ 1283 /**
1302 get defaultControl() { 1284 * True if the the screen is disabled (handles no user interaction).
1303 return $('supervised-user-creation-name'); 1285 * @type {boolean}
1304 }, 1286 */
1305 1287 disabled_: false,
1306 /** 1288
1307 * True if the the screen is disabled (handles no user interaction). 1289 get disabled() {
1308 * @type {boolean} 1290 return this.disabled_;
1309 */ 1291 },
1310 disabled_: false, 1292
1311 1293 set disabled(value) {
1312 get disabled() { 1294 this.disabled_ = value;
1313 return this.disabled_; 1295 var controls = this.querySelectorAll('button,input');
1314 }, 1296 for (var i = 0, control; control = controls[i]; ++i) {
1315 1297 control.disabled = value;
1316 set disabled(value) { 1298 }
1317 this.disabled_ = value; 1299 $('login-header-bar').disabled = value;
1318 var controls = this.querySelectorAll('button,input'); 1300 },
1319 for (var i = 0, control; control = controls[i]; ++i) { 1301
1320 control.disabled = value; 1302 /**
1321 } 1303 * Called by backend part to propagate list of possible managers.
1322 $('login-header-bar').disabled = value; 1304 * @param {Array} userList - list of users that can be managers.
1323 }, 1305 */
1324 1306 loadManagers: function(userList) {
1325 /** 1307 $('supervised-user-creation-managers-block').hidden = false;
1326 * Called by backend part to propagate list of possible managers. 1308 this.managerList_.clearPods();
1327 * @param {Array} userList - list of users that can be managers. 1309 for (var i = 0; i < userList.length; ++i)
1328 */ 1310 this.managerList_.addPod(userList[i]);
1329 loadManagers: function(userList) { 1311 if (userList.length > 0)
1330 $('supervised-user-creation-managers-block').hidden = false; 1312 this.managerList_.selectPod(this.managerList_.pods[0]);
1331 this.managerList_.clearPods(); 1313 },
1332 for (var i = 0; i < userList.length; ++i) 1314
1333 this.managerList_.addPod(userList[i]); 1315 /**
1334 if (userList.length > 0) 1316 * Cancels user creation and drops to user screen (either sign).
1335 this.managerList_.selectPod(this.managerList_.pods[0]); 1317 */
1336 }, 1318 cancel: function() {
1337 1319 var notSignedInPages = ['intro', 'manager'];
1338 /** 1320 var postCreationPages = ['created'];
1339 * Cancels user creation and drops to user screen (either sign). 1321 if (notSignedInPages.indexOf(this.currentPage_) >= 0) {
1340 */ 1322 chrome.send('hideLocalSupervisedUserCreation');
1341 cancel: function() { 1323
1342 var notSignedInPages = ['intro', 'manager']; 1324 // Make sure no manager password is kept:
1343 var postCreationPages = ['created']; 1325 this.managerList_.clearPods();
1344 if (notSignedInPages.indexOf(this.currentPage_) >= 0) { 1326
1345 chrome.send('hideLocalSupervisedUserCreation'); 1327 Oobe.showUserPods();
1346 1328 return;
1347 // Make sure no manager password is kept: 1329 }
1348 this.managerList_.clearPods(); 1330 if (postCreationPages.indexOf(this.currentPage_) >= 0) {
1349 1331 chrome.send('finishLocalSupervisedUserCreation');
1350 Oobe.showUserPods(); 1332 return;
1351 return; 1333 }
1352 } 1334 chrome.send('abortLocalSupervisedUserCreation');
1353 if (postCreationPages.indexOf(this.currentPage_) >= 0) { 1335 },
1354 chrome.send('finishLocalSupervisedUserCreation'); 1336
1355 return; 1337 updateText_: function() {
1356 } 1338 var managerDisplayId = this.context_.managerDisplayId;
1357 chrome.send('abortLocalSupervisedUserCreation'); 1339 this.updateElementText_(
1358 }, 1340 'intro-alternate-text', 'createSupervisedUserIntroAlternateText');
1359 1341 this.updateElementText_(
1360 updateText_: function() { 1342 'created-text-1', 'createSupervisedUserCreatedText1',
1361 var managerDisplayId = this.context_.managerDisplayId; 1343 this.context_.supervisedName);
1362 this.updateElementText_('intro-alternate-text', 1344 // TODO(antrim): Move wrapping with strong in grd file, and eliminate
1363 'createSupervisedUserIntroAlternateText'); 1345 // this
1364 this.updateElementText_('created-text-1', 1346 // call.
1365 'createSupervisedUserCreatedText1', 1347 this.updateElementText_(
1366 this.context_.supervisedName); 1348 'created-text-2', 'createSupervisedUserCreatedText2',
1367 // TODO(antrim): Move wrapping with strong in grd file, and eliminate this 1349 this.wrapStrong(loadTimeData.getString('managementURL')),
1368 //call. 1350 this.context_.supervisedName);
1369 this.updateElementText_('created-text-2', 1351 this.updateElementText_(
1370 'createSupervisedUserCreatedText2', 1352 'created-text-3', 'createSupervisedUserCreatedText3',
1371 this.wrapStrong( 1353 managerDisplayId);
1372 loadTimeData.getString('managementURL')), 1354 this.updateElementText_(
1373 this.context_.supervisedName); 1355 'name-explanation', 'createSupervisedUserNameExplanation',
1374 this.updateElementText_('created-text-3', 1356 managerDisplayId);
1375 'createSupervisedUserCreatedText3', 1357 },
1376 managerDisplayId); 1358
1377 this.updateElementText_('name-explanation', 1359 wrapStrong: function(original) {
1378 'createSupervisedUserNameExplanation', 1360 if (original == undefined)
1379 managerDisplayId); 1361 return original;
1380 }, 1362 return '<strong>' + original + '</strong>';
1381 1363 },
1382 wrapStrong: function(original) { 1364
1383 if (original == undefined) 1365 updateElementText_: function(localId, templateName) {
1384 return original; 1366 var args = Array.prototype.slice.call(arguments);
1385 return '<strong>' + original + '</strong>'; 1367 args.shift();
1386 }, 1368 this.getScreenElement(localId).innerHTML =
1387 1369 loadTimeData.getStringF.apply(loadTimeData, args);
1388 updateElementText_: function(localId, templateName) { 1370 },
1389 var args = Array.prototype.slice.call(arguments); 1371
1390 args.shift(); 1372 showIntroPage: function() {
1391 this.getScreenElement(localId).innerHTML = 1373 $('supervised-user-creation-password').value = '';
1392 loadTimeData.getStringF.apply(loadTimeData, args); 1374 $('supervised-user-creation-password-confirm').value = '';
1393 }, 1375 $('supervised-user-creation-name').value = '';
1394 1376
1395 showIntroPage: function() { 1377 this.lastVerifiedName_ = null;
1396 $('supervised-user-creation-password').value = ''; 1378 this.lastIncorrectUserName_ = null;
1397 $('supervised-user-creation-password-confirm').value = ''; 1379 this.passwordErrorVisible = false;
1398 $('supervised-user-creation-name').value = ''; 1380 $('supervised-user-creation-password')
1399 1381 .classList.remove('password-error');
1400 this.lastVerifiedName_ = null; 1382 this.nameErrorVisible = false;
1401 this.lastIncorrectUserName_ = null; 1383
1402 this.passwordErrorVisible = false; 1384 this.setVisiblePage_('intro');
1403 $('supervised-user-creation-password').classList.remove('password-error'); 1385 },
1404 this.nameErrorVisible = false; 1386
1405 1387 showManagerPage: function() {
1406 this.setVisiblePage_('intro'); 1388 this.setVisiblePage_('manager');
1407 }, 1389 },
1408 1390
1409 showManagerPage: function() { 1391 showUsernamePage: function() {
1410 this.setVisiblePage_('manager'); 1392 this.setVisiblePage_('username');
1411 }, 1393 },
1412 1394
1413 showUsernamePage: function() { 1395 showTutorialPage: function() {
1414 this.setVisiblePage_('username'); 1396 this.setVisiblePage_('created');
1415 }, 1397 },
1416 1398
1417 showTutorialPage: function() { 1399 showPage: function(page) {
1418 this.setVisiblePage_('created'); 1400 this.setVisiblePage_(page);
1419 }, 1401 },
1420 1402
1421 showPage: function(page) { 1403 showErrorPage: function(errorTitle, errorText, errorButtonText) {
1422 this.setVisiblePage_(page); 1404 this.disabled = false;
1423 }, 1405 $('supervised-user-creation-error-title').innerHTML = errorTitle;
1424 1406 $('supervised-user-creation-error-text').innerHTML = errorText;
1425 showErrorPage: function(errorTitle, errorText, errorButtonText) { 1407 $('supervised-user-creation-error-button').textContent =
1426 this.disabled = false; 1408 errorButtonText;
1427 $('supervised-user-creation-error-title').innerHTML = errorTitle; 1409 this.setVisiblePage_('error');
1428 $('supervised-user-creation-error-text').innerHTML = errorText; 1410 },
1429 $('supervised-user-creation-error-button').textContent = errorButtonText; 1411
1430 this.setVisiblePage_('error'); 1412 showManagerPasswordError: function() {
1431 }, 1413 this.disabled = false;
1432 1414 this.showSelectedManagerPasswordError_();
1433 showManagerPasswordError: function() { 1415 },
1434 this.disabled = false; 1416
1435 this.showSelectedManagerPasswordError_(); 1417 /*
1436 }, 1418 TODO(antrim) : this is an explicit code duplications with
1437 1419 UserImageScreen. It should be removed by issue 251179.
1438 /* 1420 */
1439 TODO(antrim) : this is an explicit code duplications with UserImageScreen. 1421 /**
1440 It should be removed by issue 251179. 1422 * Currently selected user image index (take photo button is with zero
1441 */ 1423 * index).
1442 /** 1424 * @type {number}
1443 * Currently selected user image index (take photo button is with zero 1425 */
1444 * index). 1426 selectedUserImage_: -1,
1445 * @type {number} 1427 imagesData: [],
1446 */ 1428
1447 selectedUserImage_: -1, 1429 setDefaultImages: function(imagesData) {
1448 imagesData: [], 1430 var imageGrid = this.getScreenElement('image-grid');
1449 1431 imageGrid.setDefaultImages(imagesData);
1450 setDefaultImages: function(imagesData) { 1432 this.imagesData_ = imagesData;
1451 var imageGrid = this.getScreenElement('image-grid'); 1433 },
1452 imageGrid.setDefaultImages(imagesData); 1434
1453 this.imagesData_ = imagesData; 1435
1454 }, 1436 handleActivate_: function() {
1455 1437 var imageGrid = this.getScreenElement('image-grid');
1456 1438 if (imageGrid.selectedItemUrl == ButtonImages.TAKE_PHOTO) {
1457 handleActivate_: function() { 1439 this.handleTakePhoto_();
1458 var imageGrid = this.getScreenElement('image-grid'); 1440 return;
1459 if (imageGrid.selectedItemUrl == ButtonImages.TAKE_PHOTO) { 1441 }
1460 this.handleTakePhoto_(); 1442 this.nextButtonPressed_();
1461 return; 1443 },
1462 } 1444
1463 this.nextButtonPressed_(); 1445 /**
1464 }, 1446 * Handles selection change.
1465 1447 * @param {Event} e Selection change event.
1466 /** 1448 * @private
1467 * Handles selection change. 1449 */
1468 * @param {Event} e Selection change event. 1450 handleSelect_: function(e) {
1469 * @private 1451 var imageGrid = this.getScreenElement('image-grid');
1470 */ 1452 this.updateNextButtonForUser_();
1471 handleSelect_: function(e) { 1453
1472 var imageGrid = this.getScreenElement('image-grid'); 1454 $('supervised-user-creation-flip-photo').tabIndex =
1473 this.updateNextButtonForUser_(); 1455 (imageGrid.selectionType == 'camera') ? 0 : -1;
1474 1456 if (imageGrid.cameraLive || imageGrid.selectionType != 'camera')
1475 $('supervised-user-creation-flip-photo').tabIndex = 1457 imageGrid.previewElement.classList.remove('phototaken');
1476 (imageGrid.selectionType == 'camera') ? 0 : -1; 1458 else
1477 if (imageGrid.cameraLive || imageGrid.selectionType != 'camera') 1459 imageGrid.previewElement.classList.add('phototaken');
1478 imageGrid.previewElement.classList.remove('phototaken'); 1460
1479 else 1461 if (!imageGrid.cameraLive || imageGrid.selectionType != 'camera') {
1480 imageGrid.previewElement.classList.add('phototaken'); 1462 this.context_.selectedImageUrl = imageGrid.selectedItemUrl;
1481 1463 chrome.send(
1482 if (!imageGrid.cameraLive || imageGrid.selectionType != 'camera') { 1464 'supervisedUserSelectImage',
1483 this.context_.selectedImageUrl = imageGrid.selectedItemUrl; 1465 [imageGrid.selectedItemUrl, imageGrid.selectionType]);
1484 chrome.send('supervisedUserSelectImage', 1466 }
1485 [imageGrid.selectedItemUrl, imageGrid.selectionType]); 1467 // Start/stop camera on (de)selection.
1486 } 1468 if (!imageGrid.inProgramSelection &&
1487 // Start/stop camera on (de)selection. 1469 imageGrid.selectionType != e.oldSelectionType) {
1488 if (!imageGrid.inProgramSelection && 1470 if (imageGrid.selectionType == 'camera') {
1489 imageGrid.selectionType != e.oldSelectionType) { 1471 // Programmatic selection of camera item is done in
1490 if (imageGrid.selectionType == 'camera') { 1472 // startCamera callback where streaming is started by itself.
1491 // Programmatic selection of camera item is done in 1473 imageGrid.startCamera(function() {
1492 // startCamera callback where streaming is started by itself.
1493 imageGrid.startCamera(
1494 function() {
1495 // Start capture if camera is still the selected item. 1474 // Start capture if camera is still the selected item.
1496 $('supervised-user-creation-image-preview-img').classList. 1475 $('supervised-user-creation-image-preview-img')
1497 toggle('animated-transform', true); 1476 .classList.toggle('animated-transform', true);
1498 return imageGrid.selectedItem == imageGrid.cameraImage; 1477 return imageGrid.selectedItem == imageGrid.cameraImage;
1499 }); 1478 });
1500 } else { 1479 } else {
1501 $('supervised-user-creation-image-preview-img').classList.toggle( 1480 $('supervised-user-creation-image-preview-img')
1502 'animated-transform', false); 1481 .classList.toggle('animated-transform', false);
1503 imageGrid.stopCamera(); 1482 imageGrid.stopCamera();
1504 } 1483 }
1505 } 1484 }
1506 }, 1485 },
1507 1486
1508 /** 1487 /**
1509 * Handle camera-photo flip. 1488 * Handle camera-photo flip.
1510 */ 1489 */
1511 handleFlipPhoto_: function() { 1490 handleFlipPhoto_: function() {
1512 var imageGrid = this.getScreenElement('image-grid'); 1491 var imageGrid = this.getScreenElement('image-grid');
1513 imageGrid.previewElement.classList.add('animation'); 1492 imageGrid.previewElement.classList.add('animation');
1514 imageGrid.flipPhoto = !imageGrid.flipPhoto; 1493 imageGrid.flipPhoto = !imageGrid.flipPhoto;
1515 var flipMessageId = imageGrid.flipPhoto ? 1494 var flipMessageId = imageGrid.flipPhoto ?
1516 'photoFlippedAccessibleText' : 'photoFlippedBackAccessibleText'; 1495 'photoFlippedAccessibleText' :
1517 announceAccessibleMessage(loadTimeData.getString(flipMessageId)); 1496 'photoFlippedBackAccessibleText';
1518 }, 1497 announceAccessibleMessage(loadTimeData.getString(flipMessageId));
1519 1498 },
1520 /** 1499
1521 * Handle photo capture from the live camera stream. 1500 /**
1522 */ 1501 * Handle photo capture from the live camera stream.
1523 handleTakePhoto_: function(e) { 1502 */
1524 this.getScreenElement('image-grid').takePhoto(); 1503 handleTakePhoto_: function(e) {
1525 chrome.send('supervisedUserTakePhoto'); 1504 this.getScreenElement('image-grid').takePhoto();
1526 }, 1505 chrome.send('supervisedUserTakePhoto');
1527 1506 },
1528 handlePhotoTaken_: function(e) { 1507
1529 chrome.send('supervisedUserPhotoTaken', [e.dataURL]); 1508 handlePhotoTaken_: function(e) {
1530 announceAccessibleMessage( 1509 chrome.send('supervisedUserPhotoTaken', [e.dataURL]);
1531 loadTimeData.getString('photoCaptureAccessibleText')); 1510 announceAccessibleMessage(
1532 }, 1511 loadTimeData.getString('photoCaptureAccessibleText'));
1533 1512 },
1534 /** 1513
1535 * Handle photo updated event. 1514 /**
1536 * @param {Event} e Event with 'dataURL' property containing a data URL. 1515 * Handle photo updated event.
1537 */ 1516 * @param {Event} e Event with 'dataURL' property containing a data URL.
1538 handlePhotoUpdated_: function(e) { 1517 */
1539 chrome.send('supervisedUserPhotoTaken', [e.dataURL]); 1518 handlePhotoUpdated_: function(e) {
1540 }, 1519 chrome.send('supervisedUserPhotoTaken', [e.dataURL]);
1541 1520 },
1542 /** 1521
1543 * Handle discarding the captured photo. 1522 /**
1544 */ 1523 * Handle discarding the captured photo.
1545 handleDiscardPhoto_: function(e) { 1524 */
1546 var imageGrid = this.getScreenElement('image-grid'); 1525 handleDiscardPhoto_: function(e) {
1547 imageGrid.discardPhoto(); 1526 var imageGrid = this.getScreenElement('image-grid');
1548 chrome.send('supervisedUserDiscardPhoto'); 1527 imageGrid.discardPhoto();
1549 announceAccessibleMessage( 1528 chrome.send('supervisedUserDiscardPhoto');
1550 loadTimeData.getString('photoDiscardAccessibleText')); 1529 announceAccessibleMessage(
1551 }, 1530 loadTimeData.getString('photoDiscardAccessibleText'));
1552 1531 },
1553 setCameraPresent: function(present) { 1532
1554 this.getScreenElement('image-grid').cameraPresent = present; 1533 setCameraPresent: function(present) {
1555 }, 1534 this.getScreenElement('image-grid').cameraPresent = present;
1556 1535 },
1557 setExistingSupervisedUsers: function(users) { 1536
1558 var selectedUser = null; 1537 setExistingSupervisedUsers: function(users) {
1559 // Store selected user 1538 var selectedUser = null;
1560 if (this.importList_.selectedPod) 1539 // Store selected user
1561 selectedUser = this.importList_.selectedPod.user.id; 1540 if (this.importList_.selectedPod)
1562 1541 selectedUser = this.importList_.selectedPod.user.id;
1563 var userList = users; 1542
1564 userList.sort(function(a, b) { 1543 var userList = users;
1565 // Put existing users last. 1544 userList.sort(function(a, b) {
1566 if (a.exists != b.exists) 1545 // Put existing users last.
1567 return a.exists ? 1 : -1; 1546 if (a.exists != b.exists)
1568 // Sort rest by name. 1547 return a.exists ? 1 : -1;
1569 return a.name.localeCompare(b.name, [], {sensitivity: 'base'}); 1548 // Sort rest by name.
1570 }); 1549 return a.name.localeCompare(b.name, [], {sensitivity: 'base'});
1571 1550 });
1572 this.importList_.clearPods(); 1551
1573 var selectedIndex = -1; 1552 this.importList_.clearPods();
1574 for (var i = 0; i < userList.length; ++i) { 1553 var selectedIndex = -1;
1575 this.importList_.addPod(userList[i]); 1554 for (var i = 0; i < userList.length; ++i) {
1576 if (selectedUser == userList[i].id) 1555 this.importList_.addPod(userList[i]);
1577 selectedIndex = i; 1556 if (selectedUser == userList[i].id)
1578 } 1557 selectedIndex = i;
1579 1558 }
1580 if (userList.length == 1) 1559
1581 this.importList_.selectPod(this.importList_.pods[0]); 1560 if (userList.length == 1)
1582 1561 this.importList_.selectPod(this.importList_.pods[0]);
1583 if (selectedIndex >= 0) 1562
1584 this.importList_.selectPod(this.importList_.pods[selectedIndex]); 1563 if (selectedIndex >= 0)
1585 1564 this.importList_.selectPod(this.importList_.pods[selectedIndex]);
1586 if (this.currentPage_ == 'username') 1565
1587 this.getScreenElement('import-link').hidden = (userList.length == 0); 1566 if (this.currentPage_ == 'username')
1588 }, 1567 this.getScreenElement('import-link').hidden =
1589 }; 1568 (userList.length == 0);
1590 }); 1569 },
1591 1570 };
1571 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698