Javascript get absolute position of a div - javascript

I have a div (oCell) created at runtime using javascript.
I then want to position another independant div (random-div) relative to this div. For reasons within the program random-div has to be positioned absolutely and oCell relatively. The oCell div is positioned relative as it is within a table.
My problem is I need to find the absolute position of the oCell div, rather than the relative position.
So far I have:
var oCell = document.createElement("td");
var height = oCell.getBoundingClientRect().top;
var right = oCell.getBoundingClientRect().right;
oCell.oBoxPositionTop = height;
oCell.oBoxPositionSide = right;
But from what I can understand, this is returning the relative height of oCell div, which is in turn not positioning random-div in the correct place.

The getBoundingClientRect gives coordinates in viewport coordinates (or coordinates relative to the visible content shown in your browser window). With absolute positioning, you need document coordinates. To convert viewport coordinates to document coordinates, add the scroll offsets of the page to the left and top values returned by getBoundingClientRect:
//technique used in JavaScript: Definitive Guide
var scrollOffsets = (function () {
var w = window;
// This works for all browsers except IE versions 8 and before
if (w.pageXOffset != null) return {x: w.pageXOffset, y:w.pageYOffset};
// For IE (or any browser) in Standards mode
var d = w.document;
if (document.compatMode == "CSS1Compat")
return {x:d.documentElement.scrollLeft, y:d.documentElement.scrollTop};
// For browsers in Quirks mode
return { x: d.body.scrollLeft, y: d.body.scrollTop };
}());
//Your code:
var oCell = document.createElement("td");
//changed from height to top and gets document coordinates of position
var top = oCell.getBoundingClientRect().top + scrollOffsets.y;
//changed from right to left
var left = oCell.getBoundingClientRect().left + scrollOffsets.x;
oCell.oBoxPositionTop = top;
oCell.oBoxPositionSide = left;

Related

Why aren't createjs DOMElements positioned correctly at top left of the canvas like all other objects?

(As per the title)
If you create an HTML button and place it on the canvas with createjs:
var html = document.createElement('input');
html.type = 'button';
html.id = 'testing button';
html.value = 'test';
var DOMElement = new createjs.DOMElement(html);
var target = document.getElementById(<name of a div in your HTML>);
target.appendChild(html);
//returns the first canvas element seen in the page
var canvas = document.getElementsByTagName('canvas')[0];
var stage = new createjs.Stage(canvas);
createjs.Ticker.addEventListener("tick", function(event) {
stage.update(event);
});
stage.addChild(DOMElement);
stage.update();
The button will appear outside of the canvas. This is mostly likely an artifact of the HTML and CSS (I don't have the background to say why this is); Instead of at the default position on the stage (0, 0), the top left, like all other createjs DisplayObjects.
The answer appears to be related to CSS styling. As a simple addition of two styling options has the default position of the button set at the top left (0, 0) as we expect:
var html = document.createElement('input');
html.type = 'button';
html.id = 'testing button';
html.value = 'test';
html.style.top = 0; // <--
html.style.left = 0; // <--
These properties according to MDN, determine position relative to the top and left margins:
For absolutely positioned elements (those with position: absolute or
position: fixed), it specifies the distance between the top / left
margin edge of the element and the top / left edge of its containing
block.
Source: Top & Left.
If someone could chime in for the reason as to this behavior and a little more detail that would be great, as I said I simple don't have the background in CSS or HTML to say why.

Positioning floating element using JavaScript (for animation)

I want to make floating HTML5 element move back and forward on my page. Exactly like SmoothDivScrolling that is already out there. I did try SmoothDivScrolling and it is not working well with the layout of my page.
So I have started to write my own.
If I give a position to my element using CSS I will be able to retrieve the position with:
element = document.getElementById(image);
position = element.style.left;
// removing px from the value
position = parseInt(position.substring(0,position.length-2));
This will return the left position of the element inside its parent only if the CSS contain:
left:0px;
As mentioned, I want my elements to be floating because I plan to have many more than one element;
Now since I want to animate my element I have to change the position by changing the value of 0px with:
fish.style.left = (newPosition)+'px';
It is working if I provide the style of my floating element with:
position:relative; //This doesnt really afect my floating
left:0px; //this does
So I tried to retrieve the position with DOM instead of CSS using:
var element = document.getElementById(image);
var rect = element.getBoundingClientRect();
position = rect.left;
Now this is working. It retrieves the position of the element relative to the body even if no left positioning was specified in the style.
I am wondering if there is way to change the position of that element without going trough CSS style. Because each element might have different width, floating them take care of the positioning. If I provide a position to each of them they won't be floating anymore.
The floating option avoid all the math involved on positioning. But if it's really needed I guess I will do the math.
Any suggestions?
Here is the full code for who ever wants to reinvent the wheel with me
<body style="margin:0px;">
<div id="scroller" style="position:absolute;left:400px;width:800px;border:1px solid #000000;overflow:hidden;height:auto;">
<div id="scrollWrap" style="margin:0px;position:relative;width:400px;margin:auto;border:1px solid #000000;overflow:hidden;height:150px;">
<figure id="shark" style="float:left;margin:0px;padding:0px;width:150px;display:inline-block;">
<img id="image" src="shark.jpeg" alt="The Shark" style="border:1px solid #000000;position:relative;left:0px;width:150px;height:150px;">
</figure>
</div>
</div>
<script type="text/javascript">
setInterval(function(){ do_move("shark"); }, 10);
</script>
</body>
<script type="text/javascript">
var frameDirection;
function do_move(image) {
var container = document.getElementById("scrollWrap");
var bodyRect = container.getBoundingClientRect();
var element = document.getElementById(image);
var rect = element.getBoundingClientRect();
offset = rect.left - bodyRect.left;
fish = document.getElementById(image);
horz = fish.style.left;
fishSize = document.getElementById(image).offsetWidth;
horz = parseInt(horz.substring(0,horz.length-2));
var frameWidth = document.getElementById('scroller').offsetWidth;
var wrapWidth = document.getElementById('scrollWrap').offsetWidth;
var nbrImg = document.getElementById("scrollWrap").getElementsByTagName("figure").length;
if (horz==0) {
frameDirection='right';
}
else if (horz == (wrapWidth-fishSize)) {
frameDirection='left';
}
if (horz<=wrapWidth && frameDirection == 'right') {
horz += 1;
fish.style.left = (horz)+'px';
}
else if (horz<=wrapWidth && frameDirection == 'left') {
horz -= 1;
fish.style.left = (horz)+'px';
}
}
</script>
If I understand correctly, you want to initially float your elements, then switch to absolute positioning, but keep everything in the same place, so you can animate them?
If so, this code may help you. It's not based on your html, just an example.
// get all the floating elements
var floaters = document.getElementsByClassName("floater"),
index, floater, rect;
// go over them backwards
for (index=floaters.length-1; index>=0; index--) {
floater = floaters[index];
// get current position
rect = floater.getBoundingClientRect();
// convert it to style
floater.style.left = rect.left + "px";
floater.style.top = rect.top + "px";
// switch to absolute positioning
floater.style.position = "absolute";
floater.style.float = "none";
}
I made a little jsfiddle, so you can test it.

Getting every offsetParent or the total offSetTop and total offSetLeft

I want to get the total offSetTop and the total offSetLeft of a child element which have many level of parent element and may be adding up.
Is that any shorthand way, besides of adding one by one in manual ways?
To provide an answer without jQuery:
var a = Element, b = 0, c = 0;
while (a) {
b += a.offsetLeft;
c += a.offsetTop;
a = a.offsetParent;
}
Where Element is your Element node for which you need an offsetLeft and offsetTop.
using jQuery: $( node ).offset() then .top and .left
https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
If you need the bounding rectangle relative to the top-left corner of the document, just add the current scrolling position to the top and left properties (these can be obtained using window.scrollX and window.scrollY) to get a bounding rectangle which is independent from the current scrolling position.
let { left, top } = domNode.getBoundingClientRect();
left += window.scrollX;
top += window.scrollY;

how do i get the x and y position directly under the left bottom side of the input rectangle?

I'm thinking of implementing a custom auto-complete feature so basically my idea now is that i will make an abs positioned div and give it the position here:
(image) http://i.stack.imgur.com/3c5BH.gif
So my question is with a variable referencing the textbox, how do i get the x and y position directly under the left bottom side of the input rectangle?
My script must work in latest versions of IE / FF / Safari / Opera / Chrome
I know i can use a library to do it, but no i'm interested in learning how do they do it (or maybe better ways)?
This question is a lot more complicated than it seems and involves getting the position of the element relative to the document. The code to do so can be pulled from the jquery source (http://code.jquery.com/jquery-1.6.1.js -- search for "jQuery.fn.offset")
in jQuery:
var node = $('#textbox'),
pos = box.offset(); // the complicated piece I'm using jQuery for
node.top += node.height(); // node.offsetHeight without jQuery
node.left += node.width(); // node.offsetWidth without jQuery
The answer can be extremely simplified if you don't care about FF2 or Safari3:
var box = document.getElementById('yourTextBox').getBoundingClientRect(),
left = box.left,
bottom = box.bottom;
x = x offset
y = y offset - ( textbox height +
padding-top + padding-bottom )
Good comments! For my scenario, there is always an offset parent (which is why I use position - http://api.jquery.com/position/). In hopes that it might help someone else wanting a quick fix, here's the code:
// I have a parent item (item) and a div (detail)
// that pops up at the bottom left corner of the parent:
var jItem = $(item);
var pos = jItem.position();
var marginTop = parseInt(jItem.css('margin-top'));
if (isNaN(marginTop)) {
marginTop = 0;
}
$(detail).css("top", pos.top + jItem.outerHeight() + marginTop)
.css("left", pos.left);
$(detail).show();
Just give the box a defined width and height. Then, get its top and left property and add it with the width and height. Simple. I am gonna give you Pseodocode.
<STYLE>
object{width: 100px; height: 20px;}
</STYLE>
<SCRIPT>
x = object.left;
y = object.top;
x = x + object.width;
y = y + object.height;
</SCRIPT>

Get position of map area(html)?

Is this possible? I'm trying to find the x and y coordinates of the element in relation to the browser.
var position = $(this).position();
x = position.left;
y = position.right;
Doesn't work.
Is there any way to do this?
http://adamsaewitz.com/housing/
highlight the blue room 070
The problem lies in the fact that you are accessing the top/left of an area element.
The area element is not positioned where its coords say. This is handled behind the scenes by the dom/browser.
So you need to find the image that the area relates to and grab its offset.
var imgId = $(this).closest('map').attr('name');
var imgPos = $('#' + imgId).offset();
Then, you grab the coords attribute of the area and split it to get left/top/width and use those to pinpoint the location inside the image.
var coords = $(this).attr('coords').split(',');
var box = {
left: parseInt(coords[0],10),
top: parseInt(coords[1],10),
width: parseInt(coords[2],10)-parseInt(coords[0],10),
height: parseInt(coords[3],10)-parseInt(coords[1],10)
};
Take into consideration the width/height of the info box that appears (and since you animate it, take that into consideration as well) and you get to
x = imgPos.left + box.left + box.width/2 - 65; // 65 is the info width/2
y = imgPos.top + box.top -20 -160 -1; // 20 is the animation, 160 is the info height, 1 is a safe distance from the top
demo: http://www.jsfiddle.net/XBjwN/
Edit for updated question: Since you're using <area> it's a different story, and fetching from the coords attribute is much easier, like this:
var position = $(this).attr('coords').split(',');
x = +position[0] - 50;
y = +position[1] - 170;
The offsets are just to account for the hard-coded width/height of the tooltip itself. In addition to the above, you want to use top and left rather than margin-top and margin-left. Also to account for the #content <div>'s position in the page, give it a relative position for the tooltip to sit in, like this:
#content { position: relative; }
Then...instead of .after(), use .append() so it gets added inside that parent.
You can test the result here.
For original question:
The object .position() returns has top and left properties...but you want .offset() here anyway (it's relative to the document, where .position() is relative to the offset parent), so it should look like this:
var position = $(this).offset(),
x = position.left,
y = position.top; //not right!
Or this:
var position = $(this).offset();
var x = position.left;
var y = position.top;
...but without a single var comma-separated statement, or a var on each line, you're also creating (or trying to) global variables, which will blow up in IE.
$(document).ready(function () {
$('map').imageMapResize();
$('area').hover(function () {
$('.imgpopover').css({ "display": "block", "top": $(this).attr("coords").split(',')[1]+"px", "left": $(this).attr("coords").split(',')[0]+"px" })
$('.imgpopover label').text($(this).attr("title"))
}, )
});

Categories

Resources