How to get dialogue to change upon clicking on an image? - javascript

I'm trying to create a game with dialogue, and I want my text to change as the player clicks on a next image to progress the story.
For example:
Page loads - "Hi, I'm Joe."
Clicks sliced Image once - "Nice to meet you."
Clicks 2nd time - "How are you?"
I have tried onClick but that only allows me to change it once, I've tried using var counter as well but to no avail, it overrides my previous commands, which part of this am I doing wrong here?
var clicks = 0;
function changeText() {
{
clicks = 1;
document.getElementById('text').innerHTML = "Ughh... my head... What
happened...?";
}
}
function changeText() {
{
clicks = 2;
document.getElementById('text').innerHTML = "Testing 1 2 3";
}
}
function play() {
var audio = document.getElementById("audio");
audio.play();
}
<img onClick="changeText(); audio.play()" value=Change Text src="images/awaken/images/awaken_03.jpg" alt="" width="164" height="77" id="clicks" />
<p id="text">Where... am I...?</p>

First off all - your changeText() system is flawed - you're overwriting the same function multiple times at the same time, so the only one of those that will ever get called is the last one you declare. JavaScript doesn't wait until a function gets called to continue with the program.
The audio.play() also won't work - but I'm assuming that's a work in progress.
I changed your code so that instead of setting count to a specific value, it increments every time the function gets called, and it updates the text to the correct value in an array. Here's the updated changeText function:
var count = 0;
var text = [
"Where... am I...?", /* note that this will never get called, it's simply here for filling up the array*/
"This is the first text!",
"And this is the second!"
]
var changeText = function() {
count++;
document.getElementById('text').innerHTML = text[count];
}
In the future, you'll probably also want to check if(text[count] != 'undefined'), and if so write something like "Bye!" instead.

Issues in your code
Multiple function declaration of changeText()
Extra {} in changeText()
You are not updating value of clicks.
In your html, you have written audo.play() but no audio object is available. It should be play(). I have called play() function in changeText() function. This keeps HTML clean.
Following is updated code:
var clicks = 0;
function changeText() {
var text = ""
clicks++;
switch(clicks){
case 1: text = "Ughh... my head... What happened...?";
break;
case 2: text = "Testing 1 2 3";
break;
}
document.getElementById('text').innerHTML = text;
play();
}
function play() {
var audio = document.getElementById("audio");
audio.play();
}
<img onClick="changeText()" value=Change Text src="images/awaken/images/awaken_03.jpg" alt="" width="164" height="77" id="clicks" />
<p id="text">Where... am I...?</p>

Related

When does a change to TextContent get displayed?

I'm working on Rock/Paper/Scissors game for the Odin Project. I display the result of a game in a div resultMsg, and a running tally based on that result in countMsg. Both those items are divs in the HTML and they work correctly. After a total of 5 games are won or lost, I want to (in order) clear the textContent messages, use an "alert" to give a final tally, and start over.
I expected that the two lines highlighted with "->" would clear the textContent message. However they do not until after I click [OK] to clear the alert. I'd really like to understand why that is.
The HTML relevant body:
<div id="playersChoice">
<button id='rock'>Rock</button>
<button id='paper'>Paper</button>
<button id='scissors'>Scissors</button>
</div>
<div id="result">
</div>
<div id="count">
</div>
The Javascript that's relevant.
let gamesPlayed = 0;
let playerWon = 0;
let computerWon = 0;
const countMsg = document.querySelector ('#count');
const resultMsg = document.querySelector ('#result');
// Get all the buttons within playerschoice container
const userButton = document.querySelectorAll ('#playersChoice > button');
// For each button, create an event listener for the click which will play a round.
// Note the Button.ID identifies the players choice.
userButton.forEach(button => {
button.addEventListener('click', function() {
gamesPlayed++;
resultMsg.textContent = playRound(button.id, computerPlay());
// if there are less than 5 clear wins or losses
if ((playerWon + computerWon) < 5) {
countMsg.textContent = "The current tally is your " + playerWon + " wins to the computers " + computerWon + ".";
} else {
// there have been 5 definitive games, declare the overall winner!
-> resultMsg.textContent = '';
-> countMsg.textContent = '';
gamesPlayed = 0;
playerWon = 0;
computerWon = 0;
alert("Best of 5 series results : You won " + playerWon +", lost " + computerWon + ", and tied "+ (5-playerWon-computerWon) + " of them.");
}
});
});
'''
alert() will block the current script execution, but it seems to also blocks the DOM update. That's why even though the assignement to textContent is before the alert, the text is only shown after the alert has been clicked, and the execution has resumed.
You can use a very small setTimeout to allow the DOM to update before the alert() fires:
const div = document.querySelector("div");
function test1() {
div.textContent = "Test without timeout!";
alert("Test1!");
}
function test2() {
div.textContent = "Test with timeout!";
setTimeout(() => alert("Test2!"), 10);
}
<button onclick="test1()">Test</button>
<button onclick="test2()">Test with timeout</button>
<h4>Text content:</h4>
<div></div>
Edit:
I researched a bit more, and to be more precise, DOM updates happen only after the script has finished. Since alert() blocks the current script, the DOM update will only happen after the alert has been dismissed.
This behavior can also be seen with the following snippet:
function wait(ms) {
var start = Date.now(),
now = start;
while (now - start < ms) {
now = Date.now();
}
}
function test() {
document.querySelector("div").textContent = "Test with delay!";
wait(2000);
}
<button onclick="test()">Test with delay</button>
<div></div>

Prevent createElement from creating multiple identical images

I am going to try and be as thorough as possible on this so stick with me.
My program takes user input entered on a form. This input goes through a range of if statements that will set variables to true, these variables that are set to true will then use createElement to create img inside predetermined divs. There will always be at least one img created, and up to 4 imgs at the most. This is all completed by a button click.
I learned createElement will continuously createElement with each button click posting the img right next to the original img and will do this infinitely or until the page is reloaded.
My solution was to create a counter that incremented each time the button was clicked. That took care of any extra createElements. Then I thought if the user first entered a large number that will create 2 separate and individual images say... image 1 and image 2 (which is desired), then if the user enters a lower number that only creates image 1, then image 2 would still be posted (unwanted). Of course a page refresh would clear the images created and avoid this.
So I'm not quite sure what to do...
Ideally when the button is pressed a second time then all old createElements would be cleared, and all new createElements would populate.
I removed the counter for the purpose of this question
poster__#'s are the called id's...
const movieTime = 30;
var userTimeAvailable = 25;
const button = document.getElementById("calculate");
button.onclick = function calculateTime() {
if (userTimeAvailable < movieTime) {
console.log(
"You have enough time to watch " +
Math.round((userTimeAvailable / movieTime) * 100) +
"% of the movie."
);
displayMoviePoster1 = true;
}
moviePosterGenerator();
}
function moviePosterGenerator() {
if (displayMoviePoster1 === true) {
var par = document.getElementById("poster__2");
var theatricalMoviePoster = document.createElement("img");
theatricalMoviePoster.src = "imgURL";
par.appendChild(theatricalMoviePoster);
}
}
<button class="button" id="calculate">calculate</button>
<div class="movie-poster__container" id="posters">
<div class="movie-poster" id="poster__1"></div>
<div class="movie-poster" id="poster__2"></div>
<div class="movie-poster" id="poster__3"></div>
<div class="movie-poster" id="poster__4"></div>
</div>

Can I save a random generated var so I can call the result back later in javascript

I'm working on a project where I generate a random var to create random scenes. One of them is location. I want it to be possible to generate a location with one button. Then press another button to generate a new location and when I press on the first button I want to get back the generated location I generated with that button
The function I generate the location with looks like this
function inhoudFunction()
{
var locs = ["movie", "park", "garden", "home"];
var loc = locs[Math.floor(Math.random()*locs.length)];
document.getElementById('inhoud').innerHTML="<h2>Locatie</h2>" + loc;
And these are the buttons I use to run the codes
<button type="button" onclick="introFunction()">intro</button>
<button type="button" onclick="midFunction()">mid</button>
To know if the button was pressed twice I used this code
function introFunction(){
if (introClicked == 1){
document.getElementById('introClicked').innerHTML="<div id=inhoud></div>";
}
else{
document.getElementById('introClicked').innerHTML="<div id=inhoud></div>";
inhoudFunction();
introClickedFunction();
}
And introClicked gets updated with this function
var introClicked = 0;
function introClickedFunction(){
introClicked = introClicked + 1;
}
But once I press the button twice I get nothing back
Save the generated value directly as a custom field of your <button> element.
In the example below, the element is passed to the click handler function as event.target. The function reads the gen_locations field. If it's not set, then it generates the random value and sets it.
window.addEventListener('DOMContentLoaded', _e => {
const locs = ["movie", "park", "garden", "home"];
document.getElementById('inhoud-button1').addEventListener('click', inhoudFunction);
document.getElementById('inhoud-button2').addEventListener('click', inhoudFunction);
function inhoudFunction(event) {
let genlocs = event.target.gen_locations;
if (!genlocs) {
genlocs = []
for (let i = 0; i < 2; i++) {
genlocs.push( locs[Math.floor(Math.random() * locs.length)] );
event.target.gen_locations = genlocs;
}
}
document.getElementById('inhoud').innerHTML = "<h2>Locatie</h2>" + JSON.stringify(genlocs);
}
});
<div id="inhoud"></div>
<button id="inhoud-button1">Inhound 1</button>
<button id="inhoud-button2">Inhound 2</button>
I've cleaned the code by avoiding inline javascript event handlers. Those are bad! :)
Edit: improved to show storing 2 generated randoms at once per button

Dynamically increasing font size

I would like to increase the font size of the paragraph as well as the font size of the number in the button.
I copied and pasted my sizer function from StackOverflow (a few alterations) and thought it would work and still can't get it to work. Can someone help?
Since I've spent so much time on just the first part, as a beginner programmer, I'm wondering what I am missing. Does anyone have any ideas from my code or their experience as to what I might be missing?
Thanks as always.
<html>
<button onclick='incrementer(); sizer()' id='count' value=0 />0</button>
<p id='test'>a</p>
<script>
clicks = 0
incrementer = function () {
clicks += 1
click = document.querySelector("#count").textContent = clicks;
click.innerHTML = document.getElementById("count").value = document.getElementById('test');
}
sizer = function changeFontSize() {
div = document.getElementById("test");
currentFont = div.style.fontSize.replace("pt", "");
div.style.fontSize = parseInt(currentFont) + parseInt(clicks) + "pt";
}
</script>
</html>
Some things here:
I woudn't append two functions to your onclick here. Just append one and call your second function from the first one that gets fired via onclick. That looks a lot more tidy
Don't forget to put var before every variable, without it's not valid JavaScript
I didn't quite understand what you tried with your currentFont variable, so I removed it. It's not necessary and causes the script to not working correctly
<html>
<button onclick='incrementer()' id='count' value=0 />0</button>
<p id='test'>a</p>
<script>
var clicks = 0;
var incrementer = function() {
clicks += 1;
var click = document.querySelector("#count").textContent = clicks;
click.innerHTML = document.getElementById("count").value = document.getElementById('test');
sizer();
}
var sizer = function changeFontSize() {
var div = document.getElementById("test");
div.style.fontSize = parseInt(clicks) + "pt";
}
</script>
</html>
Here's a from-scratch version that does what you're asking for. I'll point out a few things that I did to help you out.
https://codepen.io/anon/pen/VBPpZL?editors=1010
<html>
<body>
<button id="count">0</button>
<p id="test">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</p>
</body>
</html>
JS:
window.addEventListener('load', () => {
const button = document.querySelector('#count');
const paragraph = document.querySelector('#test');
const startingFontSize = window.getComputedStyle(document.body, null)
.getPropertyValue('font-size')
.slice(0, 2) * 1;
let clicks = 0;
button.addEventListener('click', () => {
clicks++;
// this is a template literal
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
const fontSize = `${startingFontSize + clicks}px`;
button.innerHTML = clicks;
button.style.fontSize = fontSize;
paragraph.style.fontSize = fontSize;
});
});
The code runs when the page is loaded, so we attach an event listener on the window object listening for the load event.
We then store references to the button and the paragraph elements. These are const variables because their values won't change. This also limits their scope to the containing function.
We get the initial font size for the body element, because in this example we aren't explicitly setting a base font in css so we're just using the one for the document. getComputedStyle is a somewhat expensive operation, and in this case we only need to get it in the beginning because it won't change, so we also store it as a const. The value is returned as a string like "16px" but we need the number, hence the slice and multiplying by one to cast the string into a number. parseInt would also do the same thing.
Notice that clicks is defined with let. This means that the variable can be changed. var still works of course, but in modern practices its best to use const and let when declaring variables. This is partly because it forces you to think about what kind of data you're working with.
We add an event listener to the button element and listen for the click event. First, we increment the clicks variable. Then we declare fontSize using a template literal which adds our new clicks count to the startingFontSize and "px" to get a string.
Finally, the innerHTML value of the button element is updated. Then we update the fontStyle property for both elements.
The issue here is that there is no initial value for the fontSize of your <p> tag so div.style.fontSize returns an empty string.
You can use window.getComputedStyle instead of div.style.fontSize and you will get the current fontSize.
There is already a post explaining this method
https://stackoverflow.com/a/15195345/7190518
You don't have an initial font-size style on your <p> tag, so it div.style.fontSize is always empty. Also, best practice is to always use var when introducing new variables in javascript.
One good trick to help debugging things like these is to use console.log() at various points, and see whats coming out in your browser console. I used console.log(div.style.fontSize) and the answer became clear.
Working below after adding <p style='font-size:12px'>a</p>:
<html>
<button style='font-size:12px;' onclick='incrementer(); sizer()' id='count' value=0 />0</button>
<p id='test' style='font-size:12px;'>a</p>
<script>
var clicks = 0
incrementer = function () {
clicks += 1
click = document.querySelector("#count").textContent = clicks;
click.innerHTML = document.getElementById("count").value = document.getElementById('test');
}
var sizer = function changeFontSize() {
var div = document.getElementById("test");
var btn = document.getElementById("count");
var newSize = parseInt(div.style.fontSize.replace("pt", "")) + parseInt(clicks);
div.style.fontSize = newSize + "pt";
btn.style.fontSize = newSize + "pt";
}
</script>
</html>
I don't understand the logic of this solution, but you can simplify it avoiding to use a lot of var (anyway always prefer let or const if you don't need to change), using a single function and writing less code.
function increment(e){
const ctrl = document.getElementById('test');
let current = parseInt(e.dataset.size);
current += 1;
e.innerHTML = current;
e.dataset.size = current;
ctrl.style.fontSize = current + 'pt';
}
<button onclick="increment(this);" data-size="20">20</button>
<p id='test' style="font-size:20pt;">A</p>

Image rotater in javascript only - no jquery

UPDATE: The answer below seemed to work, but if I have links in my text in the descriptions variable, it doesn't seem to replace the text at all. If i remove tags, or any html tags from all the text I am trying to replace, it works. Issue is, I need the text to be replaced to be html format :(
I am trying to get an image to fade, with text outside of the image to fade as well, and have another set appear in same place.
jquery can not be used due to the environment.
I came up with this, the only issue is that the very first thing that happens is the first image fades at the very start and the same image appears. Then it starts working normal after that first "glitch". After that, if seems to work perfectly.
Can someone point out my silly mistake?
<script type="text/javascript">
var links = ["http://www.firstlink.com","http://www.secondlink.com","http://www.thirdlink.com"];
var images = ["1stimage.jpg","2ndimage.jpg","3rdimage.jpg"];
var descriptions=["this is the first set of rotating text", "Now we have another set of text, in this large paragraph. Write whatever we want here", "and this is the last set of text, we have 3 images. We can add more images and more text."]
var i = 0;
var renew = setInterval(function(){
if(links.length == i){
i = 0;
}
else {
document.getElementById("bannerImage").src = images[i];
fadeIn(document.getElementById("bannerImage"), 1000);
document.getElementById("bannerLink").href = links[i];
document.getElementById("p1").innerHTML= descriptions[i];
i++;
}
},5000);
</script><script type="text/javascript">
function fadeIn(el, time) {
el.style.opacity = 0;
el.style.display = "block";
var last = +new Date();
var tick = function() {
el.style.opacity = +el.style.opacity + (new Date() - last) / time;
last = +new Date();
if (+el.style.opacity < 1) {
(window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16)
}
};
tick();
}
</script><img alt="some text" height="83" id="bannerImage" src="1stimage.jpg" width="633" />
<p id="p1">this is the first set of rotating text</p>
Change this
var images = ["1stimage.jpg","2ndimage.jpg","3rdimage.jpg"];
var descriptions=["this is the first set of rotating text", "Now we have another set of text, in this large paragraph. Write whatever we want here", "and this is the last set of text, we have 3 images. We can add more images and more text."]
to this
var images = ["2ndimage.jpg","3rdimage.jpg","1stimage.jpg"];
var descriptions=["Now we have another set of text, in this large paragraph. Write whatever we want here", "and this is the last set of text, we have 3 images. We can add more images and more text.", "this is the first set of rotating text"]

Categories

Resources