Path: blob/trunk/third_party/closure/goog/dom/classlist.js
4116 views
/**1* @license2* Copyright The Closure Library Authors.3* SPDX-License-Identifier: Apache-2.04*/56/**7* @fileoverview Utilities for detecting, adding and removing classes. Prefer8* this over goog.dom.classes for new code since it attempts to use classList9* (DOMTokenList: http://dom.spec.whatwg.org/#domtokenlist) which is faster10* and requires less code.11*12* Note: these utilities are meant to operate on HTMLElements and SVGElements13* and may have unexpected behavior on elements with differing interfaces.14*/151617goog.provide('goog.dom.classlist');1819goog.require('goog.array');202122/**23* Override this define at build-time if you know your target supports it.24* @define {boolean} Whether to use the classList property (DOMTokenList).25*/26goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST =27goog.define('goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST', false);282930/**31* A wrapper which ensures correct functionality when interacting with32* SVGElements33* @param {?Element} element DOM node to get the class name of.34* @return {string}35* @private36*/37goog.dom.classlist.getClassName_ = function(element) {38'use strict';39// If className is an instance of SVGAnimatedString use getAttribute40return typeof element.className == 'string' ?41element.className :42element.getAttribute && element.getAttribute('class') || '';43};444546/**47* Gets an array-like object of class names on an element.48* @param {Element} element DOM node to get the classes of.49* @return {!IArrayLike<?>} Class names on `element`.50*/51goog.dom.classlist.get = function(element) {52'use strict';53if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {54return element.classList;55}5657return goog.dom.classlist.getClassName_(element).match(/\S+/g) || [];58};596061/**62* Sets the entire class name of an element.63* @param {Element} element DOM node to set class of.64* @param {string} className Class name(s) to apply to element.65*/66goog.dom.classlist.set = function(element, className) {67'use strict';68// If className is an instance of SVGAnimatedString use setAttribute69if ((typeof element.className) == 'string') {70element.className = className;71return;72} else if (element.setAttribute) {73element.setAttribute('class', className);74}75};767778/**79* Returns true if an element has a class. This method may throw a DOM80* exception for an invalid or empty class name if DOMTokenList is used.81* @param {Element} element DOM node to test.82* @param {string} className Class name to test for.83* @return {boolean} Whether element has the class.84*/85goog.dom.classlist.contains = function(element, className) {86'use strict';87if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {88return element.classList.contains(className);89}90return goog.array.contains(goog.dom.classlist.get(element), className);91};929394/**95* Adds a class to an element. Does not add multiples of class names. This96* method may throw a DOM exception for an invalid or empty class name if97* DOMTokenList is used.98* @param {Element} element DOM node to add class to.99* @param {string} className Class name to add.100*/101goog.dom.classlist.add = function(element, className) {102'use strict';103if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {104element.classList.add(className);105return;106}107108if (!goog.dom.classlist.contains(element, className)) {109// Ensure we add a space if this is not the first class name added.110var oldClassName = goog.dom.classlist.getClassName_(element);111goog.dom.classlist.set(112element,113oldClassName +114(oldClassName.length > 0 ? (' ' + className) : className));115}116};117118119/**120* Convenience method to add a number of class names at once.121* @param {Element} element The element to which to add classes.122* @param {IArrayLike<string>} classesToAdd An array-like object123* containing a collection of class names to add to the element.124* This method may throw a DOM exception if classesToAdd contains invalid125* or empty class names.126*/127goog.dom.classlist.addAll = function(element, classesToAdd) {128'use strict';129if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {130Array.prototype.forEach.call(classesToAdd, function(className) {131'use strict';132goog.dom.classlist.add(element, className);133});134return;135}136137var classMap = {};138139// Get all current class names into a map.140Array.prototype.forEach.call(141goog.dom.classlist.get(element), function(className) {142'use strict';143classMap[className] = true;144});145146// Add new class names to the map.147Array.prototype.forEach.call(classesToAdd, function(className) {148'use strict';149classMap[className] = true;150});151152// Flatten the keys of the map into the className.153var newClassName = '';154for (var className in classMap) {155newClassName += newClassName.length > 0 ? (' ' + className) : className;156}157goog.dom.classlist.set(element, newClassName);158};159160161/**162* Removes a class from an element. This method may throw a DOM exception163* for an invalid or empty class name if DOMTokenList is used.164* @param {Element} element DOM node to remove class from.165* @param {string} className Class name to remove.166*/167goog.dom.classlist.remove = function(element, className) {168'use strict';169if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {170element.classList.remove(className);171return;172}173174if (goog.dom.classlist.contains(element, className)) {175// Filter out the class name.176goog.dom.classlist.set(177element,178Array.prototype.filter179.call(180goog.dom.classlist.get(element),181function(c) {182'use strict';183return c != className;184})185.join(' '));186}187};188189190/**191* Removes a set of classes from an element. Prefer this call to192* repeatedly calling `goog.dom.classlist.remove` if you want to remove193* a large set of class names at once.194* @param {Element} element The element from which to remove classes.195* @param {IArrayLike<string>} classesToRemove An array-like object196* containing a collection of class names to remove from the element.197* This method may throw a DOM exception if classesToRemove contains invalid198* or empty class names.199*/200goog.dom.classlist.removeAll = function(element, classesToRemove) {201'use strict';202if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {203Array.prototype.forEach.call(classesToRemove, function(className) {204'use strict';205goog.dom.classlist.remove(element, className);206});207return;208}209210// Filter out those classes in classesToRemove.211goog.dom.classlist.set(212element,213Array.prototype.filter214.call(215goog.dom.classlist.get(element),216function(className) {217'use strict';218// If this class is not one we are trying to remove,219// add it to the array of new class names.220return !goog.array.contains(classesToRemove, className);221})222.join(' '));223};224225226/**227* Adds or removes a class depending on the enabled argument. This method228* may throw a DOM exception for an invalid or empty class name if DOMTokenList229* is used.230* @param {Element} element DOM node to add or remove the class on.231* @param {string} className Class name to add or remove.232* @param {boolean} enabled Whether to add or remove the class (true adds,233* false removes).234*/235goog.dom.classlist.enable = function(element, className, enabled) {236'use strict';237if (enabled) {238goog.dom.classlist.add(element, className);239} else {240goog.dom.classlist.remove(element, className);241}242};243244245/**246* Adds or removes a set of classes depending on the enabled argument. This247* method may throw a DOM exception for an invalid or empty class name if248* DOMTokenList is used.249* @param {!Element} element DOM node to add or remove the class on.250* @param {?IArrayLike<string>} classesToEnable An array-like object251* containing a collection of class names to add or remove from the element.252* @param {boolean} enabled Whether to add or remove the classes (true adds,253* false removes).254*/255goog.dom.classlist.enableAll = function(element, classesToEnable, enabled) {256'use strict';257var f = enabled ? goog.dom.classlist.addAll : goog.dom.classlist.removeAll;258f(element, classesToEnable);259};260261262/**263* Switches a class on an element from one to another without disturbing other264* classes. If the fromClass isn't removed, the toClass won't be added. This265* method may throw a DOM exception if the class names are empty or invalid.266* @param {Element} element DOM node to swap classes on.267* @param {string} fromClass Class to remove.268* @param {string} toClass Class to add.269* @return {boolean} Whether classes were switched.270*/271goog.dom.classlist.swap = function(element, fromClass, toClass) {272'use strict';273if (goog.dom.classlist.contains(element, fromClass)) {274goog.dom.classlist.remove(element, fromClass);275goog.dom.classlist.add(element, toClass);276return true;277}278return false;279};280281282/**283* Removes a class if an element has it, and adds it the element doesn't have284* it. Won't affect other classes on the node. This method may throw a DOM285* exception if the class name is empty or invalid.286* @param {Element} element DOM node to toggle class on.287* @param {string} className Class to toggle.288* @return {boolean} True if class was added, false if it was removed289* (in other words, whether element has the class after this function has290* been called).291*/292goog.dom.classlist.toggle = function(element, className) {293'use strict';294var add = !goog.dom.classlist.contains(element, className);295goog.dom.classlist.enable(element, className, add);296return add;297};298299300/**301* Adds and removes a class of an element. Unlike302* {@link goog.dom.classlist.swap}, this method adds the classToAdd regardless303* of whether the classToRemove was present and had been removed. This method304* may throw a DOM exception if the class names are empty or invalid.305*306* @param {Element} element DOM node to swap classes on.307* @param {string} classToRemove Class to remove.308* @param {string} classToAdd Class to add.309*/310goog.dom.classlist.addRemove = function(element, classToRemove, classToAdd) {311'use strict';312goog.dom.classlist.remove(element, classToRemove);313goog.dom.classlist.add(element, classToAdd);314};315316317