Path: blob/trunk/third_party/closure/goog/dom/dataset.js
4143 views
/**1* @license2* Copyright The Closure Library Authors.3* SPDX-License-Identifier: Apache-2.04*/56/**7* @fileoverview Utilities for adding, removing and setting values in8* an Element's dataset.9* See {@link http://www.w3.org/TR/html5/Overview.html#dom-dataset}.10*/1112goog.provide('goog.dom.dataset');1314goog.require('goog.labs.userAgent.browser');15goog.require('goog.string');16goog.require('goog.userAgent.product');171819/**20* Whether using the dataset property is allowed.21*22* In IE (up to and including IE 11), setting element.dataset in JS does not23* propagate values to CSS, breaking expressions such as24* `content: attr(data-content)` that would otherwise work.25* See {@link https://github.com/google/closure-library/issues/396}.26*27* In Safari >= 9, reading from element.dataset sometimes returns28* undefined, even though the corresponding data- attribute has a value.29* See {@link https://bugs.webkit.org/show_bug.cgi?id=161454}.30* @const31* @private32*/33goog.dom.dataset.ALLOWED_ =34!goog.userAgent.product.IE && !goog.labs.userAgent.browser.isSafari();353637/**38* The DOM attribute name prefix that must be present for it to be considered39* for a dataset.40* @type {string}41* @const42* @private43*/44goog.dom.dataset.PREFIX_ = 'data-';454647/**48* Returns whether a string is a valid dataset property name.49* @param {string} key Property name for the custom data attribute.50* @return {boolean} Whether the string is a valid dataset property name.51* @private52*/53goog.dom.dataset.isValidProperty_ = function(key) {54'use strict';55return !/-[a-z]/.test(key);56};575859/**60* Sets a custom data attribute on an element. The key should be61* in camelCase format (e.g "keyName" for the "data-key-name" attribute).62* @param {Element} element DOM node to set the custom data attribute on.63* @param {string} key Key for the custom data attribute.64* @param {string} value Value for the custom data attribute.65*/66goog.dom.dataset.set = function(element, key, value) {67'use strict';68var htmlElement = /** @type {HTMLElement} */ (element);69if (goog.dom.dataset.ALLOWED_ && htmlElement.dataset) {70htmlElement.dataset[key] = value;71} else if (!goog.dom.dataset.isValidProperty_(key)) {72throw new Error(73goog.DEBUG ? '"' + key + '" is not a valid dataset property name.' :74'');75} else {76element.setAttribute(77goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key), value);78}79};808182/**83* Gets a custom data attribute from an element. The key should be84* in camelCase format (e.g "keyName" for the "data-key-name" attribute).85* @param {Element} element DOM node to get the custom data attribute from.86* @param {string} key Key for the custom data attribute.87* @return {?string} The attribute value, if it exists.88*/89goog.dom.dataset.get = function(element, key) {90'use strict';91// Edge, unlike other browsers, will do camel-case conversion when retrieving92// "dash-case" properties.93if (!goog.dom.dataset.isValidProperty_(key)) {94return null;95}96var htmlElement = /** @type {HTMLElement} */ (element);97if (goog.dom.dataset.ALLOWED_ && htmlElement.dataset) {98// Android browser (non-chrome) returns the empty string for99// element.dataset['doesNotExist'].100if (goog.labs.userAgent.browser.isAndroidBrowser() &&101!(key in htmlElement.dataset)) {102return null;103}104var value = htmlElement.dataset[key];105return value === undefined ? null : value;106} else {107return htmlElement.getAttribute(108goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key));109}110};111112113/**114* Removes a custom data attribute from an element. The key should be115* in camelCase format (e.g "keyName" for the "data-key-name" attribute).116* @param {Element} element DOM node to get the custom data attribute from.117* @param {string} key Key for the custom data attribute.118*/119goog.dom.dataset.remove = function(element, key) {120'use strict';121// Edge, unlike other browsers, will do camel-case conversion when removing122// "dash-case" properties.123if (!goog.dom.dataset.isValidProperty_(key)) {124return;125}126var htmlElement = /** @type {HTMLElement} */ (element);127if (goog.dom.dataset.ALLOWED_ && htmlElement.dataset) {128// In strict mode Safari will trigger an error when trying to delete a129// property which does not exist.130if (goog.dom.dataset.has(element, key)) {131delete htmlElement.dataset[key];132}133} else {134element.removeAttribute(135goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key));136}137};138139140/**141* Checks whether custom data attribute exists on an element. The key should be142* in camelCase format (e.g "keyName" for the "data-key-name" attribute).143*144* @param {Element} element DOM node to get the custom data attribute from.145* @param {string} key Key for the custom data attribute.146* @return {boolean} Whether the attribute exists.147*/148goog.dom.dataset.has = function(element, key) {149'use strict';150// Edge, unlike other browsers, will do camel-case conversion when retrieving151// "dash-case" properties.152if (!goog.dom.dataset.isValidProperty_(key)) {153return false;154}155var htmlElement = /** @type {HTMLElement} */ (element);156if (goog.dom.dataset.ALLOWED_ && htmlElement.dataset) {157return key in htmlElement.dataset;158} else if (htmlElement.hasAttribute) {159return htmlElement.hasAttribute(160goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key));161} else {162return !!(htmlElement.getAttribute(163goog.dom.dataset.PREFIX_ + goog.string.toSelectorCase(key)));164}165};166167168/**169* Gets all custom data attributes as a string map. The attribute names will be170* camel cased (e.g., data-foo-bar -> dataset['fooBar']). This operation is not171* safe for attributes having camel-cased names clashing with already existing172* properties (e.g., data-to-string -> dataset['toString']).173* @param {!Element} element DOM node to get the data attributes from.174* @return {!Object} The string map containing data attributes and their175* respective values.176*/177goog.dom.dataset.getAll = function(element) {178'use strict';179var htmlElement = /** @type {HTMLElement} */ (element);180if (goog.dom.dataset.ALLOWED_ && htmlElement.dataset) {181return htmlElement.dataset;182} else {183var dataset = {};184var attributes = element.attributes;185for (var i = 0; i < attributes.length; ++i) {186var attribute = attributes[i];187if (goog.string.startsWith(attribute.name, goog.dom.dataset.PREFIX_)) {188// We use slice(5), since it's faster than replacing 'data-' with ''.189var key = goog.string.toCamelCase(attribute.name.slice(5));190dataset[key] = attribute.value;191}192}193return dataset;194}195};196197198