like the title says, how to get the element's x, y positions with respect to their location in the web page and their positioning schemes like absolute, relative etc.
In a modern browser, getBoundingClientRect and getClientRects will give you rect objects describing your element. See https://developer.mozilla.org/en/DOM/element.getBoundingClientRect and https://developer.mozilla.org/en/DOM/element.getClientRects
If you have to work with IE8, then you'll have to do different things in different browsers to get correct answers (e.g. object-detect getBoundingClientRect and fall back on some other method if it's not present).
The jQuery offset() calculation and the Quirksmode findPos will give incorrect answers in any browser that does subpixel positioning (e.g. Firefox or IE9), because they will round the answer to an integer number of pixels. Depending on what you're doing, that may or may not be ok.
With jQuery:
var $elt = $('select an element however'),
cssPosition = $elt.css('position'),
offset = $elt.offset(),
top = offset.top,
left = offset.left;
Without jQuery, use Quirksmode's findPos function:
var elt = document.getElementBy...,
pos = findPos(elt),
top = pos[1],
left = pos[0];
Getting the computed CSS position value without a library is another can of worms. It boils down to:
element.currentStyle (IE)
getComputedStyle(element) (real browsers)
Check out this
JS:
function findPos(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
curleft = obj.offsetLeft
curtop = obj.offsetTop
while (obj = obj.offsetParent) {
curleft += obj.offsetLeft
curtop += obj.offsetTop
}
}
return [curleft,curtop];
}
HTML:
<div id="ser"> TEST</div>
RETURN CALL:
alert(findPos(document.getElementById('ser')));
I hope its help to you
Related
So based on this question I asked, what's the most reliable way of getting position of objects that's crossbrowser? Thx
In general, assuming you have an element named elem, it's actually quite easy to get the X and Y coordinates of the top-left corners of an element, assuming you want these in document coordinates. In all browsers this is returned by the elem.offsetLeft and elem.offsetTop properties.
The only trick you have to be aware of is that if elem is absolutely positioned in another element, say a div with a left / top margin of 20px, these properties will return 0, as it only takes into account the current element and not the entire chain of elements. Luckily we can use a "chain-traversal" function to capture all of the margins of elements associated with a given element, tally them up to get the correct document coordinates.
As Sime Vidas mentioned, there is also JQuery's position() and offset() properties, in this case you would want the offset() properties.
You can also use the getBoundingClientRect() method, however this returns the coordinates of an element relative to its offsetParent and thus is not entirely reliable. Look at the following examples:
// getPosition function
function getPosition(elem){
var dims = {offsetLeft:0, offsetTop:0};
do {
dims.offsetLeft += elem.offsetLeft;
dims.offsetTop += elem.offsetTop;
}
while (elem = elem.offsetParent);
return dims;
}
cont1.style.position = "absolute";
cont1.style.marginLeft = "10px";
cont2.style.position = "absolute";
cont2.style.marginLeft = "10px";
box.style.position = "absolute";
box.style.marginLeft = "10px";
console.log(getPosition(box).offsetLeft); // returns "30"
console.log(getPosition(box).offsetTop); // returns "0"
// or in JQuery
console.log($(box).offset().left) // also returns "30"
console.log($(box).offset().top) // also returns "0"
Also I suggest you read this.
If you want to find the position of an element relative to document use jQuery offset() method.
var p = $("p:last");
var offset = p.offset();
p.html( "left: " + offset.left + ", top: " + offset.top );
.offset() reference: http://api.jquery.com/offset/
If you want to find the poistion of an element relative to its parent then use jQuery position() method.
var p = $("p:first");
var position = p.position();
$("p:last").text( "left: " + position.left + ", top: " + position.top );
.position() reference: http://api.jquery.com/position/
And these methods almost gives perfect result in most of the browsers.
I like element.getBoundingClientRect(). It has good cross-browser support.
var coords = element.getBoundingClientRect();
This gives the coordinates relative to the viewport. To get the coordinates relative to the document, add document.documentElement.scrollTop to the top and document.documentElement.scrollLeft to the left.
coords.top += document.documentElement.scrollTop;
coords.left += document.documentElement.scrollLeft;
But since you are already using jQuery, you may as well just use .offset().
I'm trying to manipulate a div element. Although I have defined certain property values, I can't seem to get the initial values.
Here's the problem: Fiddle
I'm at the end of my rope... Thanks.
I think you have to use document.styleSheets, find your stylesheet, then loop through the cssRules(IE rules) list to match a selector to "#viewbase" and then you can access your style properties like you would have with inline styles, since the style info in there is also a CSSStyleDeclaration ( so you can use element.style.left and so on).
Sidenode: getComputedStyle doesn't work on most versions of IE. IE has currentStyle properties for each element, but it's not the same thing. Maybe a combination of both will also work.
UPDATE
Managed to get the initial positions, if that's what you need, you can reassign these values if i remember well.
function trigger(e) {
item = this;
if (!e) var e = window.event;
if (e.pageX || e.pageY) {
x1 = e.pageX;
y1 = e.pageY;
}
else if (e.clientX || e.clientY) {
x1 = e.clientX;
y1 = e.clientY;
}
document.getElementById("ex").innerHTML = x1;
document.getElementById("wye").innerHTML= y1;
// the stylesheet you defined, in a standalone context, it might
// have another index, (i.e. 0 if it's the only one)
list = document.styleSheets[2].cssRules;
for(var i=0;i<list.length;i++)
//match #viewbase
if(list[i].selectorText.toLowerCase() == "#"+item.id)
{ item = list[i];
break;
}
document.getElementById("xval").innerHTML = item.style.left;
document.getElementById("yval").innerHTML = item.style.top;
document.getElementById("parseX").innerHTML = parseInt(item.style.left, 10);
document.getElementById("parseY").innerHTML = parseInt(item.style.top, 10);
document.getElementById("debug").innerHTML = 'clicked!';
document.onmouseup = release;
}
The other version would be to use the following
var styleDef = window.getComputedStyle(item) || item.currentStyle;
document.getElementById("xval").innerHTML = styleDef.left;
document.getElementById("yval").innerHTML = styleDef.top;
The problem is that your style is not defined within the html but comes from css. In that case you need to use getComputedStyle to retrieve the styling information. Do something like
document.defaultView.getComputedStyle(item,null)
rather than item.style.
How about using item.offsetLeft and item.offsetTop. This will include margins and padding, but you should be able to easily compensate for this fact. Here is an updated JSFiddle.
document.getElementById("xval").innerHTML = item.offsetLeft;
document.getElementById("yval").innerHTML = item.offsetTop;
Again, in this case, these calls return 10, 10 respectively, instead of 0, 0, which you are looking for. That said, is this enough to move you past your issue?
How can I get an indication of what part of a long document is currently being displayed?
E.g. if my html contains 1,000 lines
1
2
3
...
999
1000
and the user is near the middle showing the 500th line then I would like to get "500\n501\n502" or something like that.
Obviously most scenarios would be more complex than this, but my requirement is to find which text is currently being displayed in the browser viewport so I can show a status value appropriate to the current text.
Thanks
Martin
If you have jQuery, you can use this function to check if a DOM element is currently shown in the viewport:
function isInView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom));
}
You can get a value in pixels from the scrollTop property:
document.body.scrollTop = 40;
To know what part of your document that is visible, you could loop through (say) all p-tags until you find one with a negative scrollTop value. The one before that is the one at the top of the window.
I've just seen a piece of sample code on msdn
function isinView(oObject)
{
var oParent = oObject.offsetParent;
var iOffsetTop = oObject.offsetTop;
var iClientHeight = oParent.clientHeight;
if (iOffsetTop > iClientHeight) {
alert("Special Text not in view. Expand Window to put Text in View.");
}
else{
alert("Special Text in View!");
}
}
Yes, there is a way. I will use YUI's API to illustrate my example. First your text must be in some sort of dom element, whether its a span, div, p or anything, it must be in a element. Here I will assume list item
var viewPortY = YAHOO.util.Dom.getDocumentScrollTop(),
viewPortHeight = YAHOO.util.Dom.getViewportHeight(), i = 0,
// get all the dom elements that contain the text, sorry if this isn't exact, its just a rough example
items = YAHOO.util.Dom.getElementBy(null, 'li', document.getElementById('item-container')),
viewedItems = [];
for (i = 0 ; i < items.length; i++) {
var y = YAHOO.util.Dom.getY(items[i])
if (y > viewPortY && y < (viewPortY + viewPortHeight)) {
viewedItems.push(items[i])
}
}
So essentially, I get all the dom objects that contain the text your interested in. I then loop through, and whoever's Y co-ordinate is between the viewports Y and Y + ViewPort Height, I put in an array.
I implemented what I thought was a more optimal solution for my environment:
I am writing for Android so I can easily interact with a Java class from javascript. My actual solution involved getting offsetTop of all tags I am interested in and passing the offsets to java.
Also registering an onscroll handler that passed window.pageYOffset throught to the same Java class. Then the java class can compare offsetTop of each tag with pageYOffset to see which tag is at the top of the current viewport.
I can't seem to figure out how to get the offsetTop of an element within a table. It works fine on elements outside tables, but all of the elements within a table return the same result, and it's usually at the top of the page. I tried this in Firefox and Chrome. How do I get the offsetTop of an element in a table?
offsetTop returns a value relative to offsetParent; you need to recursively add offsetParent.offsetTop through all of the parents until offsetParent is null. Consider using jQuery's offset() method.
EDIT: If you don't want to use jQuery, you can write a method like this (untested):
function offset(elem) {
if(!elem) elem = this;
var x = elem.offsetLeft;
var y = elem.offsetTop;
while (elem = elem.offsetParent) {
x += elem.offsetLeft;
y += elem.offsetTop;
}
return { left: x, top: y };
}
I've seen dozens of scripts that can catch the x and y position of an element/object within the page. But I am always having trouble with catching the x and y when the webpage is using margins at the body, or other elements, absolute/relative elements, such like that.
Is there a solution which provides the exact position, no matter what margins or paddings are used?
I use following code to move div box to follow cursor in this Web IME site
function xy(x) {
o = document.getElementById(x);
var l =o.offsetLeft; var t = o.offsetTop;
while (o=o.offsetParent)
l += o.offsetLeft;
o = document.getElementById(x);
while (o=o.offsetParent)
t += o.offsetTop;
return [l,t];
}
Its return an array [left,top],
Getting the exact position is simply a matter of adding the offsetLefts and offsetTops recursively to the offsetParents:
function getPos(ele){
var x=0;
var y=0;
while(true){
x += ele.offsetLeft;
y += ele.offsetTop;
if(ele.offsetParent === null){
break;
}
ele = ele.offsetParent;
}
return [x, y];
}
Btw, this solution would probably run twice faster than the other solution above since we only loop once.
offsetParent and other offset functions are old... use the getBoundingClientRect
function... use this:
function getAbsPosition(element) {
var rect = element.getBoundingClientRect();
return {x:rect.left,y:rect.top}
}
now you can use it like this
<div style="margin:50px;padding:50px;" id="myEl">lol</div>
<script type="text/javascript">
var coords = getAbsPosition( document.getElementById('myEl') );
alert( coords.x );alert( coords.y );
</script>
Don't worry... no matter how much margin or position or padding the element has, it always works
Here are some improvements on #Pacerier 's code in my own answer:
function getPos(el, rel)
{
var x=0, y=0;
do {
x += el.offsetLeft;
y += el.offsetTop;
el = el.offsetParent;
}
while (el != rel)
return {x:x, y:y};
}
If is just used as getPos(myElem) will return global position. If a second element is included as an argument (i.e. getPos(myElem, someAncestor)) that is an ancestor/parent of the first (at least somewhere up the chain) then it will give the position relative to that ancestor. If rel is not given (i.e. is left undefined), then it purposefully uses != instead of !== because it should stop when el gets to null and rel is undefined as well, so the non-strict equality is purposeful, don't change it. It also returns an object, since that's a bit more readable in usage than an array (and so you can do something like getPos().x).
This is derived from Pacerier's solution, so if you're gonna upvote this, consider upvoting his too.