traversing.js 4.4 KB

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