How to wrap div around multiple of the same class elements - javascript

I'm trying to wrap multiple same class divs into a div and to skip divs not with the same class. .wrap doesn't combine them, and .wrapAll throws the non-classed divs underneath. I've been tinkering around with attempts to create an alternate solution but with no avail.
Original:
<div class="entry">Content</div>
<div class="entry">Content</div>
<div class="entry">Content</div>
<div>Skip in wrap</div>
<div class="entry">Content</div>
<div class="entry">Content</div>
<div class="entry">Content</div>
continued...
Wanted Result:
<div>
<div class="entry">Content</div>
<div class="entry">Content</div>
<div class="entry">Content</div>
</div>
<div>Skip in wrap</div>
<div>
<div class="entry">Content</div>
<div class="entry">Content</div>
<div class="entry">Content</div>
</div>

You can loop pretty quickly through your <div> elements using a for loop. In the below code, just change the initial selector here to grab all those siblings divs, e.g. #content > div.entry or wherever they are:
var divs = $("div.entry");
for(var i=0; i<divs.length;) {
i += divs.eq(i).nextUntil(':not(.entry)').andSelf().wrapAll('<div />').length;
}​
You can give it a try here. We're just looping through, the .entry <div> elements using .nextUntil() to get all the .entry elements until there is a non-.entry one using the :not() selector. Then we're taking those next elements, plus the one we started with (.andSelf()) and doing a .wrapAll() on that group. After they're wrapped, we're skipping ahead either that many elements in the loop.

I just whipped up a simple custom solution.
var i, wrap, wrap_number = 0;
$('div').each(function(){ //group entries into blocks "entry_wrap_#"
var div = $(this);
if (div.is('.entry')) {
wrap = 'entry_wrap_' + wrap_number;
div.addClass(wrap);
} else {
wrap_number++;
}
});
for (i = 0; i <= wrap_number; i++) { //wrap all blocks and remove class
wrap = 'entry_wrap_' + i;
$('.' + wrap).wrapAll('<div class="wrap"/>').removeClass(wrap);
}

You could alternatively append new divs to your markup, and then append the content you want wrapped into those.
If your markup is this:
<div class="wrap">
<div class="col-1"></div>
<div class="col-1"></div>
<div class="col-1"></div>
<div class="col-1"></div>
<div class="col-1"></div>
<div class="col-2"></div>
<div class="col-2"></div>
<div class="col-2"></div>
<div class="col-2"></div>
<div class="col-2"></div>
</div>
Use the following to append two new divs (column-one and column-two) and then append the appropriate content into those divs:
// Set vars for column content
var colOne = $('.col-1').nextUntil('.col-2').addBack();
var colTwo = $('.col-2').nextAll().addBack();
// Append new divs that will take the column content
$('.wrap').append('<div class="column-first group" /><div class="column-second ground" />');
// Append column content to new divs
$(colOne).appendTo('.column-first');
$(colTwo).appendTo('.column-second');
Demo here: http://codepen.io/zgreen/pen/FKvLH

Related

How do I set data attribute value by the index of element in jQuery?

I have multiple sibling elements, some that are added dynamically and others manually or using JS. Each one has a data attribute of "data-sec_number" with a number value that increases by one for each new element down the page. At the moment I am manually writing these in.
E.g.
<div class="container">
<div class="row resource_sec" data-sec_number=1>
<div class="content sec_number" data-sec_number=1></div>
</div>
<div class="row resource_sec" data-sec_number=2>
<div class="content sec_number" data-sec_number=2></div>
</div>
<div class="row resource_sec" data-sec_number=3>
<div class="content sec_number" data-sec_number=3></div>
</div>
</div>
How can I get the value of attribute "data-sec_number" to match the index of the element .resource_sec within the .container element? E.g. the 3rd .resource_sec element will always have a "data-sec_number" value of 3.
I also have the child element of .resource_sec called .sec_number, which has the same data attribute that should mirror the parent.
The JS I have been trying to use is:
var items = $('.container .resource_sec');
var lastItem = $('.container .resource_sec:last');
var index = items.index(lastItem);
$('.resource_sec').attr('data-sec_number', index);
$('.sec_number').attr('data-sec_number', index);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="row resource_sec" data-sec_number=1>
<div class="content sec_number" data-sec_number=1></div>
</div>
<div class="row resource_sec" data-sec_number=2>
<div class="content sec_number" data-sec_number=2></div>
</div>
<div class="row resource_sec" data-sec_number=3>
<div class="content sec_number" data-sec_number=3></div>
</div>
</div>
The meaning of this line
$('.resource_sec').attr('data-sec_number', index);
is to set the attribute value. to select (query) a specific index please use:
$('.resource_sec[data-sec_number=' + index + ']')
or
$(`.resource_sec[data-sec_number=${index}]`)
If you support ES6
UPDATE:
To add a new element in jQuery you may use:
var container = $('.container')
var newElement = $('<div class="row resource_sec"></div>').appendTo(container)
Then, you can fetch the new element index by passing it to the index method,according to Jquery documentation:
If .index() is called on a collection of elements and a DOM element or jQuery object is passed in, .index() returns an integer indicating the position of the passed element relative to the original collection.
var index = container.index(newElement)
To append index to the new element attribute:
newElement.attr('data-sec_number', index)

Two dynamic class added on same element at same time

In my bootstrap website I added fullpage.js, so when a dynamically one class want to add to the page. But two dynamic class added on same element at same time.
So it changed the functionality.
One class only add to the element.
I tried but didn't worked.
Can you please help me to solve this problem.
This is my code, in this code(fp-tableCell) class added two times
<section class="icon-section fp-section fp-table active" id="section-1">
<div class="fp-tableCell" style="height:600px;">
<div class="fp-tableCell" style="height:600px;">
<div class="container">
<div class="row">
<div class="col-md-9 col-sm-12 col-xs-12">
<img src="images/product-1.png" alt="img" class="max-width">
</div>
<div class="col-md-5 col-sm-12 col-xs-12 banner-txt">
<h3 class="preHeading"">volant</h3>
<h1 class="mainHeading">an icon for iconoclasts</h1>
<p class="description">Our singular purpose was to create a product not<br>
bound by convention.
Volant is the realization of that<br> dream.</p>
</div>
</div>
</div>
</div>
</div>
</section>
The code that generates the two <div> elements appears to have been minified and is therefore very difficult to interpret. I think the easiest way to solve this problem would be to remove the duplicate <div> elements from all of the <section> elements after the document has loaded. To do this, you can insert the following code just before your closing </body> tag:
<script>
var sectionElems = document.getElementsByTagName("section"); //creates an array containing all <section> elements
var outerDiv;
var innerDiv;
//loop through each <section> element found and remove duplicate <div> element
for(var i = 0; i < sectionElems.length; i++){
outerDiv = sectionElems[i].children[0];
innerDiv = outerDiv.children[0];
//check class names to make sure it is a duplicate element
if(outerDiv.className == innerDiv.className){
outerDiv.innerHTML = innerDiv.innerHTML;
}
}
</script>
This code loops through each <section> element and writes the content of the nested <div> element into the parent <div> element, basically overwriting itself without including the nested <div> element.

Reorder divs in javascript without jquery

lets say I have html:
<div id="1">1</div>
<div id="2">2</div>
<div id="3">3</div>
how would I in javascript and not jquery reorder these divs to:
<div id="1">1</div>
<div id="3">3</div>
<div id="2">2</div>
You can use display:flex and the order css (I had to add a letter before the number for your id as SO didn't seem to like it for the css)
.container {display:flex; flex-direction:column}
#s1 {order:1;}
#s2 {order:3;}
#s3 {order:2;}
<div class="container">
<div id="s1">1</div>
<div id="s2">2</div>
<div id="s3">3</div>
</div>
More information about order
More information about flex
Update
Sorry read the question wrong - thought you wanted to do it without js
var div = document.getElementById('3')
div.parentNode.insertBefore(div, document.getElementById('2'))
<div id="1">1</div>
<div id="2">2</div>
<div id="3">3</div>
The solution given by the duplicate questions are incorrect because they make the assumption that the elements are next to each other. But even in this simple example, there is a text node containing white-space between the elements.
Given that the two elements are not nested, you can use this to swap two elements:
function swapElements (first, second) {
var tmpNode = document.createElement('div');
tmpNode.setAttribute('id', '_tmp');
var firstParent = first.parentNode;
firstParent.insertBefore(tmpNode, first);
second.parentNode.insertBefore(second, first);
firstParent.insertBefore(second, tmpNode);
firstParent.removeChild(tmpNode);
}
Use it like:
var first = document.querySelector('#1');
var second = document.querySelector('#2');
swapElements(first, second);

combine html paragraphs using javascript

I'm currently struggling on a very simple javascript task, but I'm new to it, so its confusing me a lot.
e.g. html
<div class="item">
<div class="title">Item 1 Title</div>
<div class="description-1">lorum</div>
<div class="description-2">ipsum</div>
<div class="description-combined"></div>
</div>
So I need to combine paragraphs 1 & 2, and replace the empty info in paragraph 3. I don't use jQuery yet, so my research has caused struggle because of this.... i currently have:
var p1 = getElementsByClassName ('description-1').innerHTML;
var p2 = getElementsByClassName ('description-2').innerHTML;
var p3 = p1 + P2
document.getElementsByClassName ('description-combined').innerHTML = p3
I did have p3 to have p1.concat(p2) but that didn't work. I'm using it as an external file, so i may be missing out on putting something in my HTML file too.
The edit changes the question.
What I'd probably do is loop through the .item elements, combining the descriptions within.
document.getElementsByClassName is a property of document, not a freestanding function, and it returns a list of matching elements. It's also not as widely supported as document.querySelector and document.querySelectorAll, so I'd probably use those; for what we're talking about, we'll also want Element#querySelector.
// Get a list of the items and loop through it
Array.prototype.forEach.call(document.querySelectorAll(".item"), function(item) {
// Get the two description divs, and the combined, that
// are *within* this item
var d1 = item.querySelector(".description-1");
var d2 = item.querySelector(".description-2");
var c = item.querySelector(".description-combined");
// Set the combined text (this assumes we have them all)
c.innerHTML = d1.innerHTML + d2.innerHTML;
});
.description-combined {
color: green;
}
<div class="item">
<div class="title">Item 1 Title</div>
<div class="description-1">One description 1</div>
<div class="description-2">One description 2</div>
<div class="description-combined"></div>
</div>
<div class="item">
<div class="title">Item 2 Title</div>
<div class="description-1">2 description 1</div>
<div class="description-2">2 description 2</div>
<div class="description-combined"></div>
</div>
<div class="item">
<div class="title">Item 3 Title</div>
<div class="description-1">3 description 1</div>
<div class="description-2">3 description 2</div>
<div class="description-combined"></div>
</div>
The Array.prototype.forEach.call(list, function() { ... }); thing is a way to loop through anything that's like an array, but isn't an array. It's explained more in this other answer, which also has several alternatives.

jQuery Insert closing div tag and opeing div tag after count

I am trying to get jquery to close a div and inset an opening div with a class after x amount of items.
Here is what I have tried:
$(this).after('</div> <div class=\"bar">Bar');
it outputs:
<div class="bar">Bar</div>
What I need is:
<div class="item2">
<div class="CountThese2"> Count Me </div>
<div class="CountThese2"> Count Me </div>
</div>
<div class="bar">
<div class="CountThese2"> Count Me </div>
<div class="CountThese2"> Count Me </div>
</div>
<div class="bar">
<div class="CountThese2"> Count Me </div>
<div class="CountThese2"> Count Me </div>
</div>
<div class="bar">
<div class="CountThese2"> Count Me </div>
<div class="CountThese2"> Count Me </div>
</div>
http://jsfiddle.net/yoderman94/JEtj2/
You can't add half a tag. I think what you're trying to do is wrap the elements. Your fiddle is pretty messy, but here's a simple example of how you can do that:
http://jsfiddle.net/9Q62H/
while($('#wrapper > a:lt(2)').wrapAll('<div class="bar">bar</div>').length) { }
Which turns this:
<div id="wrapper">
1
1
1
1
1
1
1
1
</div>
into this:
<div id="wrapper">
<div class="bar">bar
1
1
</div>
<div class="bar">bar
1
1
</div>
<div class="bar">bar
1
1
</div>
<div class="bar">bar
1
1
</div>
</div>
You can't manipulate the DOM that way, with or without jQuery. To accomplish the same thing, insert a new div after the current div's parent, and then move all of the current div's following siblings to the new div:
var bar = $("<div>").addClass("bar").text("Bar");
bar.insertAfter($(this).parent());
bar.append($(this).nextAll());
Edit: To preserve text nodes, including the whitespace between your links, it's not quite as simple as $(this).nextAll(), sadly. You need to use .contents() to select the text nodes, then slice at the index of this:
var contents = $(this).parent().contents();
var bar = $("<div>").addClass("bar").text("Bar");
bar.insertAfter($(this).parent());
bar.append(contents.slice(contents.index(this) + 1));
http://jsfiddle.net/JEtj2/6/
I'm going to recommend a different approach here. When you call .after() you need to be giving it a complete open and close tag. You cannot open a tag then close it later like you are trying to above.
My advice would be to try and take an approach like the following, so you can pass a complete open and close tag to .after()
var theDiv = "<div class='bar'>";
for(var i = 0; i < 2; i++) {
theDiv += '<div class="CountThese2"> Count Me </div>';
}
theDiv += "</div>";
$('#thing').after(theDiv);
See how I constructed the whole div including contents before calling .after() ?

Categories

Resources