| <!-- |
| @license |
| Copyright (c) 2015 The Polymer Project Authors. All rights reserved. |
| This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt |
| The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt |
| Code distributed by Google as part of the polymer project is also |
| subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt |
| --> |
| |
| <link rel="import" href="../polymer/polymer.html"> |
| |
| <!-- |
| `iron-meta` is a generic element you can use for sharing information across the DOM tree. |
| It uses [monostate pattern](http://c2.com/cgi/wiki?MonostatePattern) such that any |
| instance of iron-meta has access to the shared |
| information. You can use `iron-meta` to share whatever you want (or create an extension |
| [like x-meta] for enhancements). |
| |
| The `iron-meta` instances containing your actual data can be loaded in an import, |
| or constructed in any way you see fit. The only requirement is that you create them |
| before you try to access them. |
| |
| Examples: |
| |
| If I create an instance like this: |
| |
| <iron-meta key="info" value="foo/bar"></iron-meta> |
| |
| Note that value="foo/bar" is the metadata I've defined. I could define more |
| attributes or use child nodes to define additional metadata. |
| |
| Now I can access that element (and it's metadata) from any iron-meta instance |
| via the byKey method, e.g. |
| |
| meta.byKey('info'); |
| |
| Pure imperative form would be like: |
| |
| document.createElement('iron-meta').byKey('info'); |
| |
| Or, in a Polymer element, you can include a meta in your template: |
| |
| <iron-meta id="meta"></iron-meta> |
| ... |
| this.$.meta.byKey('info'); |
| |
| @group Iron Elements |
| @demo demo/index.html |
| @hero hero.svg |
| @element iron-meta |
| --> |
| |
| <script> |
| |
| (function() { |
| |
| // monostate data |
| var metaDatas = {}; |
| var metaArrays = {}; |
| var singleton = null; |
| |
| Polymer.IronMeta = Polymer({ |
| |
| is: 'iron-meta', |
| |
| properties: { |
| |
| /** |
| * The type of meta-data. All meta-data of the same type is stored |
| * together. |
| */ |
| type: { |
| type: String, |
| value: 'default', |
| observer: '_typeChanged' |
| }, |
| |
| /** |
| * The key used to store `value` under the `type` namespace. |
| */ |
| key: { |
| type: String, |
| observer: '_keyChanged' |
| }, |
| |
| /** |
| * The meta-data to store or retrieve. |
| */ |
| value: { |
| type: Object, |
| notify: true, |
| observer: '_valueChanged' |
| }, |
| |
| /** |
| * If true, `value` is set to the iron-meta instance itself. |
| */ |
| self: { |
| type: Boolean, |
| observer: '_selfChanged' |
| }, |
| |
| /** |
| * Array of all meta-data values for the given type. |
| */ |
| list: { |
| type: Array, |
| notify: true |
| } |
| |
| }, |
| |
| hostAttributes: { |
| hidden: true |
| }, |
| |
| /** |
| * Only runs if someone invokes the factory/constructor directly |
| * e.g. `new Polymer.IronMeta()` |
| * |
| * @param {{type: (string|undefined), key: (string|undefined), value}=} config |
| */ |
| factoryImpl: function(config) { |
| if (config) { |
| for (var n in config) { |
| switch(n) { |
| case 'type': |
| case 'key': |
| case 'value': |
| this[n] = config[n]; |
| break; |
| } |
| } |
| } |
| }, |
| |
| created: function() { |
| // TODO(sjmiles): good for debugging? |
| this._metaDatas = metaDatas; |
| this._metaArrays = metaArrays; |
| }, |
| |
| _keyChanged: function(key, old) { |
| this._resetRegistration(old); |
| }, |
| |
| _valueChanged: function(value) { |
| this._resetRegistration(this.key); |
| }, |
| |
| _selfChanged: function(self) { |
| if (self) { |
| this.value = this; |
| } |
| }, |
| |
| _typeChanged: function(type) { |
| this._unregisterKey(this.key); |
| if (!metaDatas[type]) { |
| metaDatas[type] = {}; |
| } |
| this._metaData = metaDatas[type]; |
| if (!metaArrays[type]) { |
| metaArrays[type] = []; |
| } |
| this.list = metaArrays[type]; |
| this._registerKeyValue(this.key, this.value); |
| }, |
| |
| /** |
| * Retrieves meta data value by key. |
| * |
| * @method byKey |
| * @param {string} key The key of the meta-data to be returned. |
| * @return {*} |
| */ |
| byKey: function(key) { |
| return this._metaData && this._metaData[key]; |
| }, |
| |
| _resetRegistration: function(oldKey) { |
| this._unregisterKey(oldKey); |
| this._registerKeyValue(this.key, this.value); |
| }, |
| |
| _unregisterKey: function(key) { |
| this._unregister(key, this._metaData, this.list); |
| }, |
| |
| _registerKeyValue: function(key, value) { |
| this._register(key, value, this._metaData, this.list); |
| }, |
| |
| _register: function(key, value, data, list) { |
| if (key && data && value !== undefined) { |
| data[key] = value; |
| list.push(value); |
| } |
| }, |
| |
| _unregister: function(key, data, list) { |
| if (key && data) { |
| if (key in data) { |
| var value = data[key]; |
| delete data[key]; |
| this.arrayDelete(list, value); |
| } |
| } |
| } |
| |
| }); |
| |
| Polymer.IronMeta.getIronMeta = function getIronMeta() { |
| if (singleton === null) { |
| singleton = new Polymer.IronMeta(); |
| } |
| return singleton; |
| }; |
| |
| /** |
| `iron-meta-query` can be used to access infomation stored in `iron-meta`. |
| |
| Examples: |
| |
| If I create an instance like this: |
| |
| <iron-meta key="info" value="foo/bar"></iron-meta> |
| |
| Note that value="foo/bar" is the metadata I've defined. I could define more |
| attributes or use child nodes to define additional metadata. |
| |
| Now I can access that element (and it's metadata) from any `iron-meta-query` instance: |
| |
| var value = new Polymer.IronMetaQuery({key: 'info'}).value; |
| |
| @group Polymer Iron Elements |
| @element iron-meta-query |
| */ |
| Polymer.IronMetaQuery = Polymer({ |
| |
| is: 'iron-meta-query', |
| |
| properties: { |
| |
| /** |
| * The type of meta-data. All meta-data of the same type is stored |
| * together. |
| */ |
| type: { |
| type: String, |
| value: 'default', |
| observer: '_typeChanged' |
| }, |
| |
| /** |
| * Specifies a key to use for retrieving `value` from the `type` |
| * namespace. |
| */ |
| key: { |
| type: String, |
| observer: '_keyChanged' |
| }, |
| |
| /** |
| * The meta-data to store or retrieve. |
| */ |
| value: { |
| type: Object, |
| notify: true, |
| readOnly: true |
| }, |
| |
| /** |
| * Array of all meta-data values for the given type. |
| */ |
| list: { |
| type: Array, |
| notify: true |
| } |
| |
| }, |
| |
| /** |
| * Actually a factory method, not a true constructor. Only runs if |
| * someone invokes it directly (via `new Polymer.IronMeta()`); |
| * |
| * @param {{type: (string|undefined), key: (string|undefined)}=} config |
| */ |
| factoryImpl: function(config) { |
| if (config) { |
| for (var n in config) { |
| switch(n) { |
| case 'type': |
| case 'key': |
| this[n] = config[n]; |
| break; |
| } |
| } |
| } |
| }, |
| |
| created: function() { |
| // TODO(sjmiles): good for debugging? |
| this._metaDatas = metaDatas; |
| this._metaArrays = metaArrays; |
| }, |
| |
| _keyChanged: function(key) { |
| this._setValue(this._metaData && this._metaData[key]); |
| }, |
| |
| _typeChanged: function(type) { |
| this._metaData = metaDatas[type]; |
| this.list = metaArrays[type]; |
| if (this.key) { |
| this._keyChanged(this.key); |
| } |
| }, |
| |
| /** |
| * Retrieves meta data value by key. |
| * @param {string} key The key of the meta-data to be returned. |
| * @return {*} |
| */ |
| byKey: function(key) { |
| return this._metaData && this._metaData[key]; |
| } |
| |
| }); |
| |
| })(); |
| </script> |