Why doesn't javascript function update DOM on first run - javascript

I have a dynamic form in which users can add inputs by clicking a button. This works fine. However when clicking to remove the input the first click does not remove an input. Every click after removes inputs as expected. I can see that it runs the function on first click to remove but nothing is updated in the DOM so the field stays. Here is my HTML:
<button onclick="AddFileField()">Add File</button>
<br />
<br />
<form action="" method="post" enctype="multipart/form-data">
<div id="fileFields"></div>
<br />
<input type="submit" value="Upload" />
</form>
And the associated javascript:
function removeField() {
$('.removeclass').click(function () {
$(this).parent().remove();
});
return false;
}
var FieldCount = 1; //to keep track of text box added
function AddFileField() {
var MaxInputs = 10; //maximum input boxes allowed
var InputsWrapper = $("#fileFields"); //Input boxes wrapper ID
var x = $("#fileFields > div").length + 1; //current text box count
if (x <= MaxInputs) //max input box allowed
{
$(InputsWrapper).append('<div class="fileInp"><label for="file' + FieldCount + '">File:</label><input type="file" name="files" class="inpinl" id="file' + FieldCount + '" />×</div>');
FieldCount++;
}
return false;
}
A fiddle showing issue. To duplicate add a couple fields then click an x. The first click does nothing, then proceeding clicks removes fields. How can I get the first click to remove the field as well?

It's because you are registering your event handler inside of another event handler.
http://jsfiddle.net/3e1ajtvo/11/
I removed your event handler and now, you pass the clicked element as elem into the function itself.
As a matter of fact you don't even really need the function, as long as jquery is exposed (it is in your case).
http://jsfiddle.net/3e1ajtvo/12/

A working fiddle is here
The issue lies in the function:
function removeField() {
$('.removeclass').click(function () {
$(this).parent().remove();
});
return false;
}
When you click the X, this function is called, which adds a click event handler to the X to remove it; however, this event handler is not called until the next time you click it. (This is why clicking X twice works).
In the updated fiddle, you simply pass this to removeField as such:
//HTML
×</div>
//JS
function removeField(me) {
$(me).parent().remove();
return false;
}

The reason for this is because you are using onclick="removeField()".
Lets take a look at your function. When you click on the remove button the following script will run. This script then creates a click handler, that will activate on next click, because when you first clicked on remove the handler was not created
function removeField() {
$('.removeclass').click(function () {
$(this).parent().remove();
});
return false;
}
So you will need to replace this is another function. Since you are using jQuery you can learn to use .on() for dynamically generated elements.
$(document).on('click', '.removeclass', function () {
$(this).parent().remove();
});
http://jsfiddle.net/Spokey/3e1ajtvo/16/

I made your code a bit more modular and changed it to use jQuery more than you were. This is just another way to do it, the other answers are also valid.
http://jsfiddle.net/3e1ajtvo/19/
var fields = {
btnAdd: $('#addField'),
inputWrapper: $('#fileFields'),
maxInputs: 10,
fieldCount: 1,
init: function(){
this.inputWrapper.on('click', '.removeclass', this.removeInput);
this.btnAdd.on('click', this.appendField);
},
removeInput: function(){
//this will refer to the html element you clicked on
$(this).parent().remove();
},
appendField: function(){
//this will refer to the html element you clicked on
if ( fields.inputWrapper.children('div').length <= fields.maxInputs ){
fields.inputWrapper.append('<div class="fileInp"><label for="file' + fields.fieldCount + '">File:</label><input type="file" name="files" class="inpinl" id="file' + fields.fieldCount + '" />×</div>');
fields.fieldCount++;
}
}
};
fields.init();

You're not executing the code to remove the row on the first click, you're just adding the click handler to the link. It works after that because the $('.removeclass').click(... then fires as expected.

Related

Prevent function execution twice within two triggered events

I have the following code:
myInput.change(function (e) { // this triggers first
triggerProcess();
});
myButton.click(function (e) { // this triggers second
triggerProcess();
});
The problem with the above is when I click myButton both events are triggered and triggerProcess() is fired twice which is not desired.
I only need triggerProcess() to fire once. How can I do that?
Small demo
You can have a static flag that disables any more triggers once the first trigger has occurred. Might look something like this:
var hasTriggered = false;
myInput.change(function (e) { // this triggers first
triggerProcess();
});
myButton.click(function (e) { // this triggers second
triggerProcess();
});
function triggerProcess () {
// If this process has already been triggered,
// don't execute the function
if (hasTriggered) return;
// Set the flag to signal that we've already triggered
hasTriggered = true;
// ...
}
For resetting the hasTriggered flag, that's entirely up to you and how this program works. Maybe after a certain event occurring in the program you'd want to reenable the ability to trigger this event again — all you'd need to do it set the hasTriggered flag back to true.
You can use the mousedown event, which will fire before the input is blurred, and then check if the input has focus by checking if it's the activeElement, and if it does have focus, don't fire the mousedown event, as the change event will fire instead.
Additionally, if you want a mousedown event to occur when the value hasn't changed, and the change event doesn't fire, you'll need a check for that as well
var myInput = $('#test1'),
myButton = $('#test2'),
i = 0;
myInput.change(function(e) { // this triggers first
$(this).data('prev', this.value);
triggerProcess();
});
myButton.mousedown(function(e) { // this triggers second
var inp = myInput.get(0);
if (document.activeElement !== inp || inp.value === myInput.data('prev'))
triggerProcess();
});
function triggerProcess() {
console.log('triggered : ' + (++i))
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="test1">
<br />
<br />
<button id="test2">
Click
</button>
In a fairly typical scenario where you have an input with a button next to ie, eg quick search.
You want to fire when the input changes (ie onblur) but also if the user clicks the button.
In the case where the user changes the input then clicks the button without changing input focus (ie no blur), the change event fires because the text has changed and the click event fires because the button has been clicked.
One option is to debounce the desired event handler.
You can use a plugin or a simple setTimeout/clearTimeout, eg:
$('#inp').change(debounceProcess)
$('#btn').click(debounceProcess);
function debounceProcess() {
if (debounceProcess.timeout != null)
clearTimeout(debounceProcess.timeout);
debounceProcess.timeout = setTimeout(triggerProcess, 100)
}
function triggerProcess() {
console.log('process')
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id="inp">
<button id="btn">Click</button>
Use a real <button>BUTTON</button>. If you click on input text, alert is triggered, then once you leave the input text to click anywhere else, that unfocuses the input text which triggers the change event, so now 2 events have been triggered from the text input.
This is an assumption since the code provided is far from sufficient to give a complete and accurate answer. The HTML is needed as well as more jQuery/JavaScript. What is myInput and myButton actually referring to, etc.?
So I bet if you change...
var myButton = $('{whatever this is}'); and <input type='button'>
...TO:
var myButton = $("button"); and <button></button>
...you should no longer have an event trigger twice for an element.
This is assuming that triggerProcess() is a function that does something that doesn't manipulate the event chain or anything else involving events. This is an entirely different ballgame if instead of click() and change() methods you are using .trigger() or triggerHandler(), but it isn't. I'm not certain why such complex answers are derived from a question with very little info...?
BTW, if myInput is a search box and myButton is the button for myInput, as freedomn-m has mentioned, simply remove:
myButton.click(...
Leave myButton as a dummy. The change event is sufficient in that circumstance.
SNIPPET
var xInput = $('input');
var xButton = $('button'); //«———Add
xInput.on('change', alarm);
xInput.on('click', alarm);
xButton.on('click', alarm);
function alarm() {
return alert('Activated')
}
/* For demo it's not required */
[type='text'] {
width: 5ex;
}
b {
font-size: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id='f1' name='f1'>
<input type='text'>
<input type='button' value='BUTTON TYPE'>
<label><b>⇦</b>Remove this button</label>
<button>BUTTON TAG</button>
<label><b>⇦</b>Replace it with this button</label>
</form>

button onclick does not fire when its position is changed

I have a textbox where onchange event adds some element at runtime. Due to this the submit button's position is changed. If user enters something in the textbox and clicks on the button the onclick event does not fire. I suspect its because at the same time the position of the button changes and browser thinks the click happened on page and not on the button.
Is there a way I can handle this situation? I can not move the button above the element which is added at runtime.
I have created a sample jsfiddle: http://jsfiddle.net/WV3Q8/3/
HTML:
<p>Enter something</p>
<input type="text" id="input" onchange="onChange()">
<div id="log"></div>
<button value="Go" style="display:block" type="button" onclick="submit();" id="btn-submit">Submit</button>
JavaScript:
function onChange(){
var value = $('#input').val();
$('#log').append('<p>New value: ' + value + '</p>');
}
function submit(){
alert('value submitted');
}
Edit 1
Test Case (Question is about 2nd test case) Its happening in all browsers (Chrome, IE 10 etc):
Enter something in the textbox and hit tab, p element is added and button's position is moved. Now click on submit button. An alert is shown.
Enter something in the textbox and click on the submit button. p element is added but the alert is not shown.
Edit 2:
I can not use other key events like keyup, keydown or keypress because of obvious reasons (they fire on every keypress).
setimeout too is out of question since there are some radio buttons which are generated at runtime on the onchange event of textbox. Its no wise to click on submit button without showing these radio buttons to user.
For your edit #2 you have to delay the append with setTimeout() method like this:
setTimeout(function(){
$('#log').append('<p>New value: ' + randomVal + '</p>');
},100);
Fiddle
Working Fiddle
A way out is to use onkeypress
<input type="text" id="input" onkeypress="onChange();">
UPDATE
If it is possible for you to use mousedown event, it work's good.
Updated Fiddle
You are missing a return true statement in onChange()
Here is the code on jsfiddle
function onChange(){
var randomVal = Math.floor((Math.random()*100)+1);
$('#log').append('<p>New value: ' + randomVal + '</p>');
return true;
}
function submit(){
alert('value submitted');
}
EDIT: Alternative solution might be calling onChange() inside submit().
I would use setTimeout with keyup event:
var time;
function onChange() {
clearTimeout(time);
time = setTimeout(function() {
var value = $('#input').val();
$('#log').append('<p>New value: ' + value + '</p>');
}, 200);
}
It will append text once user finishes typing.
Demo: http://jsfiddle.net/WV3Q8/8/
This is not good solution but you can trigger the submit function for your case like this:
function onChange(){
var value = $('#input').val();
$('#log').append('<p>New value: ' + value + '</p>');
submit();
}
function submit(){
alert('value submitted');
}
demo

JQuery focus to previous clicked input bug

I have two input fields. The main idea is that whenever you focus to one of the fields, the button click should print a random number inside it.
My problem is that when you just focus on (click on) the first field, then focus on second (or vice versa), the button click prints to both instead of just to the (last) focused field.
You can try to recreate the problem here: http://jsfiddle.net/sQd8t/3/
JS:
$('.family').focus(function(){
var iD = $(this).attr('id');
$("#sets").one('click',function() {
var ra = Math.floor((Math.random()*10)+1);
$('#'+iD).val(ra);
});
});
HTML:
<center class='mid'>
<input type="text" class="family" id="father" />
<br/><br>
<input type="text" class="family" id="mother" />
<br/>
<br/>
<input type='submit' value='Set text' id="sets"/>
</center>
In the "focus" handler, unbind any existing "click" handler:
$('#sets').unbind('click').one('click', function() { ... });
The way you had it, an additional one-shot "click" handler is bound each time a field gets focus, because jQuery lets you bind as many handlers as you like to an event. In other words, calling .one() does not unbind other handlers. When the click actually happens, all handlers are run.
edit — sorry - "unbind" is the old API; now .off() is preferred.
Put the variable iD outside, and separate the functions:
http://jsfiddle.net/sQd8t/8/
This prevents from adding too many events on each input click/focus.
No need to unbind.
var iD;
$('.family').focus(function() {
iD = $(this).attr('id');
});
$("#sets").on('click', function() {
var ra = Math.floor((Math.random() * 10) + 1);
if (iD!="")$('#' + iD).val(ra);
iD = "";
});
See http://jsfiddle.net/sQd8t/11/
$('.family').focus(function(){
$("#sets").attr('data-target',$(this).attr('id'))
});
$("#sets").click(function() {
var target=$(this).attr('data-target');
if(target){
var ra = Math.floor((Math.random()*10)+1);
$('#'+target).val(ra);
}
});
You can create a data-target attribute which contains the field which must be modified.

JQuery script doesn't work twice

I am trying to create a quiz within a website page. The aim is that every time you press next, a new question will open up within the page. However, calling upon the script a second time doesn't work.
To achieve this, I first created a link called 'next'.
Next
This calls upon a script which opens q1 from addquiz.html
<script>
$("#1").click(function() {
$("#load").load("addquiz.html" + ' #q1');
event.preventDefault();
});
</script>
In this script there is a submit button which calls upon the function goupone, which increases the id of the link by 1 (eg; from 1 to 2)
<div id="q1">
<h3>5 + 19 = ?</h3>
<input type="text" width="6" name="" id="question-1-answers" value="" />
<input type="submit" value="Check" onClick="goupone();" />
</div>
<script>
function goupone(){
var v=document.links[9].id;
vi=parseInt(v);
vi=vi+1;
document.links[9].id=vi;
}
</script>
However, when I click the next button again, nothing happens. Can anyone help?
Since you change the id from 1 to 2, the initial click handler $("#1").click() will no longer be triggered when you click on the anchor. An alternative is to either bind the event handler to an a whose attribute name is next:
<script>
$('a[name="next"]').click(function() {
$("#load").load("addquiz.html" + ' #q1');
event.preventDefault();
});
</script>
Or create a class, say next, add it to a, and use it as selector:
Next
<script>
$('a.next').click(function() {
$("#load").load("addquiz.html" + ' #q1');
event.preventDefault();
});
</script>
However, I'd refactor your entire code to simply use the following instead:
Next
<script>
$("#nextAnchor").on('click', function() {
$("#load").load("addquiz.html#q" + $(this).data("next-id"));
event.preventDefault();
});
</script>
function goupone() {
var $next = $("#nextAnchor");
var currentId = parseInt($next.data("next-id"));
var nextId = currentId + 1;
$next.data("next-id", nextId);
}
Here's a working DEMO.

Knowing the last clicked textbox via Javascript

I have a form and a button.
I need that when I click on a textfield, and then click this particular button, the textbox which was clicked last will change its value to say "BUTTON HAS BEEN CLICKED".
Is there a way via JavaScript how I can know the last textbox which was clicked?
Many thanks in advance.
You need to store a reference to the text box when you click it. The easiest way to do that is to create a global variable for the reference. Then you would update the reference with the textbox's onclick event. Here is an example:
HTML:
<input id="myTextBox" type="text" onclick="updateCurText(this);">
<input type="button" value="click me" onclick="updateText();">
JavaScript:
var currentTextBox = '';
function updateCurText(ele) {
currentTextBox = ele.id;
}
function updateText() {
document.getElementById(currentTextBox).value = 'BUTTON HAS BEEN CLICKED';
}
Live example.
jsumners is correct, however I would probably recommend avoiding global variables, and if you're using something like jQuery you have encapsulate a lot of the logic in a single file:
$(function() {
var lastBox = false, formSelector = "form.myClass";
// Change events
$(formSelector + " input[type='text']").click(function() {
lastBox = this;
});
// Button click
$(formSelector + " button").click(function() {
if (lastBox)
$(lastBox).val("BUTTON HAS BEEN CLICKED");
});
});
live

Categories