1 | ;(function(win){
|
2 | var store = {},
|
3 | doc = win.document,
|
4 | localStorageName = 'localStorage',
|
5 | scriptTag = 'script',
|
6 | storage
|
7 |
|
8 | store.disabled = false
|
9 | store.set = function(key, value) {}
|
10 | store.get = function(key) {}
|
11 | store.remove = function(key) {}
|
12 | store.clear = function() {}
|
13 | store.transact = function(key, defaultVal, transactionFn) {
|
14 | var val = store.get(key)
|
15 | if (transactionFn == null) {
|
16 | transactionFn = defaultVal
|
17 | defaultVal = null
|
18 | }
|
19 | if (typeof val == 'undefined') { val = defaultVal || {} }
|
20 | transactionFn(val)
|
21 | store.set(key, val)
|
22 | }
|
23 | store.getAll = function() {}
|
24 | store.forEach = function() {}
|
25 |
|
26 | store.serialize = function(value) {
|
27 | return JSON.stringify(value)
|
28 | }
|
29 | store.deserialize = function(value) {
|
30 | if (typeof value != 'string') { return undefined }
|
31 | try { return JSON.parse(value) }
|
32 | catch(e) { return value || undefined }
|
33 | }
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | function isLocalStorageNameSupported() {
|
39 | try { return (localStorageName in win && win[localStorageName]) }
|
40 | catch(err) { return false }
|
41 | }
|
42 |
|
43 | if (isLocalStorageNameSupported()) {
|
44 | storage = win[localStorageName]
|
45 | store.set = function(key, val) {
|
46 | if (val === undefined) { return store.remove(key) }
|
47 | storage.setItem(key, store.serialize(val))
|
48 | return val
|
49 | }
|
50 | store.get = function(key) { return store.deserialize(storage.getItem(key)) }
|
51 | store.remove = function(key) { storage.removeItem(key) }
|
52 | store.clear = function() { storage.clear() }
|
53 | store.getAll = function() {
|
54 | var ret = {}
|
55 | store.forEach(function(key, val) {
|
56 | ret[key] = val
|
57 | })
|
58 | return ret
|
59 | }
|
60 | store.forEach = function(callback) {
|
61 | for (var i=0; i<storage.length; i++) {
|
62 | var key = storage.key(i)
|
63 | callback(key, store.get(key))
|
64 | }
|
65 | }
|
66 | } else if (doc.documentElement.addBehavior) {
|
67 | var storageOwner,
|
68 | storageContainer
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 | try {
|
80 | storageContainer = new ActiveXObject('htmlfile')
|
81 | storageContainer.open()
|
82 | storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>')
|
83 | storageContainer.close()
|
84 | storageOwner = storageContainer.w.frames[0].document
|
85 | storage = storageOwner.createElement('div')
|
86 | } catch(e) {
|
87 |
|
88 |
|
89 | storage = doc.createElement('div')
|
90 | storageOwner = doc.body
|
91 | }
|
92 | function withIEStorage(storeFunction) {
|
93 | return function() {
|
94 | var args = Array.prototype.slice.call(arguments, 0)
|
95 | args.unshift(storage)
|
96 |
|
97 |
|
98 | storageOwner.appendChild(storage)
|
99 | storage.addBehavior('#default#userData')
|
100 | storage.load(localStorageName)
|
101 | var result = storeFunction.apply(store, args)
|
102 | storageOwner.removeChild(storage)
|
103 | return result
|
104 | }
|
105 | }
|
106 |
|
107 |
|
108 |
|
109 |
|
110 | var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g")
|
111 | function ieKeyFix(key) {
|
112 | return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
|
113 | }
|
114 | store.set = withIEStorage(function(storage, key, val) {
|
115 | key = ieKeyFix(key)
|
116 | if (val === undefined) { return store.remove(key) }
|
117 | storage.setAttribute(key, store.serialize(val))
|
118 | storage.save(localStorageName)
|
119 | return val
|
120 | })
|
121 | store.get = withIEStorage(function(storage, key) {
|
122 | key = ieKeyFix(key)
|
123 | return store.deserialize(storage.getAttribute(key))
|
124 | })
|
125 | store.remove = withIEStorage(function(storage, key) {
|
126 | key = ieKeyFix(key)
|
127 | storage.removeAttribute(key)
|
128 | storage.save(localStorageName)
|
129 | })
|
130 | store.clear = withIEStorage(function(storage) {
|
131 | var attributes = storage.XMLDocument.documentElement.attributes
|
132 | storage.load(localStorageName)
|
133 | for (var i=0, attr; attr=attributes[i]; i++) {
|
134 | storage.removeAttribute(attr.name)
|
135 | }
|
136 | storage.save(localStorageName)
|
137 | })
|
138 | store.getAll = function(storage) {
|
139 | var ret = {}
|
140 | store.forEach(function(key, val) {
|
141 | ret[key] = val
|
142 | })
|
143 | return ret
|
144 | }
|
145 | store.forEach = withIEStorage(function(storage, callback) {
|
146 | var attributes = storage.XMLDocument.documentElement.attributes
|
147 | for (var i=0, attr; attr=attributes[i]; ++i) {
|
148 | callback(attr.name, store.deserialize(storage.getAttribute(attr.name)))
|
149 | }
|
150 | })
|
151 | }
|
152 |
|
153 | try {
|
154 | var testKey = '__storejs__'
|
155 | store.set(testKey, testKey)
|
156 | if (store.get(testKey) != testKey) { store.disabled = true }
|
157 | store.remove(testKey)
|
158 | } catch(e) {
|
159 | store.disabled = true
|
160 | }
|
161 | store.enabled = !store.disabled
|
162 |
|
163 | if (typeof module != 'undefined' && module.exports && this.module !== module) { module.exports = store }
|
164 | else if (typeof define === 'function' && define.amd) { define(store) }
|
165 | else { win.store = store }
|
166 |
|
167 | })(Function('return this')());
|