Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/third_party/closure/goog/dom/dataset.js
4143 views
1
/**
2
* @license
3
* Copyright The Closure Library Authors.
4
* SPDX-License-Identifier: Apache-2.0
5
*/
6
7
/**
8
* @fileoverview Utilities for adding, removing and setting values in
9
* an Element's dataset.
10
* See {@link http://www.w3.org/TR/html5/Overview.html#dom-dataset}.
11
*/
12
13
goog.provide('goog.dom.dataset');
14
15
goog.require('goog.labs.userAgent.browser');
16
goog.require('goog.string');
17
goog.require('goog.userAgent.product');
18
19
20
/**
21
* Whether using the dataset property is allowed.
22
*
23
* In IE (up to and including IE 11), setting element.dataset in JS does not
24
* propagate values to CSS, breaking expressions such as
25
* `content: attr(data-content)` that would otherwise work.
26
* See {@link https://github.com/google/closure-library/issues/396}.
27
*
28
* In Safari >= 9, reading from element.dataset sometimes returns
29
* undefined, even though the corresponding data- attribute has a value.
30
* See {@link https://bugs.webkit.org/show_bug.cgi?id=161454}.
31
* @const
32
* @private
33
*/
34
goog.dom.dataset.ALLOWED_ =
35
!goog.userAgent.product.IE && !goog.labs.userAgent.browser.isSafari();
36
37
38
/**
39
* The DOM attribute name prefix that must be present for it to be considered
40
* for a dataset.
41
* @type {string}
42
* @const
43
* @private
44
*/
45
goog.dom.dataset.PREFIX_ = 'data-';
46
47
48
/**
49
* Returns whether a string is a valid dataset property name.
50
* @param {string} key Property name for the custom data attribute.
51
* @return {boolean} Whether the string is a valid dataset property name.
52
* @private
53
*/
54
goog.dom.dataset.isValidProperty_ = function(key) {
55
'use strict';
56
return !/-[a-z]/.test(key);
57
};
58
59
60
/**
61
* Sets a custom data attribute on an element. The key should be
62
* in camelCase format (e.g "keyName" for the "data-key-name" attribute).
63
* @param {Element} element DOM node to set the custom data attribute on.
64
* @param {string} key Key for the custom data attribute.
65
* @param {string} value Value for the custom data attribute.
66
*/
67
goog.dom.dataset.set = function(element, key, value) {
68
'use strict';
69
var htmlElement = /** @type {HTMLElement} */ (element);
70
if (goog.dom.dataset.ALLOWED_ && htmlElement.dataset) {
71
htmlElement.dataset[key] = value;
72
} else if (!goog.dom.dataset.isValidProperty_(key)) {
73
throw new Error(
74
goog.DEBUG ? '"' + key + '" is not a valid dataset property name.' :
75
'');
76
} else {
77
element.setAttribute(
78
goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key), value);
79
}
80
};
81
82
83
/**
84
* Gets a custom data attribute from an element. The key should be
85
* in camelCase format (e.g "keyName" for the "data-key-name" attribute).
86
* @param {Element} element DOM node to get the custom data attribute from.
87
* @param {string} key Key for the custom data attribute.
88
* @return {?string} The attribute value, if it exists.
89
*/
90
goog.dom.dataset.get = function(element, key) {
91
'use strict';
92
// Edge, unlike other browsers, will do camel-case conversion when retrieving
93
// "dash-case" properties.
94
if (!goog.dom.dataset.isValidProperty_(key)) {
95
return null;
96
}
97
var htmlElement = /** @type {HTMLElement} */ (element);
98
if (goog.dom.dataset.ALLOWED_ && htmlElement.dataset) {
99
// Android browser (non-chrome) returns the empty string for
100
// element.dataset['doesNotExist'].
101
if (goog.labs.userAgent.browser.isAndroidBrowser() &&
102
!(key in htmlElement.dataset)) {
103
return null;
104
}
105
var value = htmlElement.dataset[key];
106
return value === undefined ? null : value;
107
} else {
108
return htmlElement.getAttribute(
109
goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key));
110
}
111
};
112
113
114
/**
115
* Removes a custom data attribute from an element. The key should be
116
* in camelCase format (e.g "keyName" for the "data-key-name" attribute).
117
* @param {Element} element DOM node to get the custom data attribute from.
118
* @param {string} key Key for the custom data attribute.
119
*/
120
goog.dom.dataset.remove = function(element, key) {
121
'use strict';
122
// Edge, unlike other browsers, will do camel-case conversion when removing
123
// "dash-case" properties.
124
if (!goog.dom.dataset.isValidProperty_(key)) {
125
return;
126
}
127
var htmlElement = /** @type {HTMLElement} */ (element);
128
if (goog.dom.dataset.ALLOWED_ && htmlElement.dataset) {
129
// In strict mode Safari will trigger an error when trying to delete a
130
// property which does not exist.
131
if (goog.dom.dataset.has(element, key)) {
132
delete htmlElement.dataset[key];
133
}
134
} else {
135
element.removeAttribute(
136
goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key));
137
}
138
};
139
140
141
/**
142
* Checks whether custom data attribute exists on an element. The key should be
143
* in camelCase format (e.g "keyName" for the "data-key-name" attribute).
144
*
145
* @param {Element} element DOM node to get the custom data attribute from.
146
* @param {string} key Key for the custom data attribute.
147
* @return {boolean} Whether the attribute exists.
148
*/
149
goog.dom.dataset.has = function(element, key) {
150
'use strict';
151
// Edge, unlike other browsers, will do camel-case conversion when retrieving
152
// "dash-case" properties.
153
if (!goog.dom.dataset.isValidProperty_(key)) {
154
return false;
155
}
156
var htmlElement = /** @type {HTMLElement} */ (element);
157
if (goog.dom.dataset.ALLOWED_ && htmlElement.dataset) {
158
return key in htmlElement.dataset;
159
} else if (htmlElement.hasAttribute) {
160
return htmlElement.hasAttribute(
161
goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key));
162
} else {
163
return !!(htmlElement.getAttribute(
164
goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key)));
165
}
166
};
167
168
169
/**
170
* Gets all custom data attributes as a string map. The attribute names will be
171
* camel cased (e.g., data-foo-bar -> dataset['fooBar']). This operation is not
172
* safe for attributes having camel-cased names clashing with already existing
173
* properties (e.g., data-to-string -> dataset['toString']).
174
* @param {!Element} element DOM node to get the data attributes from.
175
* @return {!Object} The string map containing data attributes and their
176
* respective values.
177
*/
178
goog.dom.dataset.getAll = function(element) {
179
'use strict';
180
var htmlElement = /** @type {HTMLElement} */ (element);
181
if (goog.dom.dataset.ALLOWED_ && htmlElement.dataset) {
182
return htmlElement.dataset;
183
} else {
184
var dataset = {};
185
var attributes = element.attributes;
186
for (var i = 0; i < attributes.length; ++i) {
187
var attribute = attributes[i];
188
if (goog.string.startsWith(attribute.name, goog.dom.dataset.PREFIX_)) {
189
// We use slice(5), since it's faster than replacing 'data-' with ''.
190
var key = goog.string.toCamelCase(attribute.name.slice(5));
191
dataset[key] = attribute.value;
192
}
193
}
194
return dataset;
195
}
196
};
197
198