Submit button calls function without being clicked - javascript

I am trying to write a simple banking app to learn basic DOM manipulation stuff. This will be a single page website with lots of function calls and hiding/displaying containers.
Once I click the register button on the main screen, it calls registerScreen() function which then hides the main screen elements and shows a form group with text boxes and a submit button that saves the filled in information. However, saveCustomer() function calls itself as soon as I bring up the register screen. Obviously, it submits a blank form which is a problem.
I have tried different event listener methods like submit, click, getElementById().onclick, and so on. I did not want to call saveCustomer() function on HTML because I do not know how I can pass the info with that approach.
function registerScreen() {
document.getElementById("welcome-container").style.display = "none";
document.getElementById("registerScreen").style.display = "block";
let customerFirstName = document.getElementById('firstName').value;
let customerLastName = document.getElementById('lastName').value;
let customerPassword = document.getElementById('password').value;
let randomID = document.getElementById("randomID");
let ID = Math.floor((Math.random() * 999) + 100);
randomID.innerHTML += ID;
//This is the line I am having problems with
document.getElementById("submitInfo").addEventListener("click", saveCustomer(ID, customerFirstName, customerLastName, customerPassword));
}
function saveCustomer (ID, customerFirstName, customerLastName, customerPassword) {
let customer = {
id: ID,
firstname: customerFirstName,
lastname: customerLastName,
password: customerPassword,
cashAmount: 0,
}
if (localStorage.getItem("customers") === null) {
let customers = [];
customers.push(customer);
localStorage.setItem("customers", JSON.stringify(customers));
} else {
let customers = JSON.parse(localStorage.getItem("customers"));
customers.push(customer);
localStorage.setItem("customers", JSON.stringify(customers));
}
alert("Registration successful.");
}

Try wrapping saveCustomer in an anonymous callback function like so:
document.getElementById("submitInfo").addEventListener("click", () => {saveCustomer(ID, customerFirstName, customerLastName, customerPassword)});

The issue is that you are not registering a function to be called when #submitInfo is clicked, but the event listener is malformed and you are calling another function from withing the declaration. Instead, you should register a new anonymous function when clicking #submitInfo and only call the saveCustomer() from withing that anonymous function.
Below is the wrong way that you are using in your case.
<button id="btn">Click</button>
<script>
document.getElementById("btn").addEventListener("click", alertSomething("test"));
function alertSomething(text) {
alert("Inside here, alerting "+text);
}
</script>
When initializing the eventListener, it is making a call to the alertSomething() function. This will trigger the alertSomething() function as soon as the document has loaded.
What you want instead is to define a new anonymous function that will get called once the button has been clicked and only call the alertSomething() function from inside this new function. It is called anonymous function because it doesn't have a name like an ordinary function.
The correct way to accomplish this:
<button id="btn">Click</button>
<script>
document.getElementById("btn").addEventListener("click", function() {
alertSomething("test")
});
function alertSomething(text) {
alert("Inside here, alerting "+text);
}
</script>

Related

Stop a portion of Javascript function from auto firing

Is it possible to stop the script and wait for user input before continuing it?
Here is the portion that I need to stop:
var nName = document.getElementById("b1");
nName.innerHTML = "Continue";
document.getElementById("b1").onclick = newName();
So "b1" is a HTML button, I want to stop it after
nName.innerHTML = "Continue";
and wait for user click on the button before firing
document.getElementById("b1").onclick = newName();
using return completely stop the script. Is there any other possible way to do this?
You do not need to stop the script. You cannot.
Pass references to the functions (no paranthesis on the function names) like so:
document.getElementById("b1").onclick = newName;
Example:
function firstClick(){
document.getElementById('b1').innerHTML = "Continue"
// override the first click listener. "firstClick" will no longer be called.
document.getElementById('b1').onclick = newName;
}
function newName(){
document.getElementById('b1').innerHTML = "Good Job!"
}
// listen for first click
document.getElementById('b1').onclick = firstClick
<button id=b1>Click Me!</button>
In order to fully understand what is going on, I do must refer you do Google and Documentation, and most of all - Experimentation.
But in short, in not technical terms.
onclick does nothing on its own. It needs to be told what it does. The browser will do what you tell it to. There can only be 1 function assigned to it. So if you do onclick=a; onclick=b; onclick=c, only c will be called.
If you assign the function name with paranthesis onclick = newName(), what you are doing is you are running the newName() and assigning its return to the onclick. So in this case - nothing. If you do onclick=newName the borwser will automatgically add the paranthesis.
You could even create a 'triaging' function to decide what the next steps are:
function triage(){
var el = document.getElementById('b1');
if (el.innerHTML == "Continue"){
el.innerHTML = 'Good Job!';
}else{
el.innerHTML = 'Continue';
}
}
// listen for first click
document.getElementById('b1').onclick = triage
<button id=b1>Click Me!</button>

Query selector to select Button A only if site does not have Button B

I'm creating a Chrome Browser Extension that clicks some buttons automatically whenever they appear. I'm using arrive.js for the watching, which uses a query Selector to watch for the html elements to click on.
var buttonA = 'a[data-test="begin-session-button"]'
var buttonB = 'a[data-test="skill-header-practice-button"]'
document.arrive(buttonA, function () {
document.querySelector(buttonA).click();
});
document.arrive(buttonB, function () {
document.querySelector(buttonB).click();
});
The Problem I have is some sites have both buttons buttonA and buttonB. As of now both buttons would be clicked and it is a matter of luck which one gets clicked last.
Whenever there is a site with buttonA and buttonB, only click buttonA. So I'm looking to alter the query for buttonB like:
document.arrive(buttonB + ' :not:' + buttonA, function () {
document.querySelector(buttonB).click();
});
As a query in the Chrome Browser Console this would look like:
document.querySelector(
'a[data-test="skill-header-practice-button] ' +
':not:a[data-test="begin-session-button"]'
)
This is bad syntax and not working in the chrome brower console. How would the Correct Syntax look like?
Could you not do something like this
document.arrive(buttonA, function () {
document.querySelector(buttonA).click();
});
document.arrive(buttonB, function () {
if(document.querySelector(buttonA) == null){
document.querySelector(buttonB).click();
}
});
I can't say that I have used the arrive library before though so I could be completely wrong
i guess this is simpler to do it "programatically" than with complex selectors, something like (works with your code because buttonA is global, be careful that this var must be accessible to the function):
var buttonA = 'a[data-test="begin-session-button"]'
var buttonB = 'a[data-test="skill-header-practice-button"]'
document.arrive(buttonA, function () {
document.querySelector(buttonA).click();
});
document.arrive(buttonB, function () {
var buttA = document.querySelector(buttonA);
if(buttA === null){
document.querySelector(buttonB).click();
}
});

Multiple window onload functions with only Javascript

I have an external JS file that adds a window.onload function to the page.
The basic premise is that it loads up a popup window on your website whenever the user clicks on certain link class. It's written in PHP / JS so assume that the function works by itself.
Inside this JS file has the following code.
window.onload = function() {
var anchors = document.getElementsByClassName("vyper-triggers");
for (var i = 0; i < anchors.length; i++) {
var anchor = anchors[i];
anchor.onclick = function() {
if (isMobile.any()) {
window.open("$url");
} else {
document.getElementById("clickonthis").click();
}
}
}
}
Now my problem is when my user wants to add 2 different popup windows, the window.onload function doesn't stack. Also because this is an embedded javascript that my user adds himself, there is no way for me to put both functions inside one big window.onload function.
My user might put one JS file in one area of their site, and another JS file in another area, if that makes sense.
So how do I make it so that the window.onload function will stack no matter the placing of these external JS files on the page and considering that each function must be kept separate?
Rather than setting window.onload, you should use addEventListener. Listeners added this way will stack automatically.
window.addEventListener('load', function() {
console.log('First listener');
});
window.addEventListener('load', function() {
console.log('Second listener');
});
window.addEventListener('load', function() {
console.log('Third listener');
});
If you have to support versions of IE before IE9, there's a polyfill which will make this work correctly.
Probably you have multiple files and u want to check something onload.
Let's implement a basic function to add other functions and run all of them when the event onload is triggered.
So, first we check if windows.onload has a function object if not add our function. If is contains a function object merge it with our function like this:
function addLoadEvent(callback) {
const previous = window.onload
if (typeof previous === 'function') {
window.onload = (e) => {
if (previous) previous(e)
callback(e)
}
}
...
}
This is an example how to use it:
function addLoadEvent(callback) {
const previous = window.onload
if (typeof previous === 'function') {
window.onload = (e) => {
if (previous) previous(e)
callback(e)
}
} else {
window.onload = callback
}
}
function func1() {
console.log('This is the first.')
}
function func2() {
console.log('This is the second.')
}
addLoadEvent(func1);
addLoadEvent(func2);
addLoadEvent(() => {
console.log('This is the third.')
document.body.style.backgroundColor = '#EFDF95'
})

open window and run function on that window

I'd like to open a new window, this window has a list of objects, and these objects should be filtered based on a selection from the previous window. I figured I can filter the list through a function, but how do I run said function?
This is what I am able to do:
var popup = window.open('pageURL');
$(popup.document).ready(function() {
// this is where function should be
popup.alert('HelloWorld');
});
But how do I change the alert to a function?
If I have a function on my other app , function test() { alert('HelloWorld'};
How do I run this function from my first app?
Swapping popup.alert('HelloWorld'); with popup.test(); did not work.
You need the reference to the window opened to call functions in the new window, like:
var oNewWindow = window.open("new.window.url", "mywindow");
oNewWindow.onload = function(){oNewWindow.window.newWindowFunction();};
I ended up with this solution
var popup = window.open('http://s234-0057/actiontracker/SiteAssets/Avvik/html/app.aspx');
var readyStateCheckInterval = setInterval(function() {
if (popup.document.readyState === "complete") {
clearInterval(readyStateCheckInterval);
popup.test();
}
}, 50);
Where I check if the popup window is ready, and when it is, cancel check and run function. Solution is from top answer on this question, by #this.lau_
You can write it like this:
function myFunction(){
alert('HelloWorld');
}
var popup = window.open('pageURL');
$(popup.document).ready(function() {
popup.eval(myFunction + "");
popup.myFunction();
});
myFunction in file that contains this code will run in page with pageURL address.

Detecting a form.submit() performed via JavaScript

In my page there is a frame that belongs to the same domain. The content of this frame is varied and relatively unpredictable. Whenever a user clicks a button (inside the frame) that performs a post, I need to execute a function that performs some UI tasks. The problem is that I cannot edit the source of these frames for reasons beyond my control. Some of these buttons are simple form submit buttons, but others do not directly submit the form, but instead have an onclick handler that performs some checks and might submit.
Here is the problem: How do I detect if one of these onclick handlers called form.submit()? If there's no handler, then obviously I can set up a handler for onsubmit(), but is not the case for all of these buttons.
This is my code so far:
function addEventBefore(element, type, before, after) {
var old = element['on' + type] || function() {};
before = before || function() {};
after = after || function() {};
element['on' + type] = function () {
before();
old();//I can't modify this old onclick handler
after();
};
}
function setup() {
console.log('setup');
}
function takedown() {
// In this method, I want to know if old() caused a form submit
console.log('takedown');
}
function $includeFrames(jQuery, selector) {
return jQuery(selector).add(jQuery('iframe').contents().find(selector));
}
var a = $includeFrames($, 'input[type="submit"], input[type="button"]').each(function() {
var elem = $(this)[0];
addEventBefore(elem, 'click', setup, takedown);
});
In the onload event of the iframe you'll need to hook up an event listener to each form in the iframed page. You need to do this on every load, as each fresh page needs new listeners.
$("#someIframe").on('load',function() {
$(this).contents().find("form").each(function() {
$(this).on('submit',function() {... your code...})
})
}
The solution that worked for me came from a friend of mine. The solution is to shim the form.submit() function.
$(function() {
var el = document.getElementById('myform');
el.submit = function(fn) {
return function() {
myFunctionGoesHere();
fn.apply(this, arguments);
};
}(el.submit);
});
Here is a working example: http://jsfiddle.net/hW6Z4/9/

Categories

Resources