I am creating a really basic program that allows a user to cycle through images, with a set of buttons, and the major problem I'm having with it, is that it appears to just be selecting random points in the array. For example, the array starts at 1, and yet it displays the image that is in the position 0, or let's say I try to cycle backwards through images, if I go from 0 (Which is meant to be position 3), it'll jump back to the image at position 1. I can't make sense of it.
var i = 0;
var imageArr = [];
imageArr[0] = 'img/img_BMW.jpg';
imageArr[1] = 'img/img_Chr.jpg';
imageArr[2] = 'img/img_Mas.jpg';
imageArr[3] = 'img/img_Merc.jpg';
function imageCycle(){
document.imgCycle.src = imageArr[i];
if(i < imageArr.length - 1){
i++
}
else{
i = 0;
}
console.log(i);
}
function imagePrev(){
document.imgCycle.src = imageArr[i];
if(i == imageArr.length - 1){
i = 3;
}
else{
i--;
}
}
<img name="imgCycle" width="440" height="250"/>
<ul>
<li><button type="button" id="back-Btn" onclick="imagePrev();">Back</button></li>
<li><button type="button" id="forward-Btn" onclick="imageCycle();">Forward</button></li>
</ul>
You could add a method to go to the next index you want and have this function ensure that the index doesn't go out of bounds.
As a side note, binding the event handlers like you did through the onclick attribute is not really the preferred way of doing this anymore. Try using addEventListener instead.
var i = 0;
// Use some actuale images so we can see what happens in the DOM.
var imageArr = [
'//placehold.it/300/200/?text=1',
'//placehold.it/300/200/?text=2',
'//placehold.it/300/200/?text=3',
'//placehold.it/300/200/?text=4'
];
/**
* A method to alter the index. Pass 1 to go to the next slide and -1 to go to
* the previous slide. It will make sure the index is never out of bounds.
*/
function getNextIndex(index, modifier) {
// Add the modifier to the index.
index = index + modifier;
// Check if the index is less than zero, this is unvalid and we will reset the index
// to the last item in the image array. When the index is more than 0, check if it exceeds
// the index for the last item in the array. In this case reset it to 0 so we go back to
// the first image.
if (index < 0) {
index = imageArr.length - 1;
} else if (index >= imageArr.length) {
index = 0;
}
return index;
}
function updateImage(index) {
document.imgCycle.src = imageArr[index];
}
function goToNextImage() {
i = getNextIndex(i, 1);
updateImage(i);
}
function goToPreviousImage() {
i = getNextIndex(i, -1);
updateImage(i);
}
updateImage(0);
<img name="imgCycle" width="440" height="250"/>
<ul>
<li><button type="button" id="back-Btn" onclick="goToPreviousImage();">Back</button></li>
<li><button type="button" id="forward-Btn" onclick="goToNextImage();">Forward</button></li>
</ul>
You are setting the src before the value gets incremented.
Try this
var i = 0;
var imageArr = [];
imageArr[0] = 'img/img_BMW.jpg';
imageArr[1] = 'img/img_Chr.jpg';
imageArr[2] = 'img/img_Mas.jpg';
imageArr[3] = 'img/img_Merc.jpg';
function imageCycle(){
if(i < imageArr.length - 1){
i++
}
else{
i = 0;
}
document.imgCycle.src = imageArr[i];
console.log(i);
}
function imagePrev(){
if(i == imageArr.length - 1){
i = 3;
}
else{
i--;
}
document.imgCycle.src = imageArr[i];
console.log(i);
}
<img name="imgCycle" width="440" height="250"/>
<ul>
<li><button type="button" id="back-Btn" onclick="imagePrev();">Back</button></li>
<li><button type="button" id="forward-Btn" onclick="imageCycle();">Forward</button></li>
</ul>
So the person above me (#Syed) already answered the main issue but I want to point out another issue:
your imagePrev() function: It checks if i is equal to the array length minus 1, and if it does - you make i become 3.
In your case, it will make the picture be stuck on the last one, and otherwise go back (until i reaches -1 and causes issues)
Try this instead:
function imagePrev() {
if (i == 0) {
i = imageArr.length - 1;
}
else {
i--;
}
document.imgCycle.src = imageArr[i];
console.log(i);
}
Cheers
Related
Currently, im adding 1 to the index on click, to simulate a user controlled iteration of the array. I have a conditional statement where if i > length, i = 0; Yet im still getting undefined after reaching the end of the array.
const marqueeMonthlies = () => {
intervalId = setInterval(() => {
insertMarquee.empty('');
// i %= marqueeMonthlyPlates.length
insertMarquee.append(
`<div class="container" id="generatedMonthlyPlates">
<input type="text" width="100px" name="monthlyLicensePlate" id="${marqueeMonthlyPlates[i]}" class="licensePlate" placeholder="AB12345" value="${marqueeMonthlyPlates[i]}"/>
</div>`
)
// i++;
}, 5000);
}
const getNextMonthly = () => {
if ( i < marqueeMonthlyPlates.length) {
i = i+1
return marqueeMonthlyPlates[i]
} else
if (i > marqueeMonthlyPlates.length){
i = 0;
return marqueeMonthlyPlates[i];
} else
if (marqueeMonthlyPlates.length === undefined ){
i = 0;
return marqueeMonthlyPlates[i];
}
}
I tried to catch for when undefined present, to set the index back to 0, but it only corrects itself when 1 is added to i again on another click. What am I doing wrong here?
The answer was to change my greater than statement, as the goal was to bring i back to 0 when it reached the end.
if (i > marqueeMonthlyPlates.length){
i = 0;
return marqueeMonthlyPlates[i];
to
if (i >= marqueeMonthlyPlates.length){
i = 0;
return marqueeMonthlyPlates[i];
I'm creating a game where the computer tries to guess the user's number based on user feedback like too high or too low. I'm using a binary search. The functions work properly, however, every time the buttons are pressed, the code resets to make the original list from 1 to 100 making the guess 50 instead of remembering the new list and guess defined inside my functions.
var list = new Array();
for (i = 0; i <= 100; i++) {
list.push(i)
}
//console.log(list)
// List is intially an empty array (list). The
// for loop generates integers from
// 0 to 100 and pushes them into the array.
var guess = list[Math.floor((list.length / 2))];
console.log(guess);
var toolow = function(guess) {
while (list.includes(guess) == true) {
list.shift()
};
var guess = list[Math.floor((list.length / 2) - 1)];
console.log(list);
console.log(guess)
}
// toolow(guess)
var toohigh = function(guess) {
var last = parseInt(list.length);
while (list.includes(guess) == true) {
list.pop()
};
var guess = list[Math.round(list.length / 2)];
console.log(list);
console.log(guess)
}
// toohigh(guess)
<h1> Guess Your Number </h1>
<button id="TooLow" onclick="toolow(guess);"> Too Low</button>
<button id="TooHigh" onclick="toohigh(guess);">Too High</button>
your over use of the variable guess is causing all sorts of issues
no need to pass guess from onclick to the function
don't declare a var guess inside the functions
et voila - your code works now
var list = new Array();
for (i = 0; i <= 100; i++) {
list.push(i)
}
//console.log(list)
// List is intially an empty array (list). The
// for loop generates integers from
// 0 to 100 and pushes them into the array.
var guess = list[Math.floor((list.length / 2))];
console.log(guess);
var toolow = function() {
while (list.includes(guess) == true) {
list.shift()
};
guess = list[Math.floor((list.length / 2) - 1)];
console.log(list);
console.log(guess)
}
// toolow(guess)
var toohigh = function() {
var last = parseInt(list.length);
while (list.includes(guess) == true) {
list.pop()
};
guess = list[Math.round(list.length / 2)];
console.log(list);
console.log(guess)
}
// toohigh(guess)
<h1> Guess Your Number </h1>
<button id="TooLow" onclick="toolow();"> Too Low</button>
<button id="TooHigh" onclick="toohigh();">Too High</button>
I need the images to change from one to another each time the button is pressed. I have tried using SetTimeout, setInterval etc and none of these seem to work? Im not sure what I'm doing wrong
var list = [
"https://assets.publishing.service.gov.uk/media/559fbe1940f0b6156700004d/traffic-light-red.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe48ed915d1592000048/traffic-light-amber.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe3e40f0b6156700004f/traffic-light-green.jpg",
"http://thndl.com/images/1_3.png"
];
var index = 0;
function changeLights() {
index = index + 1;
if (index == list.length)
index = 0;
var myVar = setInterval(function() {
ChangeLights()
}, 1000);
}
}();
<button type="button" onclick="changeLights()">Change Lights</button>
You are calling ChangeLights instead of changeLights. But even if you call it right, you create an interval with calling the same function each 1000 ms. That means at the second call, it create a new interval and calls it again and the actual interval call the function as well.
Solution: Separate initializing of the interval and the function for doing the work.
Start with startLights and call changeLights in the interval.
var list = [
"https://assets.publishing.service.gov.uk/media/559fbe1940f0b6156700004d/traffic-light-red.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe48ed915d1592000048/traffic-light-amber.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe3e40f0b6156700004f/traffic-light-green.jpg",
"http://thndl.com/images/1_3.png"
];
var index = 0;
function changeLights() {
index = index + 1;
if (index == list.length) {
index = 0;
}
console.log(index);
}
function startLights() {
setInterval(changeLights, 1000);
}
<button type="button" onclick="startLights()">Change Lights</button>
Error
changeLights() != ChangeLights()
Warning
Is the setInterval() placing
Not apply the setInterval() inside the click function.In each time loop time second's are reduced.so its change more lower time seconds.So use with setInterval with in click and color change was separate
var list = [
"https://assets.publishing.service.gov.uk/media/559fbe1940f0b6156700004d/traffic-light-red.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe48ed915d1592000048/traffic-light-amber.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe3e40f0b6156700004f/traffic-light-green.jpg",
"http://thndl.com/images/1_3.png"
];
var index = 0;
function change() {
index = index + 1;
if (index == list.length)
index = 0;
console.log(list[index])
}
function changeLights(){
var myVar = setInterval(function() {
change()
}, 1000);
}
<button type="button" onclick="changeLights()">Change Lights</button>
As above answers indicate - the call to the function needs to be outside it. One alteration I would suggest is to use the modulus operator (index % 3) which will allow a constant cycling of the images without the need for the if statement. This works because the modulus operator gives the remainder after dividing the number by the operator - so modulus %3 will mean that for example if index is three - the remainder is 0, 4 gives 1 5 gives 2 and then 6 is back at 0. So you have a perfect cycling count giving the three values 0,1, and 2 without having to check for each one.
var list = [
"https://assets.publishing.service.gov.uk/media/559fbe1940f0b6156700004d/traffic-light-red.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe48ed915d1592000048/traffic-light-amber.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe3e40f0b6156700004f/traffic-light-green.jpg",
"http://thndl.com/images/1_3.png"
];
var index = 0;
function changeLights() {
index +=1;
document.getElementById('imageSrc').textContent = 'Source: ' + list[index %3];
document.getElementById('lights').src = list[index %3];
}
var myVar = setInterval(function() {
changeLights()
}, 1000);
<p id="imageSrc"></p>
<img id = "lights"/>
I am swapping content based on a loaded in array (so the length of the array will be dynamic each time) and I'm trying to figuire out how to handle the first and last item in this method. As in - I need when you click left from the first one it would go to the last and opposite for the last.
So I just have this -
<div class="side{{side.name}} side" ng-repeat="side in sides" ng-show="side.active" >
{{side.name}}
<i class="fa fa-chevron-circle-left" ng-click="flipLeft($index)"></i>
<i class="fa fa-chevron-circle-right" ng-click="flipRight($index)"></i>
</div>
and in the controller it just looks like this
$scope.flipLeft = function (index){
$scope.sides[index].active = false;
$scope.sides[index-1].active = true;
};
$scope.flipRight = function (index){
$scope.sides[index].active = false;
$scope.sides[index+1].active = true;
};
So all it really does is swap the .active to true or false to show or hide the content. I'm not sure how to switch around my logic so it loops around so that if you click left on the first item it goes to the last and visa versa. Thanks in advance!
Check if the index you want to set is greater than or less than the minimum/maximum values. If so, adjust:
$scope.flipLeft = function (index){
var idx = index - 1;
if (idx < 0) {
idx = $scope.sides.length - 1;
}
$scope.sides[index].active = false;
$scope.sides[idx].active = true;
};
$scope.flipRight = function (index){
var idx = index + 1;
if (idx >= $scope.sides.length) {
idx = 0;
}
$scope.sides[index].active = false;
$scope.sides[idx].active = true;
};
The easiest way is to use the mod method so that incrementing or decrementing stays in the range of valid numbers. So looking at your code I would recommend
$scope.flipLeft = function (index){
$scope.sides[index].active = false;
index = (index-1).mod($scope.sides.length)
$scope.sides[index].active = true;
};
And be sure to implement this trick: Javascript modulo not behaving.
$scope.flipLeft = function (index){
var sides = $scope.sides,
first = index,
second = (index === 0) ? sides.length - 1 : first - 1;
sides[first].active = false;
sides[second].active = true;
};
$scope.flipRight = function (index){
var sides = $scope.sides,
first = index,
second = (index === sides.length - 1) ? 0 : first + 1;
sides[first].active = false;
sides[second].active = true;
};
Bit of a weird problem here - so I will try to explain this as clearly as possible.
I have a simple ng-repeat that will show content based on what has a key value of .active set to true. I let the user scroll through the content with some arrow buttons bound to some ng-clicks. This works great, however I want to exclude one item from the array if it has the key value of side = 'help' attached to it. So basically I want the arrow clicks to skip over it in a sense. I have no control unfortunately where in the array the help item is. So here are the click functions
//flip right
$scope.flipRight = function(index, parent){
var idx = index + 1;
if (idx >= $scope.contentHere[parent].sides.length) {
idx = 0;
}
$scope.contentHere[parent].sides[index].active = false;
$scope.contentHere[parent].sides[idx].active = true;
};
//flip left
$scope.flipLeft = function(index, parent){
var idx = index - 1;
if (idx < 0) {
idx = $scope.contentHere[parent].sides.length - 1;
}
$scope.contentHere[parent].sides[index].active = false;
$scope.contentHere[parent].sides[idx].active = true;
};
So basically what I am trying to figuire out is how to have this logic skip over the item if it has .side = 'help'. I thought about using lodash to _filter the array by items that do not have the value, but it will offset the index so that will not work. I am not sure how to approach this (maybe I am thinking about this incorrectly?), and could use some direction.
Thank you for taking the time to read!
$scope.flipRight = function(index, parent){
var idx = index + 1;
if(idx >= $scope.contentHere[parent].sides.length){
idx = 0;
}
if($scope.contentHere[parent].sides[idx] == 'help'){
$scope.flipRight(idx, parent); //Added to skip over to next item
$scope.contentHere[parent].sides[index].active = false; // Added for the first item does not turn .active to false Issue
return; // Added to skip execution of following line of codes incase of recursion
}
$scope.contentHere[parent].sides[index].active = false;
$scope.contentHere[parent].sides[idx].active = true;
};
//flip left
$scope.flipLeft = function(index, parent){
var idx = index - 1;
if (idx < 0) {
idx = $scope.contentHere[parent].sides.length - 1;
}
if($scope.contentHere[parent].sides[idx] == 'help'){
$scope.flipLeft(idx, parent); //Added to skip over to next item
$scope.contentHere[parent].sides[index].active = false; // Added for the first item does not turn .active to false Issue
return; // Added to skip execution of following line of codes incase of recursion
}
$scope.contentHere[parent].sides[index].active = false;
$scope.contentHere[parent].sides[idx].active = true;
};