Target by ID elements in array assigned by get() jQuery - javascript

Apologies if I get the terminology wrong here.
I have a 'grid' of images in html that I want to use jQuery to fade in each element randomly. One item in the grid is a Logo - I want it to fade in last. The grid size could be changed and the position of the 'logo' could also be different. Here is a reduced simplified output of the list.
<ul id="homepage-grid" class="projectsgrid row">
<div id="item1">
</div>
<div id="item2">
</div>
<div id="itemlogo" style="opacity: 0;">
<a href="#" class="block" style="padding-bottom: 100%;">
<div style="background-image:url('logoonly.png')" title="" class="logoblock"></div>
</a>
</div>
<div id="item4">
</div>
<div id="item5">
</div>
</ul>
I have the following script which will collect the elements into an array.
But i can't figure out how to match the element with the 'itemlogo' ID in the collection to split it out and push it to the end of the array so it is last to 'fade in'. I have tried "div#itemlogo", "#itemlogo", "itemlogo" but nothing seems to match, and perhaps not knowing the name of what I am doing I can't find any references.
var elems = $('#homepage-grid > div').get(); // collect elements
console.log(elems);
for (var i = elems.length - 1; i > 1; i--) { // Shuffle the order
var j = Math.floor(Math.random() * (i + 1));
var elem = elems[j];
elems[j] = elems[i];
elems[i] = elem;
}
elms = elems.push(elems.splice(elems.indexOf('div#itemlogo'), 1)[0]); // pull logo to last??
var i = 0;
var timer = setInterval(function() { // animate fade them sequentially
console.log(elems[i]).id();
$(elems[i]).fadeTo( "slow" , 1);
if (i === elems.length) {
clearInterval(timer);
}
i++;
}, 150);

You're on the right path, but the key here is that you need to find a particular item. Those items are DOM elements, not strings or selectors on their own.
elems.push(
elems.splice(
elems.findIndex(node=>node.id === 'itemlogo'),
1
)[0]
);
findIndex allows you to pass a function that should return true for the item you want - in this case, you want the item whose ID is itemlogo. The rest is just the same push-splice thing you have already.
I would also like to praise your correct use of array shuffling. You can simplify it a little bit with destructuring:
[elems[i], elems[j]] = [elems[j], elems[i]];

Related

Apply random class to multiple groups of elements with no repeat

I have multiple groups of divs that I need to apply a random class to with no repeats in each of the groups. Once I've done this, I then need to 'reset' the Array back to the original values, and move onto the next group of divs where I apply a random class to each div again.
The idea is to get to something that looks like this:
<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image left">
<div class="mini-thumbnail-individual-image centre">
<div class="mini-thumbnail-individual-image right">
</div>
<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image centre">
<div class="mini-thumbnail-individual-image right">
<div class="mini-thumbnail-individual-image left">
</div>
<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image right">
<div class="mini-thumbnail-individual-image left">
<div class="mini-thumbnail-individual-image centre">
</div>
etc.
I've shamelessly taken code taken from another stackoverflow question to do with this question, but I can't figure out how to get it to work over all my elements, instead of the first three.
Here's the jQuery:
function shuffle(obj) {
var l = obj.length,
i = 0,
rnd,
tmp;
while (i < l) {
rnd = Math.floor(Math.random() * i);
tmp = obj[i];
obj[i] = obj[rnd];
obj[rnd] = tmp;
i += 1;
}
}
var classes = ["centre", "left", "right"];
shuffle(classes);
jQuery(".mini-thumbnail-individual-image").each(function() {
jQuery(this).addClass(classes.pop());
});
And here's a basic outline of my div structure – I have multiples of these which I want to iterate over and apply the random class to each <div class="mini-thumbnail-individual-image">
HTML:
<div class="col-1-6">
<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image">
<img class="mini-thumbnail-image" src="" />
</div>
<div class="mini-thumbnail-individual-image">
<img class="mini-thumbnail-image" src="" />
</div>
<div class="mini-thumbnail-individual-image">
<img class="mini-thumbnail-image" src="" />
</div>
</div>
</div>
I think I need to create a loop that looks is triggered after each iteration over the array, and once it spots the array is empty, I need to push the class names back in, and then loop over the next group of divs, until each group of divs has a random class applied, but maybe there is a simpler way that I haven't thought of yet.
Thanks in advance!
You're on the right track.
Without speaking of methods to optimize the code, here's (one) way to get quickly to where you need to be:
function shuffle(obj) {
var l = obj.length,
i = 0,
rnd,
tmp;
while (i < l) {
rnd = Math.floor(Math.random() * i);
tmp = obj[i];
obj[i] = obj[rnd];
obj[rnd] = tmp;
i += 1;
}
}
// declare OUTSIDE the function for correct scope
var classes;
// Simple function to set up the classes variable and shuffle.
function setUpClasses() {
classes = ["centre", "left", "right"];
shuffle(classes);
}
jQuery(".mini-thumbnail-individual-image").each(function() {
// Check if classes is set / empty. If so, set up the classes again.
if (!classes || classes.length < 1) {
setUpClasses();
}
jQuery(this).addClass(classes.pop());
});
If you want to look at cleaner / briefer ways to shuffle the array, this article has some other techniques. Here's one of them:
yourArray.sort(function() { return 0.5 - Math.random() });
So you could literally remove your shuffle function, and just do this:
function setUpClasses() {
classes = ["centre", "left", "right"];
classes.sort(function() { return 0.5 - Math.random() });
}
Or, if you wanted maximum brevity:
function setUpClasses() {
classes = ["centre", "left", "right"].sort(function() { return 0.5 - Math.random() });
}
Here is a working Fiddle

How can I count how many divs whose ids begin with a certain text that are inside a div using JQuery?

Here's the html:
<div class="col-sm-12" id="ProdutosPedido">
<div class="row">
<div class="col-sm-12 formProdutoAdd" id="produto_1">
...
</div>
</div>
</div>
As things happen within the page, divs are appended inside #ProdutosPedido, and #produto_1 increments to #produto_2 and so on.
This is not working for me:
console.log($("#ProdutosPedido > [id^=produto_]").length);
I need to iterate over these "produto_" and use the 'i' to refer to the current div, but I don't know how to do it. My example logs 0, and that should not be the case, since it starts with 1.
Since your produto divs are not direct children of ProdutosPedido, but its descendants, you need to use the following selector:
$("#ProdutosPedido [id^=produto_]")
Here is the working JSFiddle demo.
Pure Javascript Solution
function CountDiv() {
var nodes = document.getElementById('ProdutosPedido').getElementsByTagName('*');
var Count = 0;
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].id.substring(0, 8) == 'produto_')
Count++;
}
alert(Count);
}

swap 2 div's index using pure javascript

I have a parent div and it has 9 same div's am trying to swap two div's index. Following is my code:
HTML:
<div id="cont" class="container">
<div class="no">1</div>
<div class="no">2</div>
<div class="no">3</div>
<div class="blank"></div>
<div class="no">4</div>
<div class="no">5</div>
<div class="no">6</div>
<div class="no">7</div>
<div class="no">8</div>
</div>
now I want to swap say 5th and 6th indexed elements. I have no clue how to do that in JavaScript. I know there is function called .index() but how to do that in pure JS.
Here's one implementation: http://jsfiddle.net/x8hWj/2/
function swap(idx1, idx2) {
var container = document.getElementById('cont');
// ditch text nodes and the like
var children = Array.prototype.filter.call(
container.childNodes,
function(node) {
return node.nodeType === 1;
}
);
// get references to the relevant children
var el1 = children[idx1];
var el2 = children[idx2];
var el2next = children[idx2 + 1];
// put the second element before the first
container.insertBefore(el2, el1);
// now put the first element where the second used to be
if (el2next) container.insertBefore(el1, el2next);
else container.appendChild(el1);
}
This starts by getting a list of all element child nodes, then uses insertBefore to rearrange them.

JS target multiple classes and repeat infinitly

The JS below works exactly like it should, my JS knowledge is 0%. Only thing is i need the code below to target multiple divs but same id or different id's does not matter. It also needs to be infinite. so every 50 seconds it needs to repeat. The goal of the js below is to reset CSS3 animations i have running. Project files can be found here: www.dreamsynk.com/img/slider.
// retrieve the element
element = document.getElementById("ani");
setTimeout(function() {
// -> removing the class
element.classList.remove("one");
// -> triggering reflow /* The actual magic */
// without this it wouldn't work. Try uncommenting the line and the transition won't be retriggered.
element.offsetWidth = element.offsetWidth;
// -> and re-adding the class
element.classList.add("one");
}, (50*1000)); //40 seconds
UPDATES:
<div class="slider">
<div class="inner">
<div id="ani" class="one"></div>
<div id="ani" class="two"></div>
<div id="ani" class="three"></div>
<div id="ani" class="four"></div>
<div id="ani" class="five"></div>
<div id="ani" class="six"></div>
</div>
</div>
// retrieve an array-like object with elements
var elements = document.querySelectorAll("ani");
setTimeout(function() {
for (var i=0; i<elements.length; i++) {
var element = elements[i];
element.classList.remove("one two three four five six");
element.offsetWidth = element.offsetWidth;
element.classList.add("one two three four five six");
}
}, (50*1000)); //50 seconds
I am doing something wrong?
You should use document.getElementsByClassName if you want to have an array of elements. document.getElementById normally only gives you the first element of that ID.
The difference between an ID and a class is that an ID can be used to identify one element, whereas a class can be used to identify more than one.
You can also use document.getElementsByName(),
document.getElementsByTagName(),
document.getElementsByTagNameNS() and document.querySelectorAll() of course.
The elements you get from document.getElementsByClassName is known as a HTMLCollection, which is just an array. So if you want to add elements into the collection you can use array.push.
var array = document.getElementsByClassName("classname");
var element = document.getElementById("ani");
array.push(element);
setTimeout(function() {
var i = array.length;
while(i--) {
array[i].classList.remove("one");
array[i].offsetWidth = element.offsetWidth;
array[i].classList.add("one");
}
}, (99999));
Updates:
.classList.remove() can only do 1 class at a time. The same goes
to .classList.add().
What you can do is to create a prototype for DOMTokenList
like this:
DOMTokenList.prototype.addMany = function(classes) {
var array = classes.split(' ');
for (var i = 0, length = array.length; i < length; i++) {
this.add(array[i]);
}
}
and remove/add the classes this way:
element.classList.addMany("one two three four five six");
By the way for .querySelectorAll(selector), you are not using
a proper CSS selector.
You can read more about the syntax of CSS selector here.
And as I have mentioned before, you can't have duplicate ids.
Ids are supposed to be unique.
You can use querySelectorAll to get elements with any css path and then every 50 seconds iterate between them and do the same steps you did for your single element.
Code fixed for your use case:
HTML:
<div class="slider">
<div class="inner">
<div class="ani" id="one"></div>
<div class="ani" id="two"></div>
<div class="ani" id="three"></div>
<div class="ani" id="four"></div>
<div class="ani" id="five"></div>
<div class="ani" id="six"></div>
</div>
</div>
JavaScript:
var container = document.querySelector('slider');
var elements = Array.prototype.slice.call(container.querySelectorAll(".ani"));
setTimeout(function() {
elements.forEach(function(el) { el.classList.remove('ani'); });
container.offsetWidth = container.offsetWidth;
elements.forEach(function(el) { el.classList.add('ani'); });
}, (50*1000)); //50 seconds
// retrieve the elements
var elements = document.querySelectorAll("div");
setInterval(function() {
for(var i = 0; i < elements.length; i++){
// -> removing the class
elements[i].classList.remove("one");
// -> triggering reflow /* The actual magic */
// without this it wouldn't work. Try uncommenting the line and the transition won't be retriggered.
elements[i].offsetWidth = element.offsetWidth;
// -> and re-adding the class
elements[i].classList.add("one");
}
}, (50*1000)); //50 seconds

problems getting element position in array

UPDATED WITH THE CORRECT FIDDLE LINK
I have the following example: http://jsfiddle.net/gespinha/kRUym/52/
Every time you click an element of the array it logs to the console its position in the array and the position of the next element. What I'm trying to do is that when I click on the last element I want it to identify that the next element is actually the first (looping the array).
But when when I click on the last element it doesn't set the arrayPos variable (the number of the position in the array: articles) to zero (the first position in the array, it just continues to number 6, even though I have stated in the if argument that if it is bigger than the length of the array it should become zero.
Why is this happening?
Any suggestions?
HTML
<div class="item">index 0</div>
<div class="item">index 1</div>
<div class="item">index 2</div>
<div class="item">index 3</div>
<div class="item">index 4</div>
<div class="item">index 5</div>
JQUERY
var articles = [];
$('.item').each(function(){
var obj = $(this);
articles.push(obj);
});
for (var i = 0; i < articles.length; i++) {
$(articles[i]).data("index", i)
}
$('.item').on("click", function() {
var id = $(this).data("index");
console.log('NOW: '+id);
if(id < articles.length){
id++
} else {
id = 0;
}
console.log('NEXT: '+id);
});
How can I make this work?
I believe it's a 1 off issue...try
if (id < articles.length - 1)
You can simply use the jQuery index():
$('.item').click(function(){
alert( $(this).index() );
});
This will alert the index starting from 0.
This requires the items to be in a seperate div, the index is the index relative to the parent.
LIVE DEMO
$(function(){
var articles = [];
$('article').each(function(){
articles.push( this );
});
$(articles).click(function(){
console.log( $(this).index() );
});
});
Note that this way you'll just collect the indexable articles (every children will always be index 0). You can push the JS this element into a collection of elements and than on click reference their original index value by wrapping the JS elements into a jQuery Object Elements collection $(articles).

Categories