Restart a for loop after the end of an array - javascript

I working in JavaScript and am trying to add some images to a site.
I have a list of blog posts on a page. And I have a bunch of small stand-alone images (think small icon images) that I want to place on either side of the blog post feed. They are kind of just like random background images. As the feed gets longer, more images will automatically be placed.
Here is some example code of what I have so far. Right now I am just appending text to the page to get this working.
I need help figuring out how to restart this loop once the end of the array is reached. For example, after 6url.jpg is printed, I want to print 1url.jpg and so on if my imageCount is more than 6. I played around with continue and while loops but not sure how to implement that.
var blogIcons = ["1url.jpg", "2url.jpg", "3url.jpg", "4url.jpg", "5url.jpg", "6url.jpg"];
var blogFeedHeight = $(".blog-feed").height();
var imageDistance = 400;
// Determining how many images to place based on the blog feed height;
var imageCount = Math.ceil(blogFeedHeight/imageDistance);
// the number of images that should be inserted.
for(var i = 0; i < imageCount; i++){
$('blog-feed').append('<div class="blog-icon">' + blogIcons[i] +'</div>')
}

What you are looking for is called modulo, the rest of the euclidian division of 2 numbers.
var blogIcons = ["1url.jpg", "2url.jpg", "3url.jpg", "4url.jpg", "5url.jpg", "6url.jpg"];
var imageCount = 10;
// the number of images that should be inserted.
for (var i = 0; i < imageCount; i++) {
console.log(blogIcons[i % blogIcons.length])
}
I simplified your problem so it can run on StackOverflow. but you'll get the proper index by using "%"
So your script should look like that:
var blogIcons = ["1url.jpg", "2url.jpg", "3url.jpg", "4url.jpg", "5url.jpg", "6url.jpg"];
var blogFeedHeight = $(".blog-feed").height();
var imageDistance = 400;
// Determining how many images to place based on the blog feed height;
var imageCount = Math.ceil(blogFeedHeight/imageDistance);
// the number of images that should be inserted.
for(var i = 0; i < imageCount; i++){
$('blog-feed').append('<div class="blog-icon">' + blogIcons[i % blogIcons.length] +'</div>')
}

You don't need to restart a loop. Instead you can use modulo division to fetch an item within bounds from the array
var blogIcons = ["1url.jpg", "2url.jpg", "3url.jpg", "4url.jpg", "5url.jpg", "6url.jpg"];
for (var i = 0; i < 14; i++) {
console.log(blogIcons[i % blogIcons.length]);
}
When doing i % blogIcons.length you will get a number between 0 and blogIcons.length

Related

JS increase index number array by function

I trying to make a small text based rpg game, but I came across array in js and then I came to problems, I failing to increase the index number by using i instead of 0 like myArray[i]
I made a jsfiddle so you guys can see what I mean.
jsfiddle
When you press the button til you get a warming, it should increase the i to 2, but it don't, but still comes with warming and increasing the attack variable.
This is your attackUp function:
function attackUp(){
var i = 0;
var attackCost = xpforlevel[i];
if (attackCost < attackxp) {
alert("WARMING!");
attack++;
document.getElementById('attack').innerHTML = attack;
i++;
document.getElementById('i').innerHTML = i;
}
}
Notice that your var i = 0 statement doesn't really make sense (because everytime attackUp is called, i will be reset to = 0 at the beginning). To fix that, erase this var i = 0 statement from your function and put in the beginning of your JS code:
var i = 0;
var attackxp = 0;
var attack = 1;
Further, your function will only update i if attackCost < attackxp, otherwise it will change nothing. You need to put the i++; statement outside your if-block, like this:
function attackUp(){
//erase this line: var i = 0;
var attackCost = xpforlevel[i];
i++; //added this line
if (attackCost < attackxp) {
alert("WARMING!");
attack++;
document.getElementById('attack').innerHTML = attack;
//erase this line: i++;
document.getElementById('i').innerHTML = i;
}
}
As your i is a local variable, it is initiated as 0 every time you call attackUp(). You should put it besides attackxp and attack.
For more information about the scope of variable in JavaScript, see w3schools or this question.

Multiply an element by a number and insert using jQuery

I'm wondering if you can multiply an element using jQuery a number of times and insert it using .html()?
I am building my own slider which might help put things in context...
I am getting a number of times an element is used, which is stored in a var called eachSlideCount. So for example, this might output 10.
Then what I want to do is create a <span></span> for each of these (so 10 spans) and insert this into a div to generate a pager.
$this.next('.project-slider-count').html('<span></span>')
Is there anyway to muliply this span by the eachSlideCount number and then add to the .project-slider-count element?
I got this far... but clearly missing something...
var eachSlideCount = $this.find('.other-slides').length;
var eachSlideTotal = ($this.next('.project-slider-count').html('<span></span>')) * eachSlideCount;
$('.project-slider-count').html(eachSlideTotal);
Thanks in advance
Multiplication can only be done on numbers. If you want to repeat something, write a loop:
var span = '';
for (var i = 0; i < eachSlideCount; i++) {
span += '<span></span>';
}
$this.next('.projectslider-count').html(span);
In JavaScript, you can execute a for loop. For example, in the following:
var count = 10;
for (var i=0; i<count; i++) {
// Code
}
The body of the loop would be executed 10 times.
In jQuery, you can append a new HTML element inside an existing element using the append() method. For example, the following will add <span> elements in a loop:
var container = $("#container");
var count = 10;
for (var i=0; i<count; i++) {
container.append("<span>");
}
This is illustrated in a jsFiddle.

How to compare Array value to result of 'for' loop in javascript

I have an empty array (called zoomthumbsarray) which gets values pushed to it whilst a 'for' loop is running. This 'for' loop is checking if a thumbnail image is present in the backend against the particular product the user is viewing. If there is an image it gets added into a vertical slider. The current issue is there are non colour specific images (like lifestyle shots) that are being added into the slider multiple times.
So I need to check if the image found in the for loop is currently stored in the array. If it is present, the image has already been generated and I don't want it to get pulled into the slider again. If it hasn't then the image will get added.
Below is the code I am working on. I would presume indexOf would be used but can't get this to work.
Any help would be really appreciated.
var zoomthumbsarray = [] // Empty array which gets populated by .push below during loop
for (var i = 0; i < storeImgsArr.length; i++) { // storeImgsArr finds the quantity of attributes present against the product. This loops and increments counter if there is another attibute image
for (var e = 0; e < storeImgsArr[i].images.imgL.length; e++) { // Loop and increment counter if there is a Large image
zoomthumbsarray.push(storeImgsArr[i].images.imgS[e].slice(-16)); // Slices off last 16 characters of image path i.e. _navy_xsmall.jpg or 46983_xsalt1.jpg and pushes this into 'zoomthumbsarray' array
// if statement sits here to build the html to add the image to the slider
}
}
zoomthumbsarray = [] // Resets array to zero
ANSWER
As answered by Chris I used $.unique to only keep unique values in the array.
Then wrap an if statement around the code to build the thumb image html if the array === 0 or if the current image isn't already in the array.
Updated code below:
var zoomthumbsarray = [] // Empty array which gets populated by .push below during loop
for (var i = 0; i < storeImgsArr.length; i++) { // storeImgsArr finds the quantity of attributes present against the product. This loops and increments counter if there is another attibute image
if (zoomthumbsarray === 0 || zoomthumbsarray.indexOf(storeImgsArr[i].images.imgS[e].slice(-16)) < 0) { // If statement is true if array === 0 or if the current image isn't already in the array
for (var e = 0; e < storeImgsArr[i].images.imgL.length; e++) { // Loop and increment counter if there is a Large image
zoomthumbsarray.push(storeImgsArr[i].images.imgS[e].slice(-16)); // Slices off last 16 characters of image path i.e. _navy_xsmall.jpg or 46983_xsalt1.jpg and pushes this into 'zoomthumbsarray' array
zoomthumbsarray = $.unique(zoomthumbsarray); //Keeps only unique elements
// if statement sits here to build the html to add the image to the slider
}
}
}
zoomthumbsarray = [] // Resets array to zero
Some cheap and dirty ideas:
Using underscore/lodash:
zoomthumbsarray = _.uniq(zoomthumbsarray); //Keeps only unique elements
jQuery has one as well:
zoomthumbsarray = $.unique(zoomthumbsarray); //Keeps only unique elements
then you loop through the array and build HTML.
Update:
There's something a bit odd about the rest of the JS. Might this work (if you're using a new enough browser)?
var zoomthumbsarray = [];
storeImgsArr
.map(function(item) { return item.images.imgS; })
.forEach(function(imgS) {
zoomthumbsarray = zoomthumbsarray.concat(imgS.map(function(imagePath) {
return imagePath.slice(-16);
}));
});
zoomthumbsarray = $.unique(zoomthumbsarray);
I have tried indexOf (see first if statement below) but this doesn't work.
As #elclanrs said, indexOf does return the index in the array not a boolean. You only will need to see if it's >= 0 to test whether an image is already contained in the array.
var zoomthumbsarray = [];
for (var i = 0; i < storeImgsArr.length; i++) {
for (var e = 0; e < storeImgsArr[i].images.imgL.length; e++) {
var image = storeImgsArr[i].images.imgS[e].slice(-16);
if (zoomthumbsarray.indexOf(image) < 0) { // not yet in the array
zoomthumbsarray.push();
// and build the html to add the image to the slider
}
}
}
If you have really lots of images and notice this starts slowing the page down, then there are too many images in your page anyway. No, joke aside; …then check the optimisation by #Ivey.
instead of using an array you can use an object to store the images as keys and a dummy value (possibly true). then you can extract the keys from this object.
var images = {};
for (var i = 0; i < storeImgsArr.length; i++) {
for (var e = 0; e < storeImgsArr[i].images.imgL.length; e++) {
images[storeImgsArr[i].images.imgS[e].slice(-16))] = true;
}
}
var zoomthumbsarray = [];
for(var k in images) {
zoomthumbsarray.push(k);
// build the html to add the image to the slider
}
EDIT: Added build html comment

Loop through colours array with jQuery

I'm trying to give each div a different background colour. Here is my current code:
http://jsfiddle.net/Uy2FX/2/
var imgColours = ['#FCCF94', '#C4C9E5', '#ADE3D6'];
for (i=0; i < imgColours; i++) {
$('.img').css({backgroundColor: imgColours[0]});
}
However, I'm not quite sure where this is going wrong. I understand that's probably too simple to work, but in my mind it makes sense. Could someone point me in the right direction?
There are some relevant errors in your code.
This is probably what you wanted to do:
// V1 : Basic
var imgColours = ['#FCCF94', '#C4C9E5', '#ADE3D6'];
for (var i=0; i < imgColours.length; i++) {
$('.img:eq('+i+')').css({backgroundColor: imgColours[i]});
}
But if you want to get a random color from your array, for any number of divs, and also optimise your jQuery code a bit for better performance:
// V2 : random colors
var $imgs = $('#boxes1').find('.box'),
imgsCount = $imgs.length,
coloursCount = imgColours.length;
for (var i=0; i < imgsCount; i++) {
var rnd = Math.floor(Math.random() * coloursCount),
color = imgColours[rnd];
$imgs.eq(i).css({backgroundColor: color});
}
Or, if you want to loop through the colours following the order of the array, just change the loop:
// V3 : sequential colors
// Add V2 variables here
for (var i=0; i < imgsCount; i++) {
var color = imgColours[i%coloursCount];
$imgs.eq(i).css({backgroundColor: color});
}
UPDATED FIDDLE: http://jsfiddle.net/Uy2FX/12/
For some very basic tips on jQuery selectors performance: http://www.sitepoint.com/efficient-jquery-selectors/
You are always assigning imgColours[0] to EVERY div. I think what you are looking for is imgColours[i]
You will also need to use imgColours.length to tell your loop how long the array is.
You are also grabbing all HTML elements with the class of img, so this will change all of them each time.
To grab each element separately, you can use the CSS nth-of-type selector. Basically you can just do something like
$(".img:nth-of-type(" + i + ")")
You need to use imgColours.length
The for loop has no idea how long the array is otherwise
Edit: What's the point in this for loop if you end up using imgColours[0] anyways? If you want to loop each color, use i instead of 0.
And either way, this will not achieve a different background per div.
Try selecting by className (I'm going to use vanilla.js because it's simple)
var elements = document.getElementsByClassName("img");
for (var i = 0; i<elements.length; i++) {
var color = imgColours[Math.floor(Math.random()*imgColours.length)]; //get a RANDOM color change me if needed
elements[i].style.backgroundColor = color;
}
How about this?
var ec = 0;
var i = 0;
for(ec; ec < elements.length; ec++, i++) {
elements[ec].style.backgroundColor = imgColours[i];
if(i == (imgColours.length - 1)) i = -1;
}
http://jsfiddle.net/y2dq3/

Loading images in js for loop loads nonsequentially

Currently I have 3 or 4 galleries loaded on one page. It's a photographers site, so each gallery has about 40 images. I originally pre-loaded the images, where I would just load the first two images so the page loads quickly, then use JS in the background to cycle through a loop and load the rest. It worked well, except that it didn't honor the order, and the order is important. I have seen some examples where you hide the images until they load, but since there are about 120 large images being loaded in the page it causes the page to load slowly. Is there a way I can use my code, and sort the images once they're loaded? Or, should I load them through an array, would it still ignore the load order? Here's my jsfiddle: http://jsfiddle.net/drrobotnik/YKPEu/
The piece of js i am looking at mostly is this part:
var stack = [];
for (var i = 3; i <= 59; i++) {
var img = new Image(782,521);
img.src = 'http://anikalondon.com/Images/weddings/weddings-3-' + i + '.jpg';
$(img).bind('load', function() {
stack.push(this);
var len = stack.length+2;
$(".numbers").text(($(".enggal img:visible").index()+1)+"/"+len);
if(i>=58){$(".numbers").css("visibility", "visible");}
});
}
again, in this example it's loading the images out of order (probably whichever ones load first, not sure).
well idk if it helps but here's a sorting algorithm that you could use to order them before inserting them into the DOM
stack.sort(function(a,b){
return a.src.substring(a.src.lastIndexOf("-")+1,a.src.lastIndexOf(".")) - b.src.substring(b.src.lastIndexOf("-")+1,b.src.lastIndexOf("."))
})
What if you replaced you simplify things and use this for loop
for (var i = 3; i <= 59; i++)
{
$(".enggal").append("<img src='http://anikalondon.com/Images/weddings/weddings-3-" + i + ".jpg' />");
}
This inserts all of your images in order. You may want to add in the width/height attributes.
Without knowing the deal with how stack is used, I'm not totally sure this would work, but why don't you just save the index information to a store right away, rather than on the callback when it's done loading?
And you should also set src after you bind load or it might miss.
[totally revised from original answer]
var img,i,stack = [];
var imageLoaded=function(e) {
var len = stack.length+2,
index = parseInt(this.src.split('-')[2])-3
$(".numbers").text(($(".enggal img:visible").index()+1)+"/"+len);
if(index>=58){$(".numbers").css("visibility", "visible");}
}
for (i = 3; i <= 59; i++) {
img = new Image(782,521);
$(img).bind('load', imageLoaded);
stack.push(img);
}
// Just to make sure that the first image doesn't finish loading before the loop isdone
// throwing off the count in the imageLoaded function
for (i = 3; i <= 59; i++) {
stack[i-3].src = 'http://anikalondon.com/Images/weddings/weddings-3-' + i + '.jpg';
}

Categories

Resources