Prevent click after focus event - javascript

When user clicks on input field, two consecutive events are being executed: focus and click.
focus always gets executed first and shows the notice. But click which runs immediately after focus hides the notice. I only have this problem when input field is not focused and both events get executed consecutively.
I'm looking for the clean solution which can help me to implement such functionality (without any timeouts or weird hacks).
HTML:
<label for="example">Example input: </label>
<input type="text" id="example" name="example" />
<p id="notice" class="hide">This text could show when focus, hide when blur and toggle show/hide when click.</p>
JavaScript:
$('#example').on('focus', _onFocus)
.on('blur', _onBlur)
.on('click', _onClick);
function _onFocus(e) {
console.log('focus');
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
$('#notice').removeClass('hide');
}
function _onClick(e) {
console.log('click');
$('#notice').toggleClass('hide');
}
function _onBlur(e) {
console.log('blur');
$('#notice').addClass('hide');
}
UPDATED Fiddle is here:

I think you jumbled up the toggles. No need to prevent propagation and all that. Just check if the notice is already visible when click fires.
Demo: http://jsfiddle.net/3Bev4/13/
Code:
var $notice = $('#notice'); // cache the notice
function _onFocus(e) {
console.log('focus');
$notice.removeClass('hide'); // on focus show it
}
function _onClick(e) {
console.log('click');
if ($notice.is('hidden')) { // on click check if already visible
$notice.removeClass('hide'); // if not then show it
}
}
function _onBlur(e) {
console.log('blur');
$notice.addClass('hide'); // on blur hide it
}
Hope that helps.
Update: based on OP's clarification on click toggling:
Just cache the focus event in a state variable and then based on the state either show the notice or toggle the class.
Demo 2: http://jsfiddle.net/3Bev4/19/
Updated code:
var $notice = $('#notice'), isfocus = false;
function _onFocus(e) {
isFocus = true; // cache the state of focus
$notice.removeClass('hide');
}
function _onClick(e) {
if (isFocus) { // if focus was fired, show/hide based on visibility
if ($notice.is('hidden')) { $notice.removeClass('hide'); }
isFocus = false; // reset the cached state for future
} else {
$notice.toggleClass('hide'); // toggle if there is only click while focussed
}
}
Update 2: based on OP's observation on first click after tab focus:
On second thought, can you just bind the mousedown or mouseup instead of click? That will not fire the focus.
Demo 3: http://jsfiddle.net/3Bev4/24/
Updated code:
$('#example').on('focus', _onFocus)
.on('blur', _onBlur)
.on('mousedown', _onClick);
var $notice = $('#notice');
function _onFocus(e) { $notice.removeClass('hide'); }
function _onClick(e) { $notice.toggleClass('hide'); }
function _onBlur(e) { $notice.addClass('hide'); }
Does that work for you?

Setting a variable for "focus" seems to do the trick : http://jsfiddle.net/3Bev4/9/
Javascript:
$('#example').on('focus', _onFocus)
.on('click', _onClick)
.on('blur', _onBlur);
focus = false;
function _onFocus(e) {
console.log('focus');
$('#notice').removeClass('hide');
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
focus = true;
}
function _onClick(e) {
console.log('click');
if (!focus) {
$('#notice').toggleClass('hide');
} else {
focus = false;
}
}
function _onBlur(e) {
console.log('blur');
$('#notice').addClass('hide');
}

If you want to hide the notice onBlur, surely it needs to be:
function _onBlur(e) {
console.log('blur');
$('#notice').addClass('hide'); // Add the hidden class, not remove it
}
When doing this in the fiddle, it seemed to fix it.

The code you have written is correct, except that you have to replae $('#notice').removeClass('hide'); with $('#notice').addClass('hide');
Because onBlur you want to hide so add hide class, instead you are removing the "hide" calss.
I hope this is what the mistake you have done.
Correct if I am wrong, Because I don't know JQuery much, I just know JavaScript.

you can use many jQuery methods rather than add or move class:
Update: add a params to deal with the click function
http://jsfiddle.net/3Bev4/23/
var showNotice = false;
$('#example').focus(function(){
$('#notice').show();
showNotice = true;
}).click(function(){
if(showNotice){
$('#notice').show();
showNotice = false;
}else{
showNotice = true;
$('#notice').hide();
}
}).blur(function(){
$('#notice').hide();
});

Related

Onlick event not triggering which contains blur function

I have a form and on click on an input, I'm adding classes to that input's wrapped div.
To do this, I've made use of blur and executing my function on click. However, on some cases (very rarely) it will work (and add the class). But majority of the time, it doesn't perform the click action (because the console.log("click") doesn't appear).
My thinking is that maybe the browser is conflicting between the blur and click. I have also tried changing click to focus, but still the same results.
Demo:
$(function() {
var input_field = $("form .input-wrapper input");
$("form .input-wrapper").addClass("noData");
function checkInputHasValue() {
$(input_field).on('blur', function(e) {
var value = $(this).val();
if (value) {
$(this).parent().closest(".input-wrapper").removeClass("hasData noData").addClass("hasData");
} else {
$(this).parent().closest(".input-wrapper").removeClass("hasData noData").addClass("noData");
}
});
}
$(input_field).click(function() {
checkInputHasValue();
console.log("click");
});
});
i've done some modification in your code .
function checkInputHasValue(e) {
var value = $(e).val()
if (value) {
$(e).parent().closest(".input-wrapper").removeClass("hasData noData").addClass("hasData");
} else {
$(e).parent().closest(".input-wrapper").removeClass("hasData noData").addClass("noData");
}
}
$(document).on('blur',input_field, function(e) {
checkInputHasValue($(this));
});
$(document).on("click",input_field,function() {
checkInputHasValue($(this));
console.log("click");
});
In order to avoid conflits between events, you would separate the events and your value check. In your code, the blur event may occur multiple times.
The following code seems ok, as far as I can tell ^^
$(function() {
var input_field = $("form .input-wrapper input");
$("form .input-wrapper").addClass("noData");
function checkInputHasValue(el) {
let target = $(el).closest(".input-wrapper");
var value = $(el).val();
$(target).removeClass("hasData noData");
$(target).addClass(value.length == 0 ? "noData" : "hasData");
console.log("hasData ?", $(target).hasClass("hasData"));
}
$(input_field).on("click", function() {
console.log("click");
checkInputHasValue(this);
});
$(input_field).on("blur", function() {
checkInputHasValue(this);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="input-wrapper">
<input>
</div>
</form>

How to trigger an event when the user clears the text field and focus out of the text field using Jquery?

I need to write an event handler when user clears the text field and moves out of focus from the same.
I'm using the following function to catch "focus out" event.
$("input[type=text]").blur(function () {
}
I have the followingfunction to capture clear field event.
$("input[type=text]").keyup(function() {
if (!this.value) {
}
}
I tried using the keyup() function inside blur() since I need to capture the focus out and then clear field. This is how my code looks like:
$("input[type=text]").blur(function () {
$(this).keyup(function() {
if (!this.value) {
}
}
}
But it doesn't work. Clear field event is triggered even before focus is out of the field. Also, it is triggering the event multiple times. What is the problem here?
I think that is more simple:
$('input').on('blur', function(e) {
if(!$(this).val()) {
// IS NO VALUE IN THE INPUT
$(this).trigger('blur'); // trigger the blur event
}
});
Here you are:
$("input[type=text]").on('blur', function() {
alert('blur');
});
$("input[type=text]").on('input', function() {
if (!$(this).val()) {
alert("input nothing");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
Hope this helps.

jQuery Keydown/Keyup only works every second time

I have keyup/down events binded to the document. The Keydown will only fires every second time, without me knowing why. I tried many suggestions given on similar SO-Questions, but none of them works.
My Javascript:
$(document).on('keyup', function() {
$('div').removeClass('bar');
});
$(document).on('keydown', function(e) {
if(e.altKey) {
$('div').addClass('bar'); // only every second hit will add the class
}
});
This should point out the issue:
http://jsfiddle.net/6yxt53m9/1/
You need to add return false; to the key press functions:
$(document).on('keyup', function() {
$('div').removeClass('bar');
return false;
});
$(document).on('keydown', function(e) {
if(e.altKey) {
$('div').addClass('bar');
}
return false;
});
Updated fiddle.
use
$(document).on('keyup', function(e) {
$('div').removeClass('bar');
e.preventDefault();
});
e.preventDefault(); will reset the input
Try this.
$(document).on('keydown', function(e) {
e.preventDefault();
if(e.altKey) {
$('div').addClass('bar'); // only every second hit will add the class
}
});
The reason is alt key occurs focus moving to button of "customize and control google chorome"

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);
});
}

How to know whether the mouse is inside the window?

I can't seem to find the answer.
I have a mouseleave event, in which I want to check, when the event fired, whether the mouse is currently inside the window or not (if not, it can be the tab bar of the browser, back button, etc).
var cursorInPage = false;
$(window).on('mouseout', function() {
cursorInPage = false;
});
$(window).on('mouseover', function() {
cursorInPage = true;
});
$('#some_element').on("mouseleave",function(){
if(cursorInPage === true){
//Code here runs despite mouse not being inside window
}
});
Can I bind to a window mouseleave event? If you leave the outside scope of the document/window, does such an event fire? The above code has a problem since i believe the mouseleave of the element fires before the window
I'm not really sure what you're asking us to put for "what to write here?", but you can simply set a boolean:
var cursorInPage = false;
$(window).on('mouseout', function() {
cursorInPage = false;
});
$(window).on('mouseover', function() {
cursorInPage = true;
});
Then use that boolean to proceed:
if (cursorInPage === true) {
alert('Woo, the cursor is inside the page!');
}
Here's an example JSFiddle which changes the body background colour when the cursor enters or leaves the window area, better displayed when looking at the full-screen result.
just tested this hope it helps. heres the jsFiddle for it.
$(document,window,'html').mouseleave(function(){alert('bye')}).mouseenter(function(){alert('welcome back!')})
You can try :
$('body').mouseout(function() {
alert('Bazzinga...');
});
or
$(window).mouseleave(function() {
alert('Bazzinga...');
});
When mouse is inside element
$('#outer').mouseover(function() {
$('#log').append('<div>Handler for .mouseover() called.</div>');
});
When mouseleave element
$('#outer').mouseleave(function() {
$('#log').append('<div>Handler for .mouseleave() called.</div>');
});

Categories