Reputation: 21489
I have a list has 4 item and every item has specific background color that setted in style attribute.
<div class="list">
<div style="background: red"></div>
<div style="background: blue"></div>
<div style="background: green"></div>
<div style="background: yellow"></div>
</div>
I want to set background color of every item to next item. The above html should changed to
<div class="list">
<div style="background: yellow"></div>
<div style="background: red"></div>
<div style="background: blue"></div>
<div style="background: green"></div>
</div>
I have this code but it doesn't work.
$(".list > div").each(function(i){
var index = i == 0 ? 3 : i-1;
this.style.background = $(".list > div").eq(index)[0].style.background;
});
The code set color of last item to all items. What is problem?
setInterval(function(){
$(".list > div").each(function(i){
var index = i == 0 ? 3 : i-1;
this.style.background = $(".list > div").eq(index)[0].style.background;
});
}, 1000);
.list > div { height: 50px }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="list">
<div style="background: red"></div>
<div style="background: blue"></div>
<div style="background: green"></div>
<div style="background: yellow"></div>
</div>
Upvotes: 1
Views: 2348
Reputation: 253466
While you've posted your own answer already, I thought I'd offer a slight alternative which requires only plain JavaScript (albeit ES6) which performs the same functionality:
// setting the enclosed anonymous function to run repeatedly,
// with the interval duration as the second argument, in
// milliseconds, following the anonymous function:
setInterval(function() {
// retrieving the relevant elements, converting the result of
// document.querySelectorAll() into an arry, using Array.from():
let children = Array.from(document.querySelectorAll('.list > div')),
// retrieving an array of the background-colours of those
// found elements, using Array.prototype.map() to create a
// new array from the Array supplied:
colors = children.map(
// here we use an arrow function, 'child' is the current
// array element of the array over which we're iterating
// window.getComputedStyle(child,null) retrieves the
// computed CSS properties of the child element, and
// the backgroundColor property retrieves the current
// background-color (whether defined in a stylesheet,
// or in the style attribute):
child => window.getComputedStyle(child, null).backgroundColor
);
// here we use Array.prototype.forEach() to iterate over the
// children array:
children.forEach(function(child, index, array) {
// child: the current array-element of the array
// over which we're iterating,
// index: the index of the current array-element,
// array: a reference to the array over which we're
// iterating.
// here we set the background-color of the current
// element to the returned index-value of the
// expression
child.style.backgroundColor = colors[
// index + 1: the 'next' index value,
// %: the remainder operator,
// array.length: the length of the current array
// here we increment the index by 1, we then
// divide that number by the length of the array;
// if the index is 0 that gives:
// (0+1)%4 = 1,
// (1+1)%4 = 2,
// (2+1)%4 = 3,
// (3+1)%4 = 0
// we retreive the color held at the returned value
// in the colors Array and set that as the
// background-color of the current element:
(index + 1) % array.length
];
});
}, 1000);
setInterval(function() {
let children = Array.from(document.querySelectorAll('.list > div')),
colors = children.map(child => window.getComputedStyle(child, null).backgroundColor);
children.forEach(function(child, index, array) {
child.style.backgroundColor = colors[(index + 1) % array.length];
});
}, 1000);
.list > div {
height: 50px;
font-size: 2em;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="list">
<div style="background: red">One</div>
<div style="background: blue">Two</div>
<div style="background: green">Three</div>
<div style="background: yellow">Four</div>
</div>
References:
%
operator.Array.from()
.Array.prototype.forEach()
.Array.prototype.map()
.document.querySelectorAll()
.HTMLElement.style
.window.getComputedStyle()
.Upvotes: 1
Reputation: 62666
I think this solution is better (mostly because you don't really need to know the number of child-elements).
Just take the last element in the array and move it to be the first one. Then - set the colors for each of the child-elements, one by one.
setInterval(function(){
var colors = $(".list div").map(function(){
return this.style.background;
}).get();
colors.unshift(colors.pop())
$(".list div").each(function(i){
this.style.background = colors[i];
});
}, 1000);
.list > div { height: 50px }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="list">
<div style="background: red"></div>
<div style="background: blue"></div>
<div style="background: green"></div>
<div style="background: yellow"></div>
</div>
Upvotes: 1
Reputation: 21489
Problem of code is that in .each()
javascript set color of last item to first item and then set this color to another items. See bottom list that is example of loop:
item4
that is yellow
item1
that is yellow
item2
that is yellow
item3
that is yellow
Then color of all items changed to yellow.
You should store colors of items before changing and then change color of every item using stored colors.
setInterval(function(){
var colors = $(".list > div").map(function(){
return this.style.background;
}).get();
$(".list > div").each(function(i){
var index = i == 0 ? 3 : i-1;
this.style.background = colors[index];
});
}, 1000);
.list > div { height: 50px }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="list">
<div style="background: red"></div>
<div style="background: blue"></div>
<div style="background: green"></div>
<div style="background: yellow"></div>
</div>
Upvotes: 3