javascript getting a variable from a child to a parent - javascript

I shortened my code dramatically but below relays the point pretty efficiently, I'm trying to get the variable "Monitor" to update if the buttons pressed. I can get the variable through to my code if I put all of my code inside of the "button.onclick" function. However, my code won't run until I press the button. I need my code to run and if a button is pressed it updates my code.
<form name="form1">
<span id="buttons">
<input type="button" name="button1" value="funny1"/>
<input type="button" name="button2" value="funny2"/>
</span>
</form>
<script type="text/javascript">
var Monitor, buttonsDiv=document.getElementById("buttons");
Monitor = "funny1"
for (var i=1; i<=2; i++) {
var button = document.form1["button" + i];
button.onclick = function() {
buttons.Monitor = this.value;
};
/*lots of my own code that runs
inside of my for loop waiting
to reference monitor for an update*/
</script>

Hopefully the following code will get you going in the right direction. Instead of wiring up all the events per button, I think you were trying to get it so each button would then call into a function that would set the value of Monitor.
var Monitor = "funny1";
//selecting all elements named button
var buttons = document.querySelectorAll('input[type="button"]');
//For each of the buttons wire up an event listener
for(var i=0, length=buttons.length; i < length;i++)
{
//create a reference shorthand
var button = buttons[i];
//add the event listener for a click
button.addEventListener('click', function(event)
{
//on the event look at the event's target property to find the element that invoked the click
Monitor = event.target.value;
console.log(Monitor); //Output the value of monitor the the console
});
}
This code first finds all the inputs with type=button. I suggest you perhaps give the inputs a class instead to make the selector clearer, your choice. Secondly, I loop through the buttons and wire an event up for each one. The event then sets the value of the Monitor variable.
http://jsfiddle.net/wcf4c/

Related

Getting event listener to fire

I have a script that I am using in conjunction with a PHP form. I am trying to get a counter field that I put on the form to count up by one second after the employee id field is filled out below is my code.
<script type="text/javascript">
var counter = 0;
var timer;
var employee = document.getElementsByName("employeeID")[0];
var employeeVal = document.getElementsByName("employeeID")[0].value;
employee.addEventListener("onchange", startCount);
function countUP () {
counter = counter + 1; //increment the counter by 1
document.getElementsByName("timer_container")[0].value = counter;
}
function startCount () {
timer=setInterval('countUP()', 1000 );
}
function readonly() {
document.getElementsByName("timer_container")[0].readOnly = true;
}
</script>
I have tried different functions to see if the event listener was firing. I also tried using different events, onclick, onblur and have not had any luck. I've taken the timer function and set it to onload in the body tag directly on the HTML and that works. However I need this to be able to run as soon as someone enters info into the employee field.
First, don't use on in the event name when using .addEventListener. The on prefix is only for inline event binding with HTML event attributes (which is why it worked for you in <body onload=...>). Inline event HTML attributes shouldn't be used anymore anyway. So, your line should be:
employee.addEventListener("change", startCount);
And use the input event instead of the change event if you want it to fire as data is being entered.
employee.addEventListener("input", startCount);

Is it correct to put an event inside an event?

I have an script in which I'm going to add a file XLS, once that I validate the file format, I close a bootstrap's modal and open another modal which is an confirmation window to see whether the user is sure to upload that file.
This confirmation window has a confirmation button, once clicked I want that execute me an function which it's going to run an AJAX to make the request to the server.
However, because of that, I had the following doubts:
Which of the 2 ways is better (and the most correct) to run the code and why?
Why is the click event of the first input file executed if there has not been an event change? I mean, I add a file and the event change is executed and I can make clicks many times as I want, is not it supposed that I must add another file so that I can run the function inside again?
Put an event inside an event, has it a name?
$(document).ready(function(){
//First input file
$(document).on('change','#file', function(){
let file = $(this);
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 1</button>';
$('#button').html(button);
$('#button').click(function(){
console.log('CLICK IN FIRST INPUT FILE!');
});
});
//Second input file
$(document).on('change','#file2', function(){
let file = $(this);
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 2</button>';
$('#button2').html(button);
});
$('#button2').click(function(){
console.log('CLICK IN SECOND INPUT FILE!');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="file" name="file" />
<div id="button"></div>
<div style="margin-top:20px"></div>
<input type="file" id="file2" name="file2"/>
<div id="button2"></div>
Put an event inside an event, has it a name?
It has, the name is Bad Idea. Let me Expain. What happens when you execute the following code.
$('#button').click(function(){
console.log('CLICK IN FIRST INPUT FILE!');
});
A click event is registered to the button. Once an event is registered, it will fire everytime no matter how many times you click.
When you put that code inside another event handler like the first example, it gets executed everytime the file-input changes and a new event handler is registered. So when you select a file, and then decide to change it, file-input changes twice and you get 2 click events registered. Now click on the button, you get 2 new console log printed by one click!!! Try it..
Why is the click event of the first input file executed if there has
not been an event change
Because that's how event handler works, you register once, they get fired everytime after that.
Which of the 2 ways is better (and the most correct) to run the code
and why?
Obviously not the first one, because it is a bad idea, Not the second one either. In case of second one you are attaching event to a division that will contain the button. So you don't need to click on the button, just click anywhere right side of the button, the event gets fired!!!
So if none of them is right, what can we do?
Do not generate button/any html element by javascript for such simple tasks. Do it with HTML, plain and simple.
Do not nest event handler into another i.e put one event handler inside another, it will complicate things. Just put all event handlers directly inside document.ready event of jQuery. document.ready only fires once.
When you need to control user action then show/hide your button or other html element by javascript based on required conditions.
My suggestion is doing something like this.
$(document).ready(function(){
// Hide the button at first
$('#button').hide();
// When File-input changes
$('#file').change(function(){
if(**the file-input has a file selected**){
$('#button').show();
}
else{
$('#button').hide();
}
});
// When Button Clicked
$('#button').click(function(){
// Do the action
});
});
Which of the 2 ways is better (and the most correct) to run the code and why?
I believe this is better:
//Second input file
$(document).on('change','#file2', function(){
let file = $(this);
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 2</button>';
$('#button2').html(button);
});
$('#button2').click(function(){
console.log('CLICK IN SECOND INPUT FILE!');
});
Mainly because it's more readable and easy to follow. There is no need to have the button click event set up AFTER the input has been changed. It is better to change the STATE of the button, as you are doing. Even better would be to hide/show the button like:
$('#button2').show();
And have it initially hidden with:
<div id="button2" style="display: none">Click me</div>
Why is the click event of the first input file executed if there has not been an event change?
In my test, this all worked correctly.
How is called this?
The change events should only be called when you click and assign a file to the input.
you are binding the same event multiple times to the same button object. binding the same event to the same object in another event that may reoccur will result in binding it over and over (stacks events and fire them and in this case "it" multiple times). binding an action to an event should happen only one time per object. and I see that you are binding the click event to the div instead of the button. maybe you need to consider dynamic binding using .on() like this
$(document).ready(function(){
//first file change event
$(document).on('change','#file', function(){
let file = $(this);
//handling empty selection
if(file[0].files.length == 0){
$('#button').html("");
return;
}
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 1</button>';
$('#button').html(button);
});
//second file change event
$(document).on('change','#file2', function(){
let file = $(this);
//handling empty selection
if(file[0].files.length == 0){
$('#button2').html("");
return;
}
let nameFile = file[0].files[0].name;
let button = '<button type="button">Clic input 2</button>';
$('#button2').html(button);
});
//first button dynamic event (doesn't stack)
$('#button').on('click','button', function(){
console.log('CLICK IN FIRST INPUT FILE!');
});
//second button dynamic event (doesn't stack)
$('#button2').on('click','button', function(){
console.log('CLICK IN SECOND INPUT FILE!');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="file" name="file" />
<div id="button"></div>
<div style="margin-top:20px"></div>
<input type="file" id="file2" name="file2"/>
<div id="button2"></div>
note that you need to handle not choosing a file (e.g. files count is 0) like in my code
Put an event inside an event, has it a name?
It does have a name. It's called "daisy chaining" and it's not a good idea.
not enough rep to comment
I've had cause to do this. I had the unpleasant task of mucking through 2 years of code written by one person with little maintenance or code discipline. I wanted to keep the code structure intact, so I daisy-chained click events to perform some enhancements.
To avoid some problems mentioned in the better answers above, simply remember to call $(selector).off("click") before binding the next event.
const mainevent = (e)=>{
e.preventDefault();
your event data
.then((e) => {
second event()
})
.catch((error) =>
alert(error.message))
};
}

Javascript changing button and onClick issue

I am trying to use an onClick event in JavaScript and am running into a problem. I want to make a button that changes its id, click handler, and text back and forth when it is clicked - I want it to become a completely different button when clicked the first time, but then revert back to the original button when clicked the second time.
My idea was to write one event handler for the original button being clicked which changes it to the second button and I put this in the function "change()". I also had planned on writing one separate event handler for the new button being clicked which changes it to the original button and I put this in the function "changeBack()".
The problem is that when I click on the original button one time, change() gets called and within it changeBack() automatically gets called exactly when the onClick is defined for the new button and right before the innerHTML is changed. I commented out some of the original lines and put an alert in to illustrate this unwanted behavior. I think somehow the click is still active when the new button gets created, thus forcing it to call changeBack() even though the new button was never clicked. Any help on this would be great. Thank you.
<script type="text/javascript">
function change() {
var x = document.getElementById("button");
x.id = "alternateButton";
x.onClick = changeBack();
x.innerHTML = "Click to Change Me Back";
}
function changeBack() {
var x = document.getElementById("alternateButton");
alert('hi');
//x.id = "button";
//x.onClick = change();
//x.innerHTML = "Click Me";
}
</script>
<button id="button" onClick="change()">Click Me</button>
Events are bound to the elements and not to the ID attribute. Both the handlers are always executed when you click the button.
Also it is a good idea to avoid binding handlers using inline event handlers.
// Find the elemnt
var btn = document.getElementById('button');
// Data attribuet to keep tab of whether it is clicked or not
btn.dataset.clicked = "1";
// Attach event
btn.addEventListener('click', change);
function change() {
var txt = 'Click to Change Me Back';
// Will give you the truthy/falsy value
if(!!this.dataset.clicked) {
this.dataset.clicked = "";
// First implementation
} else {
this.dataset.clicked = "1";
txt = "Click Me";
// The other case
}
this.innerHTML = txt;
}
Check Fiddle
The above comment by Sushanth got me started on the right track by using a truth tester. However, the same problem about the mouse came up - it captures the mouse longer than I want it to (even when using onmousedown). Because of this, right when the new button gets created the old one replaces it, so the new button is never seen. Also, by changing the element's id, I ran into some really strange things such as the program stopping completely if I use an alert - and not continuing after I close the alert, but when I delete the alert, the entire program runs. I guess it's better to leave the ID's alone and only use them as a reference and change the styles dynamically with DOM access rather than the style tag and control other parts of the page using the button by referencing other functions in the switch statement (I'm really new to JavaScript so I'm not sure how else it is done).
Because of these issues but with Sushanth's comment idea, I used two testers: one for which button is currently being shown, and one for the mouse having been pressed or released. I also had some strange issues when putting the code in the header instead of the bottom of the body. Finally, I had to use some custom properties. I hope this helps anybody that wants to use a button that changes its appearance and functionality back and forth as you click on it.
<button id="button1" onmousedown="transformButton1()" onmouseup="release()">Click Me</button>
<p id="one">One</p>
<p id="two">Two</p>
<p id="three">Three</p>
<script type="text/javascript">
var x = document.getElementById("button1");
x["clicked"] = 0;
x["released"] = 1;
function transformButton1() {
var x = document.getElementById("button1");
if (x["released"] == 1) {
switch (x["clicked"]) {
case 0:
x["clicked"] = 1;
x["released"] = 0;
// Other function calls to change other elements on the page, for example:
document.getElementById("two").innerHTML = "I've Changed!!!!!";
x.innerHTML = "Click to Change Me Back";
break;
case 1:
x["clicked"] = 0;
x["released"] = 0;
// Other function calls to change other elements on the page, for example:
document.getElementById("two").innerHTML = "Two";
x.innerHTML = "Click Me";
break;
}
}
}
function release() {
document.getElementById("button1")["released"] = 1;
}
</script>
JSFiddle

Why OnChange Event is not Dispatched When Target Is Manually Set

I'm confused on how JavaScript handles Change Events and am looking for some insight.
Let's say we have two HTML controls; a Checkbox and a Button and I want to use JS to display a message that says how many times the Checkbox has changed from checked to not-checked.
<input type="checkbox" id="cb" />
<button id="btn">Change Checkbox</button>
<div id="msg"></div>
The JS can look something like this:
var count = 0;
var cb = document.getElementById("cb");
var btn = document.getElementById("btn");
var msg = document.getElementById("msg");
cb.addEventListener("change", cb_onChange);
btn.addEventListener("click", btn_onClick);
// Change the state of the Checkbox when user clicks the Button
function btn_onClick() {
cb.checked = !cb.checked;
}
// The state of the Checkbox has changed, so increment the change count and display it
function cb_onChange() {
msg.innerHTML = "Checkbox changed " + count+++" times";
}
Test it out here http://jsfiddle.net/26RWh/
Notice that the OnChange event of the Checkbox is NOT dispatched when the Checkbox is programmatically set at cb.checked = !cb.checked. - i.e. The cb_onChange listener is only executed if/when the user manually clicks the Checkbox.
How come the OnChange event isn't fired when I change the state in code?
This is the way events on input-elements work in javascript.
If you want the callback to be executet you need to manually fire the change-event on the checkbox.
There are questions about this:
do it in pure JavaScript
and with help of jquery
when the browser identifies a change event in checkbox, it sets the checked propery to !checked and calls the subscribed functions which you can assume happens in one function(f1) and which is called when the event occurs. In this case you are not calling the function f1 but just setting the property.

Disable more than one button with a click

I have 4 answer buttons that trigger a tick or a cross to be displayed depending on whether the answer is right or not ("showDiv01"/"showDiv02"), I want to disable all of the buttons after any of them are clicked, so far I can only disable the button that is clicked with "onClick=this.disabled = 'true';".
<button id="none" onClick="showDiv01(); this.disabled = 'true';">Almond White</button><br>
<button id="score" onClick="showDiv02(); this.disabled = 'true';">Raspberry Diva</button<br>
<button id="none" onClick="showDiv01(); this.disabled = 'true';">Melon Sorbet</button><br>
<button id="none" onClick="showDiv01(); this.disabled = 'true';">Gentle Lavender</button><br>
Any solutions?
I would recommend adding a common class to your buttons (for this example, say you btnClass as your class), also, you can use the same function for each button click, no need to create unique functions for buttons doing the same type of behavior:
function showDiv(el) {
//"el" should be "this" passed in to the func
var buttons = document.getElementsByClassName("btnClass");
for (var i = 0; i < buttons.length; i++) {
buttons[i].disabled = true;
}
}
<button id="none" onClick="showDiv(this)"></button>
With this passed in, you have direct access to the element being clicked through the el param in the function. So el.id will result in the ID of the clicked element.
You have showDiv01(); function called on click also. Put there code to disable buttons finding them by id.
Besides I don't think you can have same id for different buttons like "none", I would also consider keeping answer somewhere else than button id.
I would pass some parameter to showDiv01(); function like showAnswerDiv(1); or showAnswerDiv(2);.
This way you could take action based on parameter which is a lot better than making function for valid or invalid answer and pinning it to button.

Categories

Resources