clientX and clientY not giving correct mouse pointer location - javascript

I wrote this simple code to print a small dot on the location where I clicked with the mouse pointer:-
$(document).ready(function(){
$('#pane').click(function(e){
var pixel = $('<div />')
.addClass('pixel')
.css({
top: e.clientY,
left: e.clientX
});
$('#pane').append(pixel)
});
});
See this fiddle I created. When I click anywhere inside the rectangle, a small dot is printed in that location. But the problem is that dot is not printed where the mouse pointer's tip was. See the below image to see what I meant:-
I tried in both Firefox and Chrome.

Your code is working correctly,
Zoom your page and check,
i have changed pixel height and width for better understanding from 2px to 3px.
and drawing from e.clientX -1 and e.clientY -1 position so it looks exactly center.
You can find Fiddle

The most examples I've found don't work if there are a scrolled page... I used this algorythm in order to get the position:
var getOffsets = function($event){
var p = {};
var body = "search the document for the body element";
p.x = body.offsetLeft;
p.y = body.offsetTop;
while (body.offsetParent) {
p.x = p.x + body.offsetParent.offsetLeft;
p.y = p.y + body.offsetParent.offsetTop;
if (body == document.getElementsByTagName("body")[0]) {
break;
}
else {
body = body.offsetParent;
}
}
return p;
}
However, after that you have to consider also other elements, im my case:
var GetExactClickPosition = function($event){
var tr = $($event.target);
if ($event.target.localName != 'tr'){
tr = $($event.target).closest('tr');
}
var listDiv = $($event.target).closest('div');
var p = getOffsets($event);
var container = $('#mailingListExcludeMenuContainer');
container.css({
top: p.y - listDiv.scrollTop() - tr.height() - container.height() + $event.offsetY + "px",
left: p.x + $event.offsetX + "px"
});
container.show();
};
I have a list with scroller inside the main scroller of the page...
I used it in order to show a little menu at the position of the mouse click.

Related

Animations in Javascript

I'm working on my Javascript project.
In this project I have to create some animations.
In this specific case, I have to make a ball bounce up and down.
The code below works great just from the top to the bottom, but not viceversa.
var div = document.getElementById('container-ball');
function createBall(event)
{
var x = event.clientX;
var y = event.clientY;
var newBall = document.createElement('div');
newBall.style.position = "absolute"
newBall.style.width = '15px';
newBall.style.height = '15px';
var bx = newBall.style.left = x + 'px';
var by = newBall.style.top = y + 'px';
newBall.style.borderRadius = '10px';
newBall.style.backgroundColor = 'white';
var incrementPos = 0;
var id = setInterval(bounce, 5);
function bounce()
{
incrementPos++;
by = newBall.style.top = incrementPos + y + "px";
if(by == 650 + "px")
{
clearInterval(id)
var id2 = setInterval(function bounceUp()
{
incrementPosYMax -= 650
by = newBall.style.bottom = by + "px" - incrementPosYMax
}, 5)
}`/*Function that make the ball bounce down and up(but when it came at 650 px it stopped )*/ì
} /*End of the set interval */`
div.appendChild(newBall);
}
div.addEventListener("click", createBall);
This down below is the HTML CODE
<html>
<head>
<link rel= "stylesheet" href="style/style.css">
</head>
<body>
<div id ="container-ball">
</div>
<script src="js/main.js"></script>
</body>
Working example (comments see below):
const areaHeight = 150; // it is 650px in the original question
var div = document.getElementById('container-ball');
function createBall(event) {
var x = event.clientX;
var y = event.clientY;
var newBall = document.createElement('div');
newBall.className = 'ball';
var bx = newBall.style.left = x + 'px';
var by = newBall.style.top = y + 'px';
var incrementPos = 0;
var id = setInterval(bounce, 5);
let direction = 1; // 1 = down, -1 = up
function bounce() {
incrementPos += direction;
by = newBall.style.top = incrementPos + y + "px";
if (by == areaHeight + "px" || by == y + 'px') {
direction = -direction;
}
}
div.appendChild(newBall);
}
#container-ball {
width: 300px;
height: 157px;
background: gray;
}
#container-ball .ball {
position: absolute;
width: 15px;
height: 15px;
border-radius: 10px;
background-color: white;
border: 1px solid #333;
box-sizing: border-box;
}
<div id="container-ball" onclick="createBall(event)"></div>
Click on the grey box
Now, the explanation.
I've moved ball's styles to CSS - this is easier to control in the future. So when I have a class for ball, I can write in my code: newBall.className = 'ball';
I removed incrementPosYMax because I do not really understand if you need it
I understand your 'bounce' as bounce, so my ball just fall to the floor and then return to the original position. I do not really understand if you mean that (please, comment if it is wrong).
Your program is quite small, so I do not see the need for another setInterval, so all the animation in my example is inside only one setInterval
I've added new variable direction to control the direction for the ball (1 = down, -1 = up)
I do not like the parts with by == areaHeight + "px", but I keep them for you, because you use it in your code.
This code have some bugs, that you (or me if you ask) can fix. I just need to understand that my approach is correct
How the direction works:
Take a look at this line by = newBall.style.top = incrementPos + y + "px"; here you set new "y" coordinate for the ball as sum of 'original' "y" coordinate (in y) and offset (the distance that ball moved over the time) in incrementPos. So, if you increase incrementPos, then the ball's position will be lower (because "zero" in browser is at the top left corner, bigger "y" means lower the element).
Before my change, in your code you changed the offset with this line: incrementPos++; (means you increase incrementPos by 1 on every bounce step).
To move to another direction, you need to subtract 1 on every bounce step.
To reflect the "direction" of that move, I've added direction variable (so 1 means move down, and -1 means move up)
Now the offset is changed by: incrementPos += direction; (so I add this direction, not always 1)
Sometimes we need to change the "direction" with this code: direction = -direction;
The "levels" where we need to change direction is checked by this code: if (by == areaHeight + "px" || by == y + 'px') - here we check bottom (areaHeight) and top (y - it is where user clicks the mouse)

Finding an element's position using javascript

Hi guys i have following code which is i am using to create a simple tooltip.
html
<div class="x">
<div class="abc">abc</div>
</div>
javascript
//Finding the elements position
var elmPosition = function (elm) {
var x = 0,
y = 0;
while (elm) {
x += (elm.offsetLeft - elm.scrollLeft + elm.clientLeft);
y += (elm.offsetTop - elm.scrollTop + elm.clientTop);
elm = elm.offsetParent;
}
return {
x: x,
y: y
};
};
//Creating and adding the tooltip to document
document.querySelector('.abc').addEventListener("mouseover", function () {
var elm = document.createElement("div");
var position = elmPosition(document.querySelector('.abc'));
elm.textContent = 'just a tooltip';
elm.classList.add('tooltip');
document.body.appendChild(elm);
elm.style.position = 'absolute';
elm.style.top = (position.y - 20) + 'px';
});
//remove tooltip on mouse out
document.querySelector('.abc').addEventListener("mouseout", function () {
document.body.removeChild(document.body.querySelector('.tooltip'));
})
DEMO
The generated tooltip should always stay top of the mouse hovered element. This code perfectly works until the page is scrolled. When then page is scrolled the position of the tooltip is pushed to very far from the mouse hovered element. Could someone please help me to find out what the issue is. Thanks :)
What you're checking for using scrollLeft is how far elm is scrolled. What you want is how far the window is scrolled I'm guessing.
Use window.pageYOffset and window.pageXOffset like so:
while (elm) {
x += (elm.offsetLeft - window.pageXOffset + elm.clientLeft);
y += (elm.offsetTop - window.pageYOffset + elm.clientTop);
elm = elm.offsetParent;
}
EDIT
After trying it out it doesn't make much sense involving the scroll if you're not working with position: fixed. I removed it and edited your fiddle: https://jsfiddle.net/mg606dh1/2/
EDIT 2
You can also change the position to position: fixed and use the code the way you meant for it to be used: https://jsfiddle.net/mg606dh1/3/

How to extend element width both ways?

Does that title sound confusing? I thought it might well anyways.
When I person clicks on the page I want them to be able to me a little line shorter and long.
You can see what I mean here:
http://jsfiddle.net/shawn31313/HKLhE/9/show/
Do a Mousedown and them move your move to the right. It works fine.
But now, move you mouse to the left. See the problem? It goes the same direction as it did when you dragged to the right. I know this is because i'm using width and obviously width on goes one way.
This is my code so far:
$(document).ready(function() {
var dragStatus = 0,
getPos, giveRandomID;
$(document).mousedown(function(event) {
dragStatus = 0;
getPos = {
top: event.clientY,
left: event.clientX
};
giveRandomID = Math.floor(Math.random() * 99999);
});
$(document).mousemove(function() {
var line = $('#line' + giveRandomID);
if (dragStatus == 0) {
$('body').append("<div id='line" + giveRandomID + "' class='line' style='position:absolute;top:" + getPos.top + "px;left:" + getPos.left + "px;background:black;width:2px;height:5px'></div>");
dragStatus = 1;
}
if (dragStatus == 1) {
if (event.clientX > line.offset().left) {
line.css({
width: event.clientX - line.offset().left
});
} else {
line.css({
width: line.offset().left - event.clientX
});
}
//for DEG "-" Top-Math.abs(DEG*2) for Deg "+" Top+(DEG*2)
}
});
$(document).mouseup(function() {
dragStatus = 2;
});
});​
I hope someone can help me out with this. Maybe a complete different way to set this up. Just something to fix this issue
To make the line stretch to the left, you have to update the left property:
if (event.clientX > getPos.left) {
line.css({
left: getPos.left,
width: event.clientX - getPos.left
});
} else {
line.css({
left: event.clientX,
width: getPos.left - event.clientX
});
}
jsFiddle: http://jsfiddle.net/HKLhE/16/
You'll need to modify the else case (moving right) to set the left property to auto and the right property to the initial mouse click X position. Comparing to the offset().left when moving left won't work because that value is changing.
Try this out for size:
http://jsfiddle.net/HKLhE/20/
Edit: Brilliand's solution is much more elegant.

How to get amount of portions of a HTML element is visible in viewport

Is it possible to know whether or not an HTML element like image is viewable in current viewport or it will be visible on scroll?
If it is viewable completely or partially then how can I get the amount of portions is visible?
I am trying to explain it from the following image:
The two images at the bottom is partially visible within the viewport and these will be completely visible if one scroll down a little bit.
Now I want to get the the aforesaid information.
In the actual scenario I am trying to get the popup-zoom effect on hover of image in my album like google image search. Everything is fine, except if the images are placed in the described manner then the zoomed div also displaying in half.
Normal condition where image is completely in viewport:
And partially in viewport:
I really appreciate your help.
The code:
var albumDetailOnReady = function() {
$('.image').each(function(){
var photo = $(this);
var wrap = $(findParentByClassName(document.getElementById(photo.attr('id')), 'wrap'));
var row = $(findParentByClassName(document.getElementById(wrap.attr('id')), 'albumDetailRow'));
var visibleZone = $(wrap).find('.alDtlColumn');
var pictureBlock = $(visibleZone).find('.pictuteBlock');
var hiddenZone = $(wrap).find('.hiddenZone');
$(photo).load(function(){
if(177 > $(photo).width()){
var imgleft = ($(pictureBlock).width() - $(photo).width())/2 + 'px';
$(photo).css({'left': imgleft});
}
});
$(photo).hover(function(){
var y;
if($(photo).height() > $(photo).width()) {
y = ($(visibleZone).offset().top - 50) + 'px';
} else {
y = ($(visibleZone).offset().top + 50) + 'px';
}
var x;
if($(row).find('.wrap:first').attr('id') === $(wrap).attr('id')) {
x = ($(visibleZone).offset().left - 10) + 'px';
} else if($(row).find('.wrap:last').attr('id') === $(wrap).attr('id')) {
x = ($(visibleZone).offset().left - 50) + 'px';
} else {
x = ($(visibleZone).offset().left - 20) + 'px';
}
$(hiddenZone).css({
'top': y,
'left': x,
'position': 'absolute',
'z-index': '10'
});
$(hiddenZone).fadeIn('fast');
}, function(){
});
$(hiddenZone).hover(function(){},function(){
$(hiddenZone).hide().stop(true, true);
});
});
}
var findParentByClassName = function(element, clazz) {
while (element.parentNode) {
element = element.parentNode;
if (hasClass(element, clazz)) {
return element;
}
}
return null;
}
function hasClass(element, cls) {
var regex = new RegExp('\\b' + cls + '\\b');
return regex.test(element.className);
}
I am unable to show any HTML as I haven't have any, I am working in ADF framework.
But for an explanation:
I have two zone for each image: visible and hidden. Both of them are in a wrap. Now on hover an image I am showing the hidden div. The top and left of the hidden div is measured by the top and left of the visible div with some condition.
jQuery.Viewport
Very helpfull and lightweight jQuery plugin that makes an element as a handy viewport for displaying elements with absolute position. The plugin is hosted on GitHub. You can see it in action right there:
https://github.com/borbit/jquery.viewport

Create a mark on an image using relative positioning?

I'd like to be able to mark an image where a user clicks, store the coordinates, and then be able to recreate the marks at a later time. I've got the storing part down but I'm having trouble getting the mark image to show up on the image.
I found a similar question here using absolute positioning, but I'd like the coordinates to be relative to the image.
Looks like jQuery position will give me the position relative to the parent, but from there how would I create and position the mark image relative to the parent? Any help would be greatly appreciated. Thanks
<div id="container">
<img id="imgtoclick"></img>
</div>
$(document).ready(function() {
$("#imgtoclick").click(function(e) {
e.preventDefault();
var left = this.position.left;
var top = this.position.top;
//how to create mark image relative to parent
var img = $('<img>');
})
});
Following #Blenders post but in case your images are nested within positioned elements, you will need to get the coordinates recursively:
var myImg = ...
var getAbsoluteOffset = function (el) {
var x=0, y=0;
while (el) {
x += el.offsetLeft;
y += el.offsetTop;
el = el.offsetParent;
};
return {x:x,y:y};
}
myImg.onclick = function(evt) {
var offset, x, y;
offset = getAbsoluteOffset(this);
var x = evt.pageX - offset.x;
var y = evt.pageY - offset.y;
alert('x: ' + x + '\ny: ' + y);
};
This should do what you want:
$('img').click(function(event) {
var x = event.pageX - this.offsetLeft;
var y = event.pageY - this.offsetTop;
alert('X: ' + x + '\nY:' + y);
});
You would follow these steps:
Give #container this style
container
{
position: relative;
}
Give the image that will show the mark this style
mark
{
position: absolute;
left: //left from jQuery
top: //top from jQuery position
}

Categories