JQuery - Improper recalculate on window resize - javascript

I wrote a CSS class to create relative position related to the document instead of the parent element. To do this I use jQuery to set the "left" property.
$(function() {
var popoutPosition = $('.lw-popout').offset();
$(".lw-popout").css("left", "-" + popoutPosition.left + "px" );
});
This works great. The problem is it breaks when the window is resized. I have tried the code below, but it does not work. It runs on resize, but the value it calculates is not correct. Anyone have any ideas?
$(window).resize(function () {
var popoutPosition = $('.lw-popout').offset();
$(".lw-popout").css("left", "-" + popoutPosition.left + "px" );
});

your code is only going to work for a single element. If you have multiple elements of that class, they are all going to use the offset of the first element.
offset gives an offset from the document, which is affected by css styles such as left. So once you set it, your technique won't work again until you set left back to the original value.
It might be better to use the offset of the parent instead of its own offset.
More clarity:
Say that in the DOM, the element starts out 100 pixels from the left, which is determined by calling offset().
You then set the left style to "-100px".
Calling offset() again will result in 0, because that is the new position relative to the document.
If you resize the window, the element may move. Perhaps it should now be at 200 pixels from the left, but because the left attribute is set to '-100px', offset() actually gives you a left value of 100. It will always be off.
Possible solutions:
Use translatex instead of left. That moves where the element appears, but doesn't change the actual position in the dom. it will not affect future calls to offset: ie: transform: translateX(-200px)
Set left to 0px before calling offset. That will reset to the default and it can then be calculated properly.
Use position: fixed and set left to 0.
Use the parent position to determine where to position the element. If it has a fixed position within the parent it would work.

Related

Get relative position of an element to its parent

How can i get the position of an element relative to its parent?
Let's suppose we have an image object called 'clone', and a div as its parent:
var parent = clone.parent().offset();
var pos = clone.offset();
If i drag the image right in the top left corner of the div i will get as result almost the same values. But what about if i do this:
var top = pos.top - parent.top;
var left = pos.left - parent.left;
it'll give me the relative position of the image to its parent, right? But what happen if i have to store those values and display them on a different browser size?
The answer it's pretty easy, they won't show inside the div because the position may change.
After this little explaination, my question is:
Is there a way to avoid this kind of problem, and directly take the relative position to its parent?
This is the actual code i'm using, so you can give a look, and try to figure out how to make it works properly! http://dpaste.com/3M1MGQW
Have you set position: relative; to the parent so the positions are relative to it?
Well, any possitioning other tha static will work, but relative without specifing top and left may be the most painless

How to calculate where an element should be without moving it?

I need to change the horizontal position of an element. To do this I change its left attribute with .css('left', value). That would move the element relative to where it should be if there was no left value defined.
Now I need to recalculate the position to move the element somewhere else, to do that I need the position where the element should be if I had not changed its left attribute.
I could remove the left value and ask for its position but then the element would also move and would like to avoid that since I may make the element jump between positions.
How could I get the position where the element would be?
The element doesn't jump between position if you change the left style multiple times. As long as your function is running, there are no updates in the browser. You can safely reset the left style, get the positon, and then set a new left value.
One way would be to read the default left value of the element on DOM-ready and add it to the element as a data-* attribute on the element - let's call it data-default-left or something similar. You could then always refer to that value when you need the default value further on.
The data-* are easy to work with using jQuery's .data() method.
Setting left to 0, recalculating, and setting left to the new position would be the easiest change in your case. In my experience the browser will not repaint between css updates.
Some other options:
Use absolute positioning instead of relative. Then you're origin is consistent.
Use the jQuery UI position plugin. It lets you set the position of an element relative to another. Very useful.
how about use .data() to store this info before starting moving it? Then u just gather it back there everytime u need.
Simple. Store the initial left amount in a variable on dom load and then reference it later when you do your other calculations:
$(function () {
var $element = $("#ME_ELEMENT_ID");
var initialLeft = $element.offset().left;
// Change your left here
$element.css('left', '200px');
// initialLeft still contains the old value
});

jQuery offset top doesn't work correctly

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'));

Dynamically adding divs through jquery

I am adding elements like div dynamically in the page using jquery.The div CSS is position : absolute .Now my problem is when i add more than 1 div element at the same time than it all overlaps each other. Is there any way so that without changing my element's position property these are not overlaps?
Check out masonry plugin. It is dynamic layout plugin that auto arranges the div elements as the new elements are added in document it prevents the overlaps of the elements. Check out this link.
Simply specify the container div let it with id container you need to call function
$(".container").masonry();
and then when you add more div inside container you just need to call the function
var $newElems = $( newElements );
$(".container").masonry( 'appended', $newElems );
You define place of absolutely positioned objects with top, bottom, left, right css properties . So you have to alter these dynamically as well.
For example: The first element has top: 0, left:0 , the second top: 0, left: 50 and so forth...
When you add an element as positioned absolute and provide no valid top and left values the element will be positioned absolutes with both top and left as 0.
In your case all the elements you are adding should be taking position (0,0) so they are overlapping one above other.
One solution is to calculate the positions of each and layout them using adding corresponding top and left values to them along sith css({'position' : 'absolute'}) but that requires some math in most cases.
Dont worry, your browser already knows that math and you can use it in most cases, so add the divs without 'position' 'absolute'. Now browser layouts them well. After the browser has finished laying out them, take the DIVs and get their present position and use the position to layout them using absolute position.
for(var i=0; i < noOfDivs; i++){
{
$('#parentDiv').append('<div class="childDiv"/>');
}
$('.childDiv').css({
'position': 'absolute,
'top' : $(this).position().top,
'left' : $(this).position().left
});
The code is not tested, if DIVs are positioned one by one it should again cause problems, you should either iterate them from last to first or save all positions and apply them later. If jQuery is updating all positions in a single DOM access this will work fine.

How do I find the absolute position of an element using jQuery?

Is there a way of finding the absolute position of an element, i.e. relative to the start of the window, using jQuery?
.offset() will return the offset position of an element as a simple object, eg:
var position = $(element).offset(); // position = { left: 42, top: 567 }
You can use this return value to position other elements at the same spot:
$(anotherElement).css(position)
Note that $(element).offset() tells you the position of an element relative to the document. This works great in most circumstances, but in the case of position:fixed you can get unexpected results.
If your document is longer than the viewport and you have scrolled vertically toward the bottom of the document, then your position:fixed element's offset() value will be greater than the expected value by the amount you have scrolled.
If you are looking for a value relative to the viewport (window), rather than the document on a position:fixed element, you can subtract the document's scrollTop() value from the fixed element's offset().top value. Example: $("#el").offset().top - $(document).scrollTop()
If the position:fixed element's offset parent is the document, you want to read parseInt($.css('top')) instead.
In case the element is not visible $(element).offset(); and $(element).position(); retun 0 for both top and left instead of the elements real value.
i had to use
parseInt($(element).css("top"))
parseInt($(element).css("left"))
to return the needed information.
the element has position: absolute;.

Categories