Create onchange event with javascript in Firefox - javascript

I've been working on trying to trigger an onchange listener with java script in Mozilla Firefox. I've found a lot on Stack Overflow posted about this, but nothing seems to be working for my unique case.
I've created this HTML with a onchange listener from an onchange event using this helpful post (JavaScript OnChange Listener position in HTML markup). Here's my code:
<HTML>
<head>
<script type="text/javascript">
window.onload= function () {
if(window.addEventListener) {
document.getElementsByClassName('search-box')[0].addEventListener('change', loadXMLDoc, false);
} else if (window.attachEvent){
document.getElementsByClassName('search-box')[0].attachEvent("onchange", loadXMLDoc);
}
function loadXMLDoc(){
alert('It worked');
}
}
function addTextCallListener() {
var searchBox = document.getElementsByClassName("search-box")[0];
searchBox.value = "Hello";
}
</script>
</head>
<BODY>
<input type="text" class="search-box" placeholder="Player Search">
<br \>
<button type="button" onclick="addTextCallListener()">Click Me!</button>
</BODY>
</HTML>
I also saved it as this jsfiddle (for some reason I had to keep it all together for it to work, I couldn't break it up into js and html).
https://jsfiddle.net/josephfedor42/crogL0zd/1/
If you play with this jsfiddle you can see that entering text and pressing enter will trigger the listener and the pop up with the message “It worked” will appear.
But if the button “Click Me!” is pressed it only changes the value of the text box, and the onchange listener is not called.
I realize I could easily add an onchange event to this button. But I want to to trigger the listener by programatically/ superficially using javascript in my addTextCallListener() function.
I've tried the simple stuff, like calling
searchBox.onchange();
searchBox.focus();
searchBox.click();
And a combination of these to add and remove the focus. But it doesn't seem to work. I've found quite a few posts on triggering an onchange event, but nothing that works in Firefox.
Any help would be appreciated.
Thanks for that link of a possible duplicated question. I had checked out that link before.
But I gave it a try again. I saved the jsfiddle from them both and neither one work.
My implementation of Dorian's answer
https://jsfiddle.net/josephfedor42/zaakd3dj/
My implementation of Alsciende's answer
https://jsfiddle.net/josephfedor42/xhs6L6u2/

emphasize mine
According to the mdn page about the change event,
The change event is fired for <input>, <select>, and <textarea>
elements when a change to the element's value is committed by the
user.
and to whatwg specs :
When the input and change events apply (which is the case for all
input controls other than buttons and those with the type attribute in
the Hidden state), the events are fired to indicate that the user has
interacted with the control.
Therefore, setting the value of an input is not an action "committed by the user" nor a sign that "the user has interacted with the control", since it was made by the code.
So, even if the specifications for this event are kind of unclear, the event should not fire when you change its value by code.

Something like this should work:
function addTextCallListener() {
var searchBox = document.getElementsByClassName("search-box")[0];
searchBox.value = "Hello";
//fire the event
if (document.createEvent) {
searchBox.dispatchEvent('change');
} else {
searchBox.fireEvent("onchange");
}
}

Here is the code I needed to add to my function addTextCallListener:
var evObj = document.createEvent('HTMLEvents');
evObj.initEvent( 'change', true, true );
searchBox.dispatchEvent(evObj);
I updated the jsfiddle. The working code is here https://jsfiddle.net/josephfedor42/crogL0zd/7/

Replace onchange with change in this part:
document.getElementsByClassName('search-box')[0].attachEvent("onchange", loadXMLDoc);

Related

onchange not firing when date of input type="date" is clear as first action

I have a type="date" input that onchange fires some JS. My problem is that if you want to clear the date with the "cross button" on the right of the input tag, it will not fire the onchange event, unless you have previously changed the value. It seems really weird to me. My question: can I fire JS when my first action is clicking the "cross button" that delete the date?
I'm using Firefox 58.0.1
Edit: Now if working as expected (sept 2020, Firefox 80.0.1)
function myFunction(IdTag) {
var x = document.getElementById(IdTag).value;
alert('The new value is: '+x);
}
<input type="date" id="MyID" value="2018-02-06" onchange="myFunction('MyID');">
Worked for me.
I created an html file with this content:
<html>
<head></head>
<body>
<input type="date" id="MyID" value="2018-02-06" onchange="myFunction('MyID');">
<script>
function myFunction(IdTag) {
var x = document.getElementById(IdTag).value;
alert('The new value is: '+x);
}
</script>
</body>
</html>
And the event fired and also cleared the date (which was set to MM/DD/YYYY).
Make sure you're not seeing any errors in the Developer Tools.
I had this same issue as well (FF 64.0.1 on Linux) and I solved it by utilising the 'mousedown' event.
Essentially when the mousedown event triggers set up a timer that will manually trigger the onchange on your date input after a certain time, I found 500ms was sufficient for my use case.
I am using jQuery and got it to work, the process should be fairly similar for native JS:
$('input[name="start_date"]').on('mousedown',function() {
var $this = $(this);
setTimeout(function(){ $($this).trigger('change'); }, 500);
});
I had the same problem, and after some research i figured out that there is already a unconfirmed bug Report at Mozilla Bugtracker.
I am using jQuery and my solution was to call focus and blur after binding the even
$('#datefield').on('change', someFunction).focus().blur();
because the bug only appears if someone clicks on the reset button before giving the input the focus. By set and remove the focus to the input, the user does not recognize anything and the bug is bypassed.

Disabled button still fires using ".click()"

It seems disabled button "onclick" function is still fired when triggering it programmaticaly, eg:
<div>
<input type="button" onclick="save()" id="saveButton" value="save" disabled="disabled" />
<input type="button" onclick="byPassDisabled()" value="bypass disabled button"/>
<div id="counter">0</div>
function save(){
var count = parseInt($('#counter').html());
$('#counter').html(++count);
}
function byPassDisabled(){
$('#saveButton').click();
}
see http://jsfiddle.net/WzEvs/363/
In my situation, keyboards shortcuts are bound to functions triggering the ".click()" on buttons. I'll find it very annoying to have to disable the shorcuts or check if the button is disabled myself. I'd prefer a general solution fixing this problem.
But why? This behavior doesn't seem fair to me.
Any workaround?
The attribute only disables user interaction, the button is still usable programmatically.
So yeah, you gotta check
function byPassDisabled(){
$('#saveButton:enabled').click();
}
Alternatively don't use inline handlers.
$(document).on('click', '#saveButton:enabled', function(){
// ...
});
For future use...the OP code works because jQuery will still call it's own handlers even if the DOM element is disabled. If one were to use vanilla javascript, the disabled attribute would be honored.
const element = document.getElementById('saveButton');
element.click() //this would not work
You can programmatically trigger click on a disabled button.
There are ways to find if the event is a click on button by user or it has been trigger programmatically. http://jsfiddle.net/WzEvs/373/
$(function () {
$("#saveButton").on('click', function (e) {
if (!e.isTrigger) {
var count = parseInt($('#counter').html());
$('#counter').html(++count);
}
});
$("#bypassButton").on('click', function (e) {
$("#saveButton").click();
});
});
e.isTrigger is true if you call the click() programmatically. Basically you are triggering the click event manually in code.
You can trigger click still although made it disable .As Spokey said it just shows the user-interaction(the usability still persists that can be turned on programmatically) .
off or unbind the click will solve this issue.
Thanks

How do I properly capture an onchange or onkeyup event for a dynamically inserted 'input' text element?

I have a bit of JavaScript that builds some HTML for me and inserts it into a div. I am using jQuery 1.7.2 for this test.
I'm interested in attaching a custom change or keyup event handler on an input text field called gene_autocomplete_field.
Here's what I have tried so far.
The following function builds the HTML, which is inserted into a div called gene_container:
function buildGeneContainerHTML(count, arr) {
var html = "";
// ...
html += "<input type='text' size='20' value='' id='gene_autocomplete_field' name='gene_autocomplete_field' placeholder='Enter gene name...' /><br/>";
// ...
return html;
}
// ...
$('#gene_container').html( buildGeneContainerHTML(count, geneNameArr) );
In my calling HTML, I grab the gene_autocomplete_field from the gene_container element, and then I override the keyup event handler for gene_autocomplete_field:
<script>
$(document).ready(function() {
$("#gene_container input:[name=gene_autocomplete_field]").live('keyup', function(event) {
refreshGenePicker($("#gene_container input:[name=gene_autocomplete_field]").val());
});
});
</script>
When I change the text in gene_autocomplete_field, the refreshGenePicker() function just sends an alert:
function refreshGenePicker(val) {
alert(val);
}
Result
If I type any letter into the gene_autocomplete_field element, the event handler seems to call alert(val) an infinite number of times. I get one alert after another and the browser gets taken over by the dialog boxes. The value returned is correct, but I worry that refreshGenePicker() gets called over and over again. This is not correct behavior, I don't think.
Questions
How do I properly capture the keyup event once, so that I only handle a content change to the autocomplete field the one time?
Is there a different event I should use for this purpose?
UPDATE
It turns out that more than just a keyCode of 13 (Return/Enter) can be an issue — pressing Control, Alt, Esc or other special characters will trigger an event (but will be asymptomatic, as far as the infinite loop issue goes). The gene names I am filtering on do not have metacharacters in them. So I made use of an alphanumeric detection test to filter out non-alphanumeric characters from further event handling, which includes the Return key:
if (!alphaNumericCheck(event.keyCode)) return;
alert is called infinite times because you use the 'Enter' key to confirm/dismiss the alert. Use .on('change') instead. This will prevent refreshGenePicker from being called when you use enter in an alert.
JSFiddle demonstration using keyup (Click on OK to prevent infinite alerts).
JSFiddle demonstration using change
However, the 'change' event will only trigger if the input element looses focus. If you want to use refreshGenePicker on every key, use the following approach instead:
$("#gene_container input:[name=gene_autocomplete_field]").live('keyup', function(event) {
if(event.keyCode === 13) // filter ENTER
return;
refreshGenePicker($("#gene_container input:[name=gene_autocomplete_field]").val());
});
This will filter any incoming enter keyup events (jsFiddle demo). Also switch to .on and drop .live.
EDIT: Note that there are more possibilities to dismiss an alert modal, such as the escape or space key. You should add a check inside your refreshGenePicker whether the value has actually changed.
You should really use .on() if you are using jQuery > 1.7.
Check out the perftest.
And also check out my some what related question.
Also when testing equal you should really add quotes around it:
input:[name='gene_autocomplete_field']
To answer you real question :). It shouldn;t behave like that with the code you have presented. Maybe something else is wrong. Can you setup a jsfiddle with the issue?
Check out my demo and perhaps you see what's wrong with your code:
function refreshGenePicker(value) {
console.log('keyup! Value is now: ' + value);
}
(function($) {
var someHtml = '<input type="text" name="gene_autocomplete_field">';
$('body').append(someHtml);
$('body').on('keyup', 'input[name="gene_autocomplete_field"]', function(e) {
refreshGenePicker($(this).val());
});
})(jQuery);​
$(document).ready(function() {
$('#test').html('<input id="text" />');
$('#text').keyup(function() {
console.log($(this).val());
});
});​
This works just fine. Since you've got our second code block in <script> tags, you might be running it more than once - which would cause it to bind more than once and produce more than one alert each time it is bound. You could of course use .unbind() on that input before adding the keyup, but I think a much better solution would be to group all the code in a single $(document).ready(); to ensure you're only binding the object once.
http://jsfiddle.net/Ka7Ty/2/

Any event triggered on autocomplete?

I have a pretty simple form. When the user types in an input field, I want to update what they've typed somewhere else on the page. This all works fine. I've bound the update to the keyup, change and click events.
The only problem is if you select an input from the browser's autocomplete box, it does not update. Is there any event that triggers when you select from autocomplete (it's apparently neither change nor click). Note that if you select from the autocomplete box and the blur the input field, the update will be triggered. I would like for it to be triggered as soon as the autocomplete .
See: http://jsfiddle.net/pYKKp/ (hopefully you have filled out a lot of forms in the past with an input named "email").
HTML:
<input name="email" />
<div id="whatever"><whatever></div>
CSS:
div {
float: right;
}
Script:
$("input").on('keyup change click', function () {
var v = $(this).val();
if (v) {
$("#whatever").text(v);
}
else {
$("#whatever").text('<whatever>');
}
});
I recommending using monitorEvents. It's a function provide by the javascript console in both web inspector and firebug that prints out all events that are generated by an element. Here's an example of how you'd use it:
monitorEvents($("input")[0]);
In your case, both Firefox and Opera generate an input event when the user selects an item from the autocomplete drop down. In IE7-8 a change event is produced after the user changes focus. The latest Chrome does generate a similar event.
A detailed browser compatibility chart can be found here:
https://developer.mozilla.org/en-US/docs/Web/Events/input
Here is an awesome solution.
$('html').bind('input', function() {
alert('test');
});
I tested with Chrome and Firefox and it will also work for other browsers.
I have tried a lot of events with many elements but only this is triggered when you select from autocomplete.
Hope it will save some one's time.
Add "blur". works in all browsers!
$("input").on('blur keyup change click', function () {
As Xavi explained, there's no a solution 100% cross-browser for that, so I created a trick on my own for that (5 steps to go on):
1. I need a couple of new arrays:
window.timeouts = new Array();
window.memo_values = new Array();
2. on focus on the input text I want to trigger (in your case "email", in my example "name") I set an Interval, for example using jQuery (not needed thought):
jQuery('#name').focus(function ()
{
var id = jQuery(this).attr('id');
window.timeouts[id] = setInterval('onChangeValue.call(document.getElementById("'+ id +'"), doSomething)', 500);
});
3. on blur I remove the interval: (always using jQuery not needed thought), and I verify if the value changed
jQuery('#name').blur(function ()
{
var id = jQuery(this).attr('id');
onChangeValue.call(document.getElementById(id), doSomething);
clearInterval(window.timeouts[id]);
delete window.timeouts[id];
});
4. Now, the main function which check changes is the following
function onChangeValue(callback)
{
if (window.memo_values[this.id] != this.value)
{
window.memo_values[this.id] = this.value;
if (callback instanceof Function)
{
callback.call(this);
}
else
{
eval( callback );
}
}
}
Important note: you can use "this" inside the above function, referring to your triggered input HTML element. An id must be specified in order to that function to work, and you can pass a function, or a function name or a string of command as a callback.
5. Finally you can do something when the input value is changed, even when a value is selected from a autocomplete dropdown list
function doSomething()
{
alert('got you! '+this.value);
}
Important note: again you use "this" inside the above function referring to the your triggered input HTML element.
WORKING FIDDLE!!!
I know it sounds complicated, but it isn't.
I prepared a working fiddle for you, the input to change is named "name" so if you ever entered your name in an online form you might have an autocomplete dropdown list of your browser to test.
Detecting autocomplete on form input with jQuery OR JAVASCRIPT
Using: Event input. To select (input or textarea) value suggestions
FOR EXAMPLE FOR JQUERY:
$(input).on('input', function() {
alert("Number selected ");
});
FOR EXAMPLE FOR JAVASCRIPT:
<input type="text" onInput="affiche(document.getElementById('something').text)" name="Somthing" />
This start ajax query ...
The only sure way is to use an interval.
Luca's answer is too complicated for me, so I created my own short version which hopefully will help someone (maybe even me from the future):
$input.on( 'focus', function(){
var intervalDuration = 1000, // ms
interval = setInterval( function(){
// do your tests here
// ..................
// when element loses focus, we stop checking:
if( ! $input.is( ':focus' ) ) clearInterval( interval );
}, intervalDuration );
} );
Tested on Chrome, Mozilla and even IE.
I've realised via monitorEvents that at least in Chrome the keyup event is fired before the autocomplete input event. On a normal keyboard input the sequence is keydown input keyup, so after the input.
What i did is then:
let myFun = ()=>{ ..do Something };
input.addEventListener('change', myFun );
//fallback in case change is not fired on autocomplete
let _k = null;
input.addEventListener( 'keydown', (e)=>_k=e.type );
input.addEventListener( 'keyup', (e)=>_k=e.type );
input.addEventListener( 'input', (e)=>{ if(_k === 'keyup') myFun();})
Needs to be checked with other browser, but that might be a way without intervals.
I don't think you need an event for this: this happens only once, and there is no good browser-wide support for this, as shown by #xavi 's answer.
Just add a function after loading the body that checks the fields once for any changes in the default value, or if it's just a matter of copying a certain value to another place, just copy it to make sure it is initialized properly.

Checkbox inside an anchor click behavior

Consider following snippet:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
</head>
<body>
<form>
<a id="a" href="http://google.com">Goooooogle</a>
</form>
<script>
$(function() {
var checkbox = $('<input type="checkbox"></input>');
checkbox.prependTo($('#a'));
checkbox.click(function(e) {
e.stopPropagation();
// do something useful
});
});
</script>
</body>
</html>
I want to get a checkbox inside <a>, and get following on-click behavior:
Toggle check mark normally as usual
Do something useful like AJAX-request
Stay on this page, i.e. not be redirected to an a href
Also I want to not override default behavior if I click anywhere in a, but not on checkbox. I.e. I want to allow to execute all event handlers associated with a click itself.
I thought that should be pretty easy, but I can't get desired behavior. Either:
I get redirected to Google if I put a code provided.
I don't get check mark toggled if I use e.preventDefault() of return false;. Furthermore in that case checkbox ignores explicit checkbox.attr('checked', 'checked') and all other possible ways to set the check mark.
Where is the catch?
UPD: This works as expected in Chrome, e.g. I'm not redirected on click, but fails in Firefox. Is there cross-browser way?
Well, it looks like a known Firefox bug, which leads to following link on checkbox click regardless of handlers' code. As a bit dirty workaround one can use:
var checkbox = $('<input type="checkbox"></input>');
checkbox.prependTo($('#a'));
checkbox.click(function(e) {
setTimeout(function() { checkbox.prop('checked', !checkbox.prop('checked')); }, 10);
// do something useful on clicking checkbox and but not surrounding link
return false;
});
I know this is an old question but some may still be curious since it was never really fully answered without a messy hack or workaround. All you have to do is simply check where the event's target originated.
So using your example (jsfiddle):
// Don't change pages if the user is just changing the checkbox
$("#a").click(function(e) {
//e.preventDefault(); // Optional if you want to to keep the link from working normally
alert("Click came from: " + e.target.tagName);
if (e.target.tagName != "INPUT") {
// do link
alert("Doing link functionality");
} else {
// do something useful
alert("Doing checkbox functionality");
}
});
I Know this question is over 5 years old, but I had the same issue recently and the work-around I found was to add an onclick function to the checkbox and in that function call event.stopImmediatePropagation().
from w3schools: "The stopImmediatePropagation() method prevents other listeners of the same event from being called"
ie...the anchor.
function checkbox_onclick(event){
event.stopImmediatePropagation();
}
here's a modified script
var checkbox = $('<input type="checkbox"></input>');
var a = $('#a');
a.unbind("click").click(function(e) {
e.preventDefault();
checkbox.attr('checked', !checkbox.attr('checked'));
});
checkbox.prependTo(a);
checkbox.click(function(e) {
e.stopPropagation();
// do something useful
});
i unbind the click event on the <a> and rebind it with a event to check/uncheck the checkbox and also prevent the default.

Categories