Index: chrome/browser/resources/login/screen.js |
diff --git a/chrome/browser/resources/login/screen.js b/chrome/browser/resources/login/screen.js |
index fa03371f6a3d8384c9a25ee55d0c35e505250a34..6bbf1f35489b8f8470faeb82882151e5e8c55289 100644 |
--- a/chrome/browser/resources/login/screen.js |
+++ b/chrome/browser/resources/login/screen.js |
@@ -8,11 +8,58 @@ |
cr.define('login', function() { |
var Screen = cr.ui.define('div'); |
+ /** @const */ var CALLBACK_BUTTON_CLICKED = 'buttonClicked'; |
+ /** @const */ var CALLBACK_CONTEXT_CHANGED = 'contextChanged'; |
+ |
function doNothing() {}; |
+ var querySelectorAll = HTMLDivElement.prototype.querySelectorAll; |
+ |
Screen.prototype = { |
__proto__: HTMLDivElement.prototype, |
+ /** |
+ * Prefix added to sent to Chrome messages' names. |
+ */ |
+ sendPrefix_: '', |
+ |
+ /** |
+ * Context used by this screen. |
+ */ |
+ context_: null, |
+ |
+ /** |
+ * Dictionary of context observers that are methods of |this| binded to |
Denis Kuznetsov (DE-MUC)
2014/06/11 14:29:17
s/binded/bound/
dzhioev (left Google)
2014/06/20 07:24:16
Done.
|
+ * |this|. |
+ */ |
+ contextObservers_: {}, |
+ |
+ get context() { |
+ return this.context_; |
+ }, |
+ |
+ /** |
+ * Sends recent context changes to C++ handler. |
+ */ |
+ commitContextChanges: function() { |
+ this.send(CALLBACK_CONTEXT_CHANGED, this.context_.getChangesAndReset()); |
+ }, |
+ |
+ /** |
+ * Sends message to Chrome, adding needed prefix to message name. All |
+ * arguments after |messageName| are packed into message parameters list. |
+ * |
+ * @param {string} messageName Name of message without a prefix. |
+ * @param {...*} varArgs parameters for message. |
+ */ |
+ send: function(messageName, varArgs) { |
+ if (arguments.length == 0) |
+ throw Error('Message name is not provided.'); |
+ var fullMessageName = this.sendPrefix_ + messageName; |
+ var payload = Array.prototype.slice.call(arguments, 1); |
+ chrome.send(fullMessageName, payload); |
+ }, |
+ |
decorate: doNothing, |
/** |
@@ -28,6 +75,94 @@ cr.define('login', function() { |
* Called for currently active screen when screen size changed. |
*/ |
onWindowResize: doNothing, |
+ |
+ /** |
+ * Does the following things: |
+ * * Creates screen context. |
+ * * Looks for elements having "is" property and adds them as the proprties |
+ * of the screen with name equal to value of "is", i.e. HTML element |
+ * <div is="myDiv"></div> will be stored in this.myDiv. |
+ * * Looks for buttons having "action" properties and adds click handlers |
+ * to them. These handlers send |CALLBACK_BUTTON_CLICKED| messages to |
+ * C++ with "action" property's value as payload. |
+ */ |
+ makeMagic: function() { |
ygorshenin1
2014/06/11 10:44:00
Don't see how this method is used in https://coder
Denis Kuznetsov (DE-MUC)
2014/06/11 14:29:17
I agree about naming.
I'm also concerned about usi
dzhioev (left Google)
2014/06/18 14:43:39
It is called in |decorate| method of new screen.
I
dzhioev (left Google)
2014/06/18 14:43:39
* The main reason why I don't want use "id"s is th
Denis Kuznetsov (DE-MUC)
2014/06/19 19:16:36
First, attribute names are usually nouns. "Is" is
dzhioev (left Google)
2014/06/20 07:24:16
Renamed to "alias"
|
+ this.context_ = new login.ScreenContext(this); |
+ var elements = this.querySelectorAll('[is]'); |
+ for (var i = 0; i < elements.length; ++i) |
+ this[elements[i].getAttribute('is')] = elements[i]; |
+ var buttons = this.querySelectorAll('button[action]'); |
+ var self = this; |
+ for (var i = 0; i < buttons.length; ++i) { |
+ buttons[i].addEventListener('click', function(e) { |
+ var action = this.getAttribute('action'); |
+ self.send(CALLBACK_BUTTON_CLICKED, action); |
+ e.stopPropagation(); |
+ }); |
+ } |
+ }, |
+ |
+ /** |
+ * Starts observation of property with |key| of the context attached to |
+ * current screen. This method differs from "login.ScreenContext" in that |
+ * it automatically detects if observer is method of |this| and make |
+ * all needed actions to make it work correctly. So it's no need for client |
+ * to bind methods to |this| and keep resulting callback for unobserve: |
+ * |
+ * this.observeContext('key', this.onKeyChanged_); |
+ * ... |
+ * this.unobserveContext('key', this.onKeyChanged_); |
+ */ |
+ observeContext: function(key, observer) { |
Denis Kuznetsov (DE-MUC)
2014/06/11 14:29:17
subscribeForKeyChange / watchKeyChange?
dzhioev (left Google)
2014/06/18 14:43:39
See comment to ScreenContext.observe
|
+ var realObserver = observer; |
+ var propertyName = this.getPropertyNameOf_(observer); |
+ if (propertyName) { |
+ if (!this.contextObservers_.hasOwnProperty(propertyName)) |
+ this.contextObservers_[propertyName] = observer.bind(this); |
+ realObserver = this.contextObservers_[propertyName]; |
+ } |
+ this.context.observe(key, realObserver); |
+ }, |
+ |
+ /** |
+ * Removes |observer| from the list of context observers. Supports not only |
+ * regular functions but also screen methods (see comment to |
+ * |observeContext|). |
+ */ |
+ unobserveContext: function(observer) { |
+ var realObserver = observer; |
+ var propertyName = this.getPropertyNameOf_(observer); |
+ if (propertyName) { |
+ if (!this.contextObservers_.hasOwnProperty(propertyName)) |
+ return; |
+ realObserver = this.contextObservers_[propertyName]; |
+ delete this.contextObservers_[propertyName]; |
+ } |
+ this.context.unobserve(realObserver); |
+ }, |
+ |
+ /** |
+ * Calls standart |querySelectorAll| method and returns its result converted |
+ * to Array. |
+ */ |
+ querySelectorAll: function(selector) { |
+ var list = querySelectorAll.call(this, selector); |
+ return Array.prototype.slice.call(list); |
+ }, |
+ |
+ /** |
+ * Called when context changes are recieved from C++. |
+ */ |
+ contextChanged_: function(diff) { |
ygorshenin1
2014/06/11 10:44:00
nit: add @private annotation.
dzhioev (left Google)
2014/06/18 14:43:39
Done.
|
+ this.context.applyChanges(diff); |
+ }, |
+ |
+ getPropertyNameOf_: function(value) { |
ygorshenin1
2014/06/11 10:44:00
nit: add comment to this function + @private annot
dzhioev (left Google)
2014/06/18 14:43:39
Done.
|
+ for (var key in this) |
+ if (this[key] === value) |
+ return key; |
+ return ''; |
+ } |
}; |
return { |
@@ -87,6 +222,10 @@ cr.define('login', function() { |
})(propertyName); |
} |
}); |
+ constructor.contextChanged = function() { |
+ var screen = $(id); |
+ screen.contextChanged_.apply(screen, arguments); |
+ } |
constructor.prototype.name = function() { return id; }; |
constructor.register = function() { |