Cancel an onBlur event in JavaScript? - javascript

I want to set up an onBlur event for an input element that validates the value and, if invalid, "cancels" the blur and refocusses the input. However returning false from onBlur does not cancel the onBlur the way it does with onClick. Is there a solution for this (perhaps using jQuery?)

I don't know of any reliable cross-browser way to do this. Usually setting a small timeout in the onblur event and calling focus() when the timer fires works.
For example:
document.getElementById('your_input_id').onblur = function() {
var self = this;
setTimeout(function() { self.focus(); }, 10);
}

You can call focus() in the handler.
This will sometimes help.

You can accomplish this by using jQuery's focus() function inside a zero-second timeout. Here's an example:
$('#my_input').bind('blur', function(event) {
var $input = $(this);
var is_input_valid = false;
// Code to determine if input is valid
// ...
if (!is_input_valid) {
setTimeout(function() {
$input.focus();
}, 0);
return false;
}
});

Related

Avoid element blur handler when window blur invoked (browser loses focus)

To expound upon the question:
I've got an element which when clicked receives a sub-element. That sub-element is given a blur handler.
What I would like is for that handler not to be invoked when the browser loses focus (on window blur).
Towards that goal I've attempted several tacks, this being my current effort:
function clicked() {
// generate a child element
...
field = $(this).children(":first");
$(window).blur(function () {
field.unbind("blur");
});
$(window).focus(function () {
field.focus();
field.blur(function () {
save(this);
});
});
field.blur(function () {
save(this);
});
}
This doesn't work. What appears to be occurring is that when the browser loses focus, the field is losing focus first.
Nice question!
This is possible, and fairly straightforward.
field.blur(function() {
if(document.activeElement !== this) {
// this is a blur that isn't a window blur
}
});
JSFiddle
Or in vanilla JS:
field.addEventListener('blur', function() {
if(document.activeElement !== this) {
// this is a blur that isn't a window blur
}
});
Edit: Though your answer deals with the browser losing focus, know that Firefox has unusal behavior (bug?) when returning to focus. If you have a input focused, and then unfocus the window, the element's blur is triggered (which is what the question was about). If you return to something other than the input, the blur event is fired a second time.
A mildly dirty way to do this could be to use a setTimeout() prior to taking action.
var windowFocus;
$(window).focus(function() {
windowFocus = true;
});
$(window).blur(function() {
windowFocus = false;
});
function clicked() {
// generate a child element
...
field = $(this).children(":first");
field.blur(function () {
setTimeout(function() {
if (windowFocus) {
save(this);
}
}, 50);
});
}

Firing a handler once for each actual change in an HTML input element

I want to trigger an event handler once per each actual change in an input field. For example, to validate (per keypress) entry of a credit card number (the change must be on each change so debouncing/throttling is not the answer).
I cannot use input alone as IE9 will not trigger this event from backspaces or cut/delete.
I cannot use keyup alone as this does not handle changes from a mouse (eg. pasting).
I cannot use change because this only fires on blur.
I can do $('input').bind('input keyup', handler) but this will fire two separate events most of the time. Assume that the handler is expensive and running it twice is unacceptable.
I can wrap the handler so that it only runs if the current value is different to the last checked but is there a better way?
What you are doing with checking the last input is what you need to do.
This is one way you can do it to store the last value.
function handler(){
var tb = jQuery(this);
var currentValue = tb.val();
if (tb.data("lastInput") !== currentValue) {
tb.data("lastInput", currentValue);
console.log("The current value is " + currentValue);
}
}
$('input').bind('input keyup', handler);
jsFiddle
You could always extend jQuery if you really do not want that logic in your function. It is a bunch more code, but one method.
(function(){
$.fn.oneinput = function(callback) {
function testInput(){
var tb = jQuery(this);
var currentValue = tb.val();
if (tb.data("lastInput") !== currentValue ) {
tb.data("lastInput",currentValue );
if(callback) {
callback.call(this)
};
}
return this;
}
jQuery(this).bind("keyup input", testInput);
};
}(jQuery));
$('input').oneinput( function(){ console.log(this.value); });
​
jsfiddle
I think the you have to use setInterval to moniter the change in the text box
try this demo
objTextBox = document.getElementById("trackChange");
oldValue = objTextBox.value;
console.log(oldValue);
function track_change()
{
if(objTextBox.value != oldValue)
{
oldValue = objTextBox.value;
console.log("changed")
}
}
setInterval(function() { track_change()}, 100);
Note: I don't personally think that this is the best solution.But I cant find a better and at leat it will work for sure in every case keyboard or mouse change ;)
Try this
$('input').bind('keyup cut paste', function (event) {
console.log('value changed');
});
Fiddle http://jsfiddle.net/sXvK2/1/
If you don't need the handler to return a value, you can make it return false so that it doesn't fire up a second time.
What about
$el.bind('input', handler);
$el.bind('keyup', handler);
...

Get the newly focussed element (if any) from the onBlur event.

I need to get the newly focussed element (if any) while executing an onBlur handler.
How can I do this?
I can think of some awful solutions, but nothing which doesn't involve setTimeout.
Reference it with:
document.activeElement
Unfortunately the new element isn't focused as the blur event happens, so this will report body. So you are gonna have to hack it with flags and focus event, or use setTimeout.
$("input").blur(function() {
setTimeout(function() {
console.log(document.activeElement);
}, 1);
});​
Works fine.
Without setTimeout, you can use this:
http://jsfiddle.net/RKtdm/
(function() {
var blurred = false,
testIs = $([document.body, document, document.documentElement]);
//Don't customize this, especially "focusIN" should NOT be changed to "focus"
$(document).on("focusin", function() {
if (blurred) {
var elem = document.activeElement;
blurred = false;
if (!$(elem).is(testIs)) {
doSomethingWith(elem); //If we reached here, then we have what you need.
}
}
});
//This is customizable to an extent, set your selectors up here and set blurred = true in the function
$("input").blur(function() {
blurred = true;
});
})();​
//Your custom handler
function doSomethingWith(elem) {
console.log(elem);
}
Why not using focusout event? https://developer.mozilla.org/en-US/docs/Web/Events/focusout
relatedTarget property will give you the element that is receiving the focus.

How to write onshow event using JavaScript/jQuery?

I have an anchor tag on my page, I want an event attached to it, which will fire when the display of this element change.
How can I write this event, and catch whenever the display of this element changes?
This is my way of doing on onShow, as a jQuery plugin. It may or may not perform exactly what you are doing, however.
(function($){
$.fn.extend({
onShow: function(callback, unbind){
return this.each(function(){
var _this = this;
var bindopt = (unbind==undefined)?true:unbind;
if($.isFunction(callback)){
if($(_this).is(':hidden')){
var checkVis = function(){
if($(_this).is(':visible')){
callback.call(_this);
if(bindopt){
$('body').unbind('click keyup keydown', checkVis);
}
}
}
$('body').bind('click keyup keydown', checkVis);
}
else{
callback.call(_this);
}
}
});
}
});
})(jQuery);
You can call this inside the $(document).ready() function and use a callback to fire when the element is shown, as so.
$(document).ready(function(){
$('#myelement').onShow(function(){
alert('this element is now shown');
});
});
It works by binding a click, keyup, and keydown event to the body to check if the element is shown, because these events are most likely to cause an element to be shown and are very frequently performed by the user. This may not be extremely elegant but gets the job done. Also, once the element is shown, these events are unbinded from the body as to not keep firing and slowing down performance.
You can't get an onshow event directly in JavaScript. Do remember that the following methods are non-standard.
IN IE you can use
onpropertychange event
Fires after the property of an element
changes
and for Mozilla
you can use
watch
Watches for a property to be assigned
a value and runs a function when that
occurs.
You could also override jQuery's default show method:
var orgShow = $.fn.show;
$.fn.show = function()
{
$(this).trigger( 'myOnShowEvent' );
orgShow.apply( this, arguments );
return this;
}
Now just bind your code to the event:
$('#foo').bind( "myOnShowEvent", function()
{
console.log( "SHOWN!" )
});
The code from this link worked for me: http://viralpatel.net/blogs/jquery-trigger-custom-event-show-hide-element/
(function ($) {
$.each(['show', 'hide'], function (i, ev) {
var el = $.fn[ev];
$.fn[ev] = function () {
this.trigger(ev);
return el.apply(this, arguments);
};
});
})(jQuery);
$('#foo').on('show', function() {
console.log('#foo is now visible');
});
$('#foo').on('hide', function() {
console.log('#foo is hidden');
});
However the callback function gets called first and then the element is shown/hidden. So if you have some operation related to the same selector and it needs to be done after being shown or hidden, the temporary fix is to add a timeout for few milliseconds.

Detect which form input has focus using JavaScript or jQuery

How do you detect which form input has focus using JavaScript or jQuery?
From within a function I want to be able to determine which form input has focus. I'd like to be able to do this in straight JavaScript and/or jQuery.
document.activeElement, it's been supported in IE for a long time and the latest versions of FF and chrome support it also. If nothing has focus, it returns the document.body object.
I am not sure if this is the most efficient way, but you could try:
var selectedInput = null;
$(function() {
$('input, textarea, select').focus(function() {
selectedInput = this;
}).blur(function(){
selectedInput = null;
});
});
If all you want to do is change the CSS for a particular form field when it gets focus, you could use the CSS ":focus" selector. For compatibility with IE6 which doesn't support this, you could use the IE7 library.
Otherwise, you could use the onfocus and onblur events.
something like:
<input type="text" onfocus="txtfocus=1" onblur="txtfocus=0" />
and then have something like this in your javascript
if (txtfocus==1)
{
//Whatever code you want to run
}
if (txtfocus==0)
{
//Something else here
}
But that would just be my way of doing it, and it might not be extremely practical if you have, say 10 inputs :)
I would do it this way: I used a function that would return a 1 if the ID of the element it was sent was one that would trigger my event, and all others would return a 0, and the "if" statement would then just fall-through and not do anything:
function getSender(field) {
switch (field.id) {
case "someID":
case "someOtherID":
return 1;
break;
default:
return 0;
}
}
function doSomething(elem) {
if (getSender(elem) == 1) {
// do your stuff
}
/* else {
// do something else
} */
}
HTML Markup:
<input id="someID" onfocus="doSomething(this)" />
<input id="someOtherID" onfocus="doSomething(this)" />
<input id="someOtherGodForsakenID" onfocus="doSomething(this)" />
The first two will do the event in doSomething, the last one won't (or will do the else clause if uncommented).
-Tom
Here's a solution for text/password/textarea (not sure if I forgot others that can get focus, but they could be easily added by modifying the if clauses... an improvement could be made on the design by putting the if's body in it's own function to determine suitable inputs that can get focus).
Assuming that you can rely on the user sporting a browser that is not pre-historic (http://www.caniuse.com/#feat=dataset):
<script>
//The selector to get the text/password/textarea input that has focus is: jQuery('[data-selected=true]')
jQuery(document).ready(function() {
jQuery('body').bind({'focusin': function(Event){
var Target = jQuery(Event.target);
if(Target.is(':text')||Target.is(':password')||Target.is('textarea'))
{
Target.attr('data-selected', 'true');
}
}, 'focusout': function(Event){
var Target = jQuery(Event.target);
if(Target.is(':text')||Target.is(':password')||Target.is('textarea'))
{
Target.attr('data-selected', 'false');
}
}});
});
</script>
For pre-historic browsers, you can use the uglier:
<script>
//The selector to get the text/password/textarea input that has focus is: jQuery('[name='+jQuery('body').data('Selected_input')+']')
jQuery(document).ready(function() {
jQuery('body').bind({'focusin': function(Event){
var Target = jQuery(Event.target);
if(Target.is(':text')||Target.is(':password')||target.is('textarea'))
{
jQuery('body').data('Selected_input', Target.attr('name'));
}
}, 'focusout': function(Event){
var Target = jQuery(Event.target);
if(Target.is(':text')||Target.is(':password')||target.is('textarea'))
{
jQuery('body').data('Selected_input', null);
}
}});
});
</script>
You only need one listener if you use event bubbling (and bind it to the document); one per form is reasonable, though:
var selectedInput = null;
$(function() {
$('form').on('focus', 'input, textarea, select', function() {
selectedInput = this;
}).on('blur', 'input, textarea, select', function() {
selectedInput = null;
});
});
(Maybe you should move the selectedInput variable to the form.)
You can use this
<input type="text" onfocus="myFunction()">
It triggers the function when the input is focused.
Try
window.getSelection().getRangeAt(0).startContainer

Categories