I am trying to make a simple slot machine game as the first one here.
The one in the example above is a bit complex, but I only need mine to add a few classes here and there at simple click events.
Long story short, I have a play button which initiates the slot machine (shows it - this is done), and when the slot machine is shown, a SPIN button appears, and when I click that button, I can only make it add one class for the first combination (e.g. "bonus") which adds the CSS class and its respective transitions to the desired effect.
And now comes the tricky part for me, I need to click the same SPIN button again, but add a different class this time. This has to work 3 times, while when I am pressing it for the 4-th time, I need it to add another class to the id='ad-cont' div.
How can I achieve this with vanilla JS? I know there must be some sort of a loop here, but I can't figure it out.
<div id="ad-cont">
<div id="slot-frame"><img class="frame" src="../frame.png">
<div class="frame-item"></div>
<div class="frame-item"></div>
<div class="frame-item"></div>
<div class="frame-item"></div>
<div class="frame-item"></div>
</div><a id="play" href="#">PLAY</a><a id="spin" href="#">SPIN</a>
</div>
And here is what I've got so far:
var adContainer = document.getElementById('ad-cont');
var playBtn = document.getElementById('play');
var spinBtn = document.getElementById('spin');
var slotMachine = document.getElementById('slot-frame');
playBtn.addEventListener('click', function(){
adContainer.classList.add('playing');
});
spinBtn.addEventListener('click', function(){
slotMachine.classList.add('bonus');
});
Thank You all!
Have you tried using a switch and a count that resets itself?
var count = 0;
spinBtn.addEventListener('click', function(){
count++;
switch(count) {
case 1:
slotMachine.classList.add('bonus');
break;
case 2:
slotMachine.classList.add('bonus2');
break;
case 3:
slotMachine.classList.add('bonus3');
break;
case 4:
otherIdElement.classList.add('finished!');
count = 0;
break;
default:
alert("error!");
}
});
There's not enough code to really give a complete answer, but if I understand you right, I think the easiest thing to do would be to add a counter and an array of classes.
var counter = 0;
var classes = ['playing', 'playing_again', 'another_class', 'bonus']
Then you can add classes as you play:
playBtn.addEventListener('click', function(){
adContainer.classList.add(classes[counter]);
// if you need to do other things here you
// can check the counter value and proceed accordingly
counter++
});
You just need to check that counter never gets higher than the last index of classes
Related
I want to have a really simple gallery of around 5-7 images, where you can click on the image and it switches to the next one, and by the end it circles back to the beginning. My code right now only allows me to have 3 images, where it just loops between image 2 and image 3.
function swaparrows(obj, i1, i2, i3) {
var src = obj.getAttribute('src');
if (src.match(i1))
obj.setAttribute('src', i2);
else
obj.setAttribute('src', i1);
}
And for the HTML:
<img src="https://minecraft-statistic.net/en/og/player/Druio.png"
onclick="swaparrows(this, 'https://camblab.info/wp/wp-content/uploads/2017/02/pool-water.jpg', 'https://i2-prod.mirror.co.uk/incoming/article13348246.ece/ALTERNATES/s615/0_SupernumeraryRainbows_Entwistle_13621-610x859.jp', 'https://minecraft-statistic.net/en/og/player/Druio.png')" />
You can use an attribute on the element to figure out what the current index is. Then, increment that index by one and cap it off at the end of the array via the modulus operator so that it cycles circularly. Also, please do not use onclick for such long code snippets because it makes code very unmaintainable. Also, if you are not using jQuery, then apply to the whole page so that you can easily and quickly add new interactive content. If you are using jQuery, then do not do this because your page will get very laggy very quickly because jQuery embodies and promotes poor performance.
🢔 Because it appears as though you are new to Stackoverflow, I shall explain this checkmark here. After reading and reviewing my answer, if (and only if) you are thoroughly satisfied with the answer I have posted here, then you can reward me by clicking this checkmark to accept this answer as the best answer. If someone else posts a better answer, then click their checkmark. Clicking a checkmark is not permanent: if someone later on post a better answer, then you can click their checkmark and switch the best answer over to the new answer posted.
<img src="https://minecraft-statistic.net/en/og/player/Druio.png"
data-swap-index="2"
data-swap-0="https://camblab.info/wp/wp-content/uploads/2017/02/pool-water.jpg"
data-swap-1="https://i2-prod.mirror.co.uk/incoming/article13348246.ece/ALTERNATES/s615/0_SupernumeraryRainbows_Entwistle_13621-610x859.jpg"
data-swap-2="https://minecraft-statistic.net/en/og/player/Druio.png"
style="max-height:80vh" decoding="async" />
<img src="https://www.minecraft.net/content/dam/archive/og-image/minecraft-hero-og.jpg"
data-swap-index="0"
data-swap-0="https://www.minecraft.net/content/dam/archive/og-image/minecraft-hero-og.jpg"
data-swap-1="https://is4-ssl.mzstatic.com/image/thumb/Purple123/v4/10/29/2f/10292fd0-d87a-6856-7523-f67fa8051df7/AppIcon-0-1x_U007emarketing-0-85-220-9.png/246x0w.jpg"
style="max-height:80vh" decoding="async" />
<script>
addEventListener("click", function(evt){
// when anywhere on the page is clicked, this will fire
var eventObj = evt || window.event;
var target = eventObj.target;
var swapIndex = target.getAttribute("data-swap-index");
if (swapIndex !== null) {
var newSwapIndex = (swapIndex|0) + 1|0;
if (!target.hasAttribute("data-swap-" + newSwapIndex)) {
// cycle back to the first image
newSwapIndex = 0;
}
// now apply the new swap index
target.setAttribute(
"src",
target.getAttribute("data-swap-" + newSwapIndex)
);
target.setAttribute("data-swap-index", newSwapIndex);
eventObj.preventDefault(); // prevent link from opening or something
} // else the element being clicked on is not swappable
});
</script>
Notice how I prefix the attributes with data. All attributes prefixed with data- have been set aside for special custom use purposes by the WhatWG with datasets, thus it is always a good idea to prefix custom attributes with data- in order to ensure that in the future the attribute the you use is not added to the specification with special effects based upon its value.
I am creating a game which involves numbers. The idea is simple, If i click a number(from 1 to 6) and my code randomly picks one(also from 1 to 6). If my choice(onclick) equals to cpu's choice, the game will be over! If they both are unlikely numbers, my score adds up!
Now the question is, if i click "1" or "2"..(and so on) i need a very new function for all of the numbers.
The code looks like this,
<button id="runs" onclick="i0()">0</button>
<button id="runs" onclick="i1()">1</button>
<button id="runs" onclick="i2()">2</button>
<button id="runs" onclick="i3()">3</button>
<button id="runs" onclick="i4()">4</button>
<button id="runs" onclick="i5()">5</button>
<button id="runs" onclick="i6()">6</button>
I should write each and every function repeatedly which is almost the same! How can i use parameters instead which involves only one function. And how can i add an "if" statement in which the condition should say that i clicked "1".etc
Like,
if(Clicked one//for example) {
document.getElementById("someId").innerHTML = "You pressed one";//:ex
}
can i use,
function click(i0, i1, i2//etc)
if(i0 == true) {
//some code
}
Please remember! I need to use parameters (I am new to JavaScript).
First, you shouldn't be setting up your event handlers with HTML event attributes as that technique is 20+ years old and has many reasons not to use it (one of which is that you'll wind up writing a lot of redundant event handler calls as you are doing now).
Please remember! I need to use parameters
No, you don't (unless this is some sort of school assignment which you didn't state - and if that is the case, get your money back for the course because the instructor shouldn't be teaching you outdated ways of writing code, even for learning purposes). Each button is already displaying the number that corresponds to it. Using a parameter is just more redundancy in the code that makes it more brittle of a solution. You just need a centralized function that runs when any of the buttons gets clicked and then that function can simply compare the random number against the clicked button's content.
Also, you can't have multiple elements with the same id.
Take note of how much cleaner the HTML is when you separate the event handlers out of the HTML and note that this solution works no matter how many buttons you want the game to have. Just make sure that any button that is part of the game has the gameButton class and that the content of the element is the next numeric character that hasn't been used yet.
// Get all buttons into an Array
var buttons = Array.prototype.slice.call(document.querySelectorAll("button.gameButton"));
// Loop over the buttons
buttons.forEach(function(btn){
// Give each button a click event callback function
btn.addEventListener("click", function(){
// Generate a random number from 1 to the number of buttons there are in the game
var num = Math.floor(Math.random() * buttons.length) + 1 ;
var output = "The random was: " + num + ", and the clicked button was: " + this.textContent;
// The prepended + converts the text to a number
if(num === +this.textContent){
alert("You win!\n" + output);
} else {
alert("Keep trying!\n" + output);
}
});
});
/* Just for fun */
.gameButton{
background-color:#800080;
color:#ff0;
font-weight:bold;
font-size:2em;
border-radius:2em;
box-shadow:2px 2px #808080;
outline:none;
}
.gameButton:active{
box-shadow:-2px -2px #808080;
}
<button class="gameButton">1</button>
<button class="gameButton">2</button>
<button class="gameButton">3</button>
<button class="gameButton">4</button>
<button class="gameButton">5</button>
<button class="gameButton">6</button>
You don't need a separate function for each button. You can pass a parameter directly to the function call statement:
<button id="runs" onclick="i(0)">0</button>
<button id="runs" onclick="i(2)">1</button>
...
And then in your JS code:
function i(param) {
...
}
Read more, here: https://www.w3schools.com/js/js_functions.asp
As mentioned, you can not use the same ID on multiple elements.
A good way is to pull the id of the button and pass it to the function, like this:
Have a look at this other question and answers in detail:
How to get ID of button user just clicked?
I have following code working so far: JSFIDDLE DEMO
The relevant JS is here:
// Define classes & background element.
var classes = ['bg1','bg2','bg3','bg4'],
$bg = document.getElementById('blah');
// On first run:
$bg.className = sessionStorage.getItem('currentClass') || classes[0];
// On button click:
$('.swapper').mousedown(function () {
// (1) Get current class of background element,
// find its index in "classes" Array.
var currentClassIndex = classes.indexOf($bg.className);
// (2) Get new class from list.
var nextClass = classes[(currentClassIndex + 1)%classes.length];
// (3) Assign new class to background element.
$bg.className = nextClass;
// (4) Save new class in sessionStorage.
sessionStorage.setItem('currentClass', nextClass);
});
For my purposes, this functionally working great -- I can click a single button to continually swap between those four classes while also storing the current class to sessionStorage, so that when I click links on my website, the currentClass is loaded right away. (Note: on my website the setup is the same, but the classes bg1, bg2, bg3, and bg4 contain background images.)
What I'd like it to do:
When swapping from one class to another, I'd like it to do a quick/short cross-fade. Right now it just snaps from one class/background to another.
My thinking was: is there a way I can trigger a CSS class transition or animation that contains the fade, perhaps as a parent class? I know there's a jQuery fade function, but I haven't been able to get it working with my setup so that it triggers on mouseClick.
Here's an updated jsfiddle based on your comment where you said you've sort of having it work.
I've added the timeout functions
setTimeout(function(){$bg.className = nextClass}, 500);
setTimeout(function(){$($bg).fadeIn(500)}, 500)
The first timeout makes it so that the image is swapped right after the first image fades out. The second timeout gives it a bit of time to load in so it's not so jittery.
You can play with the }, 500); number to get it timed just like you want, 500 is half a second, 1000 is a second etc.
at the moment I'm working on a website that is meant to be my portfolio so I wanted it to be a challenge.
The section where I show my work is coded with PHP and is connected to a database. With a WHILE loop it adds all the database records on my website.
For this site I have decided to use Javascript for the first time, to make it more challenging and to learn this as well.
What I want is a border around every database record the PHP WHILE loop adds, which is only shown when hovered over and changes color (fixed array of colors) every time you hover over the thumbnail.
This is the code I have so far:
function loaded() {
var colors = ["#FC3E6B","#24FF00","#0087F9","#F9F900"];
var images = document.getElementById("thumbnails").getElementsByTagName("div");
console.log(images);
for (var i = 0; i < images.length; i++) {
var rand = Math.floor(Math.random()*colors.length);
images[i].style.borderStyle = 'solid';
images[i].style.borderWidth = '1px';
images[i].style.borderColor = 'transparent';
$(images[i]).hover(function(){
console.log('hovering over');
images[i].style.borderColor = colors[rand];
}, function(){
console.log('hovering out');
images[i].style.borderColor = 'transparent';
});
};
};
My problem now is that it doesn't work, or partially. This code only applies on the first entry the WHILE loop adds. In the console I can see that the "console.log(images)" only returns the first entry.
Another problem is that it also returns an error:
images[i] is undefined
images[i].style.borderColor = colors[rand];
These are the 2 things I'm struggling with at the moment. It might very well be beginner/easy mistakes since it's my first time working with Javascript.
If there is anything I forgot to mention or you need to know, let me know.
I'm looking forward to a reply.
If I understand you right you should have an HTML page (generated with PHP) that looks like:
<div id="thumbnails">
<img src="..." />
<img src="..." />
<img src="..." />
...
</div>
And if you hover one of the images you want to add a border to this an remove the border if the mouse leaves the image. I assume you are using jQuery, so you could add each image a class e.g. <img class="record" src="..." /> and try the following javascript:
$(function() {
var colors = ["#FC3E6B","#24FF00","#0087F9","#F9F900"];
$('.record').hover(
function() {
var rand = Math.floor(Math.random()*colors.length);
$(this).css('border-style', 'solid');
$(this).css('border-width', '1px');
$(this).css('border-color', colors[rand]);
},
function() {
$(this).css('border-style', 'none');
}
);
}).call(this);
Each time the cursor enters an element (in your case an image) this will get a border, if the cursor leavs it the border will be removed.
Ok, first off: (colors.length - 1) is where you want to go, an array of length 3, has 2 as highest key (0-indexed!)
Second: can you post the actual HTML, or better still: get a jsfiddle up, so we can actually ammend your code, or fork your jsfiddle?
Third: I notice you're using jQuery, have you tried using $('#thumbnails').find('div'); to get your images array? what do you get then?
In case anyone reading this wonders, the reason the original example didn't work is because it is creating a closure. The inner function has access to the variables created in the outer function, but it gets the value of variables when the outer function returns.
In this case, when the code:
images[i].style.borderColor = colors[rand];
executed, the value of i would have been 4, which is outside the range, for each image.
See this for an explanation:
JavaScript closure inside loops – simple practical example
I've never particularly used JS much, with the exception of basic animations,
The page I'm working on requires me to fade out the active div and fade the requested one in, I have around 25 different div's I'll be fading between. At the minute I can't think of how to only fade the active one out so I'm trying to fade every div but the one that's requested out.
Here's the code I'm attempting to get working
var active = 0;
for (i=0;i<array.length;i++) {
if (i != active){
document.write("$('."+array[i]+"').fadeOut(900);");
}
naturally i know the document.write shouldn't be there, but ideally that code has to be printed into the .js file I'm using, however. I don't have a clue how to print it to the .js.
any suggestions would be greatly appreciated, or a way to do this in php without a page reload!
When you find yourself generating code on the fly, it usually indicates that you want to take a step back and re-evaluate your approach. :-)
In this case, there's no need to create the JavaScript dynamically. It's just a matter of running the code.
I wasn't sure what your definition of "active" was, so here's something that fades divs in/out on the basis of what buttons you press:
The HTML:
<input type='button' value='1'>
<input type='button' value='2'>
<input type='button' value='3'>
<input type='button' value='4'>
<input type='button' value='5'>
<input type='button' value='6'>
<div id='container'>
<div class='c1'>This is c1</div>
<div class='c2'>This is c2</div>
<div class='c3'>This is c3</div>
<div class='c4'>This is c4</div>
<div class='c5'>This is c5</div>
<div class='c6'>This is c6</div>
</div>
The JavaScript (teaching version):
jQuery(function($) {
// Hook our buttons; this selector hooks all of them,
// so you probably want to narrow that down, but I
// have no idea what your definition of "active" is,
// so I made one up.
$(":button").click(function() {
// Get the value of the button, e.g., 1, 2
var val = this.value;
// Get all of the divs in the container
var divs = $("#container div");
// Fade out all of the ones that aren't our target;
// fade in the one that is
divs.not(".c" + val).fadeOut(900);
divs.filter(".c" + val).fadeIn(900);
});
});
Live copy
That does this:
Uses the jQuery ready function (the shortcut form where I just pass a function into the jQuery function) to run the code when the page is "ready" (the DOM has been built)
Looks up all divs we want to be dealing with. In my case, it's all the divs in a container, but you can use just about any CSS3 selector you want (and then some).
Uses not with a class selector to filter out the div that has the target class, then uses fadeOut to start fading the other ones out.
Uses filter to reduce the set to just our target div, and fadeIn to start fading it in.
That version is for clarity. Here's a more concise version (still perfectly clear to people who know jQuery well, but tricky for folks still finding their feet):
The JavaScript (chained version using end):
jQuery(function($) {
// Hook our buttons; this selector hooks all of them,
// so you probably want to narrow that down, but I
// have no idea what your definition of "active" is,
// so I made one up.
$(":button").click(function() {
// Get the value of the button, e.g., 1, 2
var val = this.value;
// Get all of the divs in the container
// Fade out all of the ones that aren't our target;
// fade in the one that is
$("#container div")
.not(".c" + val).fadeOut(900)
.end()
.filter(".c" + val).fadeIn(900);
});
});
Live copy
Not sure why you are using document.write instead of simply executing the javascript.
var active = 0;
for (i=0;i<array.length;i++) {
if (i != active) {
$("."+array[i]).fadeOut(900);
}
Additionally, try using a jQuery selector to select all the non-active divs by adding an additional class to each div:
var active = array[0];
var classname = "some_class";
$("div." + classname + ":not(." + active + ")").fadeOut(900);
You could even just select the visible divs that are not the active one and fade them out:
var active = array[0];
var classname = "some_class";
$("div." + classname + ":not(." + active + "):visible").fadeOut(900);