Repeating Javascript Animations? - javascript

I'm trying to make a div go up, down, up again, down again, etc. until you click on it. This is what I've got:
<!DOCTYPE html>
<html>
<head>
<title>Fun with animations dude</title>
<link rel="stylesheet" href="animation.css"/>
</head>
<body>
<div id="moving">
</div>
<script type="text/javascript">
var moving = document.getElementById("moving");
var mMargin = moving.style.marginTop | 0;
var moving = false;
moving.onclick = start;
function start() {
if (moving == false) {
moving = true;
move();
window.alert("Start!");
}
else {
moving = false;
window.alert("Aww...");
}
}
function move() {
if (moving) {
if (mMargin < 700) {
mMargin += 10;
moving.style.marginTop = mMargin + "px";
setTimeout(move, 20);
}
else {
mMargin -= 10;
moving.style.marginTop = mMargin + "px";
setTimeout(move, 20);
}
}
}
</script>
</body>
</html>
I was actually quite proud of myself for a while, until it didn't work... As you can see, I made an attempt at troubleshooting by adding those alert boxes. Neither of them were triggered, so right now it's a problem with the initial stuff, although there may be other errors as well. No errors in the console. Advice?

Hippydog's answer got me past the first part. I then realized I had to add another variable to keep the div from spazing out at the bottom of the first run. I just wanted to post what worked for anyone else looking at this for reference:
<!DOCTYPE html>
<html>
<head>
<title>Fun with animations dude</title>
<link rel="stylesheet" href="animation.css"/>
</head>
<body>
<div id="moving">
</div>
<script type="text/javascript">
var moving = document.getElementById("moving");
var mMargin = moving.style.marginTop | 0;
var isMoving = false;
var movingDown = true;
moving.onclick = start;
function start() {
if (isMoving == false) {
isMoving = true;
move();
}
else {
isMoving = false;
}
}
function move() {
if (isMoving) {
if (movingDown) {
mMargin += 10;
moving.style.marginTop = mMargin + "px";
if (mMargin >= 1000) {
movingDown = false;
}
setTimeout(move, 20);
}
else {
mMargin -= 10;
moving.style.marginTop = mMargin + "px";
if (mMargin <= 0) {
movingDown = true;
}
setTimeout(move, 20);
}
}
}
</script>
</body>
</html>
If any more experienced coders find some unforseen problem with this script, feel free to let me know.

The first and third local variables are both called moving. Renaming the second to isMoving (and updating any mentions of this variable) causes the alerts to show as expected.

Related

I have trouble hiding elements in my game if they don't match

I am working on a memory game and I asked a previous question earlier which was answered. I've had this problem and I haven't been able to find a solution with effort. So it's a memory game and when the cards are clicked, they are pushed into an array which can hold two elements at max (you can only click two cards) and then the two elements' frontSrc is checked if they are the same. I set that using an expando property. If so, have them visible and then clear the array so I can do more comparisons. However, it doesn't seem to be working as intended. I'll attach a video below. I've tried using timeout to set the length again, but that didn't work. It works for the first cards, but the other ones after that, it doesn't work.
Here is my code.
<!DOCTYPE html>
<!--
Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
Click nbfs://nbhost/SystemFileSystem/Templates/Other/html.html to edit this template
-->
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.card{
width: 35%;
}
#cards{
display: grid;
grid-template-columns:25% 25% 25% 25%;
row-gap: 25px;
}
</style>
</head>
<body onload="init()">
<section id="cards">
</section>
<script>
var arrCards = [];
var arrShowedCards = [];
//appendElements();
function init(){
createCards();
shuffleCards();
appendElements();
}
function createCards(){
var arrCardNames = ["Mouse","Penguin","Pop","Mouse","Penguin","Pop"];
for(var i = 0; i<6; i++){
var card = document.createElement("IMG");
card.src = "Images/red_back.png";
card.className = "card";
card.frontSrc = "Images/" + arrCardNames[i] + ".png";
card.id = "card" + i;
card.addEventListener("click", showCard);
document.getElementById("cards").appendChild(card);
arrCards.push(card);
}
}
function shuffleCards(){
for (let i = arrCards.length-1; i > 0; i--)
{
const j = Math.floor(Math.random() * (i + 1));
const temp = arrCards[i];
arrCards[i] = arrCards[j];
arrCards[j] = temp;
}
return arrCards;
}
function appendElements(){
for(var i = 0; i<arrCards.length; i++){
document.getElementById("cards").appendChild(arrCards[i]);
}
}
function showCard(){
var sourceString = "Images/red_back.png";
this.src = this.frontSrc;
arrShowedCards.push(this);
if(arrShowedCards.length === 2){
if(arrShowedCards[0].frontSrc === arrShowedCards[1].frontSrc){
console.log("Match!");
arrShowedCards = [];
}
else{
console.log("No match!");
setTimeout(function(){
arrShowedCards[0].src = sourceString;
arrShowedCards[1].src = sourceString;
}, 1000);
}
}
}
</script>
</body>
</html>
I am not sure how come it doesn't work for it for the other cards.
Here is the video.
https://drive.google.com/file/d/1aRPfLALHvTKjawGaiRgD1d0hWQT3BPDQ/view
If anyone finds a better way to approach this, let me know.
Thanks!
I think when not match, you need to reset arrShowedCards otherwise its length will be greater than 2 forever.
function showCard() {
var sourceString = "Images/red_back.png";
this.src = this.frontSrc;
arrShowedCards.push(this);
if (arrShowedCards.length === 2) {
var a = arrShowedCards[0], b = arrShowedCards[1];
arrShowedCards.length = 0;
if (a.frontSrc === b.frontSrc) {
console.log("Match!");
} else {
console.log("No match!");
setTimeout(function () {
a.src = sourceString;
b.src = sourceString;
}, 1000);
}
}
}

Time user is typing is zero even though it should be more in javascript

Im trying to calculate the time from when the user starts typing to when they stop. I put two variables start and end and subtracted them from each other. But it always returns zero. Can you give an easy way to calculate wpm if possible also? I want to in the end calculate the words per minute when the user types 10 words correctly. So I need the time from when they started to when they completed the prompt.
Thanks!
Javascript:
var input = document.getElementById("boch");
input.addEventListener("keyup", function (event) {
if (event.keyCode === 13) {
event.preventDefault();
document.getElementById("bocho").click();
}
});
var element = document.querySelector("#boch");
element.onkeyup = function () {
var value = element.value;
if (value.includes("m")) {
var start = Date.now();
}
if (value.includes("man")) {
document.getElementById('word-1').style.backgroundColor = 'green';
} else {
document.getElementById('word-1').style.backgroundColor = "red";
}
if (value.includes("man become")) {
document.getElementById('word-2').style.backgroundColor = 'green';
} else {
document.getElementById('word-2').style.backgroundColor = "red";
}
if (value.includes("man become as")) {
document.getElementById('word-3').style.backgroundColor = 'green';
} else {
document.getElementById('word-3').style.backgroundColor = "red";
}
if (value.includes("man become as and")) {
document.getElementById('word-4').style.backgroundColor = 'green';
} else {
document.getElementById('word-4').style.backgroundColor = "red";
}
if (value.includes("man become as and through")) {
document.getElementById('word-5').style.backgroundColor = 'green';
} else {
document.getElementById('word-5').style.backgroundColor = "red";
}
if (value.includes("man become as and through find")) {
document.getElementById('word-6').style.backgroundColor = 'green';
} else {
document.getElementById('word-6').style.backgroundColor = "red";
}
if (value.includes("man become as and through find would")) {
document.getElementById('word-7').style.backgroundColor = 'green';
} else {
document.getElementById('word-7').style.backgroundColor = "red";
}
if (value.includes("man become as and through find would here")) {
document.getElementById('word-8').style.backgroundColor = 'green';
} else {
document.getElementById('word-8').style.backgroundColor = "red";
}
if (value.includes("man become as and through find would here and")) {
document.getElementById('word-9').style.backgroundColor = 'green';
} else {
document.getElementById('word-9').style.backgroundColor = "red";
}
if (value.includes("man become as and through find would here and before")) {
document.getElementById('word-10').style.backgroundColor = 'green';
} else {
document.getElementById('word-10').style.backgroundColor = "red";
}
if (value.includes("man become as and through find would here and before")) {
var end = Date.now();
}
let millis = end-start;
console.log(millis)
}
HTML:
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<h1>
<span id="word-1">man</span> <span id="word-2">become</span> <span id="word-3">as</span>
<span id="word-4">and</span> <span id="word-5">through</span> <span id="word-6">find</span> <span id="word-7">would</span> <span id="word-8">here</span> <span id="word-9">and</span> <span id="word-10">before</span>
</h1>
<input type="text" id="boch" autocomplete="off">
</div>
<div id="typing-area">
<button id="bocho" onclick="document.getElementById('boch').value = ''">Enter</button>
</html>
<script src="main.js"></script>```
First off, value.includes("m") is true everytime, so the timer restarts every time the function is fired. Instead, use value === "m":
if (value === "m") {
start = Date.now();
}
You need to declare var end and var start outside of the if statement and set it inside:
var start;
if (value === "m") {
start = Date.now();
}
// other code...
var end;
if (value.includes("man become as and through find would here and before")) {
end = Date.now();
}
let millis = end-start;
Also, I recommend putting a space between end and start. end-start could be a variable name.

How to use jquery and javascript in same document

So I am trying to use jQuery, (in the heading) and javascript (normally) in the same document, but it seems that because of the script source thing, it conflicts with the JavaScript and doesn't word as I need it too
<head>
<title> Panel </title>
<link type="text/css" rel="stylesheet" href="clicker.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<script>
(function( $ ){
$(document).ready(function(){
$("#buckhead").click(function(){
$("#buckpanel").slideToggle(750);
});
});
})( jQuery );
</script>
</head>
Then later on in the document I put:
<script type="text/javascript">
var bcost = 1;
var clickmulti = 1;
var clicks = 0;
var bcost = 1000;
var mcost = 100;
var y = 0;
var x = 0;
document.getElementById("clicks").innerHTML = clicks;
document.getElementById("mcost").innerHTML = mcost;
document.getElementById("bcost").innerHTML = bcost;
function clickFunc() {
clicks += cps * clickmulti;
document.getElementById("clicks").innerHTML = clicks;
return true;
}
function clickMulti() {
if(clicks >= mcost && y < 50) {
clicks -= mcost;
mcost *= 1.25;
mcost = math.ceil(mcost * 1) / 1;
clickmulti += 1;
document.getElementById("clicks").innerHTML = clicks;
document.getElementById("mcost").innerHTML = mcost;
y += 1;
return true;
} else if(y == 50) {
alert("This upgrade is maxed!");
return false;
} else {
alert("You do not have enough fish to purchase this!");
return false;
}
}
function clickBase() {
if(clicks >= bcost && x < 100) {
clicks -= bcost;
bcost *= 1.25;
bcost = math.ceil(bcost * 1) / 1;
x += 1;
cps += 1;
document.getElementById("clicks").innerHTML = clicks;
document.getElementById("bcost").innerHTML = bcost;
return true;
} else if(x == 100) {
alert("This upgrade is maxed!");
return false;
} else {
alert("You do not have enough fish to purchase this!");
return false;
}
}
</script>
And it seems like the code is conflicting, because the jQuery is working just fine, as it is simple code, but the buttons to activate the JavaScript, which should be working as buttons are really easy, seems so when I click it, the functions aren't working, although almost every function is working, (ALMOST) except for
function clickFunc()
If you have the answer it would be greatly appreciated!
edit: here is the button calls, which by the way the buttons are before the second script.
<div class="fish"
<h2>Click for fish</h2><br>
<button onclick="clickFunc()" type="button">Click for fish</button><br>
<p> You have <span id="clicks"></span> fish</p>
<button type="button" onclick="clickMulti()"> Upgrade your click multiplier! (Cost:<span id="mcost"></span>)</button>
<button type="button" onclick="clickBase()">Upgrade base clicks!<br>
(Cost:<span id="bcost"></span>)</button>
</div><br><br>
Resolved, simply my problem of forgetting to make a global variable instead of a local variable. I forgot to make the global variable "cps"

In a jsf web application, a Javascript based session timer works on Chrome but not on IE

In a jsf web application based on Seam and Richfaces, I ran into a problem concerning different browsers. The code (and every variation I tried) works flawless in Chrome, but not in Internet Explorer (I am testing version 11).
The code is supposed to start and display a session-timeout countdown in the header. In the beginning of the template file, the timeout is retrieved from the application preferences and stored in a hidden field. The countdown timer is reset whenever a new page is loaded, or when an AJAX request is triggered (resetInactivityTimer()).
I am having 2 problems in IE:
It seems that the window.onloadfunction is not triggered on IE. The counter starts working fine when triggered manually in the console.
When the counter is started manually, an error occurs when an AJAX request is triggered.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Title</title>
<link rel="shortcut icon" type="image/x-icon" href="#{facesContext.externalContext.requestContextPath}/img/favicon.ico" />
<a:loadStyle src="/stylesheet/theme.css" />
<ui:insert name="head" />
</head>
<body>
<h:inputHidden id="originalTimeoutId" value="#{preferencesManager.getPreferenceValue(Preference.HTTP_SESSION_TIMEOUT)}"/>
<a:loadScript src="/scripts/script.js"/>
<a:region id="status_zone">
<a:status for="status_zone" forceId="false" id="ajaxStatus" onstart="resetInactivityTimer()">
<f:facet name="start">
<h:panelGroup>
<div style="position: absolute; left: 50%; top: 50%; text-align:center; width: 100%; margin-left: -50%;z-index: 10001;" >
<h:graphicImage value="/img/wait.gif"/>
</div>
<rich:spacer width="95%" height="95%" style="position: absolute; z-index: 10000; cusor: wait;" />
</h:panelGroup>
</f:facet>
</a:status>
<div class="main">
<ui:include src="/layout/header.xhtml" />
<ui:include src="/layout/menu.xhtml" />
<div style="margin-top: 10px;">
<ui:insert name="body" />
</div>
<ui:include src="/layout/footer.xhtml" />
</div>
</a:region>
<script type="text/javascript">
window.onload = initCountdown();
</script>
</body>
</html>
The countdown timer is displayed in the top right corner in the Header file "header.xhtml", which is loaded in the template, and therefore contained on every page:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<div class="header">
<s:graphicImage value="#{preferencesManager.getPreferenceByteContent(Preference.LOGO)}" styleClass="logo"/>
<h:panelGrid width="92%" columns="3" columnClasses="headerCol2,headerCol3,headerCol4">
<h:outputText styleClass="titel"
value="#{cM.getStringProp('de.gai_netconsult.kodaba.text.title')}"/>
<span class="timer">Automatischer Logout in: </span>
<h:outputText id="counter" styleClass="timer"></h:outputText>
</h:panelGrid>
</div>
The time is placed at the id="counter" position.
This is the Javascript code: "script.js"
var hiddenField;
var timeoutInSeconds;
var originalTimeout;
var originalCounter;
var initialized = false;
function initCountdown(){
// quit if this function has already been called
if (arguments.callee.done) return;
// flag this function so we don't do the same thing twice
arguments.callee.done = true;
// do stuff
startCountdown();
}
function getHiddenField() {
if (hiddenField != null) {
timeoutInSeconds = parseInt(hiddenField.value) * 60;
return timeoutInSeconds;
}
try {
hiddenField = document.getElementById('originalTimeoutId');
} catch (e) {
timeoutInSeconds = 0;
}
return timeoutInSeconds;
}
function getOriginalCounter(){
return document.getElementById('counter');
}
function resetInactivityTimer() {
if (initialized) {
console.log("resetInactivityTimer - initialized: " + initialized);
stopCountdown();
countdown(timeoutInSeconds, 'counter');
}
}
function startCountdown () {
timeoutInSeconds = getHiddenField();
if(timeoutInSeconds == 0) return;
originalCounter = getOriginalCounter();
if(timeoutInSeconds == null || originalCounter == null) {
setTimeout(function(){
startCountdown()}, 1000);
}
if(timeoutInSeconds != null && originalCounter != null){
initialized = true;
originalTimeout = timeoutInSeconds;
countdown(originalTimeout, 'counter');
}
}
function stopCountdown() {
var element = document.getElementById('counter');
clearTimeout(element.timerId);
}
function leadingzero(number) {
return (number < 10) ? '0' + number : number;
}
function countdown(seconds, target) {
var element = document.getElementById(target);
element.seconds = seconds;
calculateAndShow('counter');
}
function calculateAndShow(target) {
var element = document.getElementById('counter');
if (element.seconds >= 0) {
element.timerId = window.setTimeout(calculateAndShow,1000,target);
var h = Math.floor(element.seconds / 3600);
var m = Math.floor((element.seconds % 3600) / 60);
var s = element.seconds % 60;
element.innerHTML=
leadingzero(h) + ':' +
leadingzero(m) + ':' +
leadingzero(s);
element.seconds--;
} else {
completed(target);
return false;
}
}
function completed(target) {
var element = document.getElementById(target);
element.innerHTML = "<strong>Finished!<\/strong>";
}
Some things I tried is replacing
<script type="text/javascript">
window.onload = initCountdown();
</script>
with
<script type="text/javascript">
if (window.attachEvent) {window.attachEvent('onload', initCountdown());}
else if (window.addEventListener) {window.addEventListener('load', initCountdown(), false);}
else {document.addEventListener('load', initCountdown(), false);}
</script>
This leads to a "Typeconflict".
or with:
<rich:jQuery name="jcountdown" query="initCountdown()" timing="onload"/>
None of this helps.
I was able to get my timer to work in the end and I will post my solution here:
Problem 1:
<script type="text/javascript">
jQuery(document).ready(function(){
startCountdown();
});
</script>
instead of window.onload = startCountdown(); solves the problem.
Important: when using any console.log() statements, the function will only be executed when the developer console is opened! (F12).
Problem 2: (AJAX)
Richfaces version 3.3 is simply not compatible with any Internet Explorer Version above IE8.
It is important to apply a patch. This site describes the process in detail.
I also had to make many changes to the Javascript code. I am sure this could be much more elegantly written, but I confess I don't really know much Javascript at all... I'm posting my code anyway, in case somebody may find it useful:
var hiddenField;
var timeoutInSeconds;
var originalTimeout;
var originalCounter;
function getHiddenField() {
if (hiddenField != null) {
timeoutInSeconds = parseInt(hiddenField.value) * 60 -1;
timeoutInSeconds;
return timeoutInSeconds;
}
try {
hiddenField = document.getElementById('originalTimeoutId');
} catch (e) {
timeoutInSeconds = 0;
}
return timeoutInSeconds;
}
function getOriginalCounter(){
return document.getElementById('counter');
}
function startCountdown () {
timeoutInSeconds = getHiddenField();
if(timeoutInSeconds == 0) return;
originalCounter = getOriginalCounter();
if(timeoutInSeconds == null || originalCounter == null) {
setTimeout(function(){
startCountdown()}, 1000);
}
if(timeoutInSeconds != null && originalCounter != null){
originalTimeout = timeoutInSeconds;
countdown(originalTimeout, 'counter');
}
}
function countdown(seconds, target) {
var element = document.getElementById(target);
element.seconds = seconds;
calculateAndShow('counter');
}
function resetCountdown(){
var element = document.getElementById('counter');
element.seconds = timeoutInSeconds;
updateDisplay(element);
}
function calculateAndShow() {
var element = document.getElementById('counter');
if (element.seconds > 0) {
element.timerId = window.setTimeout(calculateAndShow,1000,'counter');
updateDisplay(element);
element.seconds--;
} else {
completed();
return false;
}
}
function updateDisplay(element){
var h = Math.floor(element.seconds / 3600);
var m = Math.floor((element.seconds % 3600) / 60);
var s = element.seconds % 60;
element.innerHTML =
leadingzero(h) + ':' +
leadingzero(m) + ':' +
leadingzero(s);
}
function leadingzero(number) {
return (number < 10) ? '0' + number : number;
}
function completed() {
var element = document.getElementById('counter');
element.innerHTML = "<strong>Beendet!<\/strong>";
logoutCallBackToServer();
}
Somewhere in one of your xhtml files (template, Header, menu, whatever) you also need to add this line:
<a4j:jsFunction name="logoutCallBackToServer" immediate="true" action="#{identity.logout}" />
This will ensure that the user is actually logged out precisely when the countdown reaches zero, just in case this does not 100% match the actual session time out.

How to exit a javascript function inside itself after an "if"?

I´m creating a game and I've got stuck with a counter in a function.
I want the function to loop five times and then if my element "nocolnum" has a value of 5, i need the function to exit or break.
here is my html:
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
<span id="opt1"></span>
<span id="nocolnum">0</span>
</body>
</html>
here is my js:
function func(num) {
num = num + 1;
var opt = document.getElementById('opt1');
opt.innerHTML= num + "%" ;
var move = setTimeout("func("+num+")",15);
var nocolnum = document.getElementById('nocolnum');
if(num == 100){
nocolnum.innerHTML++;
clearTimeout(move);
}
if (nocolnum == 5) {
// I dont know what to put here
// to break out
// a break, return or something??
}
var one = 0;
func(one);
}
if (nocolnum == 5) {
// I dont know what to put here
// to break out
// a break, return or something??
return false;
}
If you want to break function you can simlpy return
if (nocolnum == 5) {
return true;
}
or
if (nocolnum == 5) {
return false;
}

Categories