forked from marcuswestin/store.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
oldIE-userDataStorage.js
127 lines (114 loc) · 3.96 KB
/
oldIE-userDataStorage.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// oldIE-userDataStorage provides storage for Internet Explorer
// versions 6 and 7, where no localStorage, sessionStorage, etc
// is available.
var util = require('../src/util')
var Global = util.Global
module.exports = {
name: 'oldIE-userDataStorage',
write: write,
read: read,
each: each,
remove: remove,
clearAll: clearAll,
}
var storageName = 'storejs'
var doc = Global.document
var _withStorageEl = _makeIEStorageElFunction()
var disable = (Global.navigator ? Global.navigator.userAgent : '').match(/ (MSIE 8|MSIE 9|MSIE 10)\./) // MSIE 9.x, MSIE 10.x
function write(unfixedKey, data) {
if (disable) { return }
var fixedKey = fixKey(unfixedKey)
_withStorageEl(function(storageEl) {
storageEl.setAttribute(fixedKey, data)
storageEl.save(storageName)
})
}
function read(unfixedKey) {
if (disable) { return }
var fixedKey = fixKey(unfixedKey)
var res = null
_withStorageEl(function(storageEl) {
res = storageEl.getAttribute(fixedKey)
})
return res
}
function each(callback) {
_withStorageEl(function(storageEl) {
var attributes = storageEl.XMLDocument.documentElement.attributes
for (var i=attributes.length-1; i>=0; i--) {
var attr = attributes[i]
callback(storageEl.getAttribute(attr.name), attr.name)
}
})
}
function remove(unfixedKey) {
var fixedKey = fixKey(unfixedKey)
_withStorageEl(function(storageEl) {
storageEl.removeAttribute(fixedKey)
storageEl.save(storageName)
})
}
function clearAll() {
_withStorageEl(function(storageEl) {
var attributes = storageEl.XMLDocument.documentElement.attributes
storageEl.load(storageName)
for (var i=attributes.length-1; i>=0; i--) {
storageEl.removeAttribute(attributes[i].name)
}
storageEl.save(storageName)
})
}
// Helpers
//////////
// In IE7, keys cannot start with a digit or contain certain chars.
// See https://github.com/marcuswestin/store.js/issues/40
// See https://github.com/marcuswestin/store.js/issues/83
var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g")
function fixKey(key) {
return key.replace(/^\d/, '___$&').replace(forbiddenCharsRegex, '___')
}
function _makeIEStorageElFunction() {
if (!doc || !doc.documentElement || !doc.documentElement.addBehavior) {
return null
}
var scriptTag = 'script',
storageOwner,
storageContainer,
storageEl
// Since #userData storage applies only to specific paths, we need to
// somehow link our data to a specific path. We choose /favicon.ico
// as a pretty safe option, since all browsers already make a request to
// this URL anyway and being a 404 will not hurt us here. We wrap an
// iframe pointing to the favicon in an ActiveXObject(htmlfile) object
// (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
// since the iframe access rules appear to allow direct access and
// manipulation of the document element, even for a 404 page. This
// document can be used instead of the current document (which would
// have been limited to the current path) to perform #userData storage.
try {
/* global ActiveXObject */
storageContainer = new ActiveXObject('htmlfile')
storageContainer.open()
storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>')
storageContainer.close()
storageOwner = storageContainer.w.frames[0].document
storageEl = storageOwner.createElement('div')
} catch(e) {
// somehow ActiveXObject instantiation failed (perhaps some special
// security settings or otherwse), fall back to per-path storage
storageEl = doc.createElement('div')
storageOwner = doc.body
}
return function(storeFunction) {
var args = [].slice.call(arguments, 0)
args.unshift(storageEl)
// See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
// and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
storageOwner.appendChild(storageEl)
storageEl.addBehavior('#default#userData')
storageEl.load(storageName)
storeFunction.apply(this, args)
storageOwner.removeChild(storageEl)
return
}
}