รวมทุก 3 div ใน div


86

เป็นไปได้ไหมที่จะใช้nth-childตัวเลือกเพื่อรวม 3 div โดยใช้.wrapAll? ดูเหมือนจะหาสมการที่ถูกต้องไม่ได้

ดังนั้น...

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

กลายเป็น...

<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ปลั๊กอิน jQuery ที่ดีในการทำเช่นนั้น หวังว่าจะเป็นประโยชน์
iMoses

คำตอบ:


181

คุณสามารถทำได้ด้วย.slice()สิ่งนี้:

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

คุณสามารถลองสาธิตได้ที่นี่สิ่งที่เราทำที่นี่คือการรับองค์ประกอบที่คุณต้องการห่อและวนซ้ำโดยทำเป็น.wrapAll()ชุดเป็น 3 ชุดจากนั้นย้ายไปยัง 3 ถัดไปเป็นต้นซึ่งจะรวม 3 ครั้งต่อครั้งและ อย่างไรก็ตามจะมีเหลืออีกมากมายในตอนท้ายเช่น 3, 3, 3, 2 หากเป็นเช่นนั้น


ฉันจะทำให้มันเป็นฟังก์ชันและทำให้จำนวนของ div ที่ถูกห่อเป็นอาร์กิวเมนต์ บางอย่างเช่น applyDivGrouping (divs, divsPerGroup);
Stefan Kendall

ว้าว! ขอบคุณสำหรับการตอบกลับอย่างรวดเร็ว สองสิ่ง ... ดังนั้นเพื่อความกระจ่าง - ใช้ลูกที่ n ไม่ได้หรือ? & .. ในฐานะมือใหม่ jQuery - ฉันจะทำให้มันทำงานได้อย่างไร? ฉันห่อไว้ใน jQuery (ฟังก์ชัน ($) ... หรือไม่ขอบคุณมาก
csbourne

@csbourne - Nope :nth-child()ไม่ให้ยืมตัวเองได้ดีสำหรับการเรียกสิ่งนี้เพียงแค่ห่อไว้ใน$(function() { });กรณีที่คุณต้องการเรียกใช้หรือเรียกdocument.readyอีกอย่างว่าเมื่อคุณต้องการเรียกใช้ :)
Nick Craver

ขอบคุณ Nick สำหรับความช่วยเหลือและคำแนะนำที่ยอดเยี่ยม - ทำงานได้อย่างสมบูรณ์แบบ
csbourne

3
@Fahad ตามตรรกะของ NickCraver คุณสามารถแก้ไขโค้ดเล็ก ๆ น้อย ๆ ได้var divs = $("div > .classname");หรือ var divs = $("div .classname");ขอบคุณ

23

ฉันได้เขียนฟังก์ชันกลุ่มทั่วไปที่ทำให้สิ่งนี้ทำได้ง่ายมาก:

$.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

ปลั๊กอิน

$(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", "");
    }
});

วิธีการใช้งาน

โทรหาEveryWhat()องค์ประกอบและใส่หมายเลขสำหรับทุกองค์ประกอบที่คุณต้องการรวบรวม

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

คำพูดของผู้ห่อควรมีรูปแบบที่เหมาะสม <div class="new" />ด้วยคลาสและแท็กปิด Stackoverflow ป้องกันไม่ให้ฉันแสดงสิ่งที่ดูเหมือน แต่นี่คือลิงค์ของ div ปิดตัวเอง

ควรมีลักษณะอย่างไร

ซึ่งจะรวมทุกหมายเลขอื่น ๆ ที่คุณระบุ ฉันใช้ jquery 1.8.2 ดังนั้นอย่าลืมใช้การเรียกตัวเลือกEveryWhat(3)และหมายเลขทุกครั้ง แน่นอนว่าวางไว้ที่ด้านล่างของหน้าหรือห่อเป็นไฟล์

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

คุณสามารถใช้ทุกๆ n แล้ว.wrapInner('<div class="new" />')เพื่อให้ได้ผลลัพธ์เดียวกัน


1
คุณสามารถทำได้โดยใช้$('div > div:nth-child(3n)')และไม่ส่งผลให้เกิดสองกลุ่มสามองค์ประกอบ
Ja͢ck

7

นี่คือเวอร์ชันที่ใช้งานได้มากกว่าของ Nick ด้านบน

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

คุณจะใช้สิ่งนี้:

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

ควรแทนที่หน้าต่างด้วยเนมสเปซตัวจัดการของคุณแน่นอน

อัปเดต: เวอร์ชันที่ดีกว่าเล็กน้อยซึ่งใช้ประโยชน์จาก 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);

ใช้เช่น:

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

พารามิเตอร์ที่สองสำหรับชื่อ wrapper เป็นทางเลือก


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 = []
                }
            });
        }
    }
});

ฉันใช้แนวคิดปลั๊กอินของ Kyle และขยายให้ครอบคลุมโดยอัตโนมัติและรับสองข้อโต้แย้ง มันไม่ได้ผลสำหรับฉันที่จะเริ่มต้น แต่ฉันทำให้มันทำงานได้โดยมีการแก้ไขและเพิ่มเติมโค้ดเล็กน้อย

ในการเรียกใช้ฟังก์ชันเพียงแค่ใช้องค์ประกอบหลักของสิ่งที่คุณต้องการตัดแล้วตั้งค่าอาร์กิวเมนต์ของคุณดังนี้

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

อาร์กิวเมนต์แรกคือจำนวนองค์ประกอบที่คุณต้องการรวมเข้าด้วยกันและอาร์กิวเมนต์ที่สองคือประเภทองค์ประกอบที่คุณต้องการรวม

wrapClassคุณสามารถเปลี่ยนระดับของธาตุห่อในฟังก์ชั่นหลักภายใต้ตัวแปร


0

ฉันได้เตรียมคำตอบนี้สำหรับคำถามอื่นที่ซ้ำกับคำถามนี้ ดังนั้นตัวแปรของฉันอาจมีประโยชน์สำหรับบางคน:

ฉันคิดว่าวิธีแก้ปัญหาในการรวมองค์ประกอบทั้งสามคือ:

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)

ฉันได้เขียนโค้ดเดียวกันที่ jsbin พร้อมการปรับปรุงบางอย่างhttp://jsbin.com/necozu/17/หรือhttp://jsbin.com/necozu/16/

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.