How to get Co-ordinates on onmouseup? - javascript

I have built a javascript application for dragging and dropping divs from one place to another in the same page. I have made the dragging part. I have the co-ordinates of the div(s) where I must drop the div but I am stuck at the part where I should introduce conditions for matching the divs at target zone. Basically the divs can be dropped above any of the divs but they must drop exactly above the target div if on onmouseup event I am anywhere close to that target div. I am thinking of assigning the top and left attribute of my dragged(onmousdown) div to the target div but I may be wrong.. Please guide my through this part.
Here is the part where I need help:
function mouseUp(e)
{
e = e || window.event;
var mousePos = mouseCoords(e);
var itemPosition = getPosition(id);
//console.log("This is at: "+itemPosition);
//console.log(mousePos);
console.log(getPosition(id));
for(var i=0;i<destination.length;i++)
{
var curTarget = destination[i];
var targPos = getPosition(curTarget);
var targWidth = parseInt(curTarget.offsetWidth);
var targHeight = parseInt(curTarget.offsetHeight);
var temp = document.elementFromPoint(event.clientX, event.clientY);
}
id = null;
}
Here is the link to my code: jsfiddle The javascript part must be written inside of html to make it work properly

The question title is misleading, what you really seem to be having trouble with is finding the coordinates of the target divs. You're grabbing mouse coordinates just fine using clientX and clientY though you likely want to be using the pageX and pageY coordinates as they are relative to the rendered page and not the viewport (ie. window the user is looking at). 0,0 using the client coordinates will change as the user scrolls whereas the page coordinates will reference a particular spot on the webpage.
As for finding your drop divs you can use the method getClientBoundingRect on the element and use the top, right, bottom, and left properties on the returned object to determine if the pageX and pageY coordinates of the mouse are inside (or close to inside) the element.
Maybe there's a better way, but this is how I would do it.
function mouseUp(e){
var targets = document.getElementsByClassName("drop_here");
for(var i=0;i<targets.length;i++){
var bounds = targets[i].getClientBoundingRect();
var lenience = 5;
if(e.pageX < bounds.right + lenience &&
e.pageX > bounds.left - lenience &&
e.pageY < bounds.top - lenience &&
e.pageY > bounds.bottom + lenience){
//do my work here
}
}
}

Related

Position of mouse and element width differs in IE and Chrome (jQuery)

I am trying to detect if mouse is hovering over some element with Javascript by using mouse coordinates and element position (note that I'm not able to use hover event). For that I use this function:
var rect = $('.rectangle'),
rectLeft = rect.offset().left,
rectTop = rect.offset().top,
rectRight = rect.offset().left + rect.width(),
rectBottom = rect.offset().top + rect.height();
if (rectLeft < e.pageX
&& rectRight > e.pageX
&& rectTop < e.pageY
&& rectBottom > e.pageY) {
// in
}
else {
// out
}
While it works flawlessly in Chrome, I have some issues in IE11 (didn't try lower versions), where detection is not exact - the right border of element and pageX position of mouse differs. You can see the behavior in this snippet:
http://codepen.io/Jarino/pen/qdywGv
When you go with the mouse into the area from right border, the area doesn't turn green immediatley, but after some more pixels.
Thanks for any advice.
EDIT
This seems to be the problem specific to only my machine, which it's pretty weird. I tried this on another company computer and it works, also as Infira commented, it works on his enviroment too.

Client X/Y on Chrome (Android)

I wish to retrieve the exact X/Y coordinates where the user has pressed on the screen. The coordinates must be the same no matter what level of zoom or scroll is applied. I am using event.clientX and event.clientY to retrieve these coordinates and this behaves as expected. The code is basically as follows:
$("#canvas").touchstart(function(e){
e.preventDefault();
var Y_LIMIT = 100
if(e.clientY <= Y_LIMIT){
... do stuff
}
});
A textarea is present on the screen with a submit button to allow the user to enter text. The issue is after the tablet focuses in on the textarea and the user enters text the clientX and clientY coordinates permanently change. I wish for the values to stay the same regardless of this operation.
Is there any way to keep clientX and clientY consistent even after entering text into a textarea or input box ?
Despite the fact that there is still a question left about how clientX & clientY have changed(did they descrease or increase their values?)
If they descreased their values you could give this a try to take the absolute position of a parent HTML element(DIV?) in which your textarea is located into consideration:
Check out this answer that answers about how to get absolute position of a HTML element:
// get absolut position of an HTML element
function cumulativeOffset (element) {
var top = 0, left = 0;
do {
top += element.offsetTop || 0;
left += element.offsetLeft || 0;
element = element.offsetParent;
} while(element);
return {
top: top,
left: left
};
};
// event handler callback function to retrieve client position
function funcToGetClientCoords(evt){
var area = document.getElementById("parentDIVId");
var absoluteViewportPos = cumulativeOffset(area);
return {
x: evt.clientX + absoluteViewportPos.left,
y: evt.clientY + absoluteViewportPos.top
};
}
I did not prove this but it sounds to me as if clientX & clientY coords changed according to your relative screenview position and when you click onto a textarea you automatically zoom into this textarea and so clientX and clientY coords might be descreased.
Another try could be to remember the absolute position of your parent DIV at the beginning and when interacting with your textarea add this position to clientX/clientY positions.
Hope this helps.

Hover event on div under absolute positioned div

Is possible to obtain hover event on element, which is under absolute positioned div? That absolute positioned div is child of body element, but that under isn't, so they are not in relationship parent/child. I do drag and drop of that absolute div and i want highlight area, where user can drop, when mouse it's under that area.
enter code here
http://jsfiddle.net/Rv8kp/
Short answer would be no, you cant. But.. there is a workaround
You can add mousemove event handler for the whole document. Inside the handler you check if mouse position is in the area of the element you need to hover.
var $pos = $("#pos");
var top = $pos.offset().top;
var left = $pos.offset().left;
var bottom = top + $pos.height();
var right = left + $pos.width();
$(document).mousemove(function (e) {
if (e.pageY >= top && e.pageY <= bottom && e.pageX >= left && e.pageX <= right)
$pos.addClass("hover");
else
$pos.removeClass("hover");
});
you can view full working example here

How use JQuery/Javascript to scroll down a page when the cursor at the top or bottom edge of the screen?

Simple, I just would like to have it so when a user is dragging an item and they reach the very bottom or top of the viewport (10px or so), the page (about 3000px long) gently scrolls down or up, until they move their cursor (and thus the item being dragged) out of the region.
An item is an li tag which uses jquery to make the list items draggable. To be specific:
../jquery-ui-1.8.14.custom.min.js
http://code.jquery.com/jquery-1.6.2.min.js
I currently use window.scrollBy(x=0,y=3) to scroll the page and have the variables of:
e.pageY ... provides absolute Y-coordinates of cursor on page (not relative to screen)
$.scrollTop() ... provides offset from top of page (when scroll bar is all the way up, it is 0)
$.height()... provides the height of viewable area in the user's browser/viewport
body.offsetHeight ... height of the entire page
How can I achieve this and which event best accommodates this (currently its in mouseover)?
My ideas:
use a an if/else to check if it is in top region or bottom, scroll up if e.pageY is showing it is in the top, down if e.page& is in bottom, and then calling the $('li').mouseover() event to iterate through...
Use a do while loop... this has worked moderately well actually, but is hard to stop from scrolling to far. But I am not sure how to control the iterations....
My latest attempt:
('li').mouseover(function(e) {
totalHeight = document.body.offsetHeight;
cursor.y = e.pageY;
var papaWindow = window;
var $pxFromTop = $(papaWindow).scrollTop();
var $userScreenHeight = $(papaWindow).height();
var iterate = 0;
do {
papaWindow.scrollBy(0, 2);
iterate++;
console.log(cursor.y, $pxFromTop, $userScreenHeight);
}
while (iterate < 20);
});
Works pretty well now, user just needs to "jiggle" the mouse when dragging items sometimes to keep scrolling, but for scrolling just with mouse position its pretty solid. Here is what I finally ended up using:
$("li").mouseover(function(e) {
e = e || window.event; var cursor = { y: 0 }; cursor.y = e.pageY; //Cursor YPos
var papaWindow = parent.window;
var $pxFromTop = $(papaWindow).scrollTop();
var $userScreenHeight = $(papaWindow).height();
if (cursor.y > (($userScreenHeight + $pxFromTop) / 1.25)) {
if ($pxFromTop < ($userScreenHeight * 3.2)) {
papaWindow.scrollBy(0, ($userScreenHeight / 30));
}
}
else if (cursor.y < (($userScreenHeight + $pxFromTop) * .75)) {
papaWindow.scrollBy(0, -($userScreenHeight / 30));
}
}); //End mouseover()
This won't work as the event only fires while you're mouse is over the li.
('li').mouseover(function(e) { });
You need to be able to tell the position of the mouse relative to the viewport when an item is being dragged. When the users starts to drag an item attach an 'mousemove' event to the body and then in that check the mouse position and scroll when necessary.
$("body").on("mousemove", function(event) {
// Check mouse position - scroll if near bottom or top
});
Dont forget to remove your event when the user stops dragging.
$("body").off("mousemove", function(event) {
// Check mouse position - scroll if near bottom or top
});
This may not be exactly what you want, but it might help. It will auto-scroll when the mouse is over the 'border of the screen' (a user defined region). Say you have a 40px wide bar on the right of the screen, if the mouse reaches the first 1px, it will start scrolling. Each px you move into it, the speed will increase. It even has a nice easing animation.
http://www.smoothdivscroll.com/v1-2.htm
I get a weekly newsletter (email) from CodeProject, and it had some stuff that certainly looks like it will solve my problem... hopefully this can help others:
http://johnpolacek.github.com/scrollorama/ -- JQuery based and animates the scroll
https://github.com/IanLunn/jQuery-Parallax -- JQuery based, similar to above
http:// remysharp. com/2009/01/26/element-in-view-event-plugin/ -- JQuery, detects whether an element is currently in view of the user (super helpful for this issue!)
Also the site in #2 had some interesting code:
var windowHeight = $window.height();
var navHeight = $('#nav').height() / 2;
var windowCenter = (windowHeight / 2);
var newtop = windowCenter - navHeight;
//ToDo: Find a way to use these vars and my original ones to determine scroll regions

Detecting the position of a div

I have created a small game, in which some blocks are move around a main div. The mouse which also holding a div (I had assigned the position of cursor to that div).
I just want to trace out, whether the cursor div is moving over the blocks(those are also div). If it comes like that then the game will be over.
How can I detect whether the block or cursor div moves over each other?
If you're using jQuery, you can find the left, top, width and height of a div by using these:
$(myDiv).offset().left
$(myDiv).offset().top
myDiv.offsetWidth
myDiv.offsetHeight
Use those to work out the left, right, top and bottom of each div. Then two divs overlap each other if:
left1 < right2 && left2 < right1 && top1 < bottom2 && top2 < bottom1
This is not a straightforward task using plain javascript, because you have to trace the div's ancestry and sum the relative positions until you find an absolutely positioned div.
On the other hand, this task is quite trivial with a javascript library such as jQuery or Prototype. In jQuery, for example, $(myDiv).offset() returns the div's position relative to the document.
If you also include jQuery UI, and make your main div a "Draggable", and all other divs "Droppable", all you need is hook up on the Droppable's over event to get notified when the main div is dragged over the other one.
The concept you're talking about is called collision detection.
Very simply, you need to get the bounds of your div and then loop through all the blocks to see if they overlap.
getBoundingClientRect()
John Resig has a great article here: getBoundingClientRect is Awesome
If you don't want to use jQuery you can copy/paste from here (LGPL code); http://code.google.com/p/ra-ajax/source/browse/trunk/Ra/Js/Ra.js
The place to look for is the "absolutize" function at line no. 220 which recursively calculates the size of "ancestor nodes" in the while loop.
Pasted in here for references;
var valueT = this.offsetTop || 0;
var valueL = this.offsetLeft || 0;
var el = this.offsetParent;
while (el) {
Ra.extend(el, Ra.Element.prototype);
if( el.tagName == 'BODY' ) {
break;
}
var pos = el.getStyle('position');
if( pos == 'relative' || pos == 'absolute') {
break;
}
valueT += el.offsetTop || 0;
valueL += el.offsetLeft || 0;
el = el.offsetParent;
}
"this" here is a DOM element...
However I suspect that what you have is absolutely positioned divs inside another div with position:relative in which case you can just use;
var y = parseInt(myElement.style.top, 10);
var x = parseInt(myElement.style.left, 10);
which will be orders of magnitudes faster then doing the "offset loops"...

Categories

Resources