SetInterval does not run from HTML form's onClick event - javascript

I just wrote a timer function that does count down from 5 seconds on the page. Next I wanted to create a form that would call the timer function when submitted.
But even though the onClick triggers the function (and console logs "hi"), it never executes setInterval.
Is there a reason why setInterval works when I call the function immediately, but not when I submit the form? After some research, I still can't work out the reason for this.
<body>
<h1 id="title">
This a simple timer
<form action="">
<input type="text" name="duration" />
<input type="submit" onclick="timer()" />
</form>
</h1>
<script src="src/index.js"></script>
</body>
javascript
const title = document.getElementById("title");
const btn = document.getElementById("btn");
const timer = () => {
console.log("hi");
let interval = 5;
let countdown = window.setInterval(() => {
title.innerText = "00:" + interval;
interval--;
if (interval === 0) {
title.innerText = "DONE";
clearInterval(countdown);
}
}, 1000);
};

Since HTML forms with action attribute set to empty string submit their form to the current page, you are reloading your page every time you submit since why your JS function never gets called
what you can do is prevent default(reload) behavior by calling e.preventDefault() before your console.log("hi"); statement.
and your <input type="submit"... would change to <input type="submit" onclick="timer(event)" />
also don't forget to add the parameter to const timer = e => {...

Submitting a form in html means that the URL specified with action will be loaded with the data from you form. If you set action to an empty string, the current page is reloaded with the form's data. So in your case you are reloading your page everytime you click the submit button.
If you just want to start the timer with a button, you don't need a form and you don't need an input of type submit. Use
<body>
<h1 id="title">
This a simple timer
</h1>
<input type="text" name="duration" />
<input type="button" onclick="timer()" value="click me!" />
<script src="src/index.js"></script>
</body>
Also, you shouldn't put anything in your <h1> apart from the actual text of your title.

I see two problems here. Your html structure. You should try this instead. I added “event” so I could target the input element. But you could also give the form tag a name or set an I’d to target it directly when the submit button gets clicked.
<body>
<h1 id="title"> This a simple timer </h1>
<form action="">
<input type="text" name="duration" />
<input type="submit" onclick="timer(event)"/>
</form>
<script src="src/index.js"></script>
</body>
Previously when the onclick event triggers you update the DOM by replacing the text contents in #title and that tag wraps the form also. I think you should make them independent. And 2, the page gets reloaded so you should handle the page submission by using preventDefault(); on the form. see example below
const title = document.getElementById("title");
const btn = document.getElementById("btn");
const timer = e => {
e.preventDefault();
console.log("hi");
let interval = 5;
let countdown = window.setInterval(() => {
title.innerText = "00:" + interval;
interval--;
if (interval === 0) {
title.innerText = "DONE";
clearInterval(countdown);
}
}, 1000);
};
Here is another approach, i adjusted the html and javascript.
No onclick event
<h1 id="title"> This a simple timer </h1>
<form action="" name="simple_timer">
<input type="text" name="duration" />
<input type="submit"/>
</form>
We just set a form name.
Javascript set to listen for any submission by that form then prevents it from occuring.
const title = document.getElementById("title");
const timer = document.forms['simple_timer'];
timer.addEventListener('submit', (e) => {
e.preventDefault();
console.log("hi");
let interval = 5;
let countdown = window.setInterval(() => {
title.innerText = "00:" + interval;
interval--;
if (interval === 0) {
title.innerText = "DONE";
clearInterval(countdown);
}
}, 1000);
});
Guess that’s all.

Related

Prevent default on enter key with a button in Javascript

I have my HTML code:
<!DOCTYPE html>
<head>
<script src="../req.js"></script>
</head>
<link rel="stylesheet" href="style.css">
<html>
<body>
<h1> Recipes founder</h1>
<form class="example">
<input id ="query" type="text" placeholder="Insert a recipe.." name="search" value="">
<button id="searchRecipe" type="button" onkeydown="handler(e)" onclick="searchFile()"><i></i>Search</button>
</form>
<div id="content"></div>
</body>
</html>
and my js code associated with it:
function searchFile(e) {
// enter must do the same
const q = document.getElementById('query').value;
const total_q = `Title%3A${q}%20OR%20Description%3A${q}%20OR%20web%3A${q}`
fetch(
`http://localhost:8983/solr/recipe/select?indent=true&q.op=OR&q=${total_q}&rows=300`, { mode: 'cors' }
).then((res) => res.json())
// Take actual json
.then(({ response }) => appendData(response))
.catch(function (err) {
console.log(err)
});
}
function appendData(data) {
// clear previous research
document.getElementById("content").innerHTML = "";
let docs = data.docs;
// Take each element of the json file
for (elem of docs) {
var mainContainer = document.getElementById("content");
// title recipe
var a1 = document.createElement("a");
a1.setAttribute("href", elem.url);
var div = document.createElement("div");
div.innerHTML = elem.Title;
a1.appendChild(div);
// insert image of recipe and link for page in website
var a = document.createElement("a");
a.setAttribute("href", elem.Image);
var img = document.createElement("img");
// img.setAttribute("href", elem.url);
img.setAttribute("src", elem.Image);
a.appendChild(img);
// recipe description
var p = document.createElement("p");
p.innerHTML = elem.Description;
// Insert elements in dev
mainContainer.appendChild(a1);
mainContainer.appendChild(p);
mainContainer.appendChild(a);
}
}
function handler(event) {
if (event == "click") {
searchFile();
}
else if ((event.keyCode || event.which) == 13){
event.preventDefault();
event.cancelBubble = true;
event.returnValue = false;
event.stopPropagation();
event.preventDefault();
searchFile();
}
else {
console.log("Nothing")
}
}
What searchFile() and appendData() do is not important because they work. The target is when the user clicks on the search button or presses the enter key, searchFile() must be called. Clicking on the search button works, but the problem is when a user clicks enter, it navigates to http://localhost:8000/?search=SOMETHING (depends on what the user inserted) . I think it is the default behaviour of the enter key, I tried to prevent it using different codes but nothing works. I read that instead of using the event onkeypress we have to use onkeydown but I'm still in the same situation. I tried also to wait for the DOM to be loaded but nothing. Does someone have an idea about it?
Remove all the event handlers on the button
Make the button a submit button
Use the submit event on the form (this will trigger if the form submission is trigged by enter in the input or the button being clicked or enter being pressed over the button)
Prevent the default event behaviour (so the form data isn't submitted to a URL which the browser navigates to)
Don't bother doing any tests to try to figure out if it was a click or something else, all that matters if that the form was submitted.
const submitHandler = (event) => {
event.preventDefault();
alert("You can do your ajax search here");
};
document.querySelector('.example').addEventListener('submit', submitHandler);
<form class="example">
<input id="query" type="text" placeholder="Insert a recipe.." name="search" value="">
<button>Search</button>
</form>

How do I change a "button" button to a "submit" button onclick without submitting after the onclick event is completed?

I have a button that, when clicked, prompts the user for more info dynamically through an onclick JavaScript function:
<button type="button" id="create" onclick="addFields()">create?</button>
Once new info has been loaded into the page, I want the button to submit the form:
// .js file
function addFields(){
var container = document.getElementById("initialinfo");
var newInfo = document.createElement('div');
newInfo.setAttribute("id", "createDetails");
newInfo.innerHTML += "divs and checkboxes and radios"
container.appendChild(newInfo);
document.getElementById("create").removeAttribute("onclick");
document.getElementById("create").setAttribute('type', 'submit');
}
Unfortunately, when I do this, the form doesn't submit on the next click. Instead, after the onclick event, the button (which is now of type submit) submits the form. How do I prevent this behavior?
Prevent Default
The Event interface's preventDefault() method tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be.
<form id="my-form">
<input id="first-field" type="text"/>
<input id="second-field" class="hidden" type="text"/>
<button type="submit" id="submit">
<span class="continue">Continue</span>
<span class="submit hidden">Submit</span>
</button>
</form>
.hidden {
display: none;
}
let allFieldsShown = false;
const myForm = document.querySelector('#my-form'),
secondField = myForm.querySelector('#second-field),
continueText = myForm.querySelector('span.continue'),
submitText = myForm.querySelector('span.submit');
myForm.addEventListener('submit', submitHandler);
function submitHandler(e) {
if (!allFieldsShown) {
e.preventDefault();
showNode(secondField);
hideNode(continueText);
showNode(submitText);
allFieldsShown = true;
}
}
function showNode(node) {
if (node.classList.contains('hidden')) {
node.classList.remove('hidden');
}
}
function hideNode(node) {
node.classList.add('hidden');
}
You can trigger the form programmatically on your second button click
<form id="myForm" action="..." >
<button type="button" onclick="addFields(event)">continue?</button>
</form>
function addFields({target}){
var container = document.getElementById("initialinfo");
var newInfo = document.createElement('div');
newInfo.setAttribute("id", "createDetails");
newInfo.innerHTML += "divs and checkboxes and radios"
container.appendChild(newInfo);
// here we change the onclick event handler
target.onclick = () => {
const form = document.getElementById('myForm')
form.reportValidity() && form.submit()
}
}
Firstly you put button type submit first and call function through onclick.
Browser will get function definition first then it will submit form
<button type="submit" id="continue" onclick="addFields()">Continue></button>

Redirecting after submit with counter

I am trying to redirect with counter to another page. I want the redirect to start when I have submit the form. I want to redirect to another page after submit form.
var count = 6;
var redirect = "https://www.google.com";
function countDown() {
var timer = document.getElementById("timer");
if (count > 0) {
count--;
timer.innerHTML = "This page will redirect in " + count + " seconds.";
setTimeout("countDown()", 1000);
} else {
window.location.href = redirect;
}
}
<form method="post">
<p>
<label>Name
<input type="text" name="textfield">
</label>
</p>
<p>
<input type="submit" name="Submit" value="Submit"><br>
</form>
<span id="timer">
<script type="text/javascript">countDown();</script>
</span>
</p>
A form submit is always a request to the server. You can either use ajax to perform the submission of the form or you can just count and submit the form afterwards.
To prevent your form from submitting when a user hits the button u can prevent the default behaviour like so:
$('input [type=submit]').on('click', function( event ) {
event.preventDefault();
// use your counter here
// when counter hits 0 just submit the form with
$('form').submit();
});
or use an ajax call:
$('form').on('submit', function(event) {
event.preventDefault();
$.ajax({
url: 'url/to/form/action',
data: $(this).serialize(),
method: "POST",
success: function() {
// start your counter
// REDIRECT
}
});
});
The Problem with the first method would be that you are just delaying the form submission.
In the second case u cant reliably tell when you will get an success (or error) response since the call is asynchrous. This will result in either a delay before your counter starts or a possible delay after your counter ends if the server didnt respond until then.
You can achieve a counter by using setInterval, and making a check until it hits 0 to redirect:
<form method="post">
<p>
<label>Name
<input type="text" name="textfield">
</label>
</p>
<p>
<input type="submit" name="Submit" value="Submit">
<br>
</form>
<span id="timer">This page will redirect in <span id="count"></span> second(s).</span>
<script type="text/javascript">
var count = 6;
var redirect = "https://www.google.com";
var elem = document.getElementById('count');
elem.innerText = count
setInterval(() => {
count--
elem.innerText = count
if (count == 0) {
window.location.href = redirect;
}
}, 1000)
</script>

onclick submit can't call JavaScript function with setTimeout and document.getElementById

I am tring to call timedText() function when click on submit, and than call setTimeout() and replace tag <p> with 1 seconds, 2 seconds and 3 seconds.
<script>
function timedText()
{
var x=document.getElementById('txt1');
var t1 = setTimeout(function(){x.innerHTML="1 seconds"},1000);
var t2 = setTimeout(function(){x.innerHTML="2 seconds"},2000);
var t3 = setTimeout(function(){x.innerHTML="3 seconds"},3000);
}
</script>
<p>
<a href="#">
Izmeni<p id="txt1"></p>
</a>
</p>
<input type="submit" name="answer" value="Postavi" onclick="timedText()"/>
That is because the submit button is submitting the page.
Personally, I like to use <button onclick="dosomething()">Click me!</button>. But some browsers treat that as a submit button too... so make sure you return false; in the event handler (ie. onclick="dosomething(); return false;")
A few things changed:
Changed submit button to a standard button. Submit button probably reloading page, and never firing action. Either way, not appropriate for a function call onclick.
Changed onclick on the html button to be assigned by the javascript. It's the modern way to do this, and more reliable.
Cleaned up the html slightly. The p tag was inside the anchor, which isn't ideal. This is optional mostly though.
JSFiddle
http://jsfiddle.net/q9Juv/
HTML
<p>
Izmeni
<p id="txt1"></p>
</p>
<input type="button" id="button" name="answer" value="Postavi" />
JS
function timedText(){
var x=document.getElementById('txt1');
var t1=setTimeout(function(){x.innerHTML="1 seconds"},1000);
var t2=setTimeout(function(){x.innerHTML="2 seconds"},2000);
var t3=setTimeout(function(){x.innerHTML="3 seconds"},3000);
}
document.getElementById('button').addEventListener('click',timedText);
Perhaps this will help you to see things in a clearer way (hopefully):
<p>Izmeni<p id="txt1"></p></p>
<input type="submit" name="answer" value="Postavi" onclick="StartTimer(3)"/>
<script type="text/javascript">
var timerId = null;
var element = document.getElementById("txt1");
function StartTimer(numOfSeconds)
{
element.innerHTML = String(numOfSeconds)+" seconds";
timerId = setInterval(TimerIsr,1000);
}
function StopTimer()
{
clearInterval(timerId);
element.innerHTML = "";
}
function TimerIsr()
{
var numOfSeconds = Number(element.innerHTML.split(" ")[0]);
if (numOfSeconds > 2)
element.innerHTML = String(numOfSeconds-1)+" seconds";
else if (numOfSeconds == 2)
element.innerHTML = "1 second";
else
StopTimer();
}
</script>

jQuery disable form submit in less than xx seconds

I have a user registration form.I need to check if user form filled in less than xx seconds(5 seconds). If less than 5 seconds disable the form submit. Some thing like that disable the submit button click or return false or like that.
I wrote some jquery scripts.But not correctly working.
Here is the sample form.
<form id="registerform" class="registerform" method="post"/>
<input type="text" name="username" id="username" />
<input type="text" name="email" id="email" />
<input type="submit" name="submit" id="submitBtn" value="Submit" />
</form>
Here is the jquery scripts.
<script type=javascript>
jQuery.noConflict();
jQuery(document).ready(function ($) {
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms, 5 second for example
var checktime = 0;
jQuery('form#registerform').find(':input').each(function(){
jQuery(this).keyup(function(){
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
jQuery(this).keydown(function(){
clearTimeout(typingTimer);
});
});
function doneTyping () {
checktime = typingTimer;
return checktime;
}
jQuery('form#registerform').submit(function() {
checktime = doneTyping ();
var timerInsec = (doneTypingInterval/1000);
if(checktime < timerInsec) {
return false; // disable form submit
} else {
// if user take to fill the form more than 5 seconds, submit the form
return true;
}
});
});
</script>
I need to integrate to the wordpress registration form.That's why I tried.
If anyone have a solution/solutions to this please help me. Really appreciate that.
Thank you
This will disable your submit button for 5 seconds:
var submitButton = $('#submitBtn');
submitButton.prop("disabled", true);
setTimeout(function() {
submitButton.prop("disabled", false);
}, 5000);
Online example
You would also want to make sure, that the malicious user doesn't submit the form by other means! Make sure to run server-side validation:
if ( isset($_SESSION['last_submit_time']) ) {
$delay = intval($_SESSION['last_submit_time']) + 5;
if ( time() < $delay ) {
$_SESSION['last_submit_time'] = time();
echo "You must wait for 5 more seconds before submitting. Timer reset.";
exit;
}
}
typing timer does not contain the time , instead it contains an id for the timer thats currently ticking...and since key up will always set it to some value, it will never be false.
Also, you add add and reset timer for each input. If you want the user to spend at least 5 seconds to fill in your form, dont enable the submit button until 5 sec has passed.
function doneTyping () {
checktime = typingTimer;//will always have a value that evaluates to true
return checktime;
}
Try that... HTML:
<form id="registerform" class="registerform" method="post">
<input type="text" name="username" id="username">
<input type="text" name="email" id="email">
<input type="submit" name="submit" id="submit" value="Submit">
</form>
jQuery:
jQuery(document).ready(function ($) {
var intervalTime = 5000,
inputID = "#submit";
function initialize(interval, input) {
intervalTime = interval;
inputID = input;
jQuery(inputID).prop("disabled", true);
startCouting();
}
function startCouting() {
setTimeout(function() {
enableInput();
}, intervalTime);
}
function enableInput() {
jQuery(inputID).prop("disabled", false);
};
initialize(5000, "#submit");
});

Categories

Resources