OLD | NEW |
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 Base class for all login WebUI screens. | 6 * @fileoverview Base class for all login WebUI screens. |
7 */ | 7 */ |
8 cr.define('login', function() { | 8 cr.define('login', function() { |
9 var Screen = cr.ui.define('div'); | 9 var Screen = cr.ui.define('div'); |
10 | 10 |
| 11 /** @const */ var CALLBACK_USER_ACTED = 'userActed'; |
| 12 /** @const */ var CALLBACK_CONTEXT_CHANGED = 'contextChanged'; |
| 13 |
11 function doNothing() {}; | 14 function doNothing() {}; |
12 | 15 |
| 16 var querySelectorAll = HTMLDivElement.prototype.querySelectorAll; |
| 17 |
13 Screen.prototype = { | 18 Screen.prototype = { |
14 __proto__: HTMLDivElement.prototype, | 19 __proto__: HTMLDivElement.prototype, |
15 | 20 |
| 21 /** |
| 22 * Prefix added to sent to Chrome messages' names. |
| 23 */ |
| 24 sendPrefix_: '', |
| 25 |
| 26 /** |
| 27 * Context used by this screen. |
| 28 */ |
| 29 context_: null, |
| 30 |
| 31 /** |
| 32 * Dictionary of context observers that are methods of |this| bound to |
| 33 * |this|. |
| 34 */ |
| 35 contextObservers_: {}, |
| 36 |
| 37 get context() { |
| 38 return this.context_; |
| 39 }, |
| 40 |
| 41 /** |
| 42 * Sends recent context changes to C++ handler. |
| 43 */ |
| 44 commitContextChanges: function() { |
| 45 if (!this.context_.hasChanges()) |
| 46 return; |
| 47 this.send(CALLBACK_CONTEXT_CHANGED, this.context_.getChangesAndReset()); |
| 48 }, |
| 49 |
| 50 /** |
| 51 * Sends message to Chrome, adding needed prefix to message name. All |
| 52 * arguments after |messageName| are packed into message parameters list. |
| 53 * |
| 54 * @param {string} messageName Name of message without a prefix. |
| 55 * @param {...*} varArgs parameters for message. |
| 56 */ |
| 57 send: function(messageName, varArgs) { |
| 58 if (arguments.length == 0) |
| 59 throw Error('Message name is not provided.'); |
| 60 var fullMessageName = this.sendPrefix_ + messageName; |
| 61 var payload = Array.prototype.slice.call(arguments, 1); |
| 62 chrome.send(fullMessageName, payload); |
| 63 }, |
| 64 |
16 decorate: doNothing, | 65 decorate: doNothing, |
17 | 66 |
18 /** | 67 /** |
19 * Returns minimal size that screen prefers to have. Default implementation | 68 * Returns minimal size that screen prefers to have. Default implementation |
20 * returns current screen size. | 69 * returns current screen size. |
21 * @return {{width: number, height: number}} | 70 * @return {{width: number, height: number}} |
22 */ | 71 */ |
23 getPreferredSize: function() { | 72 getPreferredSize: function() { |
24 return {width: this.offsetWidth, height: this.offsetHeight}; | 73 return {width: this.offsetWidth, height: this.offsetHeight}; |
25 }, | 74 }, |
26 | 75 |
27 /** | 76 /** |
28 * Called for currently active screen when screen size changed. | 77 * Called for currently active screen when screen size changed. |
29 */ | 78 */ |
30 onWindowResize: doNothing, | 79 onWindowResize: doNothing, |
| 80 |
| 81 /** |
| 82 * Does the following things: |
| 83 * * Creates screen context. |
| 84 * * Looks for elements having "alias" property and adds them as the |
| 85 * proprties of the screen with name equal to value of "alias", i.e. HTML |
| 86 * element <div alias="myDiv"></div> will be stored in this.myDiv. |
| 87 * * Looks for buttons having "action" properties and adds click handlers |
| 88 * to them. These handlers send |CALLBACK_USER_ACTED| messages to |
| 89 * C++ with "action" property's value as payload. |
| 90 */ |
| 91 initialize: function() { |
| 92 this.context_ = new login.ScreenContext(); |
| 93 this.querySelectorAll('[alias]').forEach(function(element) { |
| 94 this[element.getAttribute('alias')] = element; |
| 95 }, this); |
| 96 var self = this; |
| 97 this.querySelectorAll('button[action]').forEach(function(button) { |
| 98 button.addEventListener('click', function(e) { |
| 99 var action = this.getAttribute('action'); |
| 100 self.send(CALLBACK_USER_ACTED, action); |
| 101 e.stopPropagation(); |
| 102 }); |
| 103 }); |
| 104 }, |
| 105 |
| 106 /** |
| 107 * Starts observation of property with |key| of the context attached to |
| 108 * current screen. This method differs from "login.ScreenContext" in that |
| 109 * it automatically detects if observer is method of |this| and make |
| 110 * all needed actions to make it work correctly. So it's no need for client |
| 111 * to bind methods to |this| and keep resulting callback for |
| 112 * |removeObserver| call: |
| 113 * |
| 114 * this.addContextObserver('key', this.onKeyChanged_); |
| 115 * ... |
| 116 * this.removeContextObserver('key', this.onKeyChanged_); |
| 117 */ |
| 118 addContextObserver: function(key, observer) { |
| 119 var realObserver = observer; |
| 120 var propertyName = this.getPropertyNameOf_(observer); |
| 121 if (propertyName) { |
| 122 if (!this.contextObservers_.hasOwnProperty(propertyName)) |
| 123 this.contextObservers_[propertyName] = observer.bind(this); |
| 124 realObserver = this.contextObservers_[propertyName]; |
| 125 } |
| 126 this.context.addObserver(key, realObserver); |
| 127 }, |
| 128 |
| 129 /** |
| 130 * Removes |observer| from the list of context observers. Supports not only |
| 131 * regular functions but also screen methods (see comment to |
| 132 * |addContextObserver|). |
| 133 */ |
| 134 removeContextObserver: function(observer) { |
| 135 var realObserver = observer; |
| 136 var propertyName = this.getPropertyNameOf_(observer); |
| 137 if (propertyName) { |
| 138 if (!this.contextObservers_.hasOwnProperty(propertyName)) |
| 139 return; |
| 140 realObserver = this.contextObservers_[propertyName]; |
| 141 delete this.contextObservers_[propertyName]; |
| 142 } |
| 143 this.context.removeObserver(realObserver); |
| 144 }, |
| 145 |
| 146 /** |
| 147 * Calls standart |querySelectorAll| method and returns its result converted |
| 148 * to Array. |
| 149 */ |
| 150 querySelectorAll: function(selector) { |
| 151 var list = querySelectorAll.call(this, selector); |
| 152 return Array.prototype.slice.call(list); |
| 153 }, |
| 154 |
| 155 /** |
| 156 * Called when context changes are recieved from C++. |
| 157 * @private |
| 158 */ |
| 159 contextChanged_: function(diff) { |
| 160 this.context.applyChanges(diff); |
| 161 }, |
| 162 |
| 163 /** |
| 164 * If |value| is the value of some property of |this| returns property's |
| 165 * name. Otherwise returns empty string. |
| 166 * @private |
| 167 */ |
| 168 getPropertyNameOf_: function(value) { |
| 169 for (var key in this) |
| 170 if (this[key] === value) |
| 171 return key; |
| 172 return ''; |
| 173 } |
31 }; | 174 }; |
32 | 175 |
| 176 Screen.CALLBACK_USER_ACTED = CALLBACK_USER_ACTED; |
| 177 |
33 return { | 178 return { |
34 Screen: Screen | 179 Screen: Screen |
35 }; | 180 }; |
36 }); | 181 }); |
37 | 182 |
38 cr.define('login', function() { | 183 cr.define('login', function() { |
39 return { | 184 return { |
40 /** | 185 /** |
41 * Creates class and object for screen. | 186 * Creates class and object for screen. |
42 * Methods specified in EXTERNAL_API array of prototype | 187 * Methods specified in EXTERNAL_API array of prototype |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 propertyName, descriptor); | 225 propertyName, descriptor); |
81 if (api.indexOf(propertyName) >= 0) { | 226 if (api.indexOf(propertyName) >= 0) { |
82 constructor[propertyName] = (function(x) { | 227 constructor[propertyName] = (function(x) { |
83 return function() { | 228 return function() { |
84 var screen = $(id); | 229 var screen = $(id); |
85 return screen[x].apply(screen, arguments); | 230 return screen[x].apply(screen, arguments); |
86 }; | 231 }; |
87 })(propertyName); | 232 })(propertyName); |
88 } | 233 } |
89 }); | 234 }); |
| 235 constructor.contextChanged = function() { |
| 236 var screen = $(id); |
| 237 screen.contextChanged_.apply(screen, arguments); |
| 238 } |
90 constructor.prototype.name = function() { return id; }; | 239 constructor.prototype.name = function() { return id; }; |
| 240 constructor.prototype.sendPrefix_ = 'login.' + name + '.'; |
91 | 241 |
92 constructor.register = function() { | 242 constructor.register = function() { |
93 var screen = $(id); | 243 var screen = $(id); |
94 constructor.decorate(screen); | 244 constructor.decorate(screen); |
95 Oobe.getInstance().registerScreen(screen); | 245 Oobe.getInstance().registerScreen(screen); |
96 }; | 246 }; |
97 | 247 |
98 var result = {}; | 248 var result = {}; |
99 result[name] = constructor; | 249 result[name] = constructor; |
100 return result; | 250 return result; |
101 }); | 251 }); |
102 } | 252 } |
103 }; | 253 }; |
104 }); | 254 }); |
105 | 255 |
OLD | NEW |