selector.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. function _contains(nodeA, nodeB) {
  2. // Bypass comparison on document node since
  3. // we don't deal with cross frame,
  4. // e.g. document.body.parentNode.parentNode == document (false for IE).
  5. if (nodeA.nodeType == 9 && nodeB.nodeType != 9) {
  6. return true;
  7. }
  8. while ((nodeB = nodeB.parentNode)) {
  9. if (nodeB == nodeA) {
  10. return true;
  11. }
  12. }
  13. return false;
  14. }
  15. var _getSetAttrDiv = document.createElement('div');
  16. _getSetAttrDiv.setAttribute('className', 't');
  17. var _GET_SET_ATTRIBUTE = _getSetAttrDiv.className !== 't';
  18. function _getAttr(el, key) {
  19. key = key.toLowerCase();
  20. var val = null;
  21. // IE6,IE7,IE=EmulateIE7
  22. if (!_GET_SET_ATTRIBUTE && el.nodeName.toLowerCase() != 'script') {
  23. var div = el.ownerDocument.createElement('div');
  24. div.appendChild(el.cloneNode(false));
  25. var list = _getAttrList(_unescape(div.innerHTML));
  26. if (key in list) {
  27. val = list[key];
  28. }
  29. } else {
  30. // IE8设置<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />,抛出异常
  31. try {
  32. val = el.getAttribute(key, 2);
  33. } catch(e) {
  34. val = el.getAttribute(key, 1);
  35. }
  36. }
  37. if (key === 'style' && val !== null) {
  38. val = _formatCss(val);
  39. }
  40. return val;
  41. }
  42. function _queryAll(expr, root) {
  43. var exprList = expr.split(',');
  44. if (exprList.length > 1) {
  45. var mergedResults = [];
  46. _each(exprList, function() {
  47. _each(_queryAll(this, root), function() {
  48. if (_inArray(this, mergedResults) < 0) {
  49. mergedResults.push(this);
  50. }
  51. });
  52. });
  53. return mergedResults;
  54. }
  55. root = root || document;
  56. function escape(str) {
  57. if (typeof str != 'string') {
  58. return str;
  59. }
  60. return str.replace(/([^\w\-])/g, '\\$1');
  61. }
  62. function stripslashes(str) {
  63. return str.replace(/\\/g, '');
  64. }
  65. function cmpTag(tagA, tagB) {
  66. return tagA === '*' || tagA.toLowerCase() === escape(tagB.toLowerCase());
  67. }
  68. function byId(id, tag, root) {
  69. var arr = [],
  70. doc = root.ownerDocument || root,
  71. el = doc.getElementById(stripslashes(id));
  72. if (el) {
  73. if (cmpTag(tag, el.nodeName) && _contains(root, el)) {
  74. arr.push(el);
  75. }
  76. }
  77. return arr;
  78. }
  79. function byClass(className, tag, root) {
  80. var doc = root.ownerDocument || root, arr = [], els, i, len, el;
  81. if (root.getElementsByClassName) {
  82. els = root.getElementsByClassName(stripslashes(className));
  83. for (i = 0, len = els.length; i < len; i++) {
  84. el = els[i];
  85. if (cmpTag(tag, el.nodeName)) {
  86. arr.push(el);
  87. }
  88. }
  89. } else if (doc.querySelectorAll) {
  90. els = doc.querySelectorAll((root.nodeName !== '#document' ? root.nodeName + ' ' : '') + tag + '.' + className);
  91. for (i = 0, len = els.length; i < len; i++) {
  92. el = els[i];
  93. if (_contains(root, el)) {
  94. arr.push(el);
  95. }
  96. }
  97. } else {
  98. els = root.getElementsByTagName(tag);
  99. className = ' ' + className + ' ';
  100. for (i = 0, len = els.length; i < len; i++) {
  101. el = els[i];
  102. if (el.nodeType == 1) {
  103. var cls = el.className;
  104. if (cls && (' ' + cls + ' ').indexOf(className) > -1) {
  105. arr.push(el);
  106. }
  107. }
  108. }
  109. }
  110. return arr;
  111. }
  112. function byName(name, tag, root) {
  113. var arr = [], doc = root.ownerDocument || root,
  114. els = doc.getElementsByName(stripslashes(name)), el;
  115. for (var i = 0, len = els.length; i < len; i++) {
  116. el = els[i];
  117. if (cmpTag(tag, el.nodeName) && _contains(root, el)) {
  118. if (el.getAttribute('name') !== null) {
  119. arr.push(el);
  120. }
  121. }
  122. }
  123. return arr;
  124. }
  125. function byAttr(key, val, tag, root) {
  126. var arr = [], els = root.getElementsByTagName(tag), el;
  127. for (var i = 0, len = els.length; i < len; i++) {
  128. el = els[i];
  129. if (el.nodeType == 1) {
  130. if (val === null) {
  131. if (_getAttr(el, key) !== null) {
  132. arr.push(el);
  133. }
  134. } else {
  135. if (val === escape(_getAttr(el, key))) {
  136. arr.push(el);
  137. }
  138. }
  139. }
  140. }
  141. return arr;
  142. }
  143. function select(expr, root) {
  144. var arr = [], matches;
  145. matches = /^((?:\\.|[^.#\s\[<>])+)/.exec(expr);
  146. var tag = matches ? matches[1] : '*';
  147. if ((matches = /#((?:[\w\-]|\\.)+)$/.exec(expr))) {
  148. arr = byId(matches[1], tag, root);
  149. } else if ((matches = /\.((?:[\w\-]|\\.)+)$/.exec(expr))) {
  150. arr = byClass(matches[1], tag, root);
  151. } else if ((matches = /\[((?:[\w\-]|\\.)+)\]/.exec(expr))) {
  152. arr = byAttr(matches[1].toLowerCase(), null, tag, root);
  153. } else if ((matches = /\[((?:[\w\-]|\\.)+)\s*=\s*['"]?((?:\\.|[^'"]+)+)['"]?\]/.exec(expr))) {
  154. var key = matches[1].toLowerCase(), val = matches[2];
  155. if (key === 'id') {
  156. arr = byId(val, tag, root);
  157. } else if (key === 'class') {
  158. arr = byClass(val, tag, root);
  159. } else if (key === 'name') {
  160. arr = byName(val, tag, root);
  161. } else {
  162. arr = byAttr(key, val, tag, root);
  163. }
  164. } else {
  165. var els = root.getElementsByTagName(tag), el;
  166. for (var i = 0, len = els.length; i < len; i++) {
  167. el = els[i];
  168. if (el.nodeType == 1) {
  169. arr.push(el);
  170. }
  171. }
  172. }
  173. return arr;
  174. }
  175. var parts = [], arr, re = /((?:\\.|[^\s>])+|[\s>])/g;
  176. while ((arr = re.exec(expr))) {
  177. if (arr[1] !== ' ') {
  178. parts.push(arr[1]);
  179. }
  180. }
  181. var results = [];
  182. if (parts.length == 1) {
  183. return select(parts[0], root);
  184. }
  185. var isChild = false, part, els, subResults, val, v, i, j, k, length, len, l;
  186. for (i = 0, lenth = parts.length; i < lenth; i++) {
  187. part = parts[i];
  188. if (part === '>') {
  189. isChild = true;
  190. continue;
  191. }
  192. if (i > 0) {
  193. els = [];
  194. for (j = 0, len = results.length; j < len; j++) {
  195. val = results[j];
  196. subResults = select(part, val);
  197. for (k = 0, l = subResults.length; k < l; k++) {
  198. v = subResults[k];
  199. if (isChild) {
  200. if (val === v.parentNode) {
  201. els.push(v);
  202. }
  203. } else {
  204. els.push(v);
  205. }
  206. }
  207. }
  208. results = els;
  209. } else {
  210. results = select(part, root);
  211. }
  212. if (results.length === 0) {
  213. return [];
  214. }
  215. }
  216. return results;
  217. }
  218. function _query(expr, root) {
  219. var arr = _queryAll(expr, root);
  220. return arr.length > 0 ? arr[0] : null;
  221. }
  222. K.query = _query;
  223. K.queryAll = _queryAll;