traversing.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. define([
  2. "./core",
  3. "./var/indexOf",
  4. "./traversing/var/rneedsContext",
  5. "./core/init",
  6. "./traversing/findFilter",
  7. "./selector"
  8. ], function( jQuery, indexOf, rneedsContext ) {
  9. var rparentsprev = /^(?:parents|prev(?:Until|All))/,
  10. // Methods guaranteed to produce a unique set when starting from a unique set
  11. guaranteedUnique = {
  12. children: true,
  13. contents: true,
  14. next: true,
  15. prev: true
  16. };
  17. jQuery.extend({
  18. dir: function( elem, dir, until ) {
  19. var matched = [],
  20. truncate = until !== undefined;
  21. while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
  22. if ( elem.nodeType === 1 ) {
  23. if ( truncate && jQuery( elem ).is( until ) ) {
  24. break;
  25. }
  26. matched.push( elem );
  27. }
  28. }
  29. return matched;
  30. },
  31. sibling: function( n, elem ) {
  32. var matched = [];
  33. for ( ; n; n = n.nextSibling ) {
  34. if ( n.nodeType === 1 && n !== elem ) {
  35. matched.push( n );
  36. }
  37. }
  38. return matched;
  39. }
  40. });
  41. jQuery.fn.extend({
  42. has: function( target ) {
  43. var targets = jQuery( target, this ),
  44. l = targets.length;
  45. return this.filter(function() {
  46. var i = 0;
  47. for ( ; i < l; i++ ) {
  48. if ( jQuery.contains( this, targets[i] ) ) {
  49. return true;
  50. }
  51. }
  52. });
  53. },
  54. closest: function( selectors, context ) {
  55. var cur,
  56. i = 0,
  57. l = this.length,
  58. matched = [],
  59. pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
  60. jQuery( selectors, context || this.context ) :
  61. 0;
  62. for ( ; i < l; i++ ) {
  63. for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
  64. // Always skip document fragments
  65. if ( cur.nodeType < 11 && (pos ?
  66. pos.index(cur) > -1 :
  67. // Don't pass non-elements to Sizzle
  68. cur.nodeType === 1 &&
  69. jQuery.find.matchesSelector(cur, selectors)) ) {
  70. matched.push( cur );
  71. break;
  72. }
  73. }
  74. }
  75. return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
  76. },
  77. // Determine the position of an element within the set
  78. index: function( elem ) {
  79. // No argument, return index in parent
  80. if ( !elem ) {
  81. return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
  82. }
  83. // Index in selector
  84. if ( typeof elem === "string" ) {
  85. return indexOf.call( jQuery( elem ), this[ 0 ] );
  86. }
  87. // Locate the position of the desired element
  88. return indexOf.call( this,
  89. // If it receives a jQuery object, the first element is used
  90. elem.jquery ? elem[ 0 ] : elem
  91. );
  92. },
  93. add: function( selector, context ) {
  94. return this.pushStack(
  95. jQuery.unique(
  96. jQuery.merge( this.get(), jQuery( selector, context ) )
  97. )
  98. );
  99. },
  100. addBack: function( selector ) {
  101. return this.add( selector == null ?
  102. this.prevObject : this.prevObject.filter(selector)
  103. );
  104. }
  105. });
  106. function sibling( cur, dir ) {
  107. while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
  108. return cur;
  109. }
  110. jQuery.each({
  111. parent: function( elem ) {
  112. var parent = elem.parentNode;
  113. return parent && parent.nodeType !== 11 ? parent : null;
  114. },
  115. parents: function( elem ) {
  116. return jQuery.dir( elem, "parentNode" );
  117. },
  118. parentsUntil: function( elem, i, until ) {
  119. return jQuery.dir( elem, "parentNode", until );
  120. },
  121. next: function( elem ) {
  122. return sibling( elem, "nextSibling" );
  123. },
  124. prev: function( elem ) {
  125. return sibling( elem, "previousSibling" );
  126. },
  127. nextAll: function( elem ) {
  128. return jQuery.dir( elem, "nextSibling" );
  129. },
  130. prevAll: function( elem ) {
  131. return jQuery.dir( elem, "previousSibling" );
  132. },
  133. nextUntil: function( elem, i, until ) {
  134. return jQuery.dir( elem, "nextSibling", until );
  135. },
  136. prevUntil: function( elem, i, until ) {
  137. return jQuery.dir( elem, "previousSibling", until );
  138. },
  139. siblings: function( elem ) {
  140. return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
  141. },
  142. children: function( elem ) {
  143. return jQuery.sibling( elem.firstChild );
  144. },
  145. contents: function( elem ) {
  146. return elem.contentDocument || jQuery.merge( [], elem.childNodes );
  147. }
  148. }, function( name, fn ) {
  149. jQuery.fn[ name ] = function( until, selector ) {
  150. var matched = jQuery.map( this, fn, until );
  151. if ( name.slice( -5 ) !== "Until" ) {
  152. selector = until;
  153. }
  154. if ( selector && typeof selector === "string" ) {
  155. matched = jQuery.filter( selector, matched );
  156. }
  157. if ( this.length > 1 ) {
  158. // Remove duplicates
  159. if ( !guaranteedUnique[ name ] ) {
  160. jQuery.unique( matched );
  161. }
  162. // Reverse order for parents* and prev-derivatives
  163. if ( rparentsprev.test( name ) ) {
  164. matched.reverse();
  165. }
  166. }
  167. return this.pushStack( matched );
  168. };
  169. });
  170. return jQuery;
  171. });