【问题标题】:Use jQuery to wrap around groups of elements使用 jQuery 环绕元素组
【发布时间】:2009-08-01 22:38:42
【问题描述】:

我有一个元素列表,我想在页面加载后使用标题 div 将它们分开。所以下面的代码,

<div class="header">Header 1</div>
<div class='test'>Test 1</div>
<div class='test'>Test 2</div>
<div class='test'>Test 3</div>
<div class="header">Header 2</div>
<div class='test'>Test 4</div>
<div class='test'>Test 5</div>
<div class='test'>Test 6</div>
<div class='test'>Test 7</div>
<div class='test'>Test 8</div>
<div class="header">Header 3</div>
<div class='test'>Test 9</div>
<div class='test'>Test 10</div>
<div class='test'>Test 11</div>
<div class='test'>Test 12</div>
<div class="header">Header 4</div>
<div class='test'>Test 13</div>
<div class='test'>Test 14</div>

会变成,

<div class='wrap'>
<div class="header">Header 1</div>
<div class='test'>Test 1</div>
<div class='test'>Test 2</div>
<div class='test'>Test 3</div>
</div>
<div class='wrap'>
<div class="header">Header 2</div>
<div class='test'>Test 4</div>
<div class='test'>Test 5</div>
<div class='test'>Test 6</div>
<div class='test'>Test 7</div>
<div class='test'>Test 8</div>
</div>
<div class='wrap'>
<div class="header">Header 3</div>
<div class='test'>Test 9</div>
<div class='test'>Test 10</div>
<div class='test'>Test 11</div>
<div class='test'>Test 12</div>
</div>
<div class='wrap'>
<div class="header">Header 4</div>
<div class='test'>Test 13</div>
<div class='test'>Test 14</div>
</div>

有什么想法吗?提前致谢。

【问题讨论】:

    标签: javascript jquery html css dom


    【解决方案1】:

    从 jQuery v1.4 开始,您可以使用 nextUntil() 方法,允许您执行以下操作:

    var split_at = 'div.header';
    $(split_at).each(function() {
      $(this).add($(this).nextUntil(split_at)).wrapAll("<div class='wrap'/>");
    });
    

    【讨论】:

      【解决方案2】:

      你要求做的是一个糟糕的主意。这就是你应该在服务器端做的事情。 (总有例外)。

      话虽如此,下面的代码应该可以满足您的要求。

      $('.header').each(function() {
        var head = $(this);
      
        if(!head.parent().hasClass('wrap')) {
          head.before('div class="wrap"></div>');
      
          var wrap = head.prev();
          var curr = head;
      
          do {
            var currEl = curr;
            curr = curr.next();
      
            currEl.appendTo(wrap);
          } while(curr.length > 0 && !curr.hasClass('header'));
        }
      });
      

      注意:

      我通常不使用 jQuery 进行开发,如果我不遵循 jQuery 的标准开发方式,请见谅。

      【讨论】:

      • 同意!不是一个好主意,这里没有理由使用 jQuery。
      • 即使你解决了这个问题,我建议将其更改为 not header 而不是 while .hasClass('test')... headers 之间的元素不一定都有同一个类(他们在示例中做了,但谁知道真正的代码是怎么说的)
      • 在富 HTML 编辑框之类的东西中完全在客户端进行这种 HTML 转换并不少见。
      • 也许这并不总是一个好主意,但可以构成为选项卡式交互动态创建选项卡组的基础。在这个特殊的(边缘?)案例中,我不会认为这是一个糟糕的主意
      • 如果在富文本编辑器中输入文本会怎样?我不能告诉我的用户将 div 包装在标题下方的内容中,因此实际上有一些用例。不过,@fractious 的答案对我来说似乎更好。
      【解决方案3】:

      这是另一种方法。不如 Andrew 的漂亮(编辑:虽然我试过他的但它不起作用?我敢肯定这只是一些小的疏忽)但基本上做同样的事情:

      jQuery(function($){ 
      
        var $everything = $('.header,.test'); 
        var splitAtHeaders = []; 
      
        $everything.each(function(index){ 
          var $item = $(this); 
          if ('header'===$item.attr('className') || !splitAtHeaders.length) { 
            splitAtHeaders[splitAtHeaders.length] = []; 
          } 
          splitAtHeaders[splitAtHeaders.length-1].push($item); 
        }); 
      
        $.each(splitAtHeaders, function(){ 
          var currentWrapper = null; 
          $.each(this, function(index){ 
            if (0===index || !currentWrapper) { 
              currentWrapper = this.wrap('<div class="wrap"></div>'); 
            } 
            else { 
              currentWrapper.append(this); 
            } 
          }); 
        }); 
      
      }); 
      

      这是一个演示:http://jsbin.com/ojoqi/edit

      但我确实同意,如果您能提供帮助,这应该在服务器端处理。

      编辑:我尝试修复 Andrew 的解决方案。这是我想出的:

      $('.header').each(function() {
        var next = $(this).next();
        var head = $(this).wrap('<div class="wrap"></div>');
        while (next && next.hasClass('test')) {
          var curr = next;
          next = next.next();
          head.append(curr);
        }    
      });
      

      【讨论】:

      • 这个修复结果很漂亮,我喜欢它。
      【解决方案4】:

      我会这样做:

      var divs = $( 'div' );
      var headers = divs.filter( '.header' );
      
      if ( headers.length != 0 ) {
        var start = 0;
        var wrapper = $( '<div class="wrap" />' );
      
        headers.each( function() {
          var pos = divs.index( this );
          divs.slice( start, pos - 1 ).wrapAll( wrapper.clone() );
          start = pos;
        } );
      
        divs.slice( start ).wrapAll( wrapper.clone() );
      }
      

      【讨论】:

        【解决方案5】:

        假设:标题会有不同的文本。如果没有,请使用其他东西来区分标头,例如 id 属性。

        $("div.header").each(function() {
            var $header = $(this);
        
            var $tests = $.grep(
                $("div.test"),
                function(n) {
                    return $(n).prevAll("div.header").text() == $header.text();
                });
        
            $.merge($header, $tests).wrapAll($("<div class='wrap'>"));
        });
        

        【讨论】:

          【解决方案6】:

          【讨论】:

          • 你给出的函数是一个选择器,当调用 next() 并且没有下一个元素时会“环绕”。
          猜你喜欢
          • 2012-01-21
          • 2014-01-12
          • 1970-01-01
          • 2019-06-23
          • 2016-08-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-05
          相关资源
          最近更新 更多