Chromium Code Reviews| Index: components/wug/resources/webui-view.js |
| diff --git a/components/wug/resources/webui-view.js b/components/wug/resources/webui-view.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..df64bce43f450f8101f6d0e7f83cad4b856398d2 |
| --- /dev/null |
| +++ b/components/wug/resources/webui-view.js |
| @@ -0,0 +1,182 @@ |
| +// Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +Polymer('webui-view', (function() { |
| + /** @const */ var CALLBACK_EVENT_FIRED = 'eventFired'; |
| + /** @const */ var CALLBACK_CONTEXT_CHANGED = 'contextChanged'; |
| + /** @const */ var CALLBACK_READY = 'ready'; |
| + |
| + return { |
| + /** |
| + * Dictionary of context observers that are methods of |this| bound to |
| + * |this|. |
| + */ |
| + contextObservers_: null, |
| + |
| + /** |
| + * Full path to the element in views hierarchy. |
| + */ |
| + path_: null, |
| + |
| + /** |
| + * Whether DOM is ready. |
| + */ |
| + domReady_: false, |
| + |
| + /** |
| + * Context used for sharing data with native backend. |
| + */ |
| + context: null, |
| + |
| + /** |
| + * Internal storage of |this.context|. Short name has been choosen for |
|
Nikita (slow)
2015/02/24 15:22:42
nit: You can make this comment shorter since you'r
dzhioev (left Google)
2015/02/26 14:01:37
What do you mean? this.C and this.context are diff
Nikita (slow)
2015/02/26 14:18:20
I suggested removing reasoning for using short nam
dzhioev (left Google)
2015/03/02 11:02:30
Done.
|
| + * reason: such name doesn't take much space in HTML data bindings, which |
| + * are used very often. |
| + * C binded to the native part of the context, that means that all the |
| + * changes in the native part appear in C automticaly. Reverse is not true, |
|
Nikita (slow)
2015/02/26 14:18:20
nit: automatically
dzhioev (left Google)
2015/03/02 11:02:30
Done.
|
| + * you should use: |
| + * this.context.set(...); |
| + * this.context.commitContextChanges(); |
| + * to send updates to the native part. |
| + * TODO(dzhioev): make binding two-way. |
|
Nikita (slow)
2015/02/24 15:22:42
Since this is purely an optimization I suggest rem
dzhioev (left Google)
2015/02/26 14:01:37
Done. Removed comment.
|
| + */ |
| + C: null, |
| + |
| + ready: function() { |
| + this.context = new wug.Context; |
| + this.C = this.context.storage_; |
| + this.contextObservers_ = {}; |
| + }, |
| + |
| + /** |
| + * One of element's lifecycle methods. |
| + */ |
| + domReady: function() { |
| + var id = this.getAttribute('wugid'); |
| + if (!id) |
| + console.error('"wugid" attribute is missing.'); |
|
Nikita (slow)
2015/02/24 15:22:42
nit: Should you return here and do not initialize
dzhioev (left Google)
2015/02/26 14:01:37
Done.
|
| + if (id == 'WUG_ROOT') { |
| + this.setPath_('WUG_ROOT'); |
| + } |
| + this.domReady_ = true; |
| + if (this.path_) |
| + this.init_(); |
| + }, |
| + |
| + setPath_: function(path) { |
| + this.path_ = path; |
| + if (this.domReady_) |
| + this.init_(); |
| + }, |
| + |
| + init_: function() { |
| + this.initContext_(); |
| + this.initChildren_(); |
| + window[this.path_ + '$contextChanged'] = |
| + this.onContextChanged_.bind(this); |
| + this.initialize(); |
| + this.send(CALLBACK_READY); |
| + }, |
| + |
| + fireEvent: function(_, _, source) { |
| + this.send(CALLBACK_EVENT_FIRED, source.getAttribute('event')); |
| + }, |
| + |
| + i18n: function(args) { |
| + if (!(args instanceof Array)) |
| + args = [args]; |
| + args[0] = this.getType() + '$' + args[0]; |
| + return loadTimeData.getStringF.apply(loadTimeData, args); |
| + }, |
| + |
| + /** |
| + * 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. |
| + * @private |
| + */ |
| + send: function(messageName, varArgs) { |
| + if (arguments.length == 0) |
| + throw Error('Message name is not provided.'); |
| + var fullMessageName = this.path_ + '$' + messageName; |
| + var payload = Array.prototype.slice.call(arguments, 1); |
| + chrome.send(fullMessageName, payload); |
| + }, |
| + |
| + /** |
| + * 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 |
| + * |removeObserver| call: |
| + * |
| + * this.addContextObserver('key', this.onKeyChanged_); |
|
Nikita (slow)
2015/02/24 15:22:42
Not clear whether this example on how caller shoul
dzhioev (left Google)
2015/02/26 14:01:37
Done.
|
| + * ... |
| + * this.removeContextObserver('key', this.onKeyChanged_); |
| + * @private |
| + */ |
| + addContextObserver: function(key, observer) { |
| + 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.addObserver(key, realObserver); |
| + }, |
| + |
| + /** |
| + * Removes |observer| from the list of context observers. Supports not only |
| + * regular functions but also screen methods (see comment to |
| + * |addContextObserver|). |
| + * @private |
| + */ |
| + removeContextObserver: 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.removeObserver(realObserver); |
| + }, |
| + |
| + /** |
| + * Sends recent context changes to C++ handler. |
| + * @private |
| + */ |
| + commitContextChanges: function() { |
| + if (!this.context.hasChanges()) |
| + return; |
| + this.send(CALLBACK_CONTEXT_CHANGED, this.context.getChangesAndReset()); |
| + }, |
| + |
| + /** |
| + * Called when context changed on C++ side. |
| + */ |
| + onContextChanged_: function(diff) { |
| + var changedKeys = this.context.applyChanges(diff); |
| + this.contextChanged(changedKeys); |
| + }, |
| + |
| + /** |
| + * If |value| is the value of some property of |this| returns property's |
| + * name. Otherwise returns empty string. |
| + * @private |
| + */ |
| + getPropertyNameOf_: function(value) { |
| + for (var key in this) |
| + if (this[key] === value) |
| + return key; |
| + return ''; |
| + } |
| + }; |
| +})()); |
| + |