jQuery offset top doesn't work correctly - javascript

I'm trying to create an script draw something in an element by mouse and I'm using Raphaeljs to do that.
For correct drawing I need to find top and left of ‍input‍‍ element. I'm using var offset = $("#input").offset(); to get left and top.
But the top value isn't correct. It's 10px lower than ‍‍the real top distance. I think the 10px maybe change in different resolutions then I can't add 10px to it normally then I want to know how can I fix the problem!
I uploaded my test here.

The jQuery .offset() function has this limitation:
Note: jQuery does not support getting the offset coordinates of hidden elements or accounting for borders, margins, or padding set on the body element.
The body in this case has a 10px top border, which is why your drawing is off by 10 pixels.
Recommended solution:
var offset = $("#input").offset();
x = x - offset.left - $(document.body).css( "border-left" );
y = y - offset.top + $(document.body).css( "border-top" );

After fighting with this for a while and reviewing various potential answers I have concluded that jQuery offset().top (and presumably DOM API that it uses) is too unreliable for general use. Not only is it documented as excluding html level margins, but it also returns unexpected results in several other cases.
position().top does work, but it may not be practical / possible to design the page so that it is equivalent.
Fortunately I have found that element.getBoundingClientRect().top gets the position relative to the viewport perfectly. You can then add on $(document).scrollTop() to get the position from the top of the document if required.

I have two different solutions:
1) You can calculate above element's total height with outerHeight(true) method. This method will calculate height with margins, paddings and borders.
And this won't create conflict, it will return true value.
Here is jsFiddle example.
html
<div class="header"></div>
<div class="nav"></div>
<div class="myEle"></div>
jQuery
var myEleTop = $('.header').outerHeight(true) + $('.nav').outerHeight(true);
2) If you defined top css to the element which is postioned relative to the body, you can use this value too:
parseInt($('#myEle').css('top'));

Related

How to get correct top position of a vertically aligned element?

This page http://orad.msbitsoftware.com/ tries to verticaly align the login form. When I try to get its top position via JavaScript, I get wrong result, which is the same as the chrome developer tool gets (see attached screenshot).
Can someone explain what causes this problem? How come even browser's native tools are affected? And is there a way to get the element's correct position via JavaScript?
Thanks.
It is a common way to center vertically an element of unknown height.
The top position is set to 50%, that makes the top of the element be at the center of the parent (this 50% relates to the parent height)
And the element is transformed with a vertical translation of 50%. This is related to the element height, and makes the element move vertically until it's center is at the center of the parent
top: 50%;
transform: translateY(-50%);
The top value that you get is prior to the transform. This is correct behaviour, but visually you see the transformed element.
Much better explained here Look at the -> vertically -> block level -> unknown height section
If anybody is interested in how to retrieve element's real position via Javascript:
Get element's left/top position within viewport using Element.getBoundingClientRect().
Then get viewport's position relative to the document. This is a bit tricky if you want to support older versions of IE:
var viewport_left = (window.pageXOffset || document.documentElement.scrollLeft) - (document.documentElement.clientLeft || 0);
var viewport_top = (window.pageYOffset || document.documentElement.scrollTop) - (document.documentElement.clientTop || 0);
Add element's left/top position to viewport's left/top position and you get the real position.
This works just fine in IE8+, even on elements using 2D or 3D CSS transforms.

How to open website at specific point on page in HTML?

beginner programmer so apologies if this is really obvious!
How can i get my website to open at a specific point on the page (in HTML)?
I can't find what this is called anywhere! Not Anchor etc. The website will be wider and longer than most screens. I want the screen/viewport to open at the very centre of a 2500x2500 pixel background.
I am working in DreamWeaver CC on Mac OS X 10
Thanks in advance!!
p.s no code to post, this is my first port of call in putting this together
You can get the client's screen with $(window).width() & $(window).height() , it's jQuery code so you'll have to add a balise script to the jQuery lib on your web page. Can you tell me more about what you want to do ? I have trouble understanding. You don't want any anchor but you want ? Apoligies for not understanding.
Try this bit of Javascript to fire when the page loads
window.onload = function(){
window.scrollTo(1250, 1250);
}
The window.scrollTo(x-coord,y-coord) function takes two parameters, x-coord is the pixel along the horizontal axis of the document that you want displayed in the upper left and y-coord is the pixel along the vertical axis of the document that you want displayed in the upper left.
I picked 1250, because that's 2500 divided by 2, but you may have to tweak that a little if you want that spot in the middle of the screen. You will have to get the screen's viewport and do some math.
(hint: window.innerWidth & window.innerHeight gives you the dimensions including the scroll bar; document.documentElement.clientWidth and document.documentElement.clientHeight is without the scrollbar)
The documentation for window.scrollTo() is here: https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo
Some info about the viewport dimensions can be found here: http://ryanve.com/lab/dimensions/
As bryguy said, you can calculate the center of your screen and use scrollTo(). Alternatively, if you have a particular element that you want to scroll to, give the element an id and use the scrollIntoView() function. You can also center an invisible div positioning the div absolutely and setting the top and left values to 50%:
HTML
<div id="scrollToMe" style="position: absolute; top: 50%; left: 50%;"></div>
JS
window.onload = function() {
document.getElementById('scrollToMe').scrollIntoView();
};
You can do this without jQuery. You can use the native JavaScript function window.scrollTo() to scroll to the center.
To calculate the center of the screen all you have to do is:
For vertical center
Determine the height of the viewport: The height of the viewport is stored at document.documentElement.clientHeight.
Determine the height of the entire document: You can use document.documentElement.offsetHeight or document.body.scrollHeight to get the height of the entire document.
Calculate: Now simply subtract the viewport height from the document height and divide it by two like this:
(document.documentElement.offsetHeight - document.documentElement.clientHeight)/2
For horizontal center
Determine the width of the viewport: The width of the viewport is stored at document.documentElement.clientWidth.
Determine the width of the entire document: You can use document.body.scrollWidth to accomplish this.
Calculate: Now simply subtract the viewport width from the document width and divide it by two like this:
(document.body.scrollWidth - document.documentElement.clientWidth)/2
Now time to scroll
Finally, you'll want to make the window scroll to the calculated point.
window.scrollTo(centerWidth, centerHeight);
If you want to do all of it in one step, you'd do:
window.scrollTo( (document.body.scrollWidth - document.documentElement.clientWidth)/2, (document.body.scrollHeight - document.documentElement.clientHeight)/2 );
Please note that we've used document.documentElement.clientHeight (and clientWidth) and they give you the viewport size without the scrollbars. If you wish to include the scrollbars you'll have to use other variables. You can find examples of how to get those measurements on the internet.
For more information: Center a one page horizontally scrolling site in browser (not centering a div)

Explain me that difference in pixels?

There is element
var stickyBar=$('#sticky_bar');
Which has on load position:fixed, so I getting distance between stickyBar top and document top:
var initial=stickyBar.offset().top - $(window).scrollTop();
But, when I do this:
$(window).scroll(function(){
alert(initial+", " + (stickyBar.offset().top - $(window).scrollTop()))
});
These values are different: difference is 61px.
I can't get from where it comes from.
Per the documentation, jQuery's offset() does not account for margins, borders, or paddings. You should make sure you don't have any margins, borders, or paddings affecting the outcome.
You get the values of these margins, borders, and paddings by using
parseInt($("#sticky_bar").css("padding-top"))
and its variants. Then account for those values in your code.
Try making sure through an inspector application that all values on the element (CSS Box Model) are 0. Went through Michal's fiddle and agree, the problem is somewhere on your end. User error.

Get content width of an element

offsetWidth isn't good enough for me right now, as this includes padding and border width. I want to find out the content width of the element. Is there a property for that, or do I have to take the offsetWidth and then subtract the padding and border width from the computed style?
Since this comes up first when googling but doesn't have an appropriate answer yet, here's one:
function getContentWidth (element) {
var styles = getComputedStyle(element)
return element.clientWidth
- parseFloat(styles.paddingLeft)
- parseFloat(styles.paddingRight)
}
Basically, we first get the element's width including the padding (clientWidth) and then substract the padding left and right. We need to parseFloat the paddings because they come as px-suffixed strings.
I've created a little playground for this on CodePen, check it out!
It sounds to me like you want to use getComputedStyle on the element. You can see an example of getComputedStyle vs. offsetWidth here: http://jsbin.com/avedut/2/edit
Or:
window.getComputedStyle(document.getElementById('your-element')).width;
I would suggest either scrollWidth or the clientWidth depending on whether you want to account for the scrollbar.
Check out Determining the dimensions of elements or the specification itself.
I have the similar issue where my parent element isn't the window or document... I am loading an image by Javascript and want it to center after loading.
var parent = document.getElementById('yourparentid');
var image = document.getElementById('yourimageid');
image.addEventListener('load'),function() {
parent.scrollBy((image.width-parent.clientWidth)/2,(image.height-parent.clientHeight)/2);
}
Whenever you set the src then it will scroll to the center of the image. This for me is in the context of zooming into a high res version of the image.

Find the width of an auto sized element

Basically I need the width of a span. Do to the need to use several custom characters that are not found on a keyboard I am building my own "input" field, using a "div". Each character gets wrapped in a "span" tag that has an event listener attached. This will allow the user to click anywhere in the string and have the cursor move to a position after a character, it also allows them to add or delete characters in the middle of a string.
I am using "offsetLeft" and "offsetWidth" to find the right side of a character, the problem is when a character/span is clicked the "offsetWidth" is way off. So for example, if I am using a 14 pixel font an "M" will return as 35 pixels wide when it is actually 11 pixels. And there are several variations, an average sized character like an "S" will return at 26 pixels when it is actually 9. So there is variation in the sizing. Now you may wonder how I found the actual letter size and that was using Firebug. Which if Firebug can find it I would assume so can I, I just haven't figured out how. So I hope someone here knows.
I also tried using "getComputedStyle" and "currentStyle to find the width and it returns "auto". Also tried getBoundingClientRect().width it the same as offsetWidth, the difference being that it also finds the fractions of a pixel in width, so an "M" is 35.366668701171875 pixels wide, odd.
EDIT:
Based on user1289347 post I should have noted that the "offsetWidth" causes the "offsetLeft" to be off by the errant amount as well.
Try jquery width() it computes the dom width pretty well every time I've used it. http://api.jquery.com/width/
And if jquery is out of the question
Create a DIV styled with the following styles. In your JavaScript, set the font size and attributes that you are trying to measure, put your string in the DIV, then read the current width and height of the DIV. It will stretch to fit the contents and the size will be within a few pixels of the string rendered size.
HTML:
<div id="Test">
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ</div>
CSS:
#Test
{
position: absolute;
visibility: hidden;
height: auto;
width: auto;
}
JavaScript (fragment):
var test = document.getElementById("Test");
test.style.fontSize = fontSize;
var height = (test.clientHeight + 1) + "px";
var width = (test.clientWidth + 1) + "px";
This will create a seperate testable div with your test, credit here Calculate text width with JavaScript It's a lot of work but it should get you better results by operating outside of your existing markup.

Categories