Gói mỗi 3 div trong một div


85

Có thể sử dụng nth-childbộ chọn để bọc 3 div bằng cách sử dụng .wrapAllkhông? Tôi dường như không thể tìm ra phương trình chính xác.

vì thế...

<div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
</div>

trở thành ...

<div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
   <div class="new">
        <div></div>
        <div></div>
        <div></div>
   </div>
</div>

2
gist.github.com/3181731 Một plugin jQuery tốt để thực hiện chính xác điều đó. Hy vọng bạn sẽ thấy nó hữu ích.
iMoses

Câu trả lời:


179

Bạn có thể làm điều đó với .slice(), như thế này:

var divs = $("div > div");
for(var i = 0; i < divs.length; i+=3) {
  divs.slice(i, i+3).wrapAll("<div class='new'></div>");
}

Bạn có thể thử bản trình diễn ở đây , tất cả những gì chúng tôi đang làm ở đây là lấy các phần tử bạn muốn quấn và lặp qua chúng, thực hiện một .wrapAll()đợt 3 rồi chuyển sang 3 tiếp theo, v.v. Nó sẽ kết thúc 3 phần tử một lần và tuy nhiên nhiều phần còn lại ở cuối, ví dụ 3, 3, 3, 2 nếu đúng như vậy.


Tôi muốn đặt hàm này thành một hàm và đặt số div được bọc làm đối số. Một cái gì đó như applyDivGrouping (divs, divsPerGroup);
Stefan Kendall

Chà! Cảm ơn vì đã trả lời nhanh chóng. Vài điều ... Vì vậy, chỉ để làm rõ - điều này không thể sử dụng nth-child? & .. Là một người mới làm quen với jQuery hoàn chỉnh - làm cách nào để làm cho nó hoạt động? Tôi có bọc nó trong một jQuery (function ($) ... Rất cám ơn?
csbourne

@csbourne - Nope :nth-child()không tự cho nó là tốt, vì để gọi cái này, chỉ cần bọc nó trong một $(function() { });nếu bạn muốn chạy nó document.ready, nếu không hãy gọi nó khi bạn muốn chạy nó :)
Nick Craver

Cảm ơn Nick vì sự trợ giúp và hướng dẫn tuyệt vời - hoạt động hoàn hảo.
csbourne

3
@Fahad, theo NickCraver logic, bạn có thể đơn giản chỉ chỉnh sửa chút đoạn mã var divs = $("div > .classname");HOẶC var divs = $("div .classname");Cảm ơn

23

Tôi đã viết một hàm chunk chung chung giúp việc này khá dễ thực hiện:

$.fn.chunk = function(size) {
    var arr = [];
    for (var i = 0; i < this.length; i += size) {
        arr.push(this.slice(i, i + size));
    }
    return this.pushStack(arr, "chunk", size);
}

$("div > div").chunk(3).wrap('<div class="new"></div>');


8

Plugin

$(function() {
    $.fn.EveryWhat = function(arg1) {
        var arr = [];
        if($.isNumeric(arg1)) {
            $.each(this, function(idx, item) {
                var newNum = idx + 1;
                if(newNum%arg1 == 0)
                arr.push(item);
            });
        }
        return this.pushStack(arr, "EveryWhat", "");
    }
});

Làm thế nào để sử dụng nó.

Gọi EveryWhat()phần tử và nhập một số cho mỗi phần tử bạn muốn thu thập.

$("div").EveryWhat(2).wrapInner('<div class="new" />');

Dấu ngoặc kép của wrapinner phải có định dạng đúng <div class="new" />với lớp và thẻ đóng. Stackoverflow ngăn tôi hiển thị những gì trông như thế nào nhưng đây là một liên kết của một div tự đóng.

Nó sẽ trông như thế nào

Điều đó sẽ bao gồm mọi số khác mà bạn đã chỉ định. Tôi đang sử dụng jquery 1.8.2. vì vậy hãy nhớ sử dụng cuộc gọi chọn EveryWhat(3)và một số cho mọi lúc. Tất nhiên là đặt nó ở cuối trang hoặc gói nó trong một

$(document).ready(function() {  
    //place above code here
});

Bạn có thể sử dụng mỗi thứ n và sau đó .wrapInner('<div class="new" />')cho kết quả tương tự.


1
Bạn đã có thể làm điều này với $('div > div:nth-child(3n)')và không thực sự dẫn đến hai nhóm ba yếu tố.
Ja͢ck

7

Đây là một phiên bản hữu dụng hơn của Nick ở trên:

window.WrapMatch = function(sel, count, className){
  for(var i = 0; i < sel.length; i+=count) {
    sel.slice(i, i+count).wrapAll('<div class="'+className+'" />');
  }
}

Bạn sẽ sử dụng cái này như:

var ele = $('#menu > ul > li'); 
window.WrapMatch(ele, 5, 'new-class-name');

tất nhiên phải thay thế cửa sổ bằng không gian tên Handlers của bạn.

Đã cập nhật: Một phiên bản tốt hơn một chút sử dụng jQuery

(function($){
  $.fn.wrapMatch = function(count, className) {
    var length = this.length;
    for(var i = 0; i < length ; i+=count) {
      this.slice(i, i+count).wrapAll('<div '+((typeof className == 'string')?'class="'+className+'"':'')+'/>');
    }
    return this;
  }; 
})(jQuery);

Sử dụng như:

$('.list-parent li').wrapMatch(5,'newclass');

Tham số thứ hai cho tên trình bao bọc là tùy chọn.


1
$(function() {
    $.fn.WrapThis = function(arg1, arg2) { /*=Takes 2 arguments, arg1 is how many elements to wrap together, arg2 is the element to wrap*/

        var wrapClass = "column"; //=Set class name for wrapping element

        var itemLength = $(this).find(arg2).length; //=Get the total length of elements
        var remainder = itemLength%arg1; //=Calculate the remainder for the last array
        var lastArray = itemLength - remainder; //=Calculate where the last array should begin

        var arr = [];

        if($.isNumeric(arg1))
        {
            $(this).find(arg2).each(function(idx, item) {
                var newNum = idx + 1;

                if(newNum%arg1 !== 0 && newNum <= lastArray){
                    arr.push(item);
                }
                else if(newNum%arg1 == 0 && newNum <= lastArray) {
                    arr.push(item);
                    var column = $(this).pushStack(arr);
                    column.wrapAll('<div class="' + wrapClass + '"/>'); //=If the array reaches arg1 setting then wrap the array in a column
                    arr = [];
                }
                else if(newNum > lastArray && newNum !== itemLength){ //=If newNum is greater than the lastArray setting then start new array of elements
                    arr.push(item);
                }
                else { //=If newNum is greater than the length of all the elements then wrap the remainder of elements in a column
                    arr.push(item);
                    var column = $(this).pushStack(arr);
                    column.wrapAll('<div class="' + wrapClass + '"/>');
                    arr = []
                }
            });
        }
    }
});

Tôi đã lấy ý tưởng plugin của Kyle và mở rộng nó thành gói tự động và lấy hai đối số. Nó không hoạt động đối với tôi khi bắt đầu, nhưng tôi đã chạy nó với một vài chỉnh sửa và bổ sung cho mã.

Để gọi hàm chỉ cần sử dụng phần tử mẹ của những gì bạn muốn bọc và sau đó đặt các đối số của bạn như sau.

$('#container').WrapThis(5, 'li');

Đối số đầu tiên là số lượng phần tử bạn muốn kết hợp với nhau và đối số thứ hai là loại phần tử bạn muốn kết hợp.

Bạn có thể thay đổi lớp của phần tử bao bọc trong hàm main dưới biến wrapClass.


0

Tôi đã chuẩn bị câu trả lời này cho một câu hỏi khác trùng lặp với câu hỏi này. Vì vậy, có thể biến thể của tôi sẽ hữu ích cho một số:

Tôi nghĩ giải pháp để kết hợp cả ba yếu tố là:

var $lines = $('.w-col'), // All Dom elelements with class .w-col
     holder = []; //Collect DOM elelements

$lines.each(function (i, item) {
  holder.push(item);

  if (holder.length === 3) {
    $(holder).wrapAll('<div class="w-row" />');
    holder.length  = 0;
  }
});

$(holder).wrapAll('<div class="w-row" />'); //Wrap last elements with div(class=w-row)

Tôi đã viết mã tương tự tại jsbin với một số cải tiến http://jsbin.com/necozu/17/ hoặc http://jsbin.com/necozu/16/

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.