onclick event not firing after onchange event - javascript

Does anyone know how to make a simple JavaScript onclick event fire if the process of clicking the element causes an onchange event to fire elsewhere on the page? I've created a very simple page to demonstrate this problem:
<html>
<body>
<input type="text" name="test" id="test1" onchange="return change(event);" />
Bang
Boom
<script type="text/javascript">
function change(event) {
alert("Change");
return true;
}
function bang() {
alert("Bang!");
return true;
}
function boom() {
alert("Boom!");
return true;
}
</script>
</body>
</html>
If you click the bang link you get the Bang! alert. Boom gives you the Boom alert. And if you enter text in the text field and tab out you get the Change alert. All well and good.
However, if you enter text in the text field and, without tabbing or clicking anything else first, click either Bang or Boom you get the Change alert and nothing else. I would expect to see the Change alert followed by either Bang or Boom.
What's going on here? My change event returns true. How can I ensure that my click event is fired?

Okay... So it seems like it's time for a bit of an explanation.
Explanation
You encounter this error because the onchange event is triggered as soon as focus is moved away from the element. In your example the action that takes focuse away from the input element is the mousedown event which triggers as you click down on the mouse. This means that when you mousedown on the link it fires off the onchange function and pops up the alert.
The onclick event on the other hand is triggered on the mouseup event (i.e. when you release the pressure on the mouse - prove this to yourself by click, hold/pause, release on a onlcick event). Back to your situation... Before the mouseup (i.e. onclick) happens the focus is moved to the alert triggered from your onchange function.
Fix
There are a couple of options to fix this. Most simple change from using onclick="...." to onmousedown="....".
Alternatively, you could use setTimeout like,:
function change() {
setTimeout(function (){
alert("Change event")
}, 100)
}
I suggest the onmousedown method as preferred. The setTimeout method will fail if you click and hold on the link for more than the prescribed amount on the timeout.

The problem is that the alert() function grabs the event chain somehow, test this:
<html>
<body>
<input type="text" name="test" id="test1" onchange="return change(event);" />
Bang Boom
<script type="text/javascript">
function change(event) {
console.log("change");
return true;
}
function bang() {
console.log("bang");
return true;
}
function boom() {
console.log("boom");
return true;
}
</script>
</body>
As you'll see you'll get the expected behaviour in the console.
JSBin

Rather than try and replicate your problem, I just created the solution in jsFiddle.
I seperated your HTML and your JavaScript.
HTML
<input type="text" name="test1" id="test1" />
Bang
Boom
JavaScript
var test1 = document.getElementById("test1");
var test2 = document.getElementById("test2");
var test3 = document.getElementById("test3");
test1.onchange = function (event) {
alert("Change");
};
test2.onclick = function () {
alert("Bang!");
};
test3.onclick = function () {
alert("Boom!");
};
After making a change in the text box and click out side of it will trigger the onchange event, and the onclick events will still fire. If you are expecting the change alert to fire for each key stroke change onchange to onkeyup.

Related

Javascript popup keeps coming back even I click OK

I have a textbox subscribed to 2 events. oninput and onblur. Both events have a javascript popup. The issue is that when oninput opens the popup, onblur event is triggered and opens up another popup, which is expected. But I can not click away from the second popup.
Why is it happening ? What is the best solution.
JS Fiddle here
function TestBlur() {
alert('Blur');
}
function TestInput() {
var x = $("#TextboxComments").val();
if (x == 'test') {
alert('input');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js">
</script>
<input type="text" Id="TextboxComments" onblur="TestBlur();" oninput="TestInput();">

onClick vs onFocus on input element

To move focus on the end of inputs when user click the input box,
I use something like this,
$(function() {
$('#test-input').on('click', function(evt) {
$target = $(evt.target);
var val = $target.val();
$target.val('').val(val);
});
}())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="test" id="test-input" value="abcdefgh" />
But if I change the 'click' to 'focus', it doesn't work.
$(function() {
$('#test-input').on('focus', function(evt) {
$target = $(evt.target);
var val = $target.val();
$target.val('').val(val);
});
}())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="test" id="test-input" value="abcdefgh" />
How different onClick and onFocus actions in that case?
There's some differences:
onClick: This event is fired whenever the user clicks in an object, like a button, an image, an input... After the click, then comes the:
onFocus: This event is fired when an element is selected, it doesn't need to be clicked, it can be done programmatically, calling .focus() or using the Tab key, for example. Also, using onfocus instead of onclick, can help to avoid bubbling.
To finish, use the snippet below (I added more inputs, cycle through it with TAB (or click too), you'll see the caret going to end on all of then.
Why I added a timeout?
Chrome Browser has an odd quirk where the focus event fires before the cursor is moved into the field, so, the event must wait to the cursor to get there before moving it to the end.;
$(function() {
$('.test-input').on('focus', function(evt) {
that = this;
setTimeout(function() {
that.selectionStart = that.selectionEnd = 10000;
}, 1);
});
}())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="test" class="test-input" value="abcdefgh" />
<input type="text" name="test" class="test-input" value="a1b2c3" />
<input type="text" name="test" class="test-input" value="abcdefghijklmnop" />
Extra:
If you are programming just for mobiles, will be nice to take a look at touchEvents (https://developer.mozilla.org/pt-BR/docs/Web/Events/touchstart)
This should be working just fine the first time you click on the textbox. This is when the focus event is triggered, since you're actually 'focusing on' the item. From then on, until you click anywhere outside the element, your item will already have the focus and therefore will not execute the onfocus event.
The main difference is focus event call any time when you will focus on input field like if you use tab button and focused on input field but in case of click you need to click on input field.
I think that it has to do with the fact that the code executed at the click is executed before focusing on the input and affecting a position to the cursor.
On the other hand, when you listen to the focus event, the cursor has already a position and stays at this position.
That's pure personal theory. However, if you want to make it work, I found a great solution that works in Chrome on this question: Use JavaScript to place cursor at end of text in text input element
You need to clear the value of the input, wait for one millisecond, and reapply the value:
$(function() {
$('#test-input').on('focus', function(evt) {
$target = $(evt.target);
var val = $target.val();
$target.val('');
setTimeout(() => {
$target.val(val)
},1)
});
})

Returning focus on blur with inputs, which have same class

I have on one page many inputs, which have same class and dont have ID.
Attached to bind event of class selector, for returning focus if condition is true.
But when click in another input- focus not return.
Think then 'cause in another element work blur, but dont know how need solve this.
<input class="test" value="">
<input class="test" value="">
$(document).ready(function(){
if (condition) {
// return focus - not work
$(".test").blur(function(){
setTimeout(function() {
$(this).focus();
}, 100);
});
}
});
There are two problems here.
First, once the setTimeout function executes this is now the window object instead of one of the inputs. Store the reference to the original this as part of the blur handler.
Second, the condition check should be moved. As it sits now, you will effectively be forced to never leave an input box once you blur it because the blur handler has been attached and always re-focuses. I don't know what your condition is so I am going to place it in the setTimeout callback. It could also go before the setTimeout creation.
Here's a verbose demo fiddle of an assumed implementation. Below is a watered down example:
<input class="test" value="">
<input class="test" value="">
$(document).ready(function(){
// return focus - not work
$(".test").blur(function(){
var that = this;
setTimeout(function() {
if (condition) {
$(that).focus();
}
}, 100);
});
});
The condition should be in blur event, see this fiddle: http://jsfiddle.net/UudLV/1/
It returns focus to the last focused input if the inputs value is empty.
$(".test").blur(function() {
if($(this).val().length === 0) { //Your condition, can be anything
$(this).focus(); //Return focus
}
});
Return the focus to the last focused element has nothing to do with the selector. The on blur event passes the last focused element to the callback function as context, therefore, this will be the element.
Edit*
I'm not entirely sure this is what OP wants to do.

Firefox onchange not calling function

I have a form that contains input:
<input onchange="checkDomain(true); return false;" type="text" id="dsearch" value="" name="domain" maxlength="30"/>
Which works just fine in Opera, Chrome and IE - but Firefox and Safari are having problems with calling the function checkDomain(). I added a line into the function for debugging:
function checkDomain(check)
{
console.log('checkDomain() called!');
// do rest of the stuff...
}
So, Chrome/Opera/IE calls the function with no problem after you enter text and click somewhere else - but Firefox/Safari doesn't. Anyone have a clue?
I cannot remember where I read it, but you should use .keydown()/.keyup()/.keypress() (whatever suits your needs) instead of onchange. At least for input[type=text].
you can use .blur() and .focus for their respective purposes too.
Seeing this in your question: "after you enter text and click somewhere else", makes me conclude you need the .blur() function.
$("input[type=text]").blur(function(){
console.log('checkDomain() called!')
});
maybe onblur is best for this:
<input onblur="checkDomain(true); return false;" type="text" id="dsearch" value="" name="domain" maxlength="30"/>
This problem happens when you change the behavior of your input keypress and key down.
You need to manually call the onchange trigger to fire it.
As an example consider you have a jQuery function for your inputs which do some stuff when user clicks on keyboard.
You need to call input.trigger("onchange"); to make sure the onchange is fired after keypress and keydown
/**
* Keyboard Manager
*/
(function($) {
$.fn.inputManager = function(options) {
};
options = $.extend(defaults, options);
// The key down event only use to manage key board language changes
var keyDown = function(e) {
//Do something
};
var keyPress = function(e) {
//Do something
};
return this.each(function() {
var input = $(this);
//The Firefox dose not trigger the input onchange when you change keypress and key down
//functions. So manually call it!
input.keypress(function(e) {
keyPress(e);
input.trigger("onchange");
});
input.keydown(function(e) {
keyDown(e);
input.trigger("onchange");
});
});
};
})(jQuery);

Button onclick doesn't fire after onchange input-field when user immediately clicks the button

I have an input text with an onchange event that calls a function in which an alert box displays. I also have a button whose onclick calls a different function. If the user makes a change in the input text and immediately clicks the button, the onchange event fires, displaying the alert box, but the code in the function for the onclick of the button doesn't execute. I've read that this has something to do with event bubbling, but I haven't seen any solutions. Is there a solution? Is it even possible?
Here is a little example:
<input type = "text" onchange = "showAlert1()">
<input type = "button" id = "al2" value = "Click Here" onclick = "showAlert2()">
<script type = "text/javascript">
function showAlert1()
{
alert("ONE")
}
function showAlert2()
{
alert ("TWO");
}
</script>
The onclick event handler showAlert2() doesn't fire if a change is made to the input value and user immediately clicks the button.
I want, that you write something to the input-field, click IMMEDIATELY the button and it fires
alert("ONE") AND alert("TWO")...
OR ONLY
alert("TWO")
As far as I can tell it's not a problem with bubbling (which is a problem with onchange but is a red herring in this case). The problem is that clicking the button after changing the field value is triggering blur, causing showAlert1() to run before the button's onclick gets triggered.
Here's a quick example of it working the way you described but you'll see it's an unreliable hack more than anything. Basically it buffers the execution of each function so that the button's onclick can be triggered. However it falls over if you click and hold the button longer than the buffer that is set within each function via setTimeout().
function showAlert1() {
setTimeout(function(){ alert("ONE") }, 250);
}
function showAlert2() {
setTimeout(function(){ alert("TWO") }, 250);
}
Demo: jsfiddle.net/5rTLq
how about this
function showAlert1(a) {
alert(a.value); /* use setTimeout to delay */
}
function showAlert2() {
alert(document.getElementById('txt').value);
}
test: http://jsfiddle.net/C3jRr/2/

Categories

Resources