how to randomize multiple images in javascript - javascript

i am pretty new to javascript (a little over 2 months into my studies) and am starting my first project. the end goal is to have a set of baseball team logo images (right now 6 images but eventually i would like to expand this to more) randomized every time a button is clicked. i had researched on how to do this and came across the fisher yates algorithm used in a while loop, and various uses of random number generation. decided to use the fisher yates.
at the moment, my code seems to work. i followed 1 image and i couldn't see a specific pattern. my other concerns are if i can achieve the same functionality using 1 loop and also cleaning up my code so its not so repetitive.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>sports</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div class="container">
<h1>Sports Random</h1>
<br>
<div class="row">
<div class="col-sm-2"> <img id="team1"src="images\sports\team1.jpg" alt=""></div>
<div class="col-sm-2"> <img id="team2"src="images\sports\team2.jpg" alt=""></div>
<div class="col-sm-2"> <img id="team3"src="images\sports\team3.jpg" alt=""></div>
<div class="col-sm-2"> <img id="team4"src="images\sports\team4.jpg" alt=""></div>
<div class="col-sm-2"> <img id="team5"src="images\sports\team5.jpg" alt=""></div>
<div class="col-sm-2"> <img id="team6"src="images\sports\team6.jpg" alt=""></div>
</div>
<br>
<button id="button">Random</button>
<button id="reset">Reset</button>
</div>
</div>
<script src="js/main.js"></script>
</body>
</html>
var button = document.getElementById("button");
var reset = document.getElementById("reset");
var team1 = document.getElementById("team1");
var team2 = document.getElementById("team2");
var team3 = document.getElementById("team3");
var team4 = document.getElementById("team4");
var team5 = document.getElementById("team5");
var team6 = document.getElementById("team6");
var pics = ["team1.jpg", "team2.jpg", "team3.jpg", "team4.jpg", "team5.jpg", "team6.jpg"];
var teams = [team1, team2, team3, team4, team5, team6];
button.addEventListener("click", function random() {
var i = pics.length,
rNum, temp;
// shuffle pictures using fisher yates
while (--i > 0) {
rNum = Math.floor(Math.random() * (i + 1));
temp = pics[rNum];
pics[rNum] = pics[i];
pics[i] = temp;
}
// display images
for (var i = 0; i < teams.length; i++) {
teams[i].src = "images\\sports\\" + pics[i];
}
});
reset.addEventListener("click", function reset() {
team1.src = "images\\sports\\team1.jpg";
team2.src = "images\\sports\\team2.jpg";
team3.src = "images\\sports\\team3.jpg";
team4.src = "images\\sports\\team4.jpg";
team5.src = "images\\sports\\team5.jpg";
team6.src = "images\\sports\\team6.jpg";
});

Just add an id to the div class="row" id="parent">
and replace the code like this.
var button = document.getElementById("button");
var reset = document.getElementById("reset");
var originalChildren =
Array.from(document.getElementById("parent").children);
button.addEventListener("click", function random() {
var list = document.getElementById("parent");
for (var i = list.children.length; i >= 0; i--) {
list.appendChild(list.children[Math.random() * i | 0]);
}
});
reset.addEventListener("click", function reset() {
document.getElementById("parent").innerHTML = "";
for (var i =0 ; i< originalChildren.length; i++) {
document.getElementById("parent").appendChild(originalChildren[i]);
}
});
Additionally, I would also suggest creating the children dynamically then appending them to parent instead of putting them in HTML. But, this is entirely up to you. Modified the code so you don't have to keep the elements in JS side.

Here is a Fiddle that might help you:
https://jsfiddle.net/yha6r5sy/1/
You can use list.children to add it to main div

Related

Too Much Recursion Error When Trying to Find All HTML Comments

The script below is meant to find all html comments in the page (there are 4) and return them as one string. I ran the script below and received a "Too Much Recursion" error.
Have I created an infinite loop or did I do something else?
function findComment()
{
var olElement = document.getElementById("everything");//this is the id for my body element
var comments = new Array();
if (olElement.nodeType == 8)
{
comments[comments.length] = olElement;
} else if(olElement.childNodes.length>0)
{
for (var i = 0; i<olElement.childNodes.length; i++)
{
comments = comments.concat(findComment(olElement.childNodes[i]));
}
}
alert(comments);
}
//window.onload = countListItems;
//window.onload = countTagItems;
//window.onload = getElements;
window.onload = findComment;
This is a rough cut version of how you could do it with a recursion. It is not really elegant but will do the work:
function fico(el){
if (el.nodeType==8) return [el.textContent.trim()]
else return [...el.childNodes].map(fico);
}
console.log(fico(document.querySelector("#everything")).toString().replace(/,+/g,", "));
<body id="everything">
<div>something <!-- comment1 -->
<div>with something inside
<!-- comment2 -->
<div>and something further<div>
<span>inside
<!-- comment3 --></span>
it
</div>
more regular text
<!-- comment4 --> and enough.
</div></body>
Depending on the html input the function will return an array of subarrays with further levels of subarrays. To flatten it I used the Array-method toString() and then replace() with a regular expression to throw out the multiple commas in the result. There is still a superfluous one at the beginning ;-)
And here is an alternative version that uses a global comments array like you used in your code:
var comments=[];
function fico(el){
if (el.nodeType==8) comments.push(el.textContent.trim());
else [...el.childNodes].forEach(fico);
}
fico(document.querySelector("#everything")); // collect comments ...
console.log(comments.join(', ')); // ... and display them
<body id="everything">
<div>something <!-- comment1 -->
<div>with something inside
<!-- comment2 -->
<div>and something further<div>
<span>inside
<!-- comment3 --></span>
it
</div>
more regular text
<!-- comment4 --> and enough.
</div></body>
Move the olElements variable outside the function and pass in the element you want to search. The recursion you have is always starting with 'everything';
var comments = new Array();
function findComment(element)
{
if (element.nodeType == 8)
{
comments[comments.length] = element;
} else if(element.childNodes.length>0)
{
for (var i = 0; i<element.childNodes.length; i++)
{
comments = comments.concat(findComment(element.childNodes[i]));
}
}
return comments;
}
var olElement = document.getElementById("everything");//this is the id for my body element
alert(findComment(olElement));
Update: I tried both methods above and received error that either "element" or "el" is null. So...progress. I've pulled together my full code and html and posted below:
<!DOCTYPE html>
<html>
<head>
<title>A Simple Page</title>
<script>
var comments = new Array();
function findComment(element)
{
if (element.nodeType == 8)
{
comments[comments.length] = element;
} else if(element.childNodes.length>0)
{
for (var i = 0; i<element.childNodes.length; i++)
{
comments = comments.concat(findComment(element.childNodes[i]));
}
}
return comments;
}
//window.onload = countListItems;
//window.onload = countTagItems;
//window.onload = getElements;
var olElement = document.getElementById("everything");//this is the id for my body element
window.onload = alert(findComment(olElement));
</script>
</head>
<body>
<div id="everything">
<h1>Things to Do</h1><!--this is a title-->
<ol id="toDoList"><!--this is a list-->
<li>Mow the lawn</li><!--this is a list item-->
<li>Clean the windows</li>
<li>Answer your email</li>
</ol>
<p id="toDoNotes">Make sure all these things are done so you can get some rest.</p>
</div>
</body>
</html>

Why does the browser create two pieces of div in html but when the code just says one?

I'm working on javascript a bit and have had some problems I do not understand how to solve. In my HTML code, I only have a id="felt" but as soon as I open the page in my browser, it creates two pieces of id="felt" (please see attached image for more understanding: https://imgur.com/7ACU7vt) It seems Do not be wrong with the writing of the html code, there is something that makes id="felt" created twice in the browser and I can't understand why. The second id="felt" is working but the first one is not working.
codepen: https://codepen.io/tommattias/pen/yjYoEQ
Thanks for your help!!
HTML
<html>
<head>
<title>JavaScript Card Game | The Art of Web</title>
<link rel="stylesheet" type="text/css" href="css-animation.css">
</head>
<body>
<div id="stage">
<div id="felt">
<div id="card_0"><img onclick="cardClick(0);" src="back.png"></div>
<div id="card_1"><img onclick="cardClick(1);" src="back.png"></div>
<div id="card_2"><img onclick="cardClick(2);" src="back.png"></div>
<div id="card_3"><img onclick="cardClick(3);" src="back.png"></div>
<div id="card_4"><img onclick="cardClick(4);" src="back.png"></div>
<div id="card_5"><img onclick="cardClick(5);" src="back.png"></div>
<div id="card_6"><img onclick="cardClick(6);" src="back.png"></div>
<div id="card_7"><img onclick="cardClick(7);" src="back.png"></div>
<div id="card_8"><img onclick="cardClick(8);" src="back.png"></div>
<div id="card_9"><img onclick="cardClick(9);" src="back.png"></div>
<div id="card_10"><img onclick="cardClick(10);" src="back.png"></div>
<div id="card_11"><img onclick="cardClick(11);" src="back.png"></div>
<div id="card_12"><img onclick="cardClick(12);" src="back.png"></div>
<div id="card_13"><img onclick="cardClick(13);" src="back.png"></div>
<div id="card_14"><img onclick="cardClick(14);" src="back.png"></div>
<div id="card_15"><img onclick="cardClick(15);" src="back.png"></div>
</div>
</div>
<script type="text/javascript" src="css-animation2.js"></script>
<script type="text/javascript">
var game = new CardGame("stage");
</script>
</body>
</html>
Javascript:
var CardGame = function(targetId)
{
var cards = []
var card_value =
["1C","2C","3C","4C","5C","6C","7C","8C","1H","2H","3H","4H","5H","6H","7H","8H"];
var started = false;
var matches_found = 0;
var card1 = false, card2 = false;
var moveToPlace = function(id) // deal card
{
cards[id].matched = false;
with(cards[id].style) {
zIndex = "1000";
top = cards[id].fromtop + "px";
left = cards[id].fromleft + "px";
WebkitTransform = MozTransform = OTransform = msTransform =
"rotate(60deg)";
zIndex = "0";
}
};
var cardClick = function(id)
{
if(started)
{
showCard(id);
}
else {
// shuffle and deal cards
card_value.sort(function() { return Math.round(Math.random()) - 0.5;
});
for(i=0; i < 16; i++)
{
(function(idx)
{
setTimeout(
function()
{
moveToPlace(idx);
}, idx * 100);
})(i);
}
started = true;
}
};
// initialise
var stage = document.getElementById(targetId);
var felt = document.createElement("div");
felt.id = "felt";
stage.appendChild(felt);
// template for card
var card = document.createElement("div");
card.innerHTML = "<img src=\'back.png\'>";
for(var i=0; i < 16; i++) {
var newCard = card.cloneNode(true);
newCard.fromtop = 15 + 120 * Math.floor(i/4);
newCard.fromleft = 70 + 100 * (i%4);
(function(idx) {
newCard.addEventListener("click", function() { cardClick(idx); },
false);
})(i);
felt.appendChild(newCard);
cards.push(newCard);
}
}
EDIT: When i open my browser, i get like this picture shows
https://imgur.com/7ACU7vt the one who has the text "Not working" should not show up. When i open programmer tool i can se that under id="stage", id="felt" creates two times and thats why I have one working and other one not working. My question is why does i get two id="felt" when my code only say one?
It is already existing in your html, and then within the script you create it again. You cannot have 2 different elements with the same id. Remove it from the html and see my comment

switch from image to random image onclick with JavaScript

I'm trying to build something that would resemble a slide show, where you have an image and when you click on it, it is replaced by another randomly in my series of images. I first tried with simple html, but of course the images don't switch randomly. So I did my research and found that it could be done with an array in Javascript. I just don't really know a lot about javascript…
This is what I could find but it doesn't work, I'm sure there is a stupid mistake in there that I can't see:
this is my javascript
function pickimg2() {
var imagenumber = 2 ;
var randomnumber = Math.random();
var rand1 = Math.round((imagenumber-1) * randomnumber) + 1;
myImages1 = new Array();
myImages1[1] = "img_01.gif";
myImages1[2] = "img_02.gif";
myImages1[3] = "img_03.gif";
myImages1[4] = "img_04.gif";
myImages1[5] = "img_05.gif";
myImages1[6] = "img_06.gif";
myImages1[7] = "img_07.gif";
myImages1[8] = "img_08.gif";
myImages1[9] = "img_09.gif";
var image = images[rand1];
document.randimg.src = "myImages1";
}
there is my html
<!DOCTYPE html>
<html>
<head>
<title>mur</title>
<link rel="stylesheet" href="style.css">
<link rel="JavaScript" href="script.js">
</head>
<body onLoad="pickimg2">
<div class="fenetre">
<img src="img_01.gif" name="randimg" border=0>
</div>
</body>
</html>
If someone has another solution I'm open to it!
Fix your script link like RamenChef mentioned:
<script type="text/javascript" src="script.js"></script>
Here's the updated code, check console.log to see the different image urls getting requested.
var myImages1 = new Array();
myImages1.push("img_01.gif");
myImages1.push("img_02.gif");
myImages1.push("img_03.gif");
myImages1.push("img_04.gif");
myImages1.push("img_05.gif");
myImages1.push("img_06.gif");
myImages1.push("img_07.gif");
myImages1.push("img_08.gif");
myImages1.push("img_09.gif");
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function pickimg2() {
document.randimg.src = myImages1[getRandomInt(0, myImages1.length - 1)];
}
<div class="fenetre">
<a href="#" onClick="pickimg2();return false;">
<img src="img_01.gif" name="randimg" border=0>
</a>
</div>
this code bellow is working. I hope it's what you were asking for
var images = [
"http://img1.science-et-vie.com/var/scienceetvie/storage/images/galerie/deepsea-challenge-le-film-de-james-cameron-livre-des-images-inedites-des-grands-fonds-marins-5165/19818-1-fre-FR/Deepsea-challenge-le-film-de-James-Cameron-livre-des-images-inedites-des-grands-fonds-marins_square500x500.jpg",
"http://static.mensup.fr/photos/145240/carre-premieres-images-officielles-pour-assassin-s-creed-rogue.jpg",
"http://www.pnas.org/site/misc/images/16-01910.500.jpg" ];
init();
function random_image(images) {
var random = randomize(images);
while(images[random] === document.getElementById("image").src){
random = randomize(images)
}
document.getElementById("image").src = images[random].toString();
}
function randomize(array){
return Math.floor((Math.random() * (array.length)));
}
function init() {
document.getElementById("image").addEventListener("click", function(){
random_image(images);
});
random_image(images);
}
<!DOCTYPE html>
<html>
<head>
<title>Bonjour</title>
</head>
<body >
<div class="fenetre">
<img id="image" src="" name="randimg" >
</div>
</body>
</html>

Cycle pictures using an array in JS and HTML

this works on a button click and that is how it is meant to be. The problem lies in the fact that it uses hidden images, instead of images stored in an array. Could you please show me how to do it so that it is images stored in an array.
<!doctype html>
<html>
<body>
<div id="splash">
<img src="TrafficLightRed.gif" alt="" id="mainImg">
</div>
<div id="wrapper">
<div>
<button id="clickme" onclick="changeLight();">Click to change</button>
<img src="TrafficLightRed.gif" hidden>
<img src="TrafficLightYellow.gif" hidden>
<img src="TrafficLightGreen.gif" hidden>
</div>
</div>
<script>
function changeLight() {
var currentImg = document.getElementById("mainImg");
for(var i=1;i<3;i++) {
if(document.images[i].src == currentImg.src) {
currentImg.src = document.images[i + 1].src;
return;
}
}
currentImg.src = document.images[1].src;
}
</script>
</body>
</html>
You would store the image's src in an array:
imagesArray = ["TrafficLightRed.gif","TrafficLightYellow.gif","TrafficLightGreen.gif" ];
And use the array in place of document.images[i + 1].src:
...
for(var i=0;i<imagesArray.length;i++) {
if(imagesArray[i] == currentImg.src) {
currentImg.src = imagesArray[i];
return;
}
}
...
This should do the work:
...
<script>
var images = ["TrafficLightRed.gif", "TrafficLightYellow.gif", "TrafficLightGreen.gif"];
var currentIndex = 0;
function changeLight() {
var currentImg = document.getElementById("mainImg");
currentImg.src = images[(currentIndex++) % images.length];
}
</script>
...
Now you can add more images to array images and it will automatically loop through this array.

Javascript: Uncaught TypeError: Cannot set property 'innerHTML' of null

I've browsed through a couple of questions but I couldn't find any help.
By the way this is the first time I'm asking a question here so I might not do it the right way. Anyway, the following line is causing me the problem
/* cursorPps defined above */
document.getElementById("cursorPps").innerHTML = cursorPps;
The cursorPps variable is already defined. Can someone point out what other possible stuff could have caused this error?
Edit: By the way the problem is that it is not updating the value on HTML, although the value of the variable changes.
HTML:
<html>
<head>
<title>Potato Clicker</title>
<link rel="stylesheet" type="text/css" href="interface.css">
</head>
<body>
<div id="left">
<img id="potato-img" onClick="potatoClick(clickPower)" src="stockvault-potatoes107220.jpg" width="300" height="300">
<br>
<div id="mainDisplay">
<span id="potatoes">0</span> <br> potatoes
<br>
<br>
Producing <span id="pps">0</span> potatoes per second
<br>
</div>
Cursors: <span id="cursors">0</span>
</div>
<div id="middle">
<div id="buildings" onClick="buyCursor()"> Buy Cursor </div>
</div>
<script src="main.js"></script>
</body>
</html>
Javascript:
//variables
var potatoes = 0; //potatoes
var clickPower = 1; //potatoes gained per click
var pps = 0; //potatoes per second
var cursors = 0; //cursors
var cursorCost; //cost of cursor
var cursorPps = 0; //total cursor potatoes per second
var cursorBuy; //cursor buy button
//functions
function potatoClick(number) {
potatoes = potatoes + number;
document.getElementById("potatoes").innerHTML = potatoes;
}
function buyCursor() {
var cursorCost = Math.floor(10 * Math.pow(1.2,cursors));
if (potatoes >= cursorCost) {
pps = pps - cursorPps;
cursors = cursors + 1;
potatoes = potatoes - cursorCost;
cursorPps = cursorPps + 1;
pps = pps + cursorPps;
document.getElementById("potatoes").innerHTML = potatoes;
document.getElementById("cursors").innerHTML = cursors;
document.getElementById("cursorPps").innerHTML = cursorPps;
document.getElementById("pps").innerHTML = pps;
}
else {
alert("Not enough potatoes!")
}
var nextCost = Math.floor(100 * Math.pow(1.2,cursors));
document.getElementById('cursorCost').innerHTML = nextCost;
}
window.setInterval(function () {
if (pps > 0) {
potatoClick(pps);
}
}, 1000);
Make sure that
You have an element has that ID
The element IS on the page before that Javascript is run
You bind the execution of your JS to an event (follow-up from previous) that happens after the element is on the page
The cursorPps variable has been populated
Here's a simple codepen that demonstrates a way to do it http://codepen.io/leopic/pen/wDtIB
<div id="myDiv"></div>
You have an element with that ID
var length = document.querySelectorAll('#myDiv').length;
if(length > 0) {
// This element exists in the DOM tree
}
You bind the execution of your JS to an event (follow-up from previous) that happens after the element is on the page
<body>
<div id="myDiv"></div>
<script>
var length = document.querySelectorAll('#myDiv').length;
console.log(length);
</script>
</body>
The cursorPps variable has been populated
if(cursorPps != undefined)

Categories

Resources