How to know whether the mouse is inside the window? - javascript

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

Related

How do we detect a double click outside an element?

I have this function:
this.div.click( function(e) {
...
});
I would like to listen for double clicks outside this element. I know that we can use blur() for clicks outside an element. But I would like to handle only double click events. What's the best way to do this?
You can use the .dblclick() event to listen to the double-click at the body level, and then use it's target attribute and .contains() to see if the click occurred within the div.
Something like this:
// div to check if dbl click did _not_ originate from
var mydiv = jQuery("#mydiv").get(0);
// listen to body for double clicks
$("body").dblclick(function(e) {
// if click target does not fall within #mydiv
if (mydiv !== e.target && $.contains(mydiv, e.target) !== true) {
console.log("outside of mydiv");
}
});
Here is a jsbin demo.
There is another way to do this, by modifying e.originalEvent:
$( "#mydiv" ).dblclick(function(e) {
e.originalEvent.inside = true;
});
$( "body" ).dblclick(function(e) {
if( e.originalEvent.inside ) {
console.log('inside');
} else {
console.log('outside');
};
});
I have updated Johnatan's Bin. Think it should be faster.

Prevent click after focus event

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

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

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 call a function with jQuery blur UNLESS clicking on a link?

I have a small jQuery script:
$('.field').blur(function() {
$(this).next().children().hide();
});
The children that is hidden contains some links. This makes it impossible to click the links (because they get hidden). What is an appropriate solution to this?
This is as close as I have got:
$('.field').blur(function() {
$('*').not('.adress').click(function(e) {
foo = $(this).data('events').click;
if(foo.length <= 1) {
// $(this).next('.spacer').children().removeClass("visible");
}
$(this).unbind(e);
});
});
The uncommented line is suppose to refer to the field that is blurred, but it doesn't seem to work. Any suggestions?
You can give it a slight delay, like this:
$('.field').blur(function() {
var kids = $(this).next().children();
setTimeout(function() { kids.hide(); }, 10);
});
This gives you time to click before those child links go away.
This is how I ended up doing it:
var curFocus;
$(document).delegate('*','mousedown', function(){
if ((this != curFocus) && // don't bother if this was the previous active element
($(curFocus).is('.field')) && // if it was a .field that was blurred
!($(this).is('.adress'))
) {
$('.' + $(curFocus).attr("id")).removeClass("visible"); // take action based on the blurred element
}
curFocus = this; // log the newly focussed element for the next event
});
I believe you can use .not('a') in this situation:
$('.field').not('a').blur(function() {
$(this).next().children().hide();
});
This isn't tested, so I am not sure if this will work or not.

Categories