jQuery blur event fired twice in Chrome - javascript

I created a simple 'infinite' form with input fields.
Every time an empty input is focused it creates a new one, and on blur of an empty input field, the field is removed.
See example here
I use the following code to make it all happen:
var $input = $('<div/>').html( $('<input/>').addClass('value') );
$('form').append( $input.clone() );
$('form').on( 'focus', 'input.value', function(e) {
// Add new input if the focused one is empty
if(!$.trim(this.value).length) {
$('form').append( $input.clone() );
}
}).on( 'blur', 'input.value', function(e) {
var $this = $(this);
if( !$.trim(this.value).length ) {
console.log('REMOVING INPUT');
$this.parent().remove();
} else {
$this.attr('name', 'item-'+$this.val());
}
});
The problem is however, that in Chrome the blur event is fired twice when I switch to another application (⌘tab). This gives an error, because it is not possible to remove the node, since it's already gone:
Uncaught Error: NOT_FOUND_ERR: DOM Exception 8
Firefox seems to work fine.
So why is the blur event fired twice and how can I prevent that from happening?
EDIT - Tried the answer in this question, but no luck. Still get the error message in Chrome, what am I doing wrong?
See updated fiddle
Is there a way to check if the element still exists? Because the second time blur fires the node is removed. $(this).length still is non-zero though.

Please check if this fiddle is having the behaviour as you need it,
http://jsfiddle.net/EPxkh/8/
http://www.quirksmode.org/js/introevents.html
http://www.quirksmode.org/js/events_order.html
http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html

This looks like a bug in Blink, there is a bug report about that on Chromium project's page:
http://code.google.com/p/chromium/issues/detail?id=253253

Related

How to call a function when default browser autocomplete list item selected [duplicate]

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.

Fire event with right mouse click and Paste

I want to fire an event in a textarea immediately after paste some text inside the textarea. I can do that when Shift+Ins is used; however, I cannot do it when right mouse button and then paste (from the drop down menu) is chosen. Keyup fires after Shift+Ins. None of the rest fires when Paste is chosen after right mouse button clicking... What do I have to do?
<textarea name="message" id="message"></textarea>
$("#message").on('keyup contextmenu', function(event) {
alert("ok");
});
http://jsfiddle.net/f29vuwoL/7/
Thank you
Most browsers support the input event, which is fired when something is pasted or otherwise added, regardless of how:
$("#message").on('keyup contextmenu input', function(event) {
alert("ok");
});
Updated Fiddle
Note that using input is the most general method, firing when the control gets input regardless of how, and so if you hook multiple events (as above), you'll get multiple calls for the same input. For instance, if you hook both keyup and input, on browsers that support input, you'll get two calls. Similarly for paste and input when the user pastes, on browsers that support both.
If you need to support browsers that don't have either input or paste, I'm afraid the unfortunate answer is that you need to poll. Still, polling every (say) 250ms isn't asking the browser to do that much work, and you can feature-detect whether it's necessary:
var message = $("#message");
var events = null;
var previous;
if ('oninput' in message[0]) {
// Browser supports input event
events = "input";
} else if ('onpaste' in message[0]) {
// Browser supports paste event
events = "paste keyup contextmenu";
}
if (!events) {
// Ugh, poll and fire our own
events = "pseudoinput";
previous = message.val();
setInterval(function() {
var current = message.val();
if (current != previous) {
previous = current;
message.trigger(events);
}
}, 250);
}
console.log("Using: " + events);
message.on(events, function(e) {
console.log("Got event: " + e.type);
});
Updated Fiddle
You should use input event callback. See the demo here
You can use the dedicated paste event:
$("#message").on('paste', function(event) {
alert("ok");
});
Updated jsFiddle
However you might want to check browser support - I don't think jQuery normalizes this event.
If you need IE support, it might be a little more difficult, but it depends on your requirements - does it absolutely need to be a paste action? If not, TJ Crowder's answer is the way to go.
The on input is useful if you want to detect when the contents of a textarea, input:text, input:password or input:search element have changed, because the onchange event on these elements fires when the element loses focus, not immediately after the modification.The oninput event is supported in Internet Explorer from version 9.
$("#message").on('input propertychange', function() {
console.log($(this).val());
});
Fiddle

IE9 Not allowing inputs within button tags

In Internet Explorer 9, which I understand supports the function addEventListener, is giving me a strange error when I try to use the function here:
function addEvent(evnt, elem, func) {
if (elem.addEventListener) // W3C DOM
elem.addEventListener(evnt,func,false);
else if (elem.attachEvent) { // IE DOM
elem.attachEvent("on"+evnt, func);
}
else { // No much to do
elem[evnt] = func;
}
}
(Courtesy of another question here on SO)
I get the error:
SCRIPT5007: Unable to get the value of the property 'addEventListener': object is null or undefined.
It breaks on the line if(elem.addEventListener)
I am passing it document.getElementById('search'), which is a text input field; for evnt, I am passing it keydown, and for function I am passing:
function(e) {
if (!e)
{
var e = window.event;
}
// Enter is pressed
if (e.keyCode == 13)
{
search($("#search").val());
$("#search").val("");
$("#search").blur();
}
}
I have no problems with this in Chrome, Firefox, or Safari, but IE9 is giving me grief.
Edit
Okay I've gotten the JS to run properly by putting the eventlistener in inline, but I am still getting a problem, which appears to be the parent problem behind the whole thing here: document.getElementById('search') is returning null only in IE. It works in every other browser, and it is only this one element that is returning null.
Edit 2 - I've updated the question title to reflect the true problem here.
So the root of the problem now is that the <input> is not showing up in the HTML at all (though it does show up in the source code)...? I have the input field inside of a <button>, which works in every other browser perfectly, but not in IE. How can I fix this?
It is not valid to have an <input> inside a <button> consider putting it inside a <label> instead, or a <span> with a click handler and suitable CSS.

jquery - field selects all text then unselects it on focus

trying to figure out why this is happening - I have an input text field and I want all the text to be highlighted when the field receives focus. This happens, very quickly, and then all of the text is unselected. Any idea why this would occur? Here's the code I'm using:
$("#permalink").focus(function(){
this.select();
});
You need to override the mouseup event on the input element (as mentioned in this post - thanks MrSlayer!)
See here for example: http://jsfiddle.net/f8TdX/
This is an issue in WebKit. The best option is to use a combination of the focus and mouseup events. The following comes from another answer to a similar question.
$("#permalink").focus(function() {
var $this = $(this);
$this.select();
window.setTimeout(function() {
$this.select();
}, 1);
// Work around WebKit's little problem
$this.mouseup(function() {
// Prevent further mouseup intervention
$this.unbind("mouseup");
return false;
});
});
Give this a shot
$(document).ready(function() {
$("input:text").focus(function() { $(this).select(); } );
});
Select all contents of textbox when it receives focus (JavaScript or jQuery)

focus doesn't work in IE

i have the following function
function change()
{
var input = document.getElementById('pas');
var input2 = input.cloneNode(false);
input2.type = 'password';
input.parentNode.replaceChild(input2,input);
input2.focus();
}
but focus() doesn't work in ie7, so what can i do!
i want to have the cursor inside of input!
thanks
update
great solution, thanks, but now it doesn't work in opera:(
For IE you need to use a settimeout function due to it being lazy, for example:
setTimeout(function() { document.getElementById('myInput').focus(); }, 10);
From http://www.mkyong.com/javascript/focus-is-not-working-in-ie-solution/
For opera, this may help:
how to set focus in required index on textbox for opera
UPDATE:
The following snippet of code handles the case when the element is unavailable and retries after a short period - perfect for slow loading pages and/or elements not available until some time after.
setTimeout(
function( ) {
var el = document.getElementById( "myInput" ) ;
( el != null ) ? el.focus( ) : setTimeout( arguments.callee , 10 ) ;
}
, 10 ) ;
We hit the same issue. For focusing we are using General function which is applying settimeout solution mentioned in:
http://www.mkyong.com/javascript/focus-is-not-working-in-ie-solution/
with 100 milliseconds.
Still on some screens it's not working properly. Especially when iframes are included.
There is another known and similar IE issue:
IE 9 and IE 10 cannot enter text into input text boxes from time to time ->
IE 9 and IE 10 cannot enter text into input text boxes from time to time
What I have noticed is when you have focus, without pointer, you can apply workaround by pressing TAB key (focus on next element) and than SHIFT+TAB which will return to our target element with focus and typing pointer.
In order to be sure we can type inside input we focus on random element and then on our target input.
$('body').focus();
n.focus();
So we applied the same solution in javascript/JQuery in our general focus function.
So there is an if statement
...
if($.browser.msie) {
setTimeout(function() { try {
$('body').focus(); //First focus on random element
$(n).focus(); //Now focus on target element
} catch (e) { /*just ignore */ } }, 100); //See http://www.mkyong.com/javascript/focus-is-not-working-in-ie-solution/
} else { //Standard FF, Chrome, Safari solution...
...
To be sure since there is big regression we are still keeping solution with settimeout as a backup.
Tested on IE10, IE11, Firefox 45, Chrome 49.0.2623.87
IE7 does not support the focus() method. I don't see any method.
I've had the same issue and was able to get IE to work using code behind by making a SetInitialFocus function and calling it in my PageLoad function.
Take a look at the following example and give it a shot, it worked for me.
http://www.cambiaresearch.com/c4/df9f071c-a9eb-4d82-87fc-1a66bdcc068e/Set-Initial-Focus-on-an-aspnet-Page.aspx
function change() {
var input = document.getElementById('pas');
var input2 = input.cloneNode(false);
input2.type = 'password';
input.parentNode.replaceChild(input2, input);
setTimeout(function () {
input2.focus();
}, 10);
}
In Case you are looking to set focus in 1st input element of last row in table.Name of my div where i have kept my table is tableDiv and i am setting focus to last row's 1st inputtext
setTimeout(function(){
$($('#tableDiv tr:last').find('input[type=text]')[0]).focus();
},2);
#Bojan Tadic THANK YOU!
Below Code did the trick :)
$('body').focus(); //First focus on random element
I think the issue comes up when you use input and a placeholder. Managed so solved this thanks to this answer, I was missing that $(body).focus. Made this code to run only on IE so that all my inputs can be freely accessed by 'tabbing'. Previously when I had only tabIndex on my inputs I was able to move to the next one but focus wasn't complete and couldn't write anything in it.
This is complete code.
$('input[name^="someName"]').on('keydown', function(e){
var keyCode = e.which || e.keyCode;
if(keyCode === 9){
e.preventDefault();
$('body').focus();
var nextTabIndex = parseInt($(this).attr("tabIndex"));
nextTabIndex++;
setTimeout(function(){$('input[tabIndex=' + nextTabIndex +']')[0].focus();},20);
}
});
Its is very easy using jQuery, not sure why you are doing it the hard way :)
In this example I have a class assigned to the input field I want the initial focus set called initFocus. You can use any selector you want to find your element. from your code I would use $("#pas").focus();
$(".initFocus").focus();

Categories

Resources