Child element position relative working wrong - javascript

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.

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

converting area element to div

I am a beginner in Javascript/jQuery. Thank you for reading!
EDIT:
Here is a jsfiddle with all of the code (annotated) https://jsfiddle.net/sfs1926/n1sopf79/
It does not work, but here is a working example video of what my code does so far: https://www.youtube.com/watch?v=N67Bx9jgPFo
The context is: I am trying to model layers of electronics (represented as rectangles) on a graph. There are 10,000 overlapping rectangles (each representing the position of a piece of electronics). I write these area elements in line by line from a text file that contains the coordinates of each rectangle and its title. I associate each area element with its title using an overlay id. My goal: When I mouse over a pixel on the graph, I want to display ALL rectangles associated with that pixel and their overlay id's (to the side, off the graph). So far I am able to do all of this besides displaying the rectangles.
Right now I have a HTML map 'demo' containing many area elements (all rectangles). I want to use jQuery to push each of those area elements into the array elementPositions. This I do successfully below, but with one exception: I want to create the identifier 'element' to be that area element written as a div with css. This is because I want to show and hide rectangles belonging to elementPositions using the .show() method. That is why I am converting the area elements to be divs.
Can someone help me with the syntax for how to do this conversion? I think the reason why no rectangle will 'show' is because I have not set the display or the background attribute of the div, but I'm not sure how to do this.
if( $('#demo').length >0 ) {
var elementPositions = [];
$('#demo area').each(function() {
var offset = this.coords;
var coordarray = offset.split(",");
var left = coordarray[0];
var top = coordarray[1];
var right = coordarray[2];
var bottom = coordarray[3];
var id = this.id;
var wid = right - left;
var hei = bottom - top;
var hoveredElements = [];
elementPositions.push({
element: $('<div class="area"></div>')
.css({position: 'absolute', left: left, top: top}).
width(wid).height(hei), // attempt so far!
top: top,
bottom: bottom,
left: left,
right: right,
id: id,
});
Then I hope to do something like:
$("body").mousemove(function(e) {
elementPositions.forEach( function(item) {
item.element.show();
});
}
you need to append your div before show it, append to body for example :
var elementDiv = $('<div class="area"></div>')
.css({position: 'absolute', left: left, top: top}).
width(wid).height(hei);
$("body").append(elementDiv );
elementDiv.hide();
elementPositions.push({
element: elementDiv ,
top: top,
bottom: bottom,
left: left,
right: right,
id: id,
});

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.

Moving the placement a div in 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

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