OLD | NEW |
(Empty) | |
| 1 <!-- |
| 2 @license |
| 3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 7 Code distributed by Google as part of the polymer project is also |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --> |
| 10 |
| 11 <link rel="import" href="../polymer/polymer.html"> |
| 12 |
| 13 <!-- |
| 14 Element access to Web Storage API (window.localStorage). |
| 15 |
| 16 Keeps `value` property in sync with localStorage. |
| 17 |
| 18 Value is saved as json by default. |
| 19 |
| 20 ###Usage: |
| 21 |
| 22 `ls-sample` will automatically save changes to its value. |
| 23 |
| 24 <dom-module id="ls-sample"> |
| 25 <iron-localstorage name="my-app-storage" |
| 26 value="{{cartoon}}" |
| 27 on-iron-localstorage-load-empty="initializeDefaultCartoon" |
| 28 ></iron-localstorage> |
| 29 </dom-module> |
| 30 |
| 31 <script> |
| 32 Polymer({ |
| 33 is: 'ls-sample', |
| 34 properties: { |
| 35 cartoon: { |
| 36 type: Object |
| 37 } |
| 38 }, |
| 39 // initializes default if nothing has been stored |
| 40 initializeDefaultCartoon: function() { |
| 41 this.cartoon = { |
| 42 name: "Mickey", |
| 43 hasEars: true |
| 44 } |
| 45 }, |
| 46 // use path set api to propagate changes to localstorage |
| 47 makeModifications: function() { |
| 48 this.set('cartoon.name', "Minions"); |
| 49 this.set('cartoon.hasEars', false); |
| 50 } |
| 51 }); |
| 52 </script> |
| 53 |
| 54 ###Tech notes: |
| 55 |
| 56 * * `value.*` is observed, and saved on modifications. You must use |
| 57 property notification methods to modify value for changes to be observed. |
| 58 |
| 59 * * Set `auto-save-disabled` to prevent automatic saving. |
| 60 |
| 61 * * Value is saved as JSON by default. |
| 62 |
| 63 * * To delete a key, set value to null |
| 64 |
| 65 * Element listens to StorageAPI `storage` event, and will reload upon receiving
it. |
| 66 |
| 67 * **Warning**: do not bind value to sub-properties until Polymer |
| 68 [bug 1550](https://github.com/Polymer/polymer/issues/1550) |
| 69 is resolved. Local storage will be blown away. |
| 70 `<iron-localstorage value="{{foo.bar}}"` will cause **data loss**. |
| 71 |
| 72 @demo demo/index.html |
| 73 @hero hero.svg |
| 74 --> |
| 75 <dom-module id="iron-localstorage"></dom-module> |
| 76 <script> |
| 77 |
| 78 Polymer({ |
| 79 is: 'iron-localstorage', |
| 80 |
| 81 /** |
| 82 * Fired when value loads from localStorage. |
| 83 * |
| 84 * @event iron-localstorage-load |
| 85 * @param {{externalChange:boolean}} detail - |
| 86 * externalChange: true if change occured in different window. |
| 87 */ |
| 88 |
| 89 /** |
| 90 * Fired when loaded value does not exist. |
| 91 * Event handler can be used to initialize default value. |
| 92 * |
| 93 * @event iron-localstorage-load-empty |
| 94 * @param {{externalChange:boolean}} detail - |
| 95 * externalChange: true if change occured in different window. |
| 96 */ |
| 97 properties: { |
| 98 /** |
| 99 * localStorage item key |
| 100 */ |
| 101 name: { |
| 102 type: String, |
| 103 value: '' |
| 104 }, |
| 105 /** |
| 106 * The data associated with this storage. |
| 107 * If set to null item will be deleted. |
| 108 * @type {*} |
| 109 */ |
| 110 value: { |
| 111 type: Object, |
| 112 notify: true |
| 113 }, |
| 114 |
| 115 /** |
| 116 * If true: do not convert value to JSON on save/load |
| 117 */ |
| 118 useRaw: { |
| 119 type: Boolean, |
| 120 value: false |
| 121 }, |
| 122 |
| 123 /** |
| 124 * Value will not be saved automatically if true. You'll have to do it man
ually with `save()` |
| 125 */ |
| 126 autoSaveDisabled: { |
| 127 type: Boolean, |
| 128 value: false |
| 129 }, |
| 130 /** |
| 131 * Last error encountered while saving/loading items |
| 132 */ |
| 133 errorMessage: { |
| 134 type: String, |
| 135 notify: true |
| 136 }, |
| 137 |
| 138 /** True if value has been loaded */ |
| 139 _loaded: { |
| 140 type: Boolean, |
| 141 value: false |
| 142 } |
| 143 }, |
| 144 |
| 145 observers: [ |
| 146 '_debounceReload(name,useRaw)', |
| 147 '_trySaveValue(autoSaveDisabled)', |
| 148 '_trySaveValue(value.*)' |
| 149 ], |
| 150 |
| 151 ready: function() { |
| 152 this._boundHandleStorage = this._handleStorage.bind(this); |
| 153 }, |
| 154 |
| 155 attached: function() { |
| 156 window.addEventListener('storage', this._boundHandleStorage); |
| 157 }, |
| 158 |
| 159 detached: function() { |
| 160 window.removeEventListener('storage', this._boundHandleStorage); |
| 161 }, |
| 162 |
| 163 _handleStorage: function(ev) { |
| 164 if (ev.key == this.name) { |
| 165 this._load(true); |
| 166 } |
| 167 }, |
| 168 |
| 169 _trySaveValue: function() { |
| 170 if (this._doNotSave) { |
| 171 return; |
| 172 } |
| 173 if (this._loaded && !this.autoSaveDisabled) { |
| 174 this.debounce('save', this.save); |
| 175 } |
| 176 }, |
| 177 |
| 178 _debounceReload: function() { |
| 179 this.debounce('reload', this.reload); |
| 180 }, |
| 181 |
| 182 /** |
| 183 * Loads the value again. Use if you modify |
| 184 * localStorage using DOM calls, and want to |
| 185 * keep this element in sync. |
| 186 */ |
| 187 reload: function() { |
| 188 this._loaded = false; |
| 189 this._load(); |
| 190 }, |
| 191 |
| 192 /** |
| 193 * loads value from local storage |
| 194 * @param {boolean=} externalChange true if loading changes from a different
window |
| 195 */ |
| 196 _load: function(externalChange) { |
| 197 var v = window.localStorage.getItem(this.name); |
| 198 |
| 199 if (v === null) { |
| 200 this._loaded = true; |
| 201 this._doNotSave = true; // guard for save watchers |
| 202 this.value = null; |
| 203 this._doNotSave = false; |
| 204 this.fire('iron-localstorage-load-empty', { externalChange: externalChan
ge}); |
| 205 } else { |
| 206 if (!this.useRaw) { |
| 207 try { // parse value as JSON |
| 208 v = JSON.parse(v); |
| 209 } catch(x) { |
| 210 this.errorMessage = "Could not parse local storage value"; |
| 211 console.error("could not parse local storage value", v); |
| 212 v = null; |
| 213 } |
| 214 } |
| 215 this._loaded = true; |
| 216 this._doNotSave = true; |
| 217 this.value = v; |
| 218 this._doNotSave = false; |
| 219 this.fire('iron-localstorage-load', { externalChange: externalChange}); |
| 220 } |
| 221 }, |
| 222 |
| 223 /** |
| 224 * Saves the value to localStorage. Call to save if autoSaveDisabled is set. |
| 225 * If `value` is null, deletes localStorage. |
| 226 */ |
| 227 save: function() { |
| 228 var v = this.useRaw ? this.value : JSON.stringify(this.value); |
| 229 try { |
| 230 if (this.value === null) { |
| 231 window.localStorage.removeItem(this.name); |
| 232 } else { |
| 233 window.localStorage.setItem(this.name, /** @type {string} */ (v)); |
| 234 } |
| 235 } |
| 236 catch(ex) { |
| 237 // Happens in Safari incognito mode, |
| 238 this.errorMessage = ex.message; |
| 239 console.error("localStorage could not be saved. Safari incoginito mode?"
, ex); |
| 240 } |
| 241 } |
| 242 |
| 243 }); |
| 244 |
| 245 </script> |
OLD | NEW |