My code is running well...
but there is one thing I can't solve:
when I mouseover the image the loop starts well, but on subsequent mouseovers it starts changing faster and faster...
var Image = new Array("//placehold.it/400x180/?text=Welcome",
"//placehold.it/400x180/?text=To",
"//placehold.it/400x180/?text=My",
"//placehold.it/400x180/?text=Web+page",
"//placehold.it/400x180/?text=INPHP");
var Image_Number=0;
var Image_Length= Image.length;
function change_image(num){
Image_Number = Image_Number + num;
if(Image_Number > Image_Length)
Image_Number = 0;
if(Image_Number < Image_Length)
document.slideshow.src = Image[Image_Number];
return false;
Image_Number = Image_Length;
}
function auto () {
setInterval("change_image(1)", 1000);
}
<img src="//placehold.it/400x180/?text=Welcome" name="slideshow" onmouseover="auto()" />
On every mouseover you're reassigning a brand-new-intervalâ„¢ resulting in multiple functions running at the same time.
name on IMG tag is an obsolete HTML5 attribute - See also img tag # W3.org
"change_image(1)" ...strings inside setInterval or setTimeout tigger eval. Which is bad. The real function name should be used instead: setInterval(functionName, ms)
You're not managing well the argument num
You cannot have code after a return statement
Use the mouseenter event (instead of mouseover)
and many more errors....
Here's a remake:
var images = [
"//placehold.it/400x180/?text=Welcome",
"//placehold.it/400x180/?text=To",
"//placehold.it/400x180/?text=My",
"//placehold.it/400x180/?text=Web+page",
"//placehold.it/400x180/?text=INPHP"
];
var c = 0; // c as Counter ya?
var tot = images.length;
var angryCat = false;
// Preload! Make sure all images are in tha house
for(var i=0; i<tot; i++) {
var im = new Image();
im.src= images[i];
}
function changeImage() {
document.slideshow.src = images[++c%tot];
}
function auto() {
if(angryCat) return; // No more mouse enter
angryCat = true;
setInterval(changeImage, 1000);
}
<img src="//placehold.it/400x180/?text=Welcome" name="slideshow" onmouseenter="auto()" />
The increment and loop is achieved using ++c % tot
The angryCat boolean flag helps to know it the auto() already started (mouse was there!), in that case it will return; (exit) the function preventing the creation of additional overlapping intervals on subsequent mouseenter (which was your main issue).
Additionally, I'd suggest to keep your JS away from HTML, so instead of the JS attribute event
onmouseenter="auto()"
assign an ID to your image id="myimage" and use JS:
document.getElementById("myimage").addEventListener("mouseenter", auto, false);
Related
I'm trying to learn JS and this is my little app.
Every time I press the "INSTANTIATE" button, it instantiates a tomatoe.png in my <div>.
When the user reloads the page, the tomatoe.png should appear as many times as they've pressed the "INSTANTIATE" button.
This is the code. For this purpose, I created a variable (i), and it increments on every button press.
I planned to save this variable into localStorage, and when the page gets reloaded, I want to call a loop function that instantiates the tomatoe.png i times.
function popUp() {
var img = document.createElement("img");
img.src = "tomato.png";
var src = document.getElementById("header");
src.appendChild(img);
i++;
localStorage.setItem("apples", i);
}
<button onclick="popUp()">INSTANTIATE</button>
<div id="header"></div>
So, when the user reloads the page, as many tomatoes should appear as many times they've pressed the button.
I think I have to use a loop, but I don't know how.
Just get the item in localStorage and loop until it reaches 0, creating a new image each time (localStorage don't works in StackOverflow snippets here because of security reasons, but you get the point).
var i = 0;
function popUp() {
newImage();
i++;
localStorage.setItem("apples", i);
}
function newImage() {
var img = document.createElement("img");
img.src = "tomato.png";
var src = document.getElementById("header");
src.appendChild(img);
}
var oldi = Number(localStorage.getItem("apples"));
while (oldi > 0) {
oldi--;
newImage();
}
<button onclick="popUp()">INSTANTIATE</button>
<div id="header"></div>
First of all, you have to declare i outside your function (in case you haven't done it already) and give it a value of zero, if it isn't exist in the Local Storage:
let i = localStorage.getItem("apples") || 0;
Then, create a loop, that loops i times:
for(let n = 0; n < i; n++){}
And finally, just create tomatoes:
const img = document.createElement("img");
img.src = "tomato.png";
const src = document.getElementById("header");
src.appendChild(img);
So, the full code should look like this:
document.addEventListener('DOMContentLoaded', function(){
function popUp() {
createTomato()
i++;
localStorage.setItem("apples", i);
}
function createTomato() {
const img = document.createElement("img");
img.src = "tomato.png";
const src = document.getElementById("header");
src.appendChild(img);
}
document.getElementById("instantiate").addEventListener("click", popUp)
let i = localStorage.getItem("apples") || 0;
for (let n = 0; n < i; n++) createTomato();
})
<button id="instantiate">INSTANTIATE</button>
<div id="header"></div>
Try it on codepen.io
FOr some reason my code is not executing properly. i am trying to program a slideshow with javascript. Im using a for loop to pull and populate the src files from a created array and change the pic every 3 seconds. THe page loads and the first pic is present but when the interval occurs the first pic dissapears and nothing falls in its place. What am I doing wrong?
<img name="mainSlide" id="mainSlide" src="images/mainPagePhotos/facebook-20131027-180258.png" alt="">
var mainSlidePics = ("facebook-20131027-180258.png","IMG_9694116683469.jpg","IMG_28452769990897.jpg");
window.onload = setInterval("mainSlide();", 3000);
function mainSlide() {
for(i=0; i<mainSlidePics.length; i++ ) {
document.images.mainSlide.src = "images/mainPagePhotos/" + mainSlidePics[i];
}
}
Have you tried getting the Id first?
var mainSlide = document.getElementById("mainSlide");
mainSlide.src = "images/mainPagePhotos/" + mainSlidePics[i];
also a forloop is a loop that finishes its loops even in one call.
try
var i = 0;
window.onload = setInterval("mainSlide(i);", 3000);
mainSlide(int j){
mainSlide.src = "images/mainPagePhotos/" + mainSlidePics[i];
setInterval("mainSlide(j++);", 3000);
}
First you have to correctly declare the array.
Then you have to move the counter variable outside the function triggered by setInterval.
Then pass the reference of the function to setInterval.
<img name="mainSlide" id="mainSlide" src="images/mainPagePhotos/facebook-20131027-180258.png" alt="">
<script type="text/javascript">
var mainSlidePics = ["facebook-20131027-180258.png","IMG_9694116683469.jpg","IMG_28452769990897.jpg"];
var position = 0;
function changePic() {
position = (position+1) % mainSlidePics.length;
document.images.mainSlide.src = "images/mainPagePhotos/" + mainSlidePics[position];
}
window.onload = function() {
setInterval(changePic, 3000);
};
</script>
I have a reveal presentation in an iframe. Each slide has a div with an audio player in in and the divs id is "narration".
I have a button outside the frame that is used to hide/show this div. The problem is that it only does this for the first slide and not the rest.
EDIT : This seems to hide the divs :
function checkAudio() {
if (document.getElementById('cb1').checked) {
var y = document.getElementById('ppt').contentWindow.document.getElementsByClassName('narration');
var i;
for (i = 0; i < y.length; i++) {
y[i].style.display = 'none';
}
} else {
var y = document.getElementById('ppt').contentWindow.document.getElementsByClassName('narration');
var i;
for (i = 0; i < y.length; i++) {
y[i].style.display = 'block';
}
}
}
HTML in iframe (There is one for each slide) :
<div id="narration"><p align="middle">
<audio controls="" preload="none">
<source src="mp3/2.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio></p>
</div>
JS (outside of iframe):
function checkAudio() {
if (document.getElementById('cb1').checked) {
document.getElementById('ppt').contentWindow.document.getElementById('narration').style.display = 'none';
} else {
document.getElementById('ppt').contentWindow.document.getElementById('narration').style.display = 'block';
}
}
After changing your IDs to classes (read here why), you need to update your javascript code to handle the multiple divs via a foreach loop.
function checkAudio() {
var narrationDivs = document.getElementById('ppt').contentWindow.document.getElementsByClassName('narration');
var newDisplay = "block";
if (document.getElementById('cb1').checked) {
newDisplay = "none";
}
narrationDivs.forEach(function(div) {
div.style.display = newDisplay;
});
}
In order to have the code run again when your iframe changes, you need to update your iframe changing function:
function setURL(url){
document.getElementById('ppt').src = url;
checkAudio(); // Just run the function again!
}
If you want to show a specific element using a button, you should use a specific ID. If you want to show all items using a single button you should use classes. You could also use classes to show a specific element e.g.: The 5th button will show the 5th element but this is not a good style.
When the site in the iframe loads the next frame, your code doesn't know to hide the div it presents again. You need an event to process on.
You need to poll the id so that if it shows up again, you can hide it. See: iframe contents change event?
function checkAudio() {
if (document.getElementById('cb1').checked) {
var y = document.getElementById('ppt').contentWindow.document.getElementsByClassName('narration');
var i;
for (i = 0; i < y.length; i++) {
y[i].style.display = 'none';
}
} else {
var y = document.getElementById('ppt').contentWindow.document.getElementsByClassName('narration');
var i;
for (i = 0; i < y.length; i++) {
y[i].style.display = 'block';
}
}
}
You might also want to check out the audio-slideshow plugin that allows to play separate audio files for each slide and fragment. If your main need is this, the plugin should do the job for you.
You can find a demo here and the plugin here. There is also the slideshow-recorder plugin that allows you to record your narration.
Asvin
I'm trying to create an image rotator that displays certain images at certain times, but also rotates at other times in the day.
When I first created it, I just had it rotate every three seconds. That worked fine. But once I added the code to make a different image show up at different times, it quit working all together. Part of the problem is I'm confused about where I should put the setInterval and clearInterval. Anyway, here;s the code.
<img id="mainImage" src="/arts/rotatorpics/artzone.jpg" />
JS:
var myImage = document.getElementById("mainImage");
var imageArray = ["arts/rotatorpics/artzone.jpg",
"arts/rotatorpics/bach.jpg",
"arts/rotatorpics/burns.jpg"];
var imageIndex = 0;
var changeImage = function() {
mainImage.setAttribute("src", imageArray[imageIndex]);
imageIndex++;
if (imageIndex >= imageArray.length) {
imageIndex = 0;
}
}
var newDay = new Date(); //create a new date object
var dayNight = newDay.getHours(); //gets the time of day in hours
function displayImages() {
if (dayNight >= 10 && dayNight <= 12) {
mainImage.setAttribute("src", imageArray[1]);
} else if (dayNight >= 17 && dayNight <= 19) {
mainImage.setAttribute("src", imageArray[2]);
} else {
var intervalHandle = setInterval(changeImage, 3000);
}
myImage.onclick = function() {
clearInterval(intervalHandle);
};
}​
first of all, all your variables seem to be are global, please dont do that, use an anonymous function-wrapper which executes your code (immediately (read about IIFE here. this is not part of your problem, but just good and clean coding style.
(function() {
// your code here
})();
then i think one of your problems is your displayImages-function, which you declare but never call!
just should call it at the end of your code (or just leave it out)
displayImages();
if you want your images not to be swapped between 10-12 and 17-19 your code should then work as expected. if the images should swap even at this times, you shouldnt put the setInterval into the last else (inside your displayImages-function
So far I created an array with 11 images, initialized the counter, created a function, created a for loop but here is where I get lost. I looked at examples and tutorial on the internet and I can see the code is seeming simple but I'm not getting something basic here. I don't actually understand how to call the index for the images. Any suggestions. Here is the code.
<script type="text/javascript">
var hammer=new Array("jackhammer0.gif",
"jackhammer1.gif",
"jackhammer2.gif",
"jackhammer3.gif",
"jackhammer4.gif",
"jackhammer5.gif",
"jackhammer6.gif",
"jackhammer7.gif",
"jackhammer8.gif",
"jackhammer9.gif",
"jackhammer10.gif")
var curHammer=0;
var numImg = 11;
function getHammer() {
for (i = 0; i < hammer.length; i++)
{
if (curHammer < hammer.length - 1) {
curHammer = curHammer +1;
hammer[i] = new Image();
hammer[i].src="poses/jackhammer" +(i+1) + ".gif";
var nextHammer = curHammer + 1;
nextHammer=0;
{
}
}
}
}
setTimeout("getHammer()", 5000);
</script>
</head>
<body onload = "getHammer()";>
<img id="jack" name="jack" src = "poses/jackhammer0.gif" width= "100" height ="113" alt = "Man and Jackhammer" /><br/>
<button id="jack" name="jack" onclick="getHammer()">Press button</button>
Following on what Paul, said, here's an example of what should work:
var hammer=["jackhammer0.gif","jackhammer1.gif","jackhammer2.gif","jackhammer3.gif",
"jackhammer4.gif","jackhammer5.gif","jackhammer6.gif","jackhammer7.gif",
"jackhammer8.gif","jackhammer9.gif","jackhammer10.gif"];
var curHammer=0;
function getHammer() {
if (curHammer < hammer.length) {
document.getElementById("jack").src= "poses/" + hammer[curHammer];
curHammer = curHammer + 1;
}
}
setTimeout("getHammer()", 5000);
The big missing element is that you need to call getElementById("jack") to get a reference to the DOM Image so that you can change it's source. If you're using jQuery or most other JS frameworks, just type $("#jack") to accomplish the same.
I don't understand the need for the for loop at all, just increment the index value [curHammer] each time you click, and reset if it passes your max index length (in this case 11).
Pseudo-Code:
currentHammer = -1
hammers = [ "a1.jpg", "a2.jpg", "a3.jpg"]
getHammer()
{
currentHammer = currentHammer + 1;
if(currentHammer > 2)
currentHammer = 0;
image.src = hammers[currentHammer];
}
a) are you just trying to show an animated gif? If so, why not use Adobe's Fireworks and merge all those gifs into a single gif?
b) you know that the way you have it the display is going to go crazy overwriting the gif in a circle right?
c) you might want to put a delay (or not). If so, make the load new gif a separate function and set a timeout to it (or an interval).
Also, you are being redundant. How about just changing the src for the image being displayed?:
var jackHammer = new Array();
for (var i=0;i<11;i++) { //pre-loading the images
jackHammer[i] = new image();
jackHammer[i].src = '/poses/jackHammer'+i.toString()+'.gif';
} //remember that "poses" without the "/" will only work if that folder is under the current called page.
for (var i=0;i<11;i++) { //updating the image on
document.getElementById('jhPoses').src = jackHammer[i].src;
}
on the document itself,
< img id='jhPoses' src='1-pixel-transparent.gif' width='x' height='y' alt='poses' border='0' />