使用jQuery将元素组包装起来

3
我是一个有用的助手,可以为您翻译文本。
我有一个元素列表,想要使用标题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>

任何想法?提前感谢。
6个回答

8
自从jQuery v1.4版本以后,您可以使用nextUntil()方法,使您可以像这样做:
var split_at = 'div.header';
$(split_at).each(function() {
  $(this).add($(this).nextUntil(split_at)).wrapAll("<div class='wrap'/>");
});

4
你想要做的事情是一个糟糕的主意。这种东西应该在服务器端完成。(总有例外情况)。话虽如此,以下代码应该可以实现你的要求。
$('.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的标准操作方式,请见谅。


1
同意!这不是一个很好的想法,没有理由在这里使用jQuery。 - doomspork
2
在类似富文本HTML编辑框之类的东西中,完全可以使用客户端完成这种HTML转换,这并不罕见。 - Joe Chung
1
也许这并不总是一个好主意,但可以作为动态创建选项卡组的基础,以实现选项卡交互。在这种特定(边缘?)情况下,我认为这不是一个可怕的想法。 - Andy Ford
1
如果文本是在富文本编辑器中输入的,那该怎么办呢?我不能要求用户在标题下面包裹div来放置内容,所以实际上有一些使用情况。不过,@fractious提供的答案对我来说似乎更好一些。 - helderco
@helderco:当富文本编辑器提交时,您仍然可以在服务器端处理它。没有理由在客户端执行此操作。 - Andrew Moore
显示剩余7条评论

2

这里是另一种方法。虽然不像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 但我同意,如果可以,这应该由服务器端处理。
编辑:我尝试修复安德鲁的解决方案。以下是我的结果:
$('.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);
  }    
});

那个修复很不错,我喜欢它。 - Matt Brunmeier

0
假设:标题将具有不同的文本。如果没有,请使用其他内容来区分标题,例如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'>"));
});

0
我会这样做:
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() );
}

0

你提供的函数是一个选择器,当调用next()时,它会'环绕'并且没有下一个元素。 - Benjamin Intal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接