API Docs for: 3.13.0
Show:

File: dom/js/selector-css3.js

  1. /**
  2. * The selector css3 module provides support for css3 selectors.
  3. * @module dom
  4. * @submodule selector-css3
  5. * @for Selector
  6. */
  7.  
  8. /*
  9. an+b = get every _a_th node starting at the _b_th
  10. 0n+b = no repeat ("0" and "n" may both be omitted (together) , e.g. "0n+1" or "1", not "0+1"), return only the _b_th element
  11. 1n+b = get every element starting from b ("1" may may be omitted, e.g. "1n+0" or "n+0" or "n")
  12. an+0 = get every _a_th element, "0" may be omitted
  13. */
  14.  
  15. Y.Selector._reNth = /^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/;
  16.  
  17. Y.Selector._getNth = function(node, expr, tag, reverse) {
  18. Y.Selector._reNth.test(expr);
  19. var a = parseInt(RegExp.$1, 10), // include every _a_ elements (zero means no repeat, just first _a_)
  20. n = RegExp.$2, // "n"
  21. oddeven = RegExp.$3, // "odd" or "even"
  22. b = parseInt(RegExp.$4, 10) || 0, // start scan from element _b_
  23. result = [],
  24. siblings = Y.DOM._children(node.parentNode, tag),
  25. op;
  26.  
  27. if (oddeven) {
  28. a = 2; // always every other
  29. op = '+';
  30. n = 'n';
  31. b = (oddeven === 'odd') ? 1 : 0;
  32. } else if ( isNaN(a) ) {
  33. a = (n) ? 1 : 0; // start from the first or no repeat
  34. }
  35.  
  36. if (a === 0) { // just the first
  37. if (reverse) {
  38. b = siblings.length - b + 1;
  39. }
  40.  
  41. if (siblings[b - 1] === node) {
  42. return true;
  43. } else {
  44. return false;
  45. }
  46.  
  47. } else if (a < 0) {
  48. reverse = !!reverse;
  49. a = Math.abs(a);
  50. }
  51.  
  52. if (!reverse) {
  53. for (var i = b - 1, len = siblings.length; i < len; i += a) {
  54. if ( i >= 0 && siblings[i] === node ) {
  55. return true;
  56. }
  57. }
  58. } else {
  59. for (var i = siblings.length - b, len = siblings.length; i >= 0; i -= a) {
  60. if ( i < len && siblings[i] === node ) {
  61. return true;
  62. }
  63. }
  64. }
  65. return false;
  66. };
  67.  
  68. Y.mix(Y.Selector.pseudos, {
  69. 'root': function(node) {
  70. return node === node.ownerDocument.documentElement;
  71. },
  72.  
  73. 'nth-child': function(node, expr) {
  74. return Y.Selector._getNth(node, expr);
  75. },
  76.  
  77. 'nth-last-child': function(node, expr) {
  78. return Y.Selector._getNth(node, expr, null, true);
  79. },
  80.  
  81. 'nth-of-type': function(node, expr) {
  82. return Y.Selector._getNth(node, expr, node.tagName);
  83. },
  84.  
  85. 'nth-last-of-type': function(node, expr) {
  86. return Y.Selector._getNth(node, expr, node.tagName, true);
  87. },
  88.  
  89. 'last-child': function(node) {
  90. var children = Y.DOM._children(node.parentNode);
  91. return children[children.length - 1] === node;
  92. },
  93.  
  94. 'first-of-type': function(node) {
  95. return Y.DOM._children(node.parentNode, node.tagName)[0] === node;
  96. },
  97.  
  98. 'last-of-type': function(node) {
  99. var children = Y.DOM._children(node.parentNode, node.tagName);
  100. return children[children.length - 1] === node;
  101. },
  102.  
  103. 'only-child': function(node) {
  104. var children = Y.DOM._children(node.parentNode);
  105. return children.length === 1 && children[0] === node;
  106. },
  107.  
  108. 'only-of-type': function(node) {
  109. var children = Y.DOM._children(node.parentNode, node.tagName);
  110. return children.length === 1 && children[0] === node;
  111. },
  112.  
  113. 'empty': function(node) {
  114. return node.childNodes.length === 0;
  115. },
  116.  
  117. 'not': function(node, expr) {
  118. return !Y.Selector.test(node, expr);
  119. },
  120.  
  121. 'contains': function(node, expr) {
  122. var text = node.innerText || node.textContent || '';
  123. return text.indexOf(expr) > -1;
  124. },
  125.  
  126. 'checked': function(node) {
  127. return (node.checked === true || node.selected === true);
  128. },
  129.  
  130. enabled: function(node) {
  131. return (node.disabled !== undefined && !node.disabled);
  132. },
  133.  
  134. disabled: function(node) {
  135. return (node.disabled);
  136. }
  137. });
  138.  
  139. Y.mix(Y.Selector.operators, {
  140. '^=': '^{val}', // Match starts with value
  141. '$=': '{val}$', // Match ends with value
  142. '*=': '{val}' // Match contains value as substring
  143. });
  144.  
  145. Y.Selector.combinators['~'] = {
  146. axis: 'previousSibling'
  147. };
  148.