I'm trying to build "hit the image" game where few images are displayed on page while "covered" and one image (which image is changing) is "open".
My idea was to start a while loop on user choice that will create a random id (each card has an id) and send it to another function. That part works fine I think.
Function number 2 should "flip" the cards for 1 second and then cover them again.
In the console I can see that the "flip" class is being added but not removed, but on the page all of the cards are "covered".
I think the problem is that the first function is sending random numbers too fast while the flip function has a timeout set. Can anyone confirm it?
Any ideas on how to solve?
The code is:
Please don't mind the ugly button
var currentCard;
var audioWin = new Audio('sound/win.mp3');
var idNum="a"
//gets string id and removes "flipped" class from it
function flip(idNum){
console.log("in flip");
currentCard=document.getElementById(idNum);
currentCard.classList.add('flipped');
setTimeout(function () {
currentCard.classList.remove('flipped');
}, 1000)
}
//plays sounds if users hits img while card is "open"
function ifClicked(currentCard){
if(currentCard.classList.contains('flipped')){
audioWin.play();
}
else{
//put another short sound
}
}
//creates random nums in range 1-4
function randCard(){
while(true){
var secretNum=Math.floor((Math.random()*4)+1);
idNum=secretNum.toString();
console.log(idNum);
flip(idNum);
//document.getElementById(idNum);
}
}
.card{
background-color: pink;
height: 165px;
width: 165px;
float: left;
margin: 5px;
}
.card img {
position: absolute;
}
.flipped .back {
display: none;
}
.button{
width: 60px;
height: 60px;
background-color: green;
float: left;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My App</title>
<link rel="stylesheet" href="t.css" />
</head>
<body>
<div id="container">
<div id ="1" class="card" onclick="ifClicked(this);">
<img src="img/cards/1.png">
<img class="back" src="img/cards/back.png">
</div>
<div id="2"class="card" onclick="ifClicked(this);">
<img src="img/cards/2.png">
<img class="back" src="img/cards/back.png">
</div>
<div id="3" class="card" onclick="ifClicked(this);">
<img src="img/cards/3.png">
<img class="back" src="img/cards/back.png">
</div>
<div id="4" class="card" onclick="ifClicked(this);">
<img src="img/cards/4.png">
<img class="back" src="img/cards/back.png">
</div>
</div>
<div class="button" onclick="randCard();">here</div>
</body>
<script src="j.js"></script>
</html>
yeah, I think you are on to it, I would remove the loop from this function:
function randCard(){
var secretNum=Math.floor((Math.random()*4)+1);
idNum=secretNum.toString();
console.log(idNum);
flip(idNum);
}
Then call randCard() again once the shown card times out and is turned back over:
function flip(idNum){
console.log("in flip");
currentCard=document.getElementById(idNum);
currentCard.classList.add('flipped');
setTimeout(function () {
currentCard.classList.remove('flipped');
randCard();
}, 1000)
}
And then once the DOM loads, call randCard() to start the cycle:
//PLace this right after your global variable declarations
document.addEventListener("DOMContentLoaded", function(){
//Initial call of randCard()
randCard();
}
Related
I need the "play again" button to be hidden and shown only when the user wins the game.
I'm having troubles with this task and i don't know how to approach it, i'm fairly new to javascript.
Those are the instructions for the task:
When user wins, display a Play Again button
You can show or hide an element by changing its style, see here:
https://css-tricks.com/snippets/javascript/showhide-element/
You need to reset some variables and hide the Play Again button
You need to flip all the cards
To be able to flip the cards we need to be able to select all the cards and remove their
flipped class
This will require a loop similar to:
// get all divs in the document
var divs = document.querySelectorAll('div');
for (var i = 0; i < divs.length; ++i) {
divs[i].style.color = "green";
}
Those are the game files:
HTML File:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My App</title>
<link rel="stylesheet" href="css/game.css" />
</head>
<body>
<div class="header">
<img src="img/layout/logo.png">
<h1>Memory Monsters</h1>
</div>
<div class="card" data-card="1" onclick="cardClicked(this)">
<img src="img/cards/1.png">
<img class="back" src="img/cards/back.png">
</div>
<div class="card" data-card="7" onclick="cardClicked(this)">
<img src="img/cards/7.png">
<img class="back" src="img/cards/back.png">
</div>
<div class="card" data-card="1" onclick="cardClicked(this)">
<img src="img/cards/1.png">
<img class="back" src="img/cards/back.png">
</div>
<div class="card" data-card="7" onclick="cardClicked(this)">
<img src="img/cards/7.png">
<img class="back" src="img/cards/back.png">
</div>
<div class="card" data-card="5" onclick="cardClicked(this)">
<img src="img/cards/5.png">
<img class="back" src="img/cards/back.png">
</div>
<div class="card" data-card="5" onclick="cardClicked(this)">
<img src="img/cards/5.png">
<img class="back" src="img/cards/back.png">
</div>
<script src="js/game.js"></script>
</body>
</html>
CSS file:
background-color: lightblue;
padding: 20px;
border-bottom: 10px solid darkcyan;
color:darkcyan;
font-size: 1.5em;
text-align: center;
}
.header img {
float:right;
}
.card {
background-color: pink;
height: 165px;
width: 165px;
float: left;
margin: 5px;
}
.card img {
position: absolute;
}
.flipped .back {
display: none;
}
Javascript File:
// Those are global variables, they stay alive and reflect the state of the game
var elPreviousCard = null;
var flippedCouplesCount = 0;
// This is a constant that we dont change during the game (we mark those with CAPITAL letters)
var TOTAL_COUPLES_COUNT = 3;
// Load an audio file
var audioWin = new Audio('sound/win.mp3');
// This function is called whenever the user click a card
function cardClicked(elCard) {
// If the user clicked an already flipped card - do nothing and return from the function
if (elCard.classList.contains('flipped')) {
return;
}
// Flip it
elCard.classList.add('flipped');
// This is a first card, only keep it in the global variable
if (elPreviousCard === null) {
elPreviousCard = elCard;
} else {
// get the data-card attribute's value from both cards
var card1 = elPreviousCard.getAttribute('data-card');
var card2 = elCard.getAttribute('data-card');
// No match, schedule to flip them back in 1 second
if (card1 !== card2){
setTimeout(function () {
elCard.classList.remove('flipped');
elPreviousCard.classList.remove('flipped');
elPreviousCard = null;
}, 1000)
} else {
// Yes! a match!
flippedCouplesCount++;
elPreviousCard = null;
// All cards flipped!
if (TOTAL_COUPLES_COUNT === flippedCouplesCount) {
audioWin.play();
}
}
}
}
You can create a boolean variable and place it within the 'win' if() block. Once you win, set that variable to true and add that to your HTML when it's true. Make sure you reset the variable to false if you restart the game.
If you don't know how to add HTML elements with javascript, here's a simple example. https://www.w3schools.com/jsref/met_document_createelement.asp
You can use innerHTML to insert your button (or toggle a class to show/hide it) and then remove all flipped class via a function & looping on this class.
example (probably not the shortest way to do it)
// Those are global variables, they stay alive and reflect the state of the game
var elPreviousCard = null;
var flippedCouplesCount = 0;
// This is a constant that we dont change during the game (we mark those with CAPITAL letters)
var TOTAL_COUPLES_COUNT = 3;
// Load an audio file
var audioWin = new Audio('sound/win.mp3');
// This function is called whenever the user click a card
function cardClicked(elCard) {
// If the user clicked an already flipped card - do nothing and return from the function
if (elCard.classList.contains("flipped")) {
return;
}
// Flip it
elCard.classList.add("flipped");
// This is a first card, only keep it in the global variable
if (elPreviousCard === null) {
elPreviousCard = elCard;
} else {
// get the data-card attribute's value from both cards
var card1 = elPreviousCard.getAttribute("data-card");
var card2 = elCard.getAttribute("data-card");
// No match, schedule to flip them back in 1 second
if (card1 !== card2) {
setTimeout(function() {
elCard.classList.remove("flipped");
elPreviousCard.classList.remove("flipped");
elPreviousCard = null;
}, 1000);
} else {
//alert('Yes! a match!');
flippedCouplesCount++;
elPreviousCard = null;
// All cards flipped!
if (TOTAL_COUPLES_COUNT === flippedCouplesCount) {
audioWin.play();
// and finally add a button to call resetCard()
document.getElementById("replay").innerHTML =
'<button onclick="resetCard();">replay</button>';
}
}
}
}
function resetCard() {// to erase the flipped classes
var cardclass = document.getElementsByClassName("card");
for (i = 0; i < cardclass.length; i++) {
cardclass[i].classList.remove("flipped");
document.getElementById("replay").innerHTML = "";
}
}
.header {
background-color: lightblue;
padding: 0 20px;
border-bottom: 10px solid darkcyan;
color:darkcyan;
font-size: 1.5em;
text-align: center;
}
.header img {
float:right;
}
.card {
background-color: pink;
height: 85px;
width: 85px;
float: left;
margin: 5px;
}
.card img {
position: absolute;
}
.flipped .back {
display: none;
}
<div class="header">
<img src="http://dummyimage.com/80&text=logo.png">
<h1>Memory Monsters</h1>
<p id="replay"><!-- button will show up here --></p>
</div>
<div class="card" data-card="1" onclick="cardClicked(this)">
<img src="http://dummyimage.com/80&text=1.png">
<img class="back" src="http://dummyimage.com/80&text=back.png">
</div>
<div class="card" data-card="7" onclick="cardClicked(this)">
<img src="http://dummyimage.com/80&text=7.png">
<img class="back" src="http://dummyimage.com/80&text=back.png">
</div>
<div class="card" data-card="1" onclick="cardClicked(this)">
<img src="http://dummyimage.com/80&text=1.png">
<img class="back" src="http://dummyimage.com/80&text=back.png">
</div>
<div class="card" data-card="7" onclick="cardClicked(this)">
<img src="http://dummyimage.com/80&text=7.png">
<img class="back" src="http://dummyimage.com/80&text=back.png">
</div>
<div class="card" data-card="5" onclick="cardClicked(this)">
<img src="http://dummyimage.com/80&text=5.png">
<img class="back" src="http://dummyimage.com/80&text=back.png">
</div>
<div class="card" data-card="5" onclick="cardClicked(this)">
<img src="http://dummyimage.com/80&text=5.png">
<img class="back" src="http://dummyimage.com/80&text=back.png">
</div>
I use these flashcards quite regularly. Lately, I have been using pictures as answers. However -I cannot hide the pictures. I would like for the pictures to be hidden upon webpage startup.
function myShowText(id) {
document.querySelector('#' + id + ' .answer').style.color = 'black';
}
function myHideText(id) {
document.querySelector('#' + id + ' .answer').style.color = 'white';
}
.answer {
border-style: solid;
border-color: #287EC7;
color: white;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> Flashcards VBA </title>
<rel="stylesheet" href="css/styles.css">
</head>
<body>
<script src="js/scripts.js"></script>
<h3> Flashcards </h3>
<p class="question">
The first question
</p>
<div id="bash_start">
<p class="answer">
<img src="image.jpg">
</p>
</div>
</body>
</html>
Just add the following CSS class:
.hidden {
display: none;
}
and add the class .hidden to your answer:
<p class="answer hidden">
<img src="image.jpg">
</p>
Then remove this .hidden class whenever your want to show the answer:
document.querySelector('.answer').classList.remove('hidden');
Here is a working example:
var button = document.querySelector('button');
var answer = document.querySelector('.answer');
button.addEventListener('click', function() {
answer.classList.remove('hidden');
});
.hidden {
display: none;
}
<button type="button">Show answer</button>
<p class="answer hidden">This is the answer</p>
If I understand correctly you just want your image to be hidden when the user load the page ? In that case juste put somme css on your image(s) visibility: hidden; or display: none;
Then Javascript/Jquery side you do whatever event you want to fire it and change visibility: visible; or display: block/inline-block;.
<img class="flashCards" src="https://cdn4.iconfinder.com/data/icons/champions-1/512/Champions-04-512.png">
<button id="validate_btn" onclick="validate()">Validate</button>
<style>
img.flashCards { width: 150px; visibility: hidden; }
</style>
<script>
function validate() {
var flashCards = document.getElementsByClassName('flashCards');
//Need a for loop for each image element
//If only one image use getElementById directly with the style
for(i=0;i<flashCards.length;i++) {
flashCards[i].style.visibility = 'visible';
flashCards[i].style.backgroundColor = 'green';
}
}
</script>
I have a gallery of images. I want to show a loading gif when an image is clicked. I am passing the same onclick function to all the images with their id as below:
<div id="smallimage1" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image1.jpeg"/>
</div>
<div id="smallimage2" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image2.jpeg"/>
</div>
<div id="loading" style="margin-top: -65%; display: none; z-index= 9999; position: relative;">
<img src="img/imagepreloader.gif" alt="loading...">
</div>
This is my js :
function imageClicked(id) {
// alert(id);
document.getElementById("loading").style.display = ""; // to display
//alert(loading);
return true;
}
var FirstLoading = true;
function Restoresmallimage() {
if (FirstLoading) {
FirstLoading = false;
return;
}
}
// To disable restoring submit button, disable or delete next line.
document.onfocus = Restoresmallimage;
For the first image its working fine.
But issue is when I am clicking on second image, gif is running on first image and not on the second one. How to resolve this issue? I had defined loading id in each div image.
I think the problem is you never move imagepreloader.gif. Here is my solution to have only one imagepreloader.gif for all images:
HTML:
<div id="smallimage1" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image1.jpeg"/>
</div>
<div id="smallimage2" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image2.jpeg"/>
</div>
CSS:
div {
display: inline-block;
position: relative;
}
#loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
JavaScript:
function constructImagePreloader() {
'use strict';
var imagePreloader = document.createElement('img');
imagePreloader.setAttribute('src', 'images/imagepreloader.gif');
imagePreloader.setAttribute('alt', 'loading...');
imagePreloader.setAttribute('id', 'loading');
return imagePreloader;
}
function imageClicked(id) {
document.getElementById(id).appendChild(constructImagePreloader());
return true;
}
Tell me if it suits your needs. We could go further with code optimization but I wanted to stay close from your code for now. For instance: we could remove the image preloader from the clicked image if another image is clicked.
Try this if it will work,
<div id="smallimage1" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image1.jpeg"/>
</div>
<div id="smallimage2" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image2.jpeg"/>
</div>
<div id="loading1" style="margin-top: -65%; display: none; z-index:9999; position: relative;">
<img src="img/imagepreloader.gif" alt="loading...">
</div>
<div id="loading2" style="margin-top: -65%; display: none; z-index: 9999; position: relative;">
<img src="img/imagepreloader.gif" alt="loading...">
</div>
And your script will be like this;
function imageClicked(id) {
// alert(id);
var loadingId = $(id).replace('smallimage','loading');
document.getElementById(loadingId).style.display = "block"; // to display
//alert(loading);
return true;
}
So below I have some code of what I'm working with. Right now, if you just launch the website, the #picture div has a background image, and if you press any of the buttons, that picture is replaced with something else.
So what I can't figure out is how the buttons would change what they do after pressing a button. Let's say you click on Button 1 and the background image is replaced. I want the buttons to recognize what background image is in that div and change functions accordingly, in my case, I want them to change what pictures they replace the current one with.
If the current background of #picture is X, you have ABC choices, if the background of #picture is Y, you have DEF choices, would be a TLDR explanation maybe.
<div id="adventure">
<div class="picture">
</div>
<div id="choice">
<button class="button1">Val 1</button>
<button class="button2">Val 2</button>
<button class="button3">Val 3</button>
</div>
</div>
$('.button1').click(function() {
$('.picture').css('background-image',
'url("image1")'
);
});
$('.button2').click(function() {
$('.picture').css('background-image',
'url("image2")'
);
});
$('.button3').click(function() {
$('.picture').css('background-image',
'url("image3")'
);
});
I've probably gone about doing this in a bad way but I'm really at a loss on how I would do this. I can only think up of one way of doing it and that is to have a bunch of if statements depending on what background is in the #picture div but I don't know how to implement that.
This demo relies on the class .active which determines which set of buttons (called .group) are visible, whilst the other .groups remain absent. The #switch button will toggle through each group.
You must name your images according to the id of the button it belongs to.
Example:
HTML of Button
<button id="image_of_sky.png">D</button>
URL to Image
http://domain.com/path/to/image_of_sky.png
jQuery img variable
var img = "http://domain.com/path/to/"+btn;
Snippet
$('.button').click(function() {
var btn = $(this).attr('id');
var img = "https://placehold.it/330x150?text=" + btn;
$('.picture').css('background-image',
'url(' + img + ')'
);
});
$('#switch').click(function() {
var act = $('.group.active');
var next = act.next();
act.removeClass('active');
next.addClass('active');
if (act.attr('id') == "choiceGHI") {
$('#choiceABC').addClass('active');
}
});
#adventure {
width: 395px;
}
.picture {
width: 330px;
height: 150px;
border: 1px outset grey;
}
.group {
width: 330px;
display: none;
padding: 0;
}
.button {
width: 32.5%;
margin: 0;
}
.active {
display: block;
}
#switch {
float: right;
margin: -20px 0 0 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="adventure">
<div class="picture"></div>
<div id="choiceABC" class="group active">
<button id="Image1" class="button">A</button>
<button id="Image2" class="button">B</button>
<button id="Image3" class="button">C</button>
</div>
<div id="choiceDEF" class="group">
<button id="Image4" class="button">D</button>
<button id="Image5" class="button">E</button>
<button id="Image6" class="button">F</button>
</div>
<div id="choiceGHI" class="group">
<button id="Image7" class="button">G</button>
<button id="Image8" class="button">H</button>
<button id="Image9" class="button">I</button>
</div>
<button id="switch">Switch</button>
</div>
I want to add button that let user back 30 seconds during listening songs in mp3 player but the hell I can't do it. I am playing with this for hours, here's what I use http://tympanus.net/codrops/2012/12/04/responsive-touch-friendly-audio-player . What I have got already
html
<head>
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Lato:400,700" />
<link rel="stylesheet" href="../../assets/css/audioplayer.css" />
<script src="../../assets/js/jquery.js"></script>
<script src="../../assets/js/audioplayer.js"></script>
</head>
<body>
<div class="container">
<br><br><br><br>
<div class="jumbotron">
<div class="thumbnail">
<br><br><br><br>
<h2 style="text-align: center;">You are listening mp3 number 1</h2>
<br><br><br><br>
<div id="wrapper">
<audio preload="auto" controls>
<source src="../../assets/media/audio/BlueDucks_FourFlossFiveSix.mp3">
</audio>
</div>
</div>
<div class="team">
<a><img src="http://i57.tinypic.com/30t6gd2.jpg"</a>
</div>
<div class="team" style="float: right;">
<a><img src="http://i61.tinypic.com/29zv7u8.png"</a>
</div>
</div>
</div>
<script>$( function() { $( 'audio' ).audioPlayer(); } );</script>
<script>
/*
VIEWPORT BUG FIX
iOS viewport scaling bug fix, by #mathias, #cheeaun and #jdalton
*/
(function(doc){var addEvent='addEventListener',type='gesturestart',qsa='querySelectorAll',scales=[1,1],meta=qsa in doc?doc[qsa]('meta[name=viewport]'):[];function fix(){meta.content='width=device-width,minimum-scale='+scales[0]+',maximum-scale='+scales[1];doc.removeEventListener(type,fix,true);}if((meta=meta[meta.length-1])&&addEvent in doc){fix();scales=[.25,1.6];doc[addEvent](type,fix,true);}}(document));
</script>
</body>
css
.audioplayer-back30s
{
width: 2.5em; /* 40 */
height: 100%;
text-align: left;
text-indent: -9999px;
cursor: pointer;
z-index: 2;
top: 0;
left: 0;
}
.audioplayer-back30s:hover,
.audioplayer-back30s:focus
{
background-color: #222;
}
.audioplayer-back30s a
{
display: block;
}
Rest of css and js files of this mp3 player are here http://tympanus.net/Development/AudioPlayer/AudioPlayer.zip . Really I don't have any ideas and I really need this feature, thank you guys for any help.
You can set the currentTime property of the audio-element:
// jump 30 seconds back when we click the button
$('.audioplayer-back30s').click(function(){
var audio = $('audio');
var backToSec = audio.currentTime - 30;
// make sure that we jump to a valid point in time
audio.currentTime = (backToSec >= 0) ? backToSec : 0;
});