dom-class.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. define(["./_base/lang", "./_base/array", "./dom"], function(lang, array, dom){
  2. // module:
  3. // dojo/dom-class
  4. var className = "className";
  5. /* Part I of classList-based implementation is preserved here for posterity
  6. var classList = "classList";
  7. has.add("dom-classList", function(){
  8. return classList in document.createElement("p");
  9. });
  10. */
  11. // =============================
  12. // (CSS) Class Functions
  13. // =============================
  14. var cls, // exports object
  15. spaces = /\s+/, a1 = [""];
  16. function str2array(s){
  17. if(typeof s == "string" || s instanceof String){
  18. if(s && !spaces.test(s)){
  19. a1[0] = s;
  20. return a1;
  21. }
  22. var a = s.split(spaces);
  23. if(a.length && !a[0]){
  24. a.shift();
  25. }
  26. if(a.length && !a[a.length - 1]){
  27. a.pop();
  28. }
  29. return a;
  30. }
  31. // assumed to be an array
  32. if(!s){
  33. return [];
  34. }
  35. return array.filter(s, function(x){ return x; });
  36. }
  37. /* Part II of classList-based implementation is preserved here for posterity
  38. if(has("dom-classList")){
  39. // new classList version
  40. cls = {
  41. contains: function containsClass(node, classStr){
  42. var clslst = classStr && dom.byId(node)[classList];
  43. return clslst && clslst.contains(classStr); // Boolean
  44. },
  45. add: function addClass(node, classStr){
  46. node = dom.byId(node);
  47. classStr = str2array(classStr);
  48. for(var i = 0, len = classStr.length; i < len; ++i){
  49. node[classList].add(classStr[i]);
  50. }
  51. },
  52. remove: function removeClass(node, classStr){
  53. node = dom.byId(node);
  54. if(classStr === undefined){
  55. node[className] = "";
  56. }else{
  57. classStr = str2array(classStr);
  58. for(var i = 0, len = classStr.length; i < len; ++i){
  59. node[classList].remove(classStr[i]);
  60. }
  61. }
  62. },
  63. replace: function replaceClass(node, addClassStr, removeClassStr){
  64. node = dom.byId(node);
  65. if(removeClassStr === undefined){
  66. node[className] = "";
  67. }else{
  68. removeClassStr = str2array(removeClassStr);
  69. for(var i = 0, len = removeClassStr.length; i < len; ++i){
  70. node[classList].remove(removeClassStr[i]);
  71. }
  72. }
  73. addClassStr = str2array(addClassStr);
  74. for(i = 0, len = addClassStr.length; i < len; ++i){
  75. node[classList].add(addClassStr[i]);
  76. }
  77. },
  78. toggle: function toggleClass(node, classStr, condition){
  79. node = dom.byId(node);
  80. if(condition === undefined){
  81. classStr = str2array(classStr);
  82. for(var i = 0, len = classStr.length; i < len; ++i){
  83. node[classList].toggle(classStr[i]);
  84. }
  85. }else{
  86. cls[condition ? "add" : "remove"](node, classStr);
  87. }
  88. return condition; // Boolean
  89. }
  90. }
  91. }
  92. */
  93. // regular DOM version
  94. var fakeNode = {}; // for effective replacement
  95. cls = {
  96. // summary:
  97. // This module defines the core dojo DOM class API.
  98. contains: function containsClass(/*DomNode|String*/ node, /*String*/ classStr){
  99. // summary:
  100. // Returns whether or not the specified classes are a portion of the
  101. // class list currently applied to the node.
  102. // node: String|DOMNode
  103. // String ID or DomNode reference to check the class for.
  104. // classStr: String
  105. // A string class name to look for.
  106. // example:
  107. // Do something if a node with id="someNode" has class="aSillyClassName" present
  108. // | if(dojo.hasClass("someNode","aSillyClassName")){ ... }
  109. return ((" " + dom.byId(node)[className] + " ").indexOf(" " + classStr + " ") >= 0); // Boolean
  110. },
  111. add: function addClass(/*DomNode|String*/ node, /*String|Array*/ classStr){
  112. // summary:
  113. // Adds the specified classes to the end of the class list on the
  114. // passed node. Will not re-apply duplicate classes.
  115. //
  116. // node: String|DOMNode
  117. // String ID or DomNode reference to add a class string too
  118. //
  119. // classStr: String|Array
  120. // A String class name to add, or several space-separated class names,
  121. // or an array of class names.
  122. //
  123. // example:
  124. // Add a class to some node:
  125. // | require(["dojo/dom-class"], function(domClass){
  126. // | domClass.add("someNode", "anewClass");
  127. // | });
  128. //
  129. // example:
  130. // Add two classes at once:
  131. // | require(["dojo/dom-class"], function(domClass){
  132. // | domClass.add("someNode", "firstClass secondClass");
  133. // | });
  134. //
  135. // example:
  136. // Add two classes at once (using array):
  137. // | require(["dojo/dom-class"], function(domClass){
  138. // | domClass.add("someNode", ["firstClass", "secondClass"]);
  139. // | });
  140. //
  141. // example:
  142. // Available in `dojo/NodeList` for multiple additions
  143. // | require(["dojo/query"], function(query){
  144. // | query("ul > li").addClass("firstLevel");
  145. // | });
  146. node = dom.byId(node);
  147. classStr = str2array(classStr);
  148. var cls = node[className], oldLen;
  149. cls = cls ? " " + cls + " " : " ";
  150. oldLen = cls.length;
  151. for(var i = 0, len = classStr.length, c; i < len; ++i){
  152. c = classStr[i];
  153. if(c && cls.indexOf(" " + c + " ") < 0){
  154. cls += c + " ";
  155. }
  156. }
  157. if(oldLen < cls.length){
  158. node[className] = cls.substr(1, cls.length - 2);
  159. }
  160. },
  161. remove: function removeClass(/*DomNode|String*/ node, /*String|Array?*/ classStr){
  162. // summary:
  163. // Removes the specified classes from node. No `contains()`
  164. // check is required.
  165. //
  166. // node: String|DOMNode
  167. // String ID or DomNode reference to remove the class from.
  168. //
  169. // classStr: String|Array
  170. // An optional String class name to remove, or several space-separated
  171. // class names, or an array of class names. If omitted, all class names
  172. // will be deleted.
  173. //
  174. // example:
  175. // Remove a class from some node:
  176. // | require(["dojo/dom-class"], function(domClass){
  177. // | domClass.remove("someNode", "firstClass");
  178. // | });
  179. //
  180. // example:
  181. // Remove two classes from some node:
  182. // | require(["dojo/dom-class"], function(domClass){
  183. // | domClass.remove("someNode", "firstClass secondClass");
  184. // | });
  185. //
  186. // example:
  187. // Remove two classes from some node (using array):
  188. // | require(["dojo/dom-class"], function(domClass){
  189. // | domClass.remove("someNode", ["firstClass", "secondClass"]);
  190. // | });
  191. //
  192. // example:
  193. // Remove all classes from some node:
  194. // | require(["dojo/dom-class"], function(domClass){
  195. // | domClass.remove("someNode");
  196. // | });
  197. //
  198. // example:
  199. // Available in `dojo/NodeList` for multiple removal
  200. // | require(["dojo/query"], function(query){
  201. // | query("ul > li").removeClass("foo");
  202. // | });
  203. node = dom.byId(node);
  204. var cls;
  205. if(classStr !== undefined){
  206. classStr = str2array(classStr);
  207. cls = " " + node[className] + " ";
  208. for(var i = 0, len = classStr.length; i < len; ++i){
  209. cls = cls.replace(" " + classStr[i] + " ", " ");
  210. }
  211. cls = lang.trim(cls);
  212. }else{
  213. cls = "";
  214. }
  215. if(node[className] != cls){ node[className] = cls; }
  216. },
  217. replace: function replaceClass(/*DomNode|String*/ node, /*String|Array*/ addClassStr, /*String|Array?*/ removeClassStr){
  218. // summary:
  219. // Replaces one or more classes on a node if not present.
  220. // Operates more quickly than calling dojo.removeClass and dojo.addClass
  221. //
  222. // node: String|DOMNode
  223. // String ID or DomNode reference to remove the class from.
  224. //
  225. // addClassStr: String|Array
  226. // A String class name to add, or several space-separated class names,
  227. // or an array of class names.
  228. //
  229. // removeClassStr: String|Array?
  230. // A String class name to remove, or several space-separated class names,
  231. // or an array of class names.
  232. //
  233. // example:
  234. // | require(["dojo/dom-class"], function(domClass){
  235. // | domClass.replace("someNode", "add1 add2", "remove1 remove2");
  236. // | });
  237. //
  238. // example:
  239. // Replace all classes with addMe
  240. // | require(["dojo/dom-class"], function(domClass){
  241. // | domClass.replace("someNode", "addMe");
  242. // | });
  243. //
  244. // example:
  245. // Available in `dojo/NodeList` for multiple toggles
  246. // | require(["dojo/query"], function(query){
  247. // | query(".findMe").replaceClass("addMe", "removeMe");
  248. // | });
  249. node = dom.byId(node);
  250. fakeNode[className] = node[className];
  251. cls.remove(fakeNode, removeClassStr);
  252. cls.add(fakeNode, addClassStr);
  253. if(node[className] !== fakeNode[className]){
  254. node[className] = fakeNode[className];
  255. }
  256. },
  257. toggle: function toggleClass(/*DomNode|String*/ node, /*String|Array*/ classStr, /*Boolean?*/ condition){
  258. // summary:
  259. // Adds a class to node if not present, or removes if present.
  260. // Pass a boolean condition if you want to explicitly add or remove.
  261. // Returns the condition that was specified directly or indirectly.
  262. //
  263. // node: String|DOMNode
  264. // String ID or DomNode reference to toggle a class string
  265. //
  266. // classStr: String|Array
  267. // A String class name to toggle, or several space-separated class names,
  268. // or an array of class names.
  269. //
  270. // condition:
  271. // If passed, true means to add the class, false means to remove.
  272. // Otherwise dojo.hasClass(node, classStr) is used to detect the class presence.
  273. //
  274. // example:
  275. // | require(["dojo/dom-class"], function(domClass){
  276. // | domClass.toggle("someNode", "hovered");
  277. // | });
  278. //
  279. // example:
  280. // Forcefully add a class
  281. // | require(["dojo/dom-class"], function(domClass){
  282. // | domClass.toggle("someNode", "hovered", true);
  283. // | });
  284. //
  285. // example:
  286. // Available in `dojo/NodeList` for multiple toggles
  287. // | require(["dojo/query"], function(query){
  288. // | query(".toggleMe").toggleClass("toggleMe");
  289. // | });
  290. node = dom.byId(node);
  291. if(condition === undefined){
  292. classStr = str2array(classStr);
  293. for(var i = 0, len = classStr.length, c; i < len; ++i){
  294. c = classStr[i];
  295. cls[cls.contains(node, c) ? "remove" : "add"](node, c);
  296. }
  297. }else{
  298. cls[condition ? "add" : "remove"](node, classStr);
  299. }
  300. return condition; // Boolean
  301. }
  302. };
  303. return cls;
  304. });