Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
jQuery查找某个类的next/prev元素,但不一定是同级元素_Jquery_Jquery Selectors_Next - Fatal编程技术网

jQuery查找某个类的next/prev元素,但不一定是同级元素

jQuery查找某个类的next/prev元素,但不一定是同级元素,jquery,jquery-selectors,next,Jquery,Jquery Selectors,Next,next、prev、nextAll和prevAll方法非常有用,但如果您试图查找的元素不在同一父元素中,则不可用。我想做的是这样的: <div> <span id="click">Hello</span> </div> <div> <p class="find">World></p> </div> 你好 World> 当按下id为click的span时,我想将下一个元素与类

next、prev、nextAll和prevAll方法非常有用,但如果您试图查找的元素不在同一父元素中,则不可用。我想做的是这样的:

<div>
    <span id="click">Hello</span>
</div>
<div>
    <p class="find">World></p>
</div>

你好

World>


当按下id为
click
的span时,我想将下一个元素与类
find
匹配,在这种情况下,该类不是被单击元素的同级元素,因此不会工作。

我认为解决此问题的唯一方法是对当前元素之后的元素进行递归搜索。对于这个问题,jQuery没有提供简单的解决方案。如果只希望在父元素的同级中查找元素(如示例中所示),则不需要执行递归搜索,但必须执行多个搜索

我创建了一个示例(实际上,它不是递归的),它可以满足您的需要(我希望如此)。它选择当前单击元素之后的所有元素,并使其变为红色:

<script type="text/javascript" charset="utf-8">
    $(function () {
        $('#click').click(function() {
            var parent = $(this);
            alert(parent);
            do {
                $(parent).find('.find').css('background-color','red'); 
                parent = $(parent).parent();
            } while(parent !== false);
        });
    });
</script>

$(函数(){
$('#click')。单击(函数(){
var parent=$(这是);
警惕(家长);
做{
$(父).find('.find').css('background-color','red');
parent=$(parent.parent();
}while(parent!==false);
});
});

以下表达式应该(除非语法错误!)找到父级中包含
p.find
元素的所有同级,然后找到那些
p.find
元素并将其颜色更改为蓝色

$(this).parent().nextAll(":has(p.find)").find(".find").css('background-color','blue');

当然,如果您的页面结构使得
p.find
出现在完全不同的层次结构中(例如祖父母的兄弟姐妹),那么它将不起作用。

我的解决方案将涉及稍微调整标记以使jQuery更容易。如果这不可能或不是一个吸引人的答案,请忽略

我会用一个“家长”包装你想做的事

<div class="find-wrapper">
    <div><span id="click">hello</span></div>
    <div><p class="find">world></p></div>
</div>
这使您能够灵活地在我建议的包装器中包含任何类型的标记和层次结构,并且仍然可以可靠地找到目标


祝你好运

我今天自己也在解决这个问题,我想到了以下几点:

/**
 * Find the next element matching a certain selector. Differs from next() in
 *  that it searches outside the current element's parent.
 *  
 * @param selector The selector to search for
 * @param steps (optional) The number of steps to search, the default is 1
 * @param scope (optional) The scope to search in, the default is document wide 
 */
$.fn.findNext = function(selector, steps, scope)
{
    // Steps given? Then parse to int 
    if (steps)
    {
        steps = Math.floor(steps);
    }
    else if (steps === 0)
    {
        // Stupid case :)
        return this;
    }
    else
    {
        // Else, try the easy way
        var next = this.next(selector);
        if (next.length)
            return next;
        // Easy way failed, try the hard way :)
        steps = 1;
    }

    // Set scope to document or user-defined
    scope = (scope) ? $(scope) : $(document);

    // Find kids that match selector: used as exclusion filter
    var kids = this.find(selector);

    // Find in parent(s)
    hay = $(this);
    while(hay[0] != scope[0])
    {
        // Move up one level
        hay = hay.parent();     
        // Select all kids of parent
        //  - excluding kids of current element (next != inside),
        //  - add current element (will be added in document order)
        var rs = hay.find(selector).not(kids).add($(this));
        // Move the desired number of steps
        var id = rs.index(this) + steps;
        // Result found? then return
        if (id > -1 && id < rs.length)
            return $(rs[id]);
    }
    // Return empty result
    return $([]);
}

我怀疑它在大型结构上会表现得很好,但这里是:)

试试这个。它将标记元素,创建一组与选择器匹配的元素,并从元素后面的集合中收集所有元素

$.fn.findNext = function ( selector ) {
    var set = $( [] ), found = false;
    $( this ).attr( "findNext" , "true" );
    $( selector ).each( function( i , element ) {
        element = $( element );
        if ( found == true ) set = set.add( element )
        if ( element.attr("findNext") == "true" ) found = true;
    })
    $( this ).removeAttr( "findNext" )
    return set
}
编辑

使用jquerys索引方法的解决方案更简单。但是,从中调用方法的元素需要由相同的选择器选择

$.fn.findNext = function( selector ){
    var set = $( selector );
    return set.eq( set.index( this, ) + 1 )
}
为了使功能摆脱这种障碍,我们可以使用自己的浏览器

压缩变量名时,这只会变成两行

编辑3 使用位运算,此函数可能更快

$.fn.findNextAll = function( selector ){
  var that = this[ 0 ],
    selection = $( selector ).get();
  return this.pushStack(
    !that && selection || $.grep( selection, function(n){
       return that.compareDocumentPosition(n) & (1<<2);
       // if you are looking for previous elements it should be & (1<<1);
    })
  );
}
$.fn.findNext = function( selector ){
  return this.pushStack( this.findNextAll( selector ).first() );
}
$.fn.findNextAll=函数(选择器){
var,即=此[0],
selection=$(选择器).get();
返回这个.pushStack(
!that&&selection | |$.grep(选择,函数(n)){

返回.compareDocumentPosition(n)和(1我没有想到的一个缺点可能是,您调用findNext的元素需要由同一个选择器选择,否则它只会在所有元素中循环,而找不到您标记的元素。谢谢,我已经查看了所有内容,没有其他人像您这样简洁地回答了非同级的问题。谢谢您您的工作。对于非常大的表格文档,“编辑2”将我试图做的事情的速度提高了几个数量级!@Allicar请参阅我的最新编辑。按位操作肯定比$中使用的循环更快。Inarray我深表歉意……看起来还存在一个问题:“注意:Internet Explorer 8和更早版本不支持此方法。”我想我在实现$后没有正确地测试它。如果要选择的元素是同级元素,Inarray将不起作用。它声明了全局变量“hay”。谁会修改它来查找先前的?写得很好!
$.fn.findNext = function ( selector ) {
    var set = $( [] ), found = false;
    $( this ).attr( "findNext" , "true" );
    $( selector ).each( function( i , element ) {
        element = $( element );
        if ( found == true ) set = set.add( element )
        if ( element.attr("findNext") == "true" ) found = true;
    })
    $( this ).removeAttr( "findNext" )
    return set
}
$.fn.findNext = function( selector ){
    var set = $( selector );
    return set.eq( set.index( this, ) + 1 )
}
$.fn.findNext = function ( selector ) {
  // if the stack is empty, return the first found element
  if ( this.length < 1 ) return $( selector ).first();
  var found,
      that = this.get(0);
  $( selector )
    .each( function () {
       var pos = that.compareDocumentPosition( this );
       if ( pos === 4 || pos === 12 || pos === 20 ){
       // pos === 2 || 10 || 18 for previous elements 
         found = this; 
         return false;
       }    
    })
  // using pushStack, one can now go back to the previous elements like this
  // $("#someid").findNext("div").remove().end().attr("id")
  // will now return "someid" 
  return this.pushStack( [ found ] );
},  
   $.fn.findNextAll = function( selector ){
      var that = this[ 0 ],
          selection = $( selector ).get();
      return this.pushStack(
         // if there are no elements in the original selection return everything
         !that && selection ||
         $.grep( selection, function( n ){
            return [4,12,20].indexOf( that.compareDocumentPosition( n ) ) > -1
         // if you are looking for previous elements it should be [2,10,18]
         })
      );
   }
   $.fn.findNext = function( selector ){
      return this.pushStack( this.findNextAll( selector ).first() );
   }
$.fn.findNextAll = function( selector ){
  var that = this[ 0 ],
    selection = $( selector ).get();
  return this.pushStack(
    !that && selection || $.grep( selection, function(n){
       return that.compareDocumentPosition(n) & (1<<2);
       // if you are looking for previous elements it should be & (1<<1);
    })
  );
}
$.fn.findNext = function( selector ){
  return this.pushStack( this.findNextAll( selector ).first() );
}