Moving the placement a div in JavaScript - javascript

I have a function that I built (it's kind of bare bones at the moment), but I can't find how to move the object when it expands onMouseOver so it doesn't move the others on the page, is this possible?
function expandbox(x) {
x.style.height = "100px";
x.style.width = "100px";
}
function returnbox(x) {
x.style.height = "80px";
x.style.width = "80px";
}

Make the element position relative inside a relative container, then change it's dimensions.
Make sure to give it higher z-index.
Place it with left,right,top,bottom properties of style.

If you want to keep the element in document flow, set it to position: relative and move it around using top and left, which will be relative to where the element started out.
I'll use the same type of function you made, to demonstrate:
function moveBox(x) {
x.style.position = "relative";
// move 20px down and 10px left from original position
x.style.top = "20px";
x.style.left = "-10px";
}
If you want to remove the box from document flow (following elements will not be affected by its presence) set its position to absolute instead. Top and left values will be relative to its closest positioned ancestor (or <body> if there is none, as i assume in the comment below)
function moveBox(x) {
x.style.position = "absolute";
// position box 20px from top of body
x.style.top = "20px";
// and 10px from the left
x.style.left = "10px";
}
An element is considered to be "positioned" if it has a value other than static (default, read more here), so if you want to control what the absolutely positioned element is relative to, you can give a container element position: relative

Related

positioning new element based on position of existing element?

I am using the following code (Javascript within a webpage) to create a 'new' element in the DOM dynamically. I wish to position this say 200px 'below' an existing element. However my output has the positioning of the new element(s) all wrong...as if the position (top, left) I am specifying is ignored.
var _reference = document.getElementById("outputs");
for (_count = 0; _count < _limits; _count++) {
var _structure = document.createElement("div");
_structure.setAttribute("class", "container-fluid");
_structure.setAttribute("id", "struct_" + _tally);
if (_count === 0){
_rect = _reference.getBoundingClientRect();
//get the bounding box of the "outputs" id element...
document.getElementById("outputs").appendChild(_structure);
_structure.style.top = _rect.top + "200px"; //NOT positioned 200px below 'outputs'
_structure.style.left = _rect.left; //NOT positioned same position as 'outputs'
} //_count is "0"
} //for loop
I would have thought this should be fairly straightforward...however it is driving me crazy...any help appreciated.
You'll need to set _structure.style.position to 'relative', 'absolute', 'fixed', or 'sticky' in order to use top, left, right, bottom.
You need to set your position to realtive or absolute in order for this to work, also note that position: absolute sets the position according to the nearest relative positioned parent while position: relative positions according to the current position of the element

JavaScript: Why a dynamically created div won't position top/bottom edge at .clientY?

Using JavaScript, I dynamically create a <div>(call it 'popup'), populate it with content, insert it into the DOM, and then attempt to position it relative to (.clientX, .clientY) of the click event.
The positioning scheme is simple. If .clientX is in the left half of the view port, I want popup's left edge to be at .clientX. If .clientX is in the right half of the view port, I want popup's right edge to be at .clientX. Similarly for .clientY. If it is in the top half of the view port, I want popup's top edge at .clientY; if in the bottom half, popup's bottom edge should be at .clientY.
I have the horizontal alignment working correctly but can not get the vertical to work.
The algorithm I'm using is:
function positionPopupOnPage( evt ) {
var vpWH = [];
var vpW, vpH;
var coordX = evt.clientX;
var coordY = evt.clientY;
vpWH = getViewPortWidthHeight();
vpW = vpWH[0];
vpH = vpWH[1];
popup.style.position = 'absolute';
// if not display: block, .offsetWidth & .offsetHeight === 0
popup.style.display = 'block';
popup.style.zIndex = '10100';
if ( coordX > vpW/2 ) { coordX -= popup.offsetWidth; }
if ( coordY > vpH/2 ) { coordY -= popup.offsetHeight; }
popup.style.top = coordY + 'px';
popup.style.left = coordX + 'px';
} // end fn positionPopupOnPage
The function call was positionPopupOnPage(event).The function getViewPortWidthHeight() is the one given in answer to the stackoverflow question Find the exact height and width of the viewport in a cross-browser way (no Prototype/jQuery).
The problem is that popup's top/bottom edge does not align with .clientY. In the screenshot below, (.clientX, .clientY) was the the "C" in "Charlie Fowler" which is where the mouse clicked. But popup's bottom edge is way above that position.
.
--> EDIT 0 <-- (in response to #user2330270's remarks)
Popup is inserted as high up the DOM tree as possible, as the first child of <body>. The function call is:
// insert popup above the first child of <body>
parentNode = document.getElementsByTagName("body")[0];
targetNode = parentNode.children[0];
insertPopup( parentNode, targetNode );
The function definition is:
function insertPopup( parentNode, targetNode ) {
parentNode.insertBefore(popup, targetNode);
popup.classList.add( 'popup')
existsPopup = true;
} // end fn insertPopup
There is a Pen, Table Play, at CodePen. It is the full code. The definition of positionPopupOnPage() is the third up from the bottom in the JS area, beginning at line 233.
The only CSS reaching popup is:
.popup {
position: absolute;
border: 2px solid #000;
border-radius: 10px;
width: 200px;
height: 250px;
overflow-y: auto;
background-color: rgba(0, 0, 0, .5);
color: #fff;
z-index: 1000;
display: none;
}
and the JS style assignments in positionPopupOnPage() as given above.
--> End Edit 0 <--
-->Edit 1<--
Correct the statement of the problem.The function does not work in Safari or Firefox as was initially erroneously reported. Update the positioning function to the one currently used in the Pen.
-->End Edit 1<--
Can someone help determine what is happening and how I can get popup's top/bottom edge to align with .clientY in Chrome?
Your effort and interest in my question are much appreciated. Thank you.
-Steve
From looking at your algorithm it looks right. What I would suggest is set the top position as 0px and see where it lies. If it is not at the top of the page, then you know you have CSS stopping it working correctly.
Maybe try making a simplified fiddle and you could be assisted further. The popup should be as top a level as possible in the HTML tree to keep things easy and reliable. This may also fix your issue if it is not.
The trick, for me, was to realize 4 things:
An absolutely positioned element, which the div popup is, is positioned from the page top not the view port top.
As the page is scrolled up, one has to account for the distance scrolled up, i.e. the distance from the view port top to the page top.
That distance is obtained by document.body.scrollTop.
Add that distance to the distance from the click point to the view port top, i.e. event.clientY, to get the total distance to use in setting popup's CSS top property.
The correct function to solve the problem then becomes:
// positon popup on page relative to cursor
// position at time of click event
function positionPopupOnPage( evt ) {
var VPWH = []; // view port width / height
var intVPW, intVPH; // view port width / height
var intCoordX = evt.clientX;
var intCoordY = evt.clientY; // distance from click point to view port top
var intDistanceScrolledUp = document.body.scrollTop;
// distance the page has been scrolled up from view port top
var intPopupOffsetTop = intDistanceScrolledUp + intCoordY;
// add the two for total distance from click point y to top of page
var intDistanceScrolledLeft = document.body.scrollLeft;
var intPopupOffsetLeft = intDistanceScrolledLeft + intCoordX;
VPWH = getViewPortWidthHeight(); // view port Width/Height
intVPW = VPWH[0];
intVPH = VPWH[1];
popup.style.position = 'absolute';
// if not display: block, .offsetWidth & .offsetHeight === 0
popup.style.display = 'block';
popup.style.zIndex = '10100';
if ( intCoordX > intVPW/2 ) { intPopupOffsetLeft -= popup.offsetWidth; }
// if x is in the right half of the viewport, pull popup left by its width
if ( intCoordY > intVPH/2 ) { intPopupOffsetTop -= popup.offsetHeight; }
// if y is in the bottom half of view port, pull popup up by its height
popup.style.top = intPopupOffsetTop + 'px';
popup.style.left = intPopupOffsetLeft + 'px';
} // end fn positionPopupOnPage
With thanks to user ershwetabansal on CSS Tricks for leading me to point 2 above.

Javascript positioning center style

I wanted to set my second div element indside of my first div element center. I think somehow I managed to center it. But I think I made some mistakes and it seems to me it is not properly centered and also this JavaScript style seems to me bad. Is there any better way doing it? Is my JavaScript code is correct?
FIDDLE
HTML
<div class='first'>
<div class='second'>
</div>
</div>
JavaScript
var first = document.getElementsByClassName('first')[0];
var second = document.getElementsByClassName('second')[0];
var height = first.offsetHeight;
second.style.width = height/2+"px";
second.style.height = height/2+"px";
second.style.marginLeft = height/4+"px";
second.style.marginTop = height/4+"px";
offsetHeight will get the height of the element including borders, clientHeight won't. Instead of:
var height = first.offsetHeight;
Try:
var height = first.clientHeight;
JSFiddle
I've also used top and left with position:absolute for positioning, as this take the element out of the page flow and I assume this is the behaviour you are looking for.
References:
offsetHeight
clientHeight
(Follow the links and take a look at the box-model diagrams)
Reason is drawing round take 3px thats why not positioning but you divide 2.1 that result come that you need.
Check this Demo jsFiddle
JavaScript
var first = document.getElementsByClassName('first')[0];
var second = document.getElementsByClassName('second')[0];
var height = first.offsetHeight;
second.style.width = height/2.1+"px";
second.style.height = height/2.1+"px";
second.style.marginLeft = height/4+"px";
second.style.marginTop = height/4+"px";
var second = document.getElementsByClassName('second')[0];`
var left = (screen.width/2)-(100/2);
var top = (screen.height/2)-(100/2);
second.style.width = "100px"; //set as per your requirement
second.style.height = "100px"; //set as per your requirement
second.style.left= left +"px";
second.style.top = top +"px";
Just in case, you're interested, I tried to come up with a CSS only solution.
http://jsfiddle.net/53M6A/1/
Here's the changes I made to the .second class.
.second{
left: 50%; //move 50% to left
top: 50%; // move 50% down
margin-left: -50px; //move half of it's own size back to the left
margin-top: -50px; //move half of it's own size back to the top
position: relative; //make it relative, so it can be moved around by left/top
width:100px;
height:100px;
background: #fff;
border-radius:50%;
}
I've been playing a little in your fiddle and finally, I changed your 2 last lines for these:
first.style.display = "table-cell";
first.style.verticalAlign = "middle";
second.style.margin = "0 auto";
Fiddle
Seems perfectly centered to me.

Child element position relative working wrong

I have a div element of css width and height, 800x600. I am using javascript to generate three object elements in the div that should be in a diagonal line, touching each other. I am using position:relative, and the left and top css properties to position the object elements. However when I do it this way, there is a horizontal gap between the squares that shouldn't be there. When I use positon:fixed, they line up how I want it but not inside the div element.
Html of my div element
<div id="Stage" style="background:black;width:800px;height:600px;margin-left:auto;margin-right:auto;overflow:hidden;">
and my javascript
w="w";
level_data =
[
[w,0,0],
[0,w,0],
[0,0,w],
];
function generate(level_data){
for(row=0;row<level_data.length;row++){
for(col=0;col<level_data[row].length;col++){
posx = col*50; posy=row*50;
if(level_data[row][col]=="w"){
entity = document.createElement('object');
entity.style.position = "relative";
entity.style.left = String(posx)+"px"; entity.style.top = String(posy)+"px";
entity.data = "Objects/Sprites/Wall.jpg";
document.getElementById("Stage").appendChild(entity);
}
}
}
}
generate(level_data);
This is what I get: Link1
This is what I want: Link2 but the redsquares inside the big black square instead. What's the problem?
position: fixed positions elements relative to the viewport. position: relative gives that result because object element probably has some default value for widht and height. You'll need something like this:
entity.style.position = "absolute";
entity.style.left = String(posx)+"px";
entity.style.top = String(posy)+"px";
entity.style.width = "50px";
entity.style.height = "50px";
When using position: absolute, the code is supposed to work even without dimensions for the entity. Notice , that when using position: relative you should not multiply position values with col, they should be just 50px.

CSS: Child div overlapping parent

I have something vaguely like the following:
<div id="body">
surrounding text
<div id="pane" style="overflow: auto; height: 500px; width: 500px;">
lots and lots of text here
<span id="some_bit">tooltip appears below-right of here</span>
</div>
more surrounding text (should be overlapped by tooltip)
</div>
and:
<div id="tooltip" style="width: 100px; height: 100px;">Whee</div>
What I want to do is insert the tooltip such that it is positioned above the pane it's in. If it's attached to an element that's next to the pane boundary (like above), then it should be visible above the pane, and above the text surrounding the pane.
It should NOT a) extend the pane, such that you have to scroll down to see the tooltip (like in http://saizai.com/css_overlap.png), or b) be cut off, so you can't see all of the tooltip.
I'm inserting this with JS, so I can add a wrapper position:relative div or the like if needed, calculate offsets and make it position:absolute, etc. I would prefer to not assume anything about the pane's position property - the tooltip should be insertable with minimal assumptions of possible page layout. (This is just one example case.)
It's for a prototype tooltip library I'm writing that will be open source.
ETA: http://jsfiddle.net/vCb2y/5/ behaves visually like I want (if you keep re-hovering the trigger text), but would require me to update the position of the tooltip on all DOM changes and scrolling behavior. I would rather the tooltip be positioned with pure CSS/HTML so that it has the same visual behavior (i.e. it overlaps all other elements) but stays in its position relative to the target under DOM changes, scrolling, etc.
ETA 2: http://tjkdesign.com/articles/z-index/teach_yourself_how_elements_stack.asp (keep defaults except set cyan div 'a' to position:relative; imagine 'A' is the pane and 'a' the tooltip) seems to more closely behave as I want, but I've not been able to get it to work elsewhere. Note that if you make 'A' overflow: auto, it breaks the overlapping behavior of 'a'.
I can't think of a pure HTML/CSS solution for this.
The overflow declaration is the issue here. If the tooltip is in #pane:
you establish a positioning context within #pane, then the tooltip shows next to #some_bit (regardless of scrolling, etc.) but it gets cut-off.
you do not establish a positioning context, then the tooltip is not clipped but it has no clue where #some_bit is on the page.
I'm afraid you'll need JS to monitor where #some_bit is on the page and position the tooltip accordingly. You'd also need to kill that tooltip as soon as #some_bit is outside of the viewing area (not an issue if the trigger is mouseover).
Actually, if the trigger is mouseover then you may want to use the cursor coordinates to position the tooltip (versus calculating the position of #some_bit).
I would just put the tooltip outside of the #pane div and position it absolutely using JavaScript since you're using JS anyway.
I don't use Prototype so I don't know how it's done in Prototype, but in jQuery, you'd use $(element).position() to get the element position. If you have to do it manually, it's a little more complicated.
And you'll probably want to add a little extra logic to prevent the tooltip from extending outside of the document.
Edit: CSS used
#tooltip {
z-index: 9999;
display: none;
position: absolute;
}
JS used
Note: in jQuery, but it should be easy to change it to Prototype syntax.
$('#some_bit').hover(function() {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
// hovered element
var offset = $(this).offset();
var top = offset.top + docViewTop;
var left = offset.left;
var width = $(this).width();
var height = $(this).height();
var right = left + width;
var bottom = top + height;
// pane
var poffset = $('#pane').offset();
var ptop = poffset.top + docViewTop;
var pleft = poffset.left;
var pwidth = $('#pane').width();
var pheight = $('#pane').height();
var pright = pleft + pwidth;
var pbottom = ptop + pheight;
// tooltip
var ttop = bottom;
var tleft = right;
var twidth = $('#tooltip').width();
var theight = $('#tooltip').height();
var tright = tleft + twidth;
var tbottom = ttop + theight;
if (tright > pright)
tleft = pright - twidth;
if (tbottom > pbottom)
ttop = pbottom - theight;
if (tbottom > docViewBottom)
ttop = docViewBottom - theight;
$('#tooltip').offset({top: ttop, left: tleft});
$('#tooltip').css('display', 'block');
}, function() {
$('#tooltip').hide();
});
Edit: See it here.

Categories