I have a bunch of divs like this:
What I would like to do is flip the divs, so the first element becomes the last and the last element becomes first, essentially flipping divs around so 1element,2element,3element would become 3element, 2element, 1element.
I am not sure if this is even possible as there is nothing to distinguish those divs as they all have the same id and class name.
This question is similar to this one: Javascript only - sort a bunch of DIVs
except that here divs have the same id, class name so it makes it all harder.
You can first get all elements with your class, convert it into an array and call reverse() function that flips the array, then loop through the reversed array and append children back to your target div.
Sample codes
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div>
Original:
<div class="test">1</div>
<div class="test">2</div>
<div class="test">3</div>
<div class="test">4</div>
<div class="test">5</div>
</div>
<br />
<div id="target">
Reversed:
<!-- Will be created with Javascript -->
</div>
<script>
const reversedDivs = Array.from(document.getElementsByClassName("test")).reverse();
const targetDiv = document.getElementById("target");
// Create another list in reversed order
reversedDivs.forEach(div => {
const newDiv = div.cloneNode(true);
targetDiv.appendChild(newDiv);
})
</script>
</body>
</html>
Here's a working example: https://codesandbox.io/s/html-reverse-list-u3kld?fontsize=14&hidenavigation=1&theme=dark
...as there is nothing to distinguish those divs as they all have the same id and class name...
Ah, but there is! Where they are in their parent. You can get an array of the elements, reverse it, and then append them to the parent, which will move them so that they're in that reverse order:
var container = document.getElementById("container");
var divs = Array.from(container.children);
divs.reverse();
divs.forEach(function(div) {
container.appendChild(div);
});
Live Example:
setTimeout(function() {
var container = document.getElementById("container");
var divs = Array.from(container.children);
divs.reverse();
divs.forEach(function(div) {
container.appendChild(div);
});
}, 800);
.ib {
display: inline-block;
}
<div id="container"><div class="ib">1</div><div class="ib">2</div><div class="ib">3</div><div class="ib">4</div><div class="ib">5</div></div>
Note that I was careful to do the markup so that there wouldn't be any Text nodes in there, because the children collection only includes Elements, not Text nodes. But if you want to reverse all the children, including text nodes, use childNodes instead of children:
setTimeout(function() {
var container = document.getElementById("container");
var divs = Array.from(container.childNodes);
divs.reverse();
divs.forEach(function(div) {
container.appendChild(div);
});
}, 800);
.ib {
display: inline-block;
}
<div id="container">
<div class="ib">1</div>
<div class="ib">2</div>
<div class="ib">3</div>
<div class="ib">4</div>
<div class="ib">5</div>
</div>
Note that I've kept the code to ES5 level (not ES2015+), except that Array.from is more recent. You can easily polyfill it, or use
var divs = Array.prototype.slice.call(container.children/*or childNodes*/);
instead.
Related
I'm trying to find out if it's possible to clone an HTML div with JS, edit it and append it again as a new element. So my source is, for example, this code here:
<div class="wrapper">
<div class="element">
<input id="test--1" value="ABC"/>
</div>
</div>
After copying this element, I need to find a way to change the attribute id of the new cloned input, clear the input value and paste it again in the wrapper so that it looks like this at the end:
<div class="wrapper">
<div class="element">
<input id="test--1" value="ABC"/>
</div>
<div class="element">
<input id="test--2" value=""/>
</div>
</div>
Does that make sense to you? If yes, how can I get this done? Or is it better to assign the content to a variable to append it? I'm looking for the best way here and maybe my idea is a solution too.
You can use pure JavaScript to do this by just cloning the .element div using the cloneNode() method, assign new id and value to the clone div and finally append it back to the document using the insertBefore() method like this:
let x = document.querySelector(".element");
let y = x.cloneNode(true);
y.children[0].id = "test--2";
y.children[0].defaultValue = "";
x.parentNode.insertBefore(y, x.nextSibling);
<div class="wrapper">
<div class="element">
<input id="test--1" value="ABC"/>
</div>
</div>
JSFiddle with the above code: https://jsfiddle.net/AndrewL64/jvc7reza/18/
Based on this answer you could do like:
$('#cloneBtn').on('click', function() {
// get the last input having ID starting with test--
var $inp = $('[id^="test--"]:last'); // Or use :first if you need
// Get parent element
var $div = $inp.closest('.element');
// Create clone
var $div_clone = $div.clone();
// Retrieve number from ID and increment it
var num = parseInt($inp.prop("id").match(/\d+/g), 10) + 1;
// Generate new number and assign to input
$div_clone.find('[id^="test--"]').prop({id: 'test--' + num, value: ''});
// Insert cloned element
$div.after($div_clone); // Or use .before() if you need
});
.element {
padding: 10px;
outline: 2px solid #0bf;
}
<button id="cloneBtn">CLICK TO CLONE</button>
<div class="wrapper">
<div class="element">
<input id="test--1" value="ABC" />
</div>
</div>
Once done inspect the input elements to see the new IDs
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
Scrambled elements, retrieve highest ID, increment, clone, append.
If your numbered IDs are scrambled, we first need a way to retrieve the highest ID number. Here's an implementation in pure JavaScript:
function cloneElement () {
const inpAll = document.querySelectorAll('[id^="test--"]');
if (!inpAll.length) return; // do nothing if no elements to clone
const maxID = Math.max.apply(Math, [...inpAll].map(el => +el.id.match(/\d+$/g)[0]));
const incID = maxID + 1;
const element = document.querySelector('.element'); // Get one for cloning
const eleClone = element.cloneNode(true);
const inpClone = eleClone.querySelector('[id^="test--"]');
inpClone.id = 'test--'+ incID;
inpClone.value = incID; // just for test. Use "" instead
document.querySelector('.wrapper').prepend(eleClone);
}
document.querySelector('#cloneBtn').addEventListener('click', cloneElement);
.element {
padding: 10px;
outline: 2px solid #0bf;
}
<button id="cloneBtn">CLICK TO CLONE</button>
<div class="wrapper">
<div class="element">
<input id="test--1" value="1" />
</div>
<div class="element">
<input id="test--23" value="23" />
</div>
<div class="element">
<input id="test--7" value="7" />
</div>
</div>
Once done inspect the input elements to see the new IDs
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
I don't know what data you know, why you want to do such a thing but it can be done :-)
One way is like that:
const elemToCopy = document.getElementById("test--1").parentNode; // I assume you know id
const copiedElem = elemToCopy.cloneNode(true);
const newInput = copiedElem.querySelector("#test--1");
newInput.id = "test--2";
newInput.value = "";
elemToCopy.parentNode.append(copiedElem);
Let me know in a comment if something is not clear :-)
Yes, use jQuery's .clone().
Here is an example that might be relevant to your situation:
let newElement = $('.element').clone();
newElement.find('input').attr('id', 'test--2').val('');
$('.wrapper').append(newElement);
Explanation
In the first line, we created a new cloned element by using jQuery clone().
Then, we found it's child input, changed it's ID and reset the val().
Finally, we found the .wrapper element and appended the new cloned element to it.
This question already has answers here:
Getting first visible element with jQuery
(3 answers)
Closed 3 years ago.
I'm trying to select the first element with a specific class that is also visible. I only want to select the one element and store it as a variable.
var elements = document.getElementsByClassName('className'); // Get all visible elements with classname.
var element= elements[0]; // Return only the first element from this NodeList
For my specific use case, I'm attempting to then retrieve its background image, so this is what I've got so far. My variable returns "undefined".
var bg = element.css('background-image'); // Returns url('http://www.google.com/imageurl')
I'm using jQuery, but plain JavaScript is welcome, too. Whatever gets the job done the best.
Here's what I would do using JQuery:
var element = $(".classname:visible:first");
var bg = element.css('background-image');
element contains the first element of the specified classname that is visible.
You could use the :visible selector. Something like this $('.classname:visible') .
https://api.jquery.com/visible-selector/
$('selector:visible') will get you visible elements matching the given selector
.eq(n) will return the nth node from those matched
.css('backgroundImage') will give you the background image
.match(/"(.+)"/)[1] will then return just the URL of the background image:
var specialElement = $('.example:visible').eq(1);
specialElement.append(specialElement.css('backgroundImage').match(/"(.+)"/)[1]);
body {
color: white;
}
.example {
visibility: hidden;
}
.special {
visibility: visible;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<head>
<title>example</title>
</head>
<body>
<header>
<h1>Hello World</h1>
</header>
<main>
<section>
<article class="example" style="background-image:url('https://images.pexels.com/photos/374815/pexels-photo-374815.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500');">
<h2>Bananas</h2>
<p>Bananas are a great source of potassium.</p>
</article>
<article class="example special" style="background-image:url('https://images.pexels.com/photos/707194/pexels-photo-707194.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500');">
<h2>Apples</h2>
<p>An apple a day will keep the doctor away!</p>
</article>
<article class="example" style="background-image:url('https://images.pexels.com/photos/1667580/pexels-photo-1667580.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500');">
<h2>Oranges</h2>
<p>Oranges make great juice.</p>
</article>
</section>
</main>
</body>
The following HTML markup and script is faulty, but I'm not getting why:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>More Ways To Target Elements</title>
</head>
<body>
<div id="div1">
<div id div="div2">
<p id="p1">Chicago</p>
<p>Kansas City</p>
<p>St. Louis</p>
</div>
</div>
<script>
var div = document.getElementById('div2');
for (var i = 0; i < div.childNodes.length; i++) {
if (div.childNodes[i].childNodes[0].nodeType === 3) {
alert(div.childNodes[i].childNodes[0].innerHTML);
}
}
</script>
</body>
</html>
I tried minifying the whole thing but I get the same results from the console, which says:
Uncaught TypeError: Cannot read property 'childNodes' of null
Any suggestions, anyone?
There are a few problems there:
Your HTML is invalid and you have no element with the id div2 (<div id div="div2"> should be <div id="div2">). That's what's causing the error you're starting out with.
But once you fix it, you'll run into more errors:
Not all nodes have childNodes, only Element nodes do. Specifically, Text nodes do not. But you're assuming all of the child nodes of #div2 are Element nodes. They aren't, some are Text nodes.
If you only want to look at Element nodes in #div2, use div.children rather than div.childNodes. children only contains Elements, not other kinds of nodes.
You're assuming all of the children of #div2 have at least one child node, because (if you implement #2 above) you're doing div.children[i].childNodes[0].nodeType. That will throw an exception if there are no child nodes, because childNodes[0] will give you undefined and you can't read .nodeType from undefined. You need a guard there.
Text nodes don't have innerHTML. If you want the text of a Text node, you use nodeValue.
With those changes:
var div = document.getElementById('div2');
for (var i = 0; i < div.children.length; i++) {
if (div.children[i].childNodes[0]) {
alert(div.children[i].childNodes[0].nodeValue);
}
}
<div id="div1">
<div id="div2">
<p id="p1">Chicago</p>
<p>Kansas City</p>
<p>St. Louis</p>
</div>
</div>
But, if the goal is to show the text content of the children of #div2, I'd probably use querySelectorAll and use textContent (not supported on older IE) or innerText on the elements (which are not the same thing, but the differences don't matter here) instead, as it would be simpler:
// Get the name to use (textContent isn't supported on older IE)
var propName = "textContent" in document.body ? "textContent" : "innerText";
// Get the immediate children of #div2,
// alert their contents
var list = document.querySelectorAll('#div2 > *');
for (var i = 0; i < list.length; i++) {
alert(list[i][propName]);
}
<div id="div1">
<div id="div2">
<p id="p1">Chicago</p>
<p>Kansas City</p>
<p>St. Louis</p>
</div>
</div>
I have a this html page, Whenever the element with class name FreeSeat is clicked I want to change the colour of that div element.Below is my html page
<html>
<head>
<title>
QuickBus
</title>
<link type="text/css" rel="stylesheet" href="Seat.css">
</head>
<body>
<div id="Bus">
<div class="Row">
<div class="FreeSeat" ></div>
<div class="FreeSeat" ></div>
<div class="ResSeat" ></div>
<div class="ResSeat" ></div>
<div class="ResSeat" ></div>
</div>
</div>
<body>
</html>
It will be very helpful if anyone can help me out with this .
Considering that you want to use pure JS and not any library, you'd have to manually add event listeners to your classes.
And it has been solved for a similar problem here
var freeclass = document.getElementsByClassName("FreeSeat");
var myFunction_Free = function() {
this.style.color = "blue";
}
for(var i=0;i<freeclass.length;i++){
freeclass[i].addEventListener('click', myFunction_Free, false);
}
But for your case, here's a working fiddle
JQuery is amazing for these sorts of things.
Say you have a div with id 'box1'
<div id='box1'></div>
Style it with css
#box1 {
width:100px;
height:100px;
background-color:white;
border:1px solid black;
}
Using JQuery, you can make this call:
$( "#box1" ).click(function() {
$('#box1').css('background-color', 'red');
});
And now whenever your div is clicked, the colour will change, you can customise this however much you like.
Here is a JSFiddle demo.
Also, since you didn't specify exactly what you want to change the colour of, in my example jquery, it is telling the browser that when a div with an id of box1is clicked, change the background-color of the div with an id of box1, you can change anything though.
If you have a <p> tag you can change that too when the div is clicked, hope this helped!
You can use the following method to change the background color of an element by class:
const free_seat = document.getElementsByClassName('FreeSeat');
free_seat[0].style.backgroundColor = '#ff0';
Each element can be referenced by its index:
free_seat[0] // first div
free_seat[1] // second div
Therefore, we can create a function that will be called whenever the click event is delivered to the target:
const change_color = () => {
this.style.backgroundColor = '#ff0';
};
for (let i = 0; i < free_seat.length; i++) {
free_seat[i].addEventListener('click', change_color);
}
Note: You can also use document.querySelectorAll('.FreeSeat') to obtain a NodeList of elements of a certain class.
You can use simply the css focus pseudo-class for this:
#foo:focus {
background-color:red;
}
<div id="foo" tabindex="1">hello world!</div>
Dont forget to set the tabindex.
I would like to add animation effect to following code when showing tree items.
I know that jquery has slide functions, and css has "transition", but not sure how to apply these to my code. Any ideas?
<head>
<script language="JavaScript">
function show(){
var elements = document.getElementsByClassName("label");
for(var i = 0, length = elements.length; i < length; i++) {
elements[i].style.display = 'block';
}
}
</script>
<style>
.label {
-webkit-padding-start: 20px;
display: none;
}
</style>
</head>
<body>
<div>
<div onclick="show()">1st Row</div>
<div>
<div class="label">First</div>
<div class="label">Second</div>
<div class="label">Third</div>
</div>
<div>2nd Row</div>
</div>
</body>
If you are planning to use jQuery then you can use slideDown and slideUp method to show/hide elements with animation. There is slideToggle method which alternatively show/hides the element with animcation. You can modify your show method as below
Working demo
function show(obj){
var $this = $(obj);//Here obj points to the element clicked
//Now you have to show/hide the next sibling of the element clicked
//We will use next() method which gives the next sibling of element
//And then call slideToggle on it to show/hide alternatively
$this.next().slideToggle();
}
Change in the markup
<div onclick="show(this)">1st Row</div>
function show() {
$('.label').slideDown();
}
This selects all elements with the .label class and slides them into view. There is also a .fadeIn() function.
Also, you can attach click handlers by selectors (like an id or class):
<div>
<div class="row">1st Row</div>
<div>
<div class="label">First</div>
<div class="label">Second</div>
<div class="label">Third</div>
</div>
<div class="row">2nd Row</div>
</div>
Notice I removed the onClick="" statement and added a class to the row div. Then you can select the element you want to attach the click event to and keep all the code in one place:
$('.row').bind('click', function () {
$(this).next().find('.label').slideToggle();
});
This JavaScript above adds a click handler to all elements with the row class and toggles the display of all of the elements with the label class in the next element.
Here is a jsfiddle: http://jsfiddle.net/L34g3/.