I have the follow jQuery event binding. Refer to the image below to see the DOM. The hover callbacks behave correctly when hovering over .gift-price, .gift-vendor, and .gift-name. However, when hovering over the image (.gift-photo), the mouseenter and mouseleave callbacks are called for every movement of the mouse. Why is this happening?
$('div.gift-gallery-item').hover(
function(e) {
var offset = $(this).offset();
var itemWidth = $(this).width();
var itemHeight = $(this).height();
var hoverItem = $('div#gift-gallery-item-hover');
hoverItem.height(140).width(itemWidth * 2);
hoverItem.css('left', offset.left).css('top', offset.top);
hoverItem.show();
console.log('in: ' + offset.left +', '+ offset.top);
console.log(this);
},
function(e) {
$('div#gift-gallery-item-hover').hide();
console.log('out!');
}
)
DOM Reference Image
The yellow boxes are .gift-gallery-item divs:
Solved my own problem. Basically hover was behaving correctly, but when the absolutely positioned hover info div was under the mouse, the mouseleave event was being trigged on the gift-gallery-item. Simple solution was to split up the hover into its mouseenter and mouseleave events, and bind mouseleave only once using one() instead of bind(). Then in the hover info div's mouseleave event, i rebind the mouseleave on the gift-gallery-item.
$('div.gift-gallery-item').bind('mouseenter', function(e) {
var offset = $(this).offset();
var itemWidth = $(this).width();
var itemHeight = $(this).height();
var hoverItem = $('div#gift-gallery-item-hover');
hoverItem.height(140).width(itemWidth * 2);
hoverItem.css('left', offset.left).css('top', offset.top);
hoverItem.show();
console.log('in: ' + offset.left +', '+ offset.top);
console.log(this);
});
$('div.gift-gallery-item').one('mouseleave', mouseLeaveEvent);
var mouseLeaveEvent = function() {
$('div#gift-gallery-item-hover').hide();
console.log('out!');
};
$('div#gift-gallery-item-hover').hover(
function(e) {
},
function(e) {
$('div.gift-gallery-item').one('mouseleave', mouseLeaveEvent);
}
);
Related
I'm trying to replicate Zara's product functionality: (click on product image)
https://www.zara.com/es/en/woman/outerwear/view-all/tweed-coat-with-metal-buttons-c733882p5205048.html
I have it almost working from a jsfiddle I found:
https://jsfiddle.net/y6p9pLpb/1/
$(function() {
$('.product-wrapper a').click(function() {
$('.image-zoom img').attr('src', $(this).find('img').attr('src'));
$('.image-zoom').show();
$('.product-wrapper').css('display', 'none');
return false;
});
$('.image-zoom').mousemove(function(e) {
var h = $(this).find('img').height();
var vptHeight = $(document).height();
var y = -((h - vptHeight) / vptHeight) * e.pageY;
$('div img').css('top', y + "px");
});
$('.image-zoom').click(function() {
$('.image-zoom').hide();
$('.product-wrapper').css('display', 'block');
});
});
There's only one thing I can't solve.
When I click on the image and expands, this one jumps to match its respective position relative to the cursor.
Is there any way I can solve that? Like Zara does...
Thanks in advance!
The issue is that the image jumps to your cursor once you move it, right? This should do what you're looking for!
https://jsfiddle.net/8z67g96b/
I just broke out the position change as a function, and also call it when you click the thumbnail - that way, the image already has the cursor's position influencing it when it first appears.
function zoomTracking(event){
var h = $('.image-zoom img').height();
var vptHeight = $(document).height();
var y = -((h - vptHeight) / vptHeight) * event.pageY;
$('.image-zoom img').css('top', y + "px");
}
$('.product-wrapper a').click(function(e) {
$('.image-zoom img').attr('src', $(this).find('img').attr('src'));
$('.image-zoom').show()
zoomTracking(e);
$('.product-wrapper').css('display', 'none');
return false;
});
$('.image-zoom').mousemove(function(e) {
zoomTracking(e);
});
In the fiddle, it has a section relating to the position of the mouse and the width/height of the image:
$('.image-zoom').mousemove(function(e) {
var h = $(this).find('img').height();
var vptHeight = $(document).height();
var y = -((h - vptHeight) / vptHeight) * e.pageY;
$('div img').css('top', y + "px");
});
Simply remove this portion and it won't do any moving with the mouse, just expand onClick.
I want to move child element when dragging on parent and the element itself, and the parent shouldn't be moved.
here is my demo
As in the demo, I want to move the red box when either drag on it or drag on its parent (the background), but I couldn't compute the right position, could you help me?
Other question is why I can't offthe mousemove event when I set .off('mousemove', mousemove')
Thank you very much
I have done some changes. This works ;)
DEMO
$(function(){
var graph = $('.graph')[0];
var parent = $(graph).parent();
var lockX = 0;
var lockY = 0;
var mousemove = function(e){
$(graph).offset({
top: e.pageY + lockY,
left: e.pageX + lockX
});
};
parent.on('mousedown', function(e) {
lockY = $(graph).offset().top - e.pageY;
lockX = $(graph).offset().left - e.pageX;
$(this).addClass('draggable')
.on('mousemove', mousemove)
.on('mouseup', function(){
$(this).off('mousemove', mousemove)
})
event.preventDefault()
});
$('.graph').parent().on('mouseup', function(e) {
$('.draggable')
.off('mousemove', mousemove)
.removeClass('draggable');
});
});
EDIT
The only actual change I made to make it work was:
.offset({
// instead of: e.pageY - $('.draggable').outerHeight() / 2 + dtop
top: e.pageY + dtop,
// instead of: e.pageX - $('.draggable').outerWidth() / 2 + dleft
left: e.pageX + dleft
})
PS: In the example in the JS Fiddle I changed dleft and dtop respectively to lockX and lockY. Ofcourse, that is a pure semantical thing.
I have a div and inside that there's an image. Now when I click the image I can get the image by $(this) and a border is displayed to let the user know that it can be resized.
html:
<div id="content">
<p>Something <img src="http://placehold.it/350x150"/> Lorem expetendis .</p>
</div>
js:
$("#content img").on("click", function () {
$(this).addClass("resize_handler");
});
Then I though of getting the initial x and y axis on mousedown and compare it to the mousemove. And then change the height/width of the image accordingly.
$(document).mousemove(function (event) {
if (clicking == true) {
x_axis = event.pageX;
y_axis = event.pageY;
delta_x_axis = x_axis - initial_x_axis;
delta_y_axis = initial_y_axis - y_axis;
}
});
Check out jsfiddle.
But it didn't help either, because as I try to drag, the image gets selected. How to make the image resizable when clicked with its aspect ratio? I would really appreciate your help and guidance. Thank you.
Here is the fiddle: http://jsfiddle.net/jmyem32r/4/.
You should do your enhance, now it looks really ugly, but main principle is shown. To make a draggable behaviour, you should use a boolean switcher that is toggled with image mousedown event, and document mouseup. Also you should cancel default mousedown behaviour by calling event.preventDefault method.
$(document).ready(function (event) {
var x_axis;
var y_axis;
var initial_x_axis;
var initial_y_axis;
var isDragging = false;
$('#content img').mousedown(function (event) {
event.preventDefault();
isDragging = true;
initial_x_axis = event.pageX;
initial_y_axis = event.pageY;
$("#initial").text("initial-x: " + initial_x_axis + ", initial-y: " + initial_y_axis);
$(this).addClass("resize_handler");
});
$(document).mouseup(function () {
isDragging = false;
});
$(document).mousemove(function (event) {
if(isDragging) {
x_axis = event.pageX;
y_axis = event.pageY;
var newWidth = $('#content img')[0].width / (initial_x_axis / x_axis);
$('#content img').css('width', newWidth + 'px');
}
});
});
I am trying to create and effect where you have a vertical list, and when you hover it with your mouse, a separate "cursor" div should travel up and down vertically along this list, horizontally aligned with your pointer.
I am using this code:
$(document).mousemove( function(e) {
mouseY = e.pageY;
mouseX = e.pageX;
translateY = 'translateY(' + mouseY + 'px)';
translateX = 'translateX(' + mouseX + 'px)';
});
Then with jQuery:
$(".sidebarnav").mouseover(function(){
$('.sidebarnav .cursor').css({'transform': translateY});
});
All this kind of work, but the cursor div does not perfectly align with my mouse pointer. It does if you move real slow and with precision, but it doesn't if you move a bit faster. Is there any technical reason to this lack of precision, or is my code just wrong?
Here is a jsfiddle
http://jsfiddle.net/txks3wtj/
A fiddle would definitely help. But if I understand your code correctly I believe you can't just update the .cursor's position on mouseover of the .sidebarnav - instead you need to update its position on mousemove ie all the time.
Since you don't want the cursor to move when not hovering the sidebar you'd need to keep track of whether or not it is hovered. Something like:
var isOver = false;
$('.sidebarnav').mouseover(function () {
isOver = true;
}).mouseout(function () {
isOver = false;
});
$(document).mousemove( function(e) {
mouseY = e.pageY;
mouseX = e.pageX;
translateY = 'translateY(' + mouseY + 'px)';
translateX = 'translateX(' + mouseX + 'px)';
if (isOver) {
$('.sidebarnav .cursor').css({'transform': translateY});
}
});
Untested.
Edit: It would increase performance if you cached your queries as well;
var sidebar = $('.sidebarnav');
var cursor = sidebar.find('.cursor');
Edit2: You may have better results with mouseenter and mouseleave too I think. I think over/out triggers as soon as you hover a child of the element as well.
I'm trying to make a jquery function to follow the mouse coursor with a div, when it is on mousedown and when it is on mouseup it stay in the last position it was.
any sugestion.
Why not simply use drag and drop by jquery:
<script>
$(function() {
$( "#draggable" ).draggable();
});
</script>
Jquery draggable
I've put together a simple working example that defines a Draggable object. You specify the drag item (the element that you're moving around), as well as a drag boundary (the space—or element—that you are moving the item inside of). The concept of a boundary is important if you ever want to restrict a draggable item to a certain space on the page (such as a container), or define a relative coordinate system on which to base your math.
My solution isn't the fastest, but it demonstrates the concept:
$(function() {
window.mousedown = 0;
$(window).on('mousedown mouseup', function(e) {
if(e.type == 'mousedown') { this.mousedown++; }
else { this.mousedown--; }
});
var Draggable = function(dragItem, dragBoundary) {
this.item = $(dragItem).css('position', 'absolute');
this.item.on('mousemove', $.proxy(this.handleDragEvent, this));
this.boundary = $(dragBoundary).css('position', 'relative');
};
Draggable.prototype.handleDragEvent = function(e) {
if(window.mousedown) {
var mousePosition = this.mapToBoundary([e.clientX, e.clientY]);
var mouseX = mousePosition[0],
mouseY = mousePosition[1];
if(typeof this.prevMouseX == "undefined") this.prevMouseX = mouseX;
if(typeof this.prevMouseY == "undefined") this.prevMouseY = mouseY;
this.itemX = this.item.offset().left - this.boundary.offset().left;
this.itemY = this.item.offset().top - this.boundary.offset().top;
var deltaX = mouseX - this.prevMouseX,
deltaY = mouseY - this.prevMouseY;
this.item.css({
'left': this.itemX + deltaX,
'top': this.itemY + deltaY
});
this.prevMouseX = mouseX;
this.prevMouseY = mouseY;
}
};
Draggable.prototype.mapToBoundary = function(coord) {
var x = coord[0] - this.boundary.offset().left;
var y = coord[1] - this.boundary.offset().top;
return [x,y];
};
var draggable = new Draggable($('.draggable'), $('.container'));
});
Notice that we are maintaining a mousedown value on global, allowing us to determine when it would be appropriate to drag around our element (we only add a mousemove listener to the drag item itself). I've also included a spacer div above the boundary div to demonstrate how you can move the boundary anywhere around the page and the coordinate system is still accurate. The code to actually restrict a draggable item within its assigned boundary could be written using simple math.
Here is the fiddle: http://jsfiddle.net/bTh9s/3/
EDIT:
Here is the start to some code for restricting a Draggable item within its container.
Draggable.prototype.restrictItemToBoundary = function() {
var position = this.item.position();
position.right = position.left + this.item.outerWidth();
position.bottom = position.top + this.item.outerHeight();
if(position.left <= 0) {
this.item.css('left', 1);
} else if(position.right >= this.boundary.outerWidth()) {
this.item.css('left', this.boundary.outerWidth() - this.item.outerWidth());
}
if(position.top <= 0) {
this.item.css('top', 1);
} else if(position.bottom >= this.boundary.outerHeight()) {
this.item.css('top', this.boundary.outerHeight() - this.item.outerHeight());
}
};
This method should be called inside of Draggable.handleDragEvent just after you update the CSS positioning of the drag item. It seems this solution is glitchy, but it's a start.