I am creating a div using jquery and I am trying to center it at a specific point. The text in the div is dynamic, and it's not centered in a particular parent html, but rather I want to center it on just a specific point.
So basically I have
var centerX = 100; // dynamically computer in my code
$('<div/>').text('sometext').css({'left': (centerPointX - $('#mydiv').width() / 2) + 'px'});
But the width of mydiv is not known until it is rendered, so I'm not sure how to go about centering at the x point. Do I need an outer container in which to center in relative to?
Firstly $('#mydiv') only gets the element if it is available in the DOM.
So you would first be required to inject the element into the DOM and then access the width property . Otherwise it will be 0 when you try to access the width property of the element.
Related
Let's say I have an <li> element inside a scrollable div and the scroll was set to show that element in the viewport.
I need to get the distance between that element and its scrollable parent, as shown in the picture above, but both element.getBoundingClientRect().top and element.offsetTop give me the wrong values. Can that be done?
I made a pen, to make things a little bit easier:
http://codepen.io/Darksoulsong/pen/LbYMex
A piece of my code:
document.addEventListener("DOMContentLoaded", function(event) {
var selectedEl = document.getElementById('consequatur-51');
var selectedElRect = selectedEl.getBoundingClientRect();
var sidebar = document.getElementById('sidebar');
sidebar.scrollTop = selectedEl.offsetTop - 60;
document.getElementById('offsetTop').innerText = selectedEl.offsetTop;
document.getElementById('rectTop').innerText = selectedElRect.top;
});
I found out how to make it work. Actually, #Dummy's answer gave me some important insights.
Basically, the formulae is:
childElementDistanceFromParentTop = actualChildElementDistancefromTop - parentElementDistanceFromTop
With these coordinates I can even tell if the element is visible in the viewport or not.
Updated pen: http://codepen.io/Darksoulsong/pen/rWawrZ
var parentTop = parentElem.getBoundingClientRect().top; // Initial parent's top distance from the top of the viewport;
var currentChildTop = childElement.getBoundingClientRect().top; // Initial child's top distance from the top of the viewport;
If you do var childParentDistance = Math.abs(parentTop - currentChildTop), you will get the initial distance between the child element and its parent. But as you scroll, you need to account for the scroll amount. Like this
var scrolledParentDistance= Math.abs(parentTop - parentElem.getBoundingClientRect().top);
and if you subtract scrolledParentDistance from childParentDistance, you will get the new distance between this child and its parent
I was in a similar situation, and I guess one of the missing parts was the distance that a human observer does not see; as scrollable containers usually hide their overflowing content. Hence I felt adding my answer may be useful, with a little example.
Find a way to programmatically scroll a parent element that hides content which overflows it and has:
position: fixed;
top: whateveryouwant;
height: 80%;
overflow-y: scroll;
in a way such that a specific child's top border is aligned with your parent's top.
With the CSS above you have a parent div which always fills 80% of your screen's height, with a getBoundingClientRect().top value which thus always stays the same for a given device.
You then need to build a formula where you can use parent.scrollTo(0,outputOfFormula); to scroll the parent in a way such that the targeted child's top is aligned with your parent's top.
#TrashCan was actually almost there, and he / she was right that what's missing is that you have to consider the amount by which the parent scrolled, to account for all possible cases. So all in all you have something like this:
------------------------------------ Viewport's Top
------------------------------------ Popup (Parent)'s Top
| |
| --- | Horizontal Level of Targeted Child's Top
| |
| |
------------------------------------ Popup (Parent)'s Bottom
------------------------------------ Viewport's Bottom
Which gives you:
d(Viewport's Top - Horizontal Level of Targeted Child's Top) = child.getBoundingClientRect().top
d(Viewport's Top - Popup (Parent)'s Top) = parent.getBoundingClientRect().top
d(Popup (Parent)'s Top - Horizontal Level of Targeted Child's Top) = d1 - d2
If you count the pixels on your screen that separate your parent's top form your child's top, you now get exactly d3. But d3 may not be the correct value to use to scroll down your parent to display the child at its top. If your Popup has already been scrolled down, d3 only represents a part of the actual distance of your parent's top to your child's top. Your child may actually be situated much much lower inside your Popup, so you'd be missing all of that distance needed to be scrolled down too. To thus complete the formula and get the actual distance we have to scroll our parent to display our child within its top, we have to add parent.scrollTop to d3. If we did not scroll the parent by any pixel, the scrollTop property will simply be 0.
Hence for this scenario, you need to use:
child.getBoundingClientRect().top - parent.getBoundingClientRect().top + parent.scrollTop
and then do
parent.scrollTo(0,result)
and you're covered for all cases of this scenario.
Sorry if this is already out there somewhere, but I've been looking for a while and haven't found anything. I'd like to know if there's any way to, given the x and y coordinates/offset for an absolutely positioned element on a page, change that element into a relatively positioned element, but have it stay in the same visual spot, changing its location in the DOM. For example, given this html
<div id="divOne"></div>
<div id="divTwo"></div>
<div id="divThree"></div>
if divOne were positioned absolutely and its position happened to visually fall between divTwo and divThree, is there a way for me to convert its x,y position so I would be able to tell jQuery to place it after divOne and before divTwo in the DOM? I'm well versed in Javascript and jQuery, I'm just looking for a method I may not know about or for an answer from someone who may have come across this before.
by removing the absolute positioning of the dragged div you must place its tag to a different place in the dom in order to get it repositioned.
For example if you drag #divOne so that it visually moves between #divTwo and #divThree what you should do is remove the absolute positioning of #divOne and move its tag between the two other divs:
<div id="divTwo"></div>
<div id="divOne"></div>
<div id="divThree"></div>
If you have a well-defined grid this will work.
If I were you what I would do is to give a standard class to any div in my grid that I want be re-arrangeable. E.g., the class "arrangeable". When the drag-end fires I would calculate where my dragged div must be placed in the dom using this formula:
The dragged div should be moved to another place on the dom. What it will happen is that the dragged div will take the place of an existing one and "push" the existing just after it. For example by dragging #divOne between #divTwo and #divThree, #divOne takes the place of #divThree and pushes it after it. Supposing that the user stops the drag and releases left click when the dragged div is over the existing div whose place is going to be taken (let's name it "pushedDiv") by the dragged one then all you have to do is to recognize the pushedDiv, remove the dragged one from the dom, place right before the recognized one and make its position relative.
In order to realize which is the pushedDiv you can use this routine:
//on drag end, where mouse has x and y coords:
var pushedDiv;
$(".arrangeable").each(function(index,value){
var theoffset = $(this).offset();
if(x >= theoffset .left && x <= theoffset .left + $(this).width() && y >= theoffset .top && y <= theoffset .top + $(this).height()){
pushedDiv = $(this);
}
});
// if pushedDiv is still null then the user didn't release the left click over a div of class "arrangeable". Else, the pushedDiv will be the one we are looking for
I have a scrollable div somewhere on-screen.
I have a child of that div somewhere in it.
How can I scroll the div to place this child in the center of the visible region?
(How would I determine the visible width and height of the div, and how would I scroll to place a rectangular control centered in this?)
element.scrollIntoView() might be what your looking for.
http://jsfiddle.net/a9s2G/
scrollIntoView docs
If you use jQuery you can try scrollTo plugin.
In pure js this can be done using element.scrollTop. You will need to get position of your element inside <div> and than using that value scroll main div.
To calculate inner element position you will need to get it offset top and left property related to the parent element using offsetTop and offsetLeft properties.
To center your element you may also need to use element.scrollLeft
I want to display an overlay (html div) when a user clicks on an element in an SVG diagram. To visualize the problem I'm having, suppose that the SVG image has a horizontal row of 6 elements. At the click event, I get the element's coordinates and use them to display the overlay next to it. The problem is that as I click the elements from left to right, I notice that the horizontal offset between the element and the overlay keeps getting smaller. That is, the 6th element displays the overlay much closer to it than the first element. This happens in both Chrome and FF, and it's an issue because sometime the overlay covers the element itself.
At first I was using JQuery's position() property, which didn't exhibit the behavior that I described above, but it returned very different values in Chrome and Firefox, plus it is not officially supported by JQuery on svg elements. So I tried with DOM's standard offsetLeft and offsetTop, as well as svg's x.animVal.value property and various libraries that I found on the web, but they all have the same erratic offset problem. I presume that this happens because the svg image is scaled, so I'm looking for I way to just get an svg's element position relative to the actual html document which contains it. Is there a way to do this?
In case you haven't worked something out since March (and for anyone else having this problem), try getBoundingClientRect() on your SVG node.
Returns a ClientRect object that gives you top, bottom, left, right, width, and height relative to the document. Was able to use this to position Twitter Bootstrap popovers (divs) next to SVG rects.
jQuery's position() does not work well for SVG elements. There is a ticket for that.
You can use the native SVG method getBBox() to get the position of a SVG element.
Example
$('svg circle')[0].getBBox();
You can get the position coordinate relative to the page of any element, also <svg>, with this little function:
function getOffset(element)
{
var bound = element.getBoundingClientRect();
var html = document.documentElement;
return {
top: bound.top + window.pageYOffset - html.clientTop,
left: bound.left + window.pageXOffset - html.clientLeft
};
}
var offset = getOffset(svg);var x = offset.left;var y = offset.top;
live demo: https://codepen.io/martinwantke/pen/rpNLWr
I Want to create a stack type control where a series of stacked sub-divs can be re-ordered within a container div.
The sub-div 'views' would be the same size and absolutely positioned on top of each other.
The z-index css property seems to apply z-order at the document level, which makes no sense to me- How can an element in a given div have a higher z-order than something that is placed after that div? It just ignores the nested div heirarchy?
So the question is: Is there a way to manipulate relative z-order within a given div?
Thanks,
Yarin
How can an element in a given div have
a higher z-order than something that
is placed after that div? It just
ignores the nested div heirarchy?
Z-index only modifies the "layer" (imagine Photoshop) that the element is displayed on. Structurally, the box-model is not changed. Visually, it appears to be, but only if the positioning for the elements have been modified (through CSS) so that the z-index actually means something. Here's an example; notice how B appears above A and C event though C has the greatest z-index.
To modify the z-index of elements, relative to the container div that they are contained in, you have to make sure that the lowest z-index in the container is greater than the greatest z-index outside of the container. Then, you adjust the other z-indexes to offset them. This function (uses jQuery) gets the element with the greatest z-index, from the passed elements:
function getTopElement(elems){
// Store the greates z-index that has been seen so far
var maxZ = 0;
// Stores a reference to the element that has the greatest z-index so far
var maxElem;
elems.each(function(){
var z = parseInt($(this).css("z-index"), 10);
// Ignore z-index of auto
if (!isNaN(z)){
if (parseInt($(this).css("z-index"), 10) > maxZ) {
maxElem = $(this);
maxZ = parseInt($(this).css("z-index"), 10);
alert (maxZ);
}
}
});
return maxElem;
};
Use:
var topDiv = getTopElement($("div"));
var topZIndex = topDiv.css("z-index");
That should get you started.
Edit:
To fill in missing z-indexes, use this code:
var elements = $("div");
var newZ = parseInt(getTopElement(elements).css("z-index"), 10);
elements.each(function(){
if (isNaN(parseInt($(this).css("z-index"),10))){
$(this).css("z-index", ++newZ);
}
});
What it does is it changes elements with a z-index of auto to one-plus whatever the greatest z-index is in the collection (elements);
To see what I mean, check out this demo.
If you want only one div to be visible then change its opacity to 1 in Firefox and 100 in IE and set the others to 0. Here's a slide show example that does just that. I would imagine yours wouldn't be based on a timer so you would need some other method to switch them.