What is wrong with the line in the header?
The below example is supposed to make a button which will increment a counter each time it is clicked. However, I enforce a delay of 2000 ms between button clicks. The version below works, however, if I use the commented out line instead of
document.getElementById("rollButton").onclick=function(){calculation()};
(both in function afterWaiting())
I get various odd results, for instance that the counter starts incrementing by a lot more than 1, and the waiting time disappears?
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
function afterWaiting()
{
$("#rollButton").css("color","black");
//$("#rollButton").click(function(){calculation()});
document.getElementById("rollButton").onclick=function(){calculation()};
}
var counter=0;
function calculation()
{
////Enforcing wait:
document.getElementById("rollButton").style.color="red";
document.getElementById("rollButton").onclick="";
window.setTimeout("afterWaiting()",2000);
counter=counter+1;
document.getElementById("test").innerHTML=counter;
}
</script>
</head>
<body>
<button type="button" onclick="calculation()" id="rollButton"> Roll! </button>
<p id="test"> </p>
</body>
</html>
What have I misunderstood?
thanks in advance :)
JSFiddle:
http://jsfiddle.net/Bwxb9/
The difference is that when you apply event handlers through onclick as you do in your original version, you can only bind one handler to the element. And using onclick="" kind of clears it.
When using jQuery .click(handler) you bind a new handler each time you call it (and you can unbind it with unbind('click') (and not with onclick=""). So after a couple of calls to afterWaiting you have applied mulitple click handlers on your element, and on each click the calculation function runs multiple times..
So, one way to correct it is to replace
document.getElementById("rollButton").onclick="";
with
$('#rollButton').unbind('click');
The only code required is
<button type="button" id="rollButton"> Roll! </button>
<p id="test"> </p>
var counter = 0;
var $test = $('#test');
var $rollButton = $('#rollButton');
function increment(){
$test.html(counter++);
$rollButton.off('click', increment);
setTimeout(function(){
$rollButton.on('click', increment);
}, 2000);
}
$rollButton.on('click', increment);
Demo: Fiddle
Updated: as suggested by Andy, but I would recommend Andy's answer as it involves no additional event manipulation
var counter = 0;
var $test = $('#test');
var $rollButton = $('#rollButton');
function increment(){
$test.html(counter++);
setTimeout(function(){
$rollButton.one('click', increment);
}, 2000);
}
$rollButton.one('click', increment);
Demo: Fiddle
That's generally a bit of an odd and confusing approach.
Here's how i'd do it, without mixing jquery and pure js (onclick) too much:
http://jsfiddle.net/LGvKS/
var wait = false;
counter = 0;
$('button').click(function(){
if(!wait){
$('span').text(++counter);
wait=true;
setTimeout(function(){
wait=false;
},2000);
}
});
Related
I've written some code in html and javascript and when I drag it into chrome to test it, I get error code 5 in return. I've tried everything that chrome itself recommends when this happens as well as trying with different code, which works. heres my code:
<!DOCTYPE html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var x = 1
var total = 0
var increment = 1
setInterval(function(){ total + increment; }, 1000);
while (x = 1) {
$(document).ready(function(){
$("#id").click(function(){
$("h1").text(total + 1);
});
});
}
</script>
</head>
<body>
<h1>0</h1>
<button id="id">??????????</button>
</body>
keep in mind, I'm extremely new to both of these languages, so I'm learning as I go.
There are some issues in your code:
your while loop runs forever since x=1 will remain true (which is causing the error), furthermore x isn't changed in the loop
the function in setInterval is doing nothing since there is no assignment =
Anyway, you don't need the most stuff. It is enough to get the value of h1 and increment it directly. If the script tag is put before the closing body tag you don't need the $(document).ready-part. So the following is all javascript you need:
Working example:
$("#id").click(function() {
$("h1").text(parseInt($("h1").text()) + 1);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>0</h1>
<button id="id">??????????</button>
By the way, you don't need jQuery for that and can use plain javascript.
Working example:
document.getElementById('id').addEventListener('click', function() {
document.querySelector("h1").textContent = parseInt(document.querySelector("h1").textContent) + 1;
});
<h1>0</h1>
<button id="id">??????????</button>
You don't have to declare variable x at all. Also, you don't need while loop.
Your loop will go to infinity because condition while(x=1) will be always true.
I guess infinite while loop crashes your Chrome browser.
<!DOCTYPE html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var total = 0
$(document).ready(function() {
$("#id").click(function() {
total++;
$("h1").text(total);
});
});
</script>
</head>
<body>
<h1>0</h1>
<button id="id">??????????</button>
</body>
I just wanna make a button to start adding some text in my body, and a button to stop adding this text.
I figured out that I can use a setTimeout in a function or a setInterval...but I couldn't Clear both of them because of the local scope...I can't declare both of them as a global scope, I want my button.onclick activate them not by default.
/* global document*/
var myStart = document.querySelector('#start'),
myEnd = document.querySelector('#end'),
myRepeat;
function start() {
"use strict";
document.body.innerHTML += '<br>Welcome StackOverFlowMembers!';
myRepeat = setTimeout(start, 1000)
}
function stop() {
"use strict";
clearTimeout(myRepeat);
}
myStart.onclick = start;
myEnd.onclick = stop;
<body>
<button id="start">Start!</button>
<button id="end">End!</button>
<script src="script.js"></script>
</body>
The problem here is not the scope of the variables. Everything is actually fine with your code on that.
The problem is here:
document.body.innerHTML += '<br>Welcome StackOverFlowMembers!';
If you replace it with:
console.log('Hello!');
Both buttons will work normally. Check this fiddle.
Basically, when you use innerHTML you destroy the event listeners. You can find more on that in this answer
As #anpel's answer explains, your innerHTML call is trashing your event listeners. In the code below, I work around that by putting the onclick attribute directly into the HTML button elements. The boolean doRepeat variable governs whether a subsequent timeout gets initiated.
/* global document*/
var myStart = document.querySelector('#start'),
myEnd = document.querySelector('#end'),
doRepeat;
function start() {
"use strict";
document.body.innerHTML += '<br>Welcome StackOverFlowMembers!';
if (doRepeat) {
setTimeout(start, 1000);
}
}
<body>
<button id="start" onclick="doRepeat=true;start();">Start!</button>
<button id="end" onclick="doRepeat=false;">End!</button>
<script src="script.js"></script>
</body>
Alternatively, you can make a separate <div> into which your function writes its text-- instead how you're doing innerHTML to the entire HTML body, which destroys all child listeners-- and you won't have to worry about your event listeners getting destroyed since those listeners aren't on children of the target div.
Here's a JS Fiddle to demonstrate that: https://jsfiddle.net/j9voxg7s/
I am trying to make an idle game rather like candy box. I will have a number at the side of the page which rises by one every second. However, the code shown below does not seem to be working. Could anyone tell me why it is not working; how to fix it and where they got their info from. Thank you in advance.
<script type="text/javascript">
var i = 0;
function increment(){
i++;
document.getElementById('money').innerHTML = i;
}
setInterval(increment(), 1000);
</script>
<h2><u>The best game of the century</u></h2>
<p>you have £<span id="money"></span>.</p>
</body>
</html>
You have two issues:
You are calling your script before the DOM is rendered, so at the point the script runs, there is no element with ID of money.
In your setInterval call, you only need the function name (increment) without the parentheses. Including the parentheses (as increment()) only calls the function at that specific moment, rather than referencing it to be called at each interval. (See the Microsoft page on setInterval for more detailed information.)
See this code:
<h2><u>The best game of the century</u></h2>
<p>you have £<span id="money"></span>.</p>
<script type="text/javascript">
var i = 0;
function increment() {
i++;
document.getElementById('money').innerHTML = i;
}
setInterval(increment, 1000);
</script>
change setInterval(increment(), 1000); to setInterval(increment, 1000);
Its not working because as per document https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval
it takes a function reference to be executed.. but calling the function increment() like this will only execute once and the return of that function will be used which will be null and not intended hope this clears it
var i = 0;
function increment(){
//console.log(i);
i++;
document.getElementById('money').innerHTML = i;
}
setInterval(increment, 1000);
<h2><u>The best game of the century</u></h2>
<p>you have £<span id="money"></span>.</p>
I took this example from w3schools and modify it to this. The code below is not working.
What I intend to do is hide the div with id "demo1". It is not working. What is the problem?
<!DOCTYPE html>
<html>
<head>
<script>
function myFunction(div_id)
{
//here the div_id variable seems to unparsable by the DOM event
document.getElementById(div_id).innerHTML = hello;
}
</script>
</head>
<body>
<p>Click the button to trigger a function.</p>
<button onclick="myFunction('demo1')">Click me</button>
<div id="demo1"></div>
<div id="demo2"></div>
</body>
</html>
The variable hello is not defined. You were probably looking to set the innerHTML as a String:
function myFunction(div_id) {
document.getElementById(div_id).innerHTML = "hello";
// -----------------------------------------^-----^
}
DEMO: http://jsfiddle.net/uzuKp/1/
Even though you took an example from W3Schools and modified it, I'd suggest binding events separate from the HTML and storing associated data in data-* attributes. In your example, it can be as something like this:
<p>Click the button to trigger a function.</p>
<button data-div-id="demo1">Click me</button>
<button data-div-id="demo2">Click me</button>
<button data-div-id="demo1">Click me</button>
<div id="demo1">demo1</div>
<div id="demo2">demo2</div>
And the JS:
function clickHandler() {
var targetDivId, targetDiv;
targetDivId = this.getAttribute("data-div-id");
targetDiv = document.getElementById(targetDivId);
targetDiv.innerHTML = "Hello" + new Date().getTime();
}
function loadHandler() {
var buttons, i, j, cur;
buttons = document.getElementsByTagName("button");
for (i = 0, j = buttons.length; i < j; i++) {
cur = buttons[i];
cur.onclick = clickHandler;
}
}
window.onload = loadHandler;
DEMO: http://jsfiddle.net/3K4RD/
Although I would also suggest looking at the following article to see different ways to bind events: addEventListener vs onclick
One final suggestion I have is to not set the innerHTML property. You may have a simple example here, but it's usually a better idea to use DOM methods like appendChild (to add a node) and document.createTextNode (to create text that can be appended). Of course, that would require the contents to be cleared out first, something like:
while (targetDiv.firstChild) {
targetDiv.removeChild(targetDiv.firstChild);
}
targetDiv.appendChild(document.createTextNode("Hello"));
DEMO: http://jsfiddle.net/52Kwe/
You could also store the specific string that needs to be set as the innerHTML as a data-* attribute (especially if it differs between buttons).
UPDATE:
Per your recent edit, the style property is a special property, which is actually a special object with style properties that you need to set. So for your example, you have to set the .style.display value, like:
document.getElementById(div_id).style.display = "none";
document.getElementById(div_id).style.display = 'none';
document.getElementById(div_id).style.visibility= 'hidden';
I have a jQuery application which finds a specific div, and edit's its inner HTML. As it does this, it adds several divs with onclicks designed to call a function in my JS.
For some strange reason, clicking on these never works if I have a function defined in my code set to activate. However, it works fine when calling "alert("Testing");".
I am quite bewildered at this as I have in the past been able to make code-generated onclicks work just fine. The only thing new here is jQuery.
Code:
function button(votefor)
{
var oc = 'function(){activate();}'
return '<span onclick=\''+oc+'\' class="geoBut">'+ votefor +'</span>';
}
Elsewhere in code:
var buttons = '';
for (var i = 2; i < strs.length; i++)
{
buttons += button(strs[i]);
}
var output = '<div name="pwermess" class="geoCon"><div class="geoBox" style=""><br/><div>'+text+'</div><br/><div>'+buttons+'</div><br/><div name="percentages"></div</div><br/></div>';
$(obj).html(output);
Elsewhere:
function activate()
{
alert("Testing");
}
You may want to take a look at jQuery.live(eventType, eventHandler), which binds an event handler to objects (matching a selector) whenever they are created, e.g.:
$(".somebtn").live("click", myClickHandler);
Follows a dummy example, may be this can help you.
<!DOCTYPE html>
<html>
<head>
<style>
</style>
<script src="http://cdn.jquerytools.org/1.2.5/jquery.tools.min.js"></script>
<script type="text/javascript">
$(function() {
$('.go-right').click(function(){
c="Hello world";
$("#output").html(c);
});
});
</script>
</head>
<body >
<div id="output"></div>
<a class="go-right">RIGHT</a>
</body>
</html>
Change this:
var oc = 'function(){activate();}'
To be this instead:
var oc = 'activate();'