PageRenderTime 38ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/django/contrib/admin/media/js/getElementsBySelector.js

https://code.google.com/p/mango-py/
JavaScript | 167 lines | 138 code | 2 blank | 27 comment | 18 complexity | 92ac9f95add35b1991062b62ce933b23 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /* document.getElementsBySelector(selector)
  2. - returns an array of element objects from the current document
  3. matching the CSS selector. Selectors can contain element names,
  4. class names and ids and can be nested. For example:
  5. elements = document.getElementsBySelect('div#main p a.external')
  6. Will return an array of all 'a' elements with 'external' in their
  7. class attribute that are contained inside 'p' elements that are
  8. contained inside the 'div' element which has id="main"
  9. New in version 0.4: Support for CSS2 and CSS3 attribute selectors:
  10. See http://www.w3.org/TR/css3-selectors/#attribute-selectors
  11. Version 0.4 - Simon Willison, March 25th 2003
  12. -- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6, Internet Explorer 5 on Windows
  13. -- Opera 7 fails
  14. */
  15. function getAllChildren(e) {
  16. // Returns all children of element. Workaround required for IE5/Windows. Ugh.
  17. return e.all ? e.all : e.getElementsByTagName('*');
  18. }
  19. document.getElementsBySelector = function(selector) {
  20. // Attempt to fail gracefully in lesser browsers
  21. if (!document.getElementsByTagName) {
  22. return new Array();
  23. }
  24. // Split selector in to tokens
  25. var tokens = selector.split(' ');
  26. var currentContext = new Array(document);
  27. for (var i = 0; i < tokens.length; i++) {
  28. token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');;
  29. if (token.indexOf('#') > -1) {
  30. // Token is an ID selector
  31. var bits = token.split('#');
  32. var tagName = bits[0];
  33. var id = bits[1];
  34. var element = document.getElementById(id);
  35. if (!element || (tagName && element.nodeName.toLowerCase() != tagName)) {
  36. // ID not found or tag with that ID not found, return false.
  37. return new Array();
  38. }
  39. // Set currentContext to contain just this element
  40. currentContext = new Array(element);
  41. continue; // Skip to next token
  42. }
  43. if (token.indexOf('.') > -1) {
  44. // Token contains a class selector
  45. var bits = token.split('.');
  46. var tagName = bits[0];
  47. var className = bits[1];
  48. if (!tagName) {
  49. tagName = '*';
  50. }
  51. // Get elements matching tag, filter them for class selector
  52. var found = new Array;
  53. var foundCount = 0;
  54. for (var h = 0; h < currentContext.length; h++) {
  55. var elements;
  56. if (tagName == '*') {
  57. elements = getAllChildren(currentContext[h]);
  58. } else {
  59. try {
  60. elements = currentContext[h].getElementsByTagName(tagName);
  61. }
  62. catch(e) {
  63. elements = [];
  64. }
  65. }
  66. for (var j = 0; j < elements.length; j++) {
  67. found[foundCount++] = elements[j];
  68. }
  69. }
  70. currentContext = new Array;
  71. var currentContextIndex = 0;
  72. for (var k = 0; k < found.length; k++) {
  73. if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) {
  74. currentContext[currentContextIndex++] = found[k];
  75. }
  76. }
  77. continue; // Skip to next token
  78. }
  79. // Code to deal with attribute selectors
  80. if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
  81. var tagName = RegExp.$1;
  82. var attrName = RegExp.$2;
  83. var attrOperator = RegExp.$3;
  84. var attrValue = RegExp.$4;
  85. if (!tagName) {
  86. tagName = '*';
  87. }
  88. // Grab all of the tagName elements within current context
  89. var found = new Array;
  90. var foundCount = 0;
  91. for (var h = 0; h < currentContext.length; h++) {
  92. var elements;
  93. if (tagName == '*') {
  94. elements = getAllChildren(currentContext[h]);
  95. } else {
  96. elements = currentContext[h].getElementsByTagName(tagName);
  97. }
  98. for (var j = 0; j < elements.length; j++) {
  99. found[foundCount++] = elements[j];
  100. }
  101. }
  102. currentContext = new Array;
  103. var currentContextIndex = 0;
  104. var checkFunction; // This function will be used to filter the elements
  105. switch (attrOperator) {
  106. case '=': // Equality
  107. checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
  108. break;
  109. case '~': // Match one of space seperated words
  110. checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };
  111. break;
  112. case '|': // Match start with value followed by optional hyphen
  113. checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
  114. break;
  115. case '^': // Match starts with value
  116. checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
  117. break;
  118. case '$': // Match ends with value - fails with "Warning" in Opera 7
  119. checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
  120. break;
  121. case '*': // Match ends with value
  122. checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
  123. break;
  124. default :
  125. // Just test for existence of attribute
  126. checkFunction = function(e) { return e.getAttribute(attrName); };
  127. }
  128. currentContext = new Array;
  129. var currentContextIndex = 0;
  130. for (var k = 0; k < found.length; k++) {
  131. if (checkFunction(found[k])) {
  132. currentContext[currentContextIndex++] = found[k];
  133. }
  134. }
  135. // alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue);
  136. continue; // Skip to next token
  137. }
  138. // If we get here, token is JUST an element (not a class or ID selector)
  139. tagName = token;
  140. var found = new Array;
  141. var foundCount = 0;
  142. for (var h = 0; h < currentContext.length; h++) {
  143. var elements = currentContext[h].getElementsByTagName(tagName);
  144. for (var j = 0; j < elements.length; j++) {
  145. found[foundCount++] = elements[j];
  146. }
  147. }
  148. currentContext = found;
  149. }
  150. return currentContext;
  151. }
  152. /* That revolting regular expression explained
  153. /^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/
  154. \---/ \---/\-------------/ \-------/
  155. | | | |
  156. | | | The value
  157. | | ~,|,^,$,* or =
  158. | Attribute
  159. Tag
  160. */