Jquery - techniques for extending 'perimeter' for mouseout? - javascript

I would like to implement behaviour such that a mouseover/hover event is triggered when the mouse pointer hovers over a certain div, but such that the mouseout event tiggers not when the pointer leaves the div, but when it leaves the area 10px ourside the div.
Is there any way of achieving this that doesn't involve creating a larger parent div to bind the mouseout event to?

My comment got me interested to see if it was possible and it's actually quite easy. No idea how well it would run in different browsers and with lots of divs but it works in this example:
http://jsbin.com/exulef/2/edit
var hello = $('#hello');
var position = hello.offset();
var height = hello.height();
var width = hello.width();
$(document).mousemove(function(e) {
if (hello.data('inside')) {
if ((e.pageX < position.left - 10 || e.pageX > position.left + width + 10) ||
(e.pageY < position.top - 10 || e.pageY > position.top + height + 10)) {
hello.text(position.top + " : " + position.left + " : " + e.pageX + " : " + e.pageY + " Outside")
.data('inside', false);
}
}
else {
if ((e.pageX > position.left && e.pageX < position.left + width) &&
(e.pageY > position.top && e.pageY < position.top + height)) {
hello.text(position.top + " : " + position.left + " : " + e.pageX + " : " + e.pageY + " Inside")
.data('inside', true);
}
}
});
hello is just a square div. Would be quite easy to turn into a plugin as well which I might do later, lol.
Edit - I did make this into a plugin in the end: http://jmonkee.net/wordpress/2011/09/07/jquery-extended-hover-plugin/

There is a way to do that without an external div, but it imply that your div will have a margin even when not hovered.
It uses the fact that the padding is inside the div, and the margin is outside.
When nothing happens, we have a margin, we have to go inside the div to hover.
When it's hovered, the margin becomes padding, this way we're inside the div for a little bit more when the mouse leaves the div.
When we're leaving the padding, it's back to margin.
The css is something like:
.a{
margin:10px;
}
div.b{
padding:10px;
margin:0;
}
Note that it's important to have a b selector that's a bit more specific in order to have it apply without using important and without taking attention of the order.
The js would be:
$(".a").bind("mouseenter",function(){
$(this).addClass("b");
}).bind("mouseleave",function(){
$(this).removeClass("b");
});
Example here: http://jsfiddle.net/ynecV/

Hmm, I would go with wrapping desired div in another one and binding mouseout on it - it would be most reliable solution.
BUT, if you insist on not creating another div, then I would bind custom mousemove handler that would be binded (on document) on mouseenter over div, and would detect the fact that mouse move away from div bounding box for more than 10px. If so, mousemove handler would fire custom jQuery event and then it would unbind itself.

Related

Get mouse position relative to a zoomed out div

What I'm looking to accomplish is to get the position of the mouse in relation to a zoomed out div with matrix transform. As you will see in the fiddle below I have a red div with a width of 4000px, but since it's zoomed out it appears smaller then said 4000px. What should happen is if you click on the intersecting lines in the red div, relX should read (around) 2000 and relY should read around 325.
$(".crazyWide").click(function(e){
var clickPos = $(this).offset();
var relX = e.pageX - clickPos.left;
var relY = e.pageY - clickPos.top;
//Used to display current click coords
$(".debug").empty();
$(".debug").prepend("relX: " + relX + " relY: " + relY);
});
Fiddle
The element is shrunk to a factor of 0.12 in both directions. As such, you can calculate the relative mouse click position by dividing the relX and relY by 0.12:
$(".debug").prepend("relX: " + (relX / 0.12) + " relY: " + (relY / 0.12));
Updated fiddle

Subtract Display Pixels from Mouse Position

Full code can be viewed on JSBin - http://jsbin.com/inibAya/1/edit
So I'm working on a wysiwyg website designer and I added a crosshair to show the corrinates the mouse position is within the canvas. (NOTE: a div acts as the canvas not a html5 canvas element)
The div#canvas is positioned at...
#canvas {
position: absolute;
top:0; left:44px; right:291px; bottom:16px;
overflow: auto;
}
Whatever calculation I tried to remove the 44px from the canvas's display I got NaN or undefined. When the user moves their mouse I want it to start at 0 from the top left and move onwards. Does anyone know of anyway to get this to work?
Here's my JQuery/JavaScript:
// Crosshair
var cH = $('#crosshair-h'), cV = $('#crosshair-v');
$('#canvas').mousemove(function(e) {
cH.css('top', e.pageY);
cV.css('left', e.pageX);
$('#mousepos').text( "X: " + e.pageX + "px, Y: " + e.pageY + "px");
});
From e.pageX's documentation:
Description: The mouse position relative to the left edge of the document.
You will need to account for your canvas's offset (of 44px) to solve your problem.
var canvasPosition = $(canvas).position();
$(canvas).on('mousemove', function(e) {
var x = e.pageX - canvasPosition.left;
var y = e.pageY - canvasPosition.top;
cH.css('top', e.pageY);
cV.css('left', e.pageX);
$('#mousepos').text( "X: " + x + "px, Y: " + y + "px");
});
JSBin.

Hover like effect while dragging

I want to make a "hover" like effect while dragging an object over other objects. The objects that can be hovered is inside an iframe while the object the user can drag is outside the iframe. This fiddle illustrates what i am trying to do: http://jsfiddle.net/9yyKN/14/
$("#ha").draggable({
drag: function () {
$(".box").each(function() {
$(this).removeClass("under");
if (event.pageX > $(this).position().left
&& event.pageX < ($(this).position().left + $(this).width())
&& event.pageY > $(this).position().top
&& event.pageX < ($(this).position().top + $(this).height()) )
{
$(this).addClass("under");
}
});
}
});
The boxes should have a little inset shadow when i am dragging the "ha" box over them (the "under" class). I tried do compare their position with the cursor position, but it didn't end up working very well.
The iframe also have a div over it so i can drag objects over it without the drag effect going weird. But because of that :hover, .mouseover() etc. won't work. I have not put an iframe in this fiddle though. I just tried to simplify my problem.
Any ideas for making this work?
You have a small mistake your condition should be:
if ( event.pageX > $(this).position().left
&& event.pageX < ($(this).position().left + $(this).width())
&& event.pageY > $(this).position().top
&& event.pageY < ($(this).position().top + $(this).height()) )
Have a look here: http://jsfiddle.net/straeger/fggKn/
Here is a more precisely version http://jsfiddle.net/straeger/TbwAT/1/

Jquery 1.9.1 - move created element based on cursor position when hovering

I need to move image that is being created when I hover on thumb while moving mouse over that thumb. How can I do this?
I have function like this (it is working):
var body = $('body'),
slike = $('.oglas_slika');
function image_hover(url){
var image = '<img class="oglas_slika_velika" src="' + url +'">';
return image;
}
slike.hover(
function(e){
body.append( image_hover( $(this).data('url') ) );
$(".oglas_slika_velika")
.css("top", (e.pageY) + "px")
.css("left", (e.pageX) + "px")
.fadeIn("slow");
},
function(){
body.find('.oglas_slika_velika').remove();
}
);
I tried this one but I am getting flickering (image is appearing at random places on the page while moving mouse ):
var body = $('body'),
slike = $('.oglas_slika');
function image_hover(url){
var image = '<img class="oglas_slika_velika" src="' + url +'">';
return image;
}
slike.hover(
function(){
body.append( image_hover( $(this).data('url') ) );
$(this).on('mousemove', function(e){
$(".oglas_slika_velika")
.css("top", (e.pageY) + "px")
.css("left", (e.pageX) + "px")
.fadeIn("slow");
return false;
});
},
function(){
body.find('.oglas_slika_velika').remove();
}
);
jsFiddle Demo
The flickering is a result of the element created causing the mouseout section of hover to be called. This is removing the image element, and once the element is removed, the mouseover section of hover is called, and the image is recreated, along with the call to fadeIn. The animation queue is overloaded in the process and eventually throws an error (Uncaught RangeError: Maximum call stack size exceeded) which will cause extremely inconsistent results.
The remedy this, you should keep track of where the mouseover area is with an object:
var sp = {};
sp.top = slike.position().top;
sp.left = slike.position().left;
sp.right = sp.left + slike.width();
sp.bottom = sp.top + slike.height();
and also keep track of the image sizes:
var w;
var h;
which could be filled once appended
body.append( image_hover( ) );
w = $(".oglas_slika_velika").width();
h = $(".oglas_slika_velika").height();
Next would be to ensure that the mouse cursor was truly mousing out of the hover region by checking the collision between the created image and the cursor
if( e.pageY + h > sp.bottom || e.pageY - h < sp.top){
body.find('.oglas_slika_velika').remove();
}else{
if( e.pageX + w > sp.right || e.pageX - w < sp.left ){
body.find('.oglas_slika_velika').remove();
}
}
Although this takes slightly more work, it is also a lot more precise and less prone to error. It will allow the image to directly track the mouse instead of being pushed to an offset.
If it is not important to have the image directly at the place of the mouse, then
#Luigi De Rosa's answer will work very well and require less effort.
Try to add 10px of "margin" in this way
.css("top", (e.pageY)+10 + "px")
.css("left", (e.pageX)+10 + "px")
The problem is that if you go with the mouse to bottom right, your mouse goes on .oglas_slika_velika and it trigger out .oglas_slika (so the remove function)
I hope that it makes a sense for you
jsFiddle here: http://jsfiddle.net/bzGTQ/

stop a previous function from continuing to be excuted with jquery

I have the following function to create a slider. It works (almost perfectly)... The problem I'm having now is that once you click down on the slider it moves around like it should, but I can't figure out how to stop it from moving when I release the mouse?
Suggestions?
Thanks!
var moveSlider = function(){
//sets the current position and offset variables
var currentPosition;
var offset;
//looks for the mousedown event on the slider
$("#slider").mousedown(function(e){
//sets the offset = to the mouse coordinate of the page - the offset of the slider
offset = e.pageX - this.offsetLeft;
console.log("offset: " + offset);
//tracks the mosemovement in the document
$(document).mousemove(function(e){
currentPosition = e.pageX - offset;
//takes the mouse current position (minues the offset) and sets an absolute position
$('#slider').css('left', currentPosition + "px");
console.log("CURRENT POSITION: " + currentPosition);
//checks to make sure it's within the box
if(currentPosition <= 0){
$('#slider').css('left', 0 + "px");
}else if(currentPosition >= 400){
$('#slider').css('left', 400-20 + "px");
}
});
});
$("#slider").mouseup(function(){
$('#slider').css('left', currentPosition + "px")
console.log("Fixed");
});
};
EDIT:
MVCHR, I went off your example, and came up with the following. The mouse move still works, but when you release the mouse it keeps moving. Im sure I"m missing something stupid
Edit, again: Silly mistake, I still had the mouse move in there. Took it out and it works perfectly now! Thanks :)
Thanks again
var moveSlider = function(){
//sets the current position and offset variables
var currentPosition;
var offset;
var rightOffset
//looks for the mousedown event on the slider
$("#slider").mousedown(function(e){
//sets the offset = to the mouse coordinate of the page - the offset of the slider
offset = e.pageX - this.offsetLeft;
console.log("offset: " + offset);
$(document).bind('mousemove', mmHandler);
});
var mmHandler = function (e) {
//tracks the mosemovement in the document
$(document).mousemove(function(e){
currentPosition = e.pageX - offset;
//takes the mouse current position (minues the offset) and sets an absolute position
$('#slider').css('left', currentPosition + "px");
console.log("CURRENT POSITION: " + currentPosition);
//checks to make sure it's within the box
if(currentPosition <= 0){
$('#slider').css('left', 0 + "px");
}else if(currentPosition >= 400){
$('#slider').css('left', 400-20 + "px");
}
});
};
$(document).mouseup(function(e) {
// some code then
$(document).unbind('mousemove', mmHandler);
});
};
In your mouse up event handler add in:
$(document).unbind('mousemove');
You should probably put the function for handling the bound mouse move into something you can pass to the unbind because the code above will affect all mousemove handlers on the document that may be set.
unbind api docs
In case you have other functions bound to mousemove that you don't want to remove, move your mousemove function to a named function that you bind on mousedown and unbind on mouseup. Note that you'll also want to put the mouseup on document and not #slider assuming your slider doesn't move vertically.
Something like this:
var mmHandler = function (e) {
// mousemove code here
};
$("#slider").mousedown(function(e) {
// some code then
$(document).bind('mousemove', mmHandler);
});
$(document).mouseup(function(e) {
// some code then
$(document).unbind('mousemove', mmHandler);
});

Categories

Resources