I need to group tooltips about errors showed by jQuery Validator. So I have written simple loop with setInterval to check if in the same row are more than one input with error class.
setInterval(function() {
$('.xrror').remove();
$('div.row-4:has([name].error)').each(function() {
var tmp = $('[name].error', this);
if(tmp.length > 1) {
$('label.error', this).hide();
tmp.last().parent().append(
$(document.createElement('label')).addClass('error').addClass('xrror').append(
$(document.createElement('span')).text('Fields with errors were marked with red color')
)
);
} else {
$('[name].error', this).parent().find('label.error').show();
}
});
}, 50);
And in Opera it's causing blinking on opened Select element.
Instead of using a setInterval function every 50 miliseconds, which will consume a lot of resources, you should bind your function on events like submit, or change. As it seems to be related to a form validation, you do not need to do anything unless the user modify a field.
Related
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.
$("#id_address_input").bind("blur",function(e){
//do a lot of stuff, set variables.
});
So, I have a text box that when the user gets off of it...this thing gets fired and processes.
Ok, the problem is this:
When the user clicks the form Submit button, this blur thing gets fired. And in the middle of processing, the form submits. This messes everything up.
How do I fix this?
I thought about adding a delay on form.submit, so that it'll finish processing. But, that's a bad idea because I haven idea how fast the user's browser and/or Google Maps is.
In your blur handler, you must be doing something that "yields" to the browser (a setTimeout, an asynchronous ajax call, etc.), because otherwise, the browser will not interrupt your JavaScript code to submit the form. See below for an example proving it.
If you are doing something that yields to the browser from within the blur handler, you'll have to prevent the form submission with a submit handler and then have it get submitted when everything (including the various actions in the blur handler) is ready. This may be a bit complicated.
The best answer is to remove whatever it is in the blur handler that's yielding to the browser. If you can't do that, you're probably looking at a locking counter on the form and having the submission handler check that locking counter:
// Somewhere, ensure the form has a lock count of zero
$('#theForm').data('submitlock', 0);
// Your blur handler increments the lock
// In the blur handler:
$('#theForm').data('submitlock', $('#theForm').data('submitlock') + 1);
// ...and when done
$('#theForm').data('submitlock', $('#theForm').data('submitlock') - 1);
// The submit handler might look something like this:
$('#theForm').submit(function() {
// Get a jQuery wrapper for the form
var $this = $(this);
// Locked?
if ($this.data('submitlock') > 0) {
// Yes, set up the recheck and prevent form submission
setTimeout(recheck, 10);
return false;
}
// Function to periodically retry submission
function recheck() {
// Still locked?
if ($this.data('submitlock') > 0) {
// Keep waiting
setTimeout(recheck, 10);
}
else {
// Nope, submit the form using the underlying DOM object's submit function
$this[0].submit();
}
}
});
Live example (a version of our blocking example below, but updated to yield to the browser)
Beware that if your form is being submitted to a new window, you may run afoul of pop-up blockers (since the new window isn't in direct response to a user click). But if you're not doing something like that, you're in good shape with the above.
Here's an example of a blur handler causing a substantial delay (four seconds) before the form is submitted (live copy):
HTML:
<form action='http://www.google.com/search' target='_new'>
<label>Search for:
<input type='text' name='q' value='foo'></label>
<br><input type='submit' value='Search'>
</form>
JavaScript:
$('input[name=q]').blur(function() {
var end, counter;
display("Start blurring");
counter = 0;
end = new Date().getTime() + 4000;
while (new Date().getTime() < end) {
++counter;
if (counter % 100000 == 0) {
display("Still blurring");
}
}
display("Done blurring");
});
Put your cursor in the text box, and then click Search. You'll see a four-second delay, and then the search will open in a new window. I've tested this on Chrome, Firefox, and Opera (on Linux), IE6 on Windows 2000, and IE7 on Windows XP. All behaved the same way.
Do your form submit using javascript. Write a function which calls on onsubmit and check to see if the things that were supposed to happen on blur event have finished. Then only submit your form
Try a flag?
var doSubmit = true;
$("#id_address_input").bind("blur",function(e){
doSubmit = false;
//do a lot of stuff, set variables.
doSubmit = true;
});
$("#form").submit(function(){
if(doSubmit){
return true;
}else{
// keep checking until doSubmit is true
window.setInterval(function(){if(doSubmit){$("#form").submit();}},1000);
return false;
}
});
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();
I have some text inputs which I'm validating when a user tabs to the next one. I would like the focus to stay on a problematic input after showing an alert. I can't seem to nail down the correct syntax to have JQuery do this. Instead the following code shows the alert then focuses on the next text input. How can I prevent tabbing to the next element after showing an alert?
$('input.IosOverrideTextBox').bind({
blur: function(e) {
var val = $(this).val();
if (val.length == 0) return;
var pval = parseTicks(val);
if (isNaN(pval) || pval == 0.0) {
alert("Invalid override: " + val);
return false;
}
},
focus: function() {
$(this).select();
}
});
I don't like forced focus, but can't you just focus after the blur takes place?
element.focus();
If doing that in the blur event doesn't always work (I'm not sure exactly when it fires, before or after the actual blur takes place), a redundant timeout will do, as well: setTimeout(function () { element.focus() }, 0).
But please don't do this. Heck, you should never be using alert or any kind of modal dialog for a web interface, either. How about adding a invalid class to the form field, putting a message off to the side of it, and disabling submit until all fields are valid? That's a much less invasive solution that allows me to fill out the form in whatever way is best for me, rather than whatever way is simplest for you.
You can do this with the validation plugin by default.
focusInvalid default: true
Focus the last active or first invalid element on submit via validator.focusInvalid(). The last active element is the one that had focus when the form was submitted, avoiding to steal its focus. If there was no element focused, the first one in the form gets it, unless this option is turned off.
Then you'd only need to have the focus event handler do your select and let the plugin handle validation.
I have an input text login/password, i use a label which i display inside the input, when the input takes the focus, the label is hidden, when the input it is blurred if the value is not equal to "" the label is displayed again, it works great using the focus() / blur() functions, but, how could i handle the browser auto filling, because the change() function won't work, since the focus is never gained, is there a way to handle this ?
I don't want to disable autocomplete by setting it to off, i think, it is not really user friendly to this.
I thought to use a timer, every n ms but i would have like to use a better method.
Any ideas ?
Here is my script :
$('#form-login input.inputbox').focus(
function()
{
$('#label-' + $(this).attr('id')).addClass('hidden');
}
);
$('#form-login input.inputbox').blur(
function()
{
if ($(this).val() == "")
{
$('#label-' + $(this).attr('id')).removeClass('hidden');
}
}
);
There are several jQuery plugins that already do this; I recommend this one.
To answer your question (if you really want to reinvent the wheel), are you talking about autocomplete or saved logins?
If you're talking about autocomplete, it will only happen when the field is focused (AFAIK), so you don't need to worry.
If you're talking about saved logins, I believe that they will be filled in either before or just after the page finishes loading, so you can check on page load (or 1 second later with setTimeout) whether the field is empty.
HTML5 has a new placeholder attribute to do this, but browsers don't support it yet.
By the way, instead of giving each label an ID, you can use the following selector:
$('label[for='" + $(this).attr('id') + "'])
I did this before and used window.onload. I'd recommend creating two functions that handle the 'focus' and 'blur' functionality, which you can call from several places.
function inputFocus( elem )
{
// hide the label
}
function inputBlur( elem )
{
// show the label
}
window.onload = function()
{
// get username/password values first
if ( username.length > 0 ) {
// call inputFocus with jQuery object
}
if ( password.length > 0 ) {
// call inputFocus with jQuery object
}
}