Changing background with sprite doesn't work - javascript

I've got this code for chaging a background image. I used setTimeout and everything but still it doesn't seem to work. Could anybody be kind enough and tell me what is possibly wrong?
var banner = document.getElementById("banner");
function changeBg () {
var i=0;
var images = ["0 235px", "0 0"];
while (true) {
setTimeout(function(){
banner.style.backgroundPosition = images[i]
},3000)
i++;
if (i>=images.length) {
i=0;
}
}
}
changeBg();

maybe that like this will work.
var banner = document.getElementById("banner");
function changeBg () {
var i=0;
var images = ["0 235px", "0 0"];
setInterval(3000,function(){banner.style.backgroundPosition = images[i];i++;if (i>=images.length) {
i=0;
} })
}
}changeBg();

Related

How can I reuse a function properly?

I try to make 3 basic slideshow.
I made this code for the first one and wanted to use it on the other 2 as well with the New slideS() method and with some parameter changing.But it's not working,even the first function is'nt working if I put parameter in it.
Can somebody explain me why is this not working and how to fix it?Thanks beforehand!
var img = document.getElementById("asd");
var imgArr = ["1.jpg", "3.png", "3.png"];
var i = 0;
function slideS(a) {
a.src = imgArr[i];
if (i < imgArr.length - 1) {
i++;
} else {
i = 0;
}
setTimeout("slideS()", 1500);
}
slideS(img)
You could do something like this, using an object oriented approach:
function SlideShow(el, imagesArray, msDelay) {
this.el = el;
this.images = imagesArray;
this.delay = (msDelay) ? msDelay : 1000;
this.timer = null;
this.Run = function () {
var self = this;
var index = 0;
this.timer = setInterval(function(){
self.el.src = self.images[index++ % self.images.length];
}, this.delay);
}
this.Stop = function() {
this.timer = null;
}
}
var img = document.getElementById("asd");
var imgArr = ["1.jpg", "3.png", "3.png"];
var delay = 1500;
var ss = new SlideShow(img, imgArr, delay);
ss.Run();
...
ss.Stop();
Would that work for you? Then you are using pure functions and an object that can be used to start, stop, and manage any slide show.
I think you want like:
Remove setTimeout. And use setInterval:
setInterval(function(){
slideS(img)
},1500)
You could use a closure over the element and the array and use setInterval instead of setTimeout.
function slide(id, array) {
function swap() {
image.src = array[i];
i++;
i %= array.length;
}
var image = document.getElementById(id),
i = 0;
setInterval(swap, 1500);
}
slide('image1', ['http://lorempixel.com/400/200/', 'http://lorempixel.com/400/200/', 'http://lorempixel.com/400/200/']);
<image id="image1"></image>
I assume it works when the function doesn't take a parameter?
Then, the reason it would work with no parameter, but stop working with a parameter, is that the setTimeout tries to recursively call the function but doesn't pass a parameter. So you'd change that to
setTimeout(() => {slideS(a);}, 1500);
But then when you try to run multiple instances of this concurrently, you'll get into trouble because your'e using global variables. You'll need to use something more local (perhaps closures?) for your lcv, for example.
try this... you are making mistake at some places
var img = document.getElementById("asd");
var imgArr = ["1.jpg", "3.png", "3.png"];
var i = 0;
function slideS(a) {
a.src = imgArr[i];
if (i < imgArr.length - 1) {
i++;
} else {
i = 0;
}
setTimeout(() => slideS(a), 1500);
/* you need to pass function to setTimeout and pass refrence of image that's 'a' */
// or use function instead of arrow function
setTimeout(function() { slides(a) }, 1500);
}
slideS(img)
hope this helps..
You have to use setInterval instead of setTimeout
var img = document.getElementById("asd");
var imgArr = ["https://i.stack.imgur.com/lgt0W.png", "https://i.stack.imgur.com/X0fKm.png", "https://i.stack.imgur.com/YfPSD.png"];
var i = 0;
function slideS(a) {
a.src = imgArr[i];
if (i < imgArr.length - 1) {
i++;
} else {
i = 0;
}
}
slideS(img); //initial call to start it without having to wait for 1500 ms to pass
setInterval(function() {
slideS(img);
}, 1500);
<img id="asd">

get interval ID from else statement when set in IF

I am attempting to create a responsive slider, that will change to a simple set of dot points when in mobile mode (< 940).
The issue I am facing is in my else statement I am unable to clearintervals that were made in the if statement, because t comes up as undefined. I have resorted to using
for (var i = 1; i < 99999; i++) window.clearInterval(i); to clear the interval which works, but I don't like it because it's ugly and cumbersome, is there another way of accomplishing this?
$(document).ready(function() {
function rePosition() {
//get responsive width
var container_width = $('.container').width();
//Slider for desktops only
if(container_width >= 940) {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var n = 1;
var t = 0;
$('.slider_container').hover(function() {
clearInterval(t);
}, function() {
t = setInterval(sliderLoop,6000);
});
var marginSize = i = 1;
//Called in Doc Load
function sliderLoop(trans_speed) {
if (trans_speed) {
var trans_speed = trans_speed;
}
else
{
var trans_speed = 3000;
}
if (i < number_of_slides) {
marginSize = -(slide_width * i++);
}
else
{
marginSize = i = 1;
}
$('.slider').animate({ marginLeft: marginSize }, trans_speed);
}
t = setInterval(sliderLoop,6000);
$('.items li').hover(function() {
$('.slider').stop();
clearInterval(t);
var item_numb = $(this).index();
i = item_numb;
sliderLoop(500);
}, function() {
t = setInterval(sliderLoop,6000);
});
}
else
{
for (var i = 1; i < 99999; i++)
window.clearInterval(i);
$('.slider').stop(true, true);
$('.slider').css('margin-left', '0px');
//rearrange content
if($('.slider .slide .slide_title').length < 1) {
$('.items ul li').each(function() {
var item_numb = $(this).index();
var content = $(this).text();
$('.slider .slide:eq(' + item_numb + ')').prepend('<div class="title slide_title">' + content + '</div>')
});
}
}
}
rePosition();
$(window).resize(function() {
rePosition();
});
});
Teemu's comment is correct. I'll expand on it. Make an array available to all of the relevant code (just remember that globals are bad).
$(document).ready(function() {
var myIntervalArray = [];
Now, whenever you create an interval you will need to reference later, do this:
var t = setInterval();//etc
myIntervalArray.push(t); //or just put the interval directly in.
Then to clear them, just loop the array and clear each interval.
for (var i=0; i<myIntervalArray.length; i++)
clearInterval(myIntervalArray[i]);
}
Umm, wouldn't t only be defined when the if part ran... as far as I can tell, this is going to run and be done... the scope will be destroyed. If you need to maintain the scope across calls, you'll need to move your var statements outside of reposition(), like so:
$(document).ready(function() {
var t = 0;
...
function rePosition() { ... }
});

Javascript - loading images

I have a javascript which uses many images, and I want to load them all before the user starts clicking around. The images are a little bit big, so it takes a while. Here's my code:
startTest();
function preloadImages() {
console.log("preload images");
for(var i = 1; i <= 132; i++) {
var img = new Image();
images[i-1] = "images/"+i+".png";
img.src = images[i-1];
if(i == 132) {
img.load = doneLoading();
}
}
}
function doneLoading() {
console.log("done loading");
document.getElementById("laading").style.display = "none";
console.log("loading gone");
showReady();
}
function startTest() {
console.log("start test");
trialCount = 0;
document.getElementById("laading").style.display = "block";
preloadImages();
var hammertime = Hammer(document.body).on("touch", function(event) {
registerTouch(event);
});
startTestTime = +new Date();
console.log("end start test");
}
As you can see, startTest() is first called, which calls preload images. Here's the issue:
When I load the page in the browser, the javascript console indicates that "done loading" has been printed, however the spinny wheel on the tab in the browser shows that the webpage is still loading...
What's going on here? How can I figure out once all my images are done loading?
You need to check on each image load that the image is the last one to load. Check using a count variable (loaded).
function preloadImages() {
var loaded = 0;
for(var i = 0; i <= 132; i++) {
var img = new Image();
images.push("images/"+(i+1)+".png");
img.src = images[i];
img.onload = function(){
loaded++;
if(!(loaded < 132)){
// all images have loaded
doneLoading();
}
}
}
}
In order to do a pre-loading, you will have to keep checking the complete status for each image that is being downloaded. Since, you can't know beforehand how much time it will take for each image to download (depending on latency or size), you will have to implement a timer which will keep polling the complete status on each image.
Here is one possible algorithm:
var timer = null,
numImages = 132,
allImages = new Array;
function preLoadImages() {
document.getElementById('loadcaption').innerHTML = 'Loading images... ';
for (var i = 0; i < numImages; i++) {
var tmp = "images/" + i + ".png";
allImages[i] = new Image();
allImages[i].onLoad = imgOnLoad(tmp);
allImages[i].src = tmp;
}
timer = window.setInterval('checkLoadComplete()', 250);
}
function imgOnLoad(imgName) { window.status = 'Loading image... ' + imgName; }
function checkLoadComplete() {
for (var i = 0; i < allImages.length; i++) {
if (!allImages[i].complete) {
imgOnLoad(allImages[i].src);
document.getElementById('loadcaption').innerHTML = 'Loading images... ' + Math.round((i/allImages.length)*100,0) + ' %';
return;
}
}
window.clearInterval(timer);
document.getElementById('loadcaption').innerHTML = 'Completed.';
window.status = '';
}
Where loadcaption is a simple HTML element to show progress. (You can also use an animated gif for loading animation).
The idea is to keep checking the complete status on each image by calling checkLoadComplete by a timer. Once all images are (load) complete, the for loop exits and the timer is cleared.
You start the pre-loading process by calling preLoadImages(); function.

Nav background color changes upon scroll

I want part of my navigation background to change color to match the content color as the user scrolls down.
An exact example of this is available at blobfolio.com.
My attempt:
window.onscroll = function () {
var background = document.body.scrollTop < 200 ? '#fff' : 'red',
elems = document.getElementsByTagName('nav');
for (var i=0; i<elems.length; i++) {
elems[i].style.background = background;
}
}
I think that it will include for loops. I have tried in this JSFiddle but the entire background changes, which isn't what I want.
I am really quite stuck, any help would be much appreciated!
Also I am trying to do this in pure JavaScript - no frameworks.
I think this does what you're asking for:
window.onscroll = function () {
var i = 0;
var elements = document.getElementsByClassName("container");
for(var j=elements.length-1; j>0; j--)
{
if (parseInt(elements[j].getBoundingClientRect().top) <= 0)
{
i = j;
break;
}
}
var nav = document.getElementsByClassName("nav");
for (var j=0; j<nav.length; j++)
nav[j].style.backgroundColor = "";
nav[i].style.backgroundColor = window.getComputedStyle(elements[i]).getPropertyValue("background-color");
}
window.onscroll();
Here's a demo on JSFiddle.
Doing it in pure JavaScript was quite fun :D
You can try something like this
window.onscroll = function () {
var top=0;
var top=document.body.scrollTop;
if(top < 200){
$("a[href='#home']").parent().css("background-color","Green");
$("a[href='#home']").parent().siblings().css("background-color","");
}
if((top >= 200) && (top < 800)){
$("a[href='#Services']").parent().css("background-color","red");
$("a[href='#Services']").parent().siblings().css("background-color","");
}
}
JS Fiddle Demo
Sorry If you don't want to use Jquery. Here I am just giving you an idea to how to achieve that.
Give this a try. Working Demo
window.onscroll = function () {
var offset = Math.max(document.documentElement.scrollTop, document.body.scrollTop),,
lis = document.getElementsByTagName('li');
var colorMap = [
{ value: 200, color : 'green'} ,
{ value: 800, color : 'red' },
{ value: 2800, color: 'purple'}
];
var isColorSet = false;
for (var i=0; i<colorMap.length; i++) {
lis[i].style.background='black';
if (!isColorSet && offset < colorMap[i].value) {
lis[i].style.background = colorMap[i].color;
isColorSet = true;
}
}
}
Let me know if it works for you.
Please find Updated Demo Link here

Creating a delay in for-loop iterations

I've written the following function with hopes to add 1px onto the top margin to animate a window sliding out of the page.
Currently it works fine and removes the window from the page, However I'm having problems creating the delay interval in each iteration of the for loop. I've thought about using setTimeout(), but with this I cant just break; the for loop I have to call a function,
Any ideas?
function slideOut() {
var obj = document.getElementById("cInstructs");
var orig = 66;
for(i=0; i<2000; i++) {
orig++;
obj.style.marginTop = orig+"px";
}
};
Thanks in advance!
A suggestion would be to check the jQuery .slideDown() function- http://api.jquery.com/slideDown/
var i;
function incrAndDelay(i) {
setTimeout(...);
i+=1;
return i;
}
function slideOut() {
var obj = document.getElementById("cInstructs");
var orig = 66;
for(i=0; i<2000; incrAndDelay(i)) {
orig++;
obj.style.marginTop = orig+"px";
}
};
Still have to call a function but not in the loop body.
var intId;
function slideOut() {
clearInterval(intId);
var count = 0;
var obj = document.getElementById("cInstructs");
var orig = 66;
intId = setInterval(function(){
orig++;
obj.style.marginTop = orig+"px";
if((++count == 2000)){
clearInterval(intId);
}
}, 100);
}

Categories

Resources