Log in

View Full Version : "autostretching" divs



ItsMeOnly
08-09-2006, 11:04 PM
IN http://rambo.id.uw.edu.pl/viewer.html I attempted to create "tableless" dwesign, and while it looks seemingly OK, it required some very fuzzy logic and obscure math to get that right: particularily "window border" and "scrolled window" divs have ugly hardcoded dimensions.

My question is: does anyone know or has heard of "snapping" divs to other elements' "containers" so their sizes are calculated by browser (they simply gonna stretch from A to B, even if position of B can be changed- yes, I want to implement "window resizing"), and are not needed to be hardcoded.

Twey
08-09-2006, 11:16 PM
You mean height: 100%; width: 100%; ? I don't quite grasp what you mean by:
"snapping" divs to other elements' "containers"

ItsMeOnly
08-09-2006, 11:28 PM
Well, in X/Motif terminology it would be something like this:
XmCreateWidget("appWindow", someWidgetClass,
"viewerAera",
XmNbottomAttachment, "statusBar",
XmNtopAttachment, "toolBar", ...);
...more or less,

There are no "attachments" in CSS (unfortunately), there's only positioning and dimensions, so I'm hoping somebody came with some workaround...

my point is, that div ("viewerAera") with height 100% inside another div ("appWindow") surrounded by top and bottom divs (the mentioned statusBar and toolBar id's), was going mad and rendered either thru the bottom "statusBar" div or on right side of it. I tried relative positioning, but then it went even worse because floating images in divs would simply overlap across the "bars".

Twey
08-09-2006, 11:32 PM
Aha, I see.

What you want to do, I think, is to put all three elements -- toolbar, window and status bar -- into one element and set their widths to 100%, then stretch the outer container.

ItsMeOnly
08-09-2006, 11:42 PM
not just that, the statusBar and toolBar should remain fixed in, in order, top and bottom of "appWindow" div, while "viewerArea" is meant to stretch "snapping" to them, when "appWindow" changes size.

Twey
08-09-2006, 11:52 PM
For that, you just need to give them fixed percentage heights.

ItsMeOnly
08-10-2006, 12:02 AM
... yeah, and that's the problem that raises obvious question: since IE doesn't support table, table-row, table-cell display properties (and it looks like IE7 still won't) I can't exactly use them, thus images and text inserted into divs, that need to be small in percentage, will overflow the box- theoretically I can use <br style="clear: both" />, but it's gonna create nocicable "gap" at the bottom of divs. I know, because tried...

Well, seems that the only solution is either not to care about 62% of viewers with IE :-p, or still having table-based layout :)

Twey
08-10-2006, 12:12 AM
If the divs are set to margin:0; padding:0; display:block; and overflow:hidden; that shouldn't be a problem.

ItsMeOnly
08-10-2006, 08:52 AM
http://rambo.id.uw.edu.pl/test.html
A test behaviour page demonstrating what happens and what I want to avoid

jscheuer1
08-10-2006, 09:40 AM
If everything is contained inside, say - a division with dynamic dimensions expressed in pixel units, you can use css style to set the contained elements:


float:left;

and their height and width to whatever percentage of the container that you wish them to occupy. Then they will stack from left to right across the container as long as their widths do not add up to more than 100% (or perhaps a little less). The one tricky part is that although IE will generally work OK with just that, all other browsers require you to have an empty division at the bottom of the container with its style set to:


clear:left;

Otherwise, you will have unfilled elements not extending for the height of the container.

If you want some/one of the content elements to wrap to the next line, either give them clear:left; style or make sure that the preceding row of elements adds up to 100% width.

ItsMeOnly
08-10-2006, 11:06 AM
all true, but watch what will happen when I apply such scheme- madness, bottom div renders completely outside main- red div, and in fact bottom yellow lies about its top position.

I think I came up with elegant solution, mainly simple javascript code to update dimensions of "green" div according to mouse movements.
check the file manager again (http://rambo.id.uw.edu.pl/fmanager.html)....

jscheuer1
08-10-2006, 05:41 PM
I don't see any green div at that location at present but, if you're happy with it, great!

ItsMeOnly
08-10-2006, 07:31 PM
http://rambo.id.uw.edu.pl
Except for viewer, the "window resizing" scripts have been implemented everywhere

Implementing "top resizing" raised another question: is there any way to make browser calculate blah.style.height and/or blah.style.bottom (as pixel values) except for hardcoding it (like in CSS)?
Exploder shows it as "undefined"; moz/FF leaves empty- thus I cannot "attach" bottom of "blah".

jscheuer1
08-10-2006, 09:43 PM
There's:

blah.offsetHeight

That will return the height of the element 'blah' as a raw number that represents the number of pixels of height it currently occupies.

Twey
08-10-2006, 09:58 PM
You might find these functions handy:
function Oblong(/* Number */ l, /* Number */ t, /* Number */ r, /* Number */ b) {
this.left = l;
this.top = t;
this.right = r;
this.bottom = b;
this.width = this.right - this.left;
this.height = this.bottom - this.top;
this.vcentre = this.top + this.height / 2;
this.hcentre = this.left + this.width / 2;
this.centre = { 'x' : this.hcentre, 'y' : this.vcentre };
};

/* boolean */ Oblong.prototype.collides = function(/*Oblong*/ your) {
var my = this,
inh = (my.left < your.right && my.right > your.left),
inv = (my.top < your.bottom && my.bottom > your.top);
return (inh && inv);
};

/* boolean */ Oblong.prototype.contains = function(/*Oblong*/ your) {
var my = this,
inh = (your.right > my.left && your.left < my.right),
inv = (your.bottom > my.top && your.top < my.bottom);
return (inh && inv);
};

/* boolean */ Oblong.prototype.isInside = function(/*Oblong*/ your) {
var my = this,
inh = (your.right > my.right && your.left < my.left),
inv = (your.bottom > my.bottom && your.top < my.top);
return (inh && inv);
};

/*Oblong*/ function getBoundingBox(/* HTMLElement */ obj) {
// Code inspired by quirksmode.org.
var curleft = 0,
oObj = obj;
if (obj.offsetParent)
while (obj.offsetParent) {
curleft += obj.offsetLeft;
obj = obj.offsetParent;
}
else if (obj.x) curleft += obj.x;

obj = oObj;

var curtop = 0;
if (obj.offsetParent)
while (obj.offsetParent) {
curtop += obj.offsetTop;
obj = obj.offsetParent;
}
else if (obj.y) curtop += obj.y;

var curright = curleft + oObj.offsetWidth,
curbottom = curtop + oObj.offsetHeight;

return new Oblong(curleft, curtop, curright, curbottom);
}

ItsMeOnly
08-10-2006, 10:07 PM
actually .offsetHeight was just the thing I was looking for, cause I can get parent.offsetHeight, I can get top and bottom bars' offsetHeights and automagically fit the middle div when resizing! Thanks!

Twey
08-10-2006, 10:59 PM
Yes, I just thought that, working with this kind of script, you might find those functions handy somewhere on down the line. :)

ItsMeOnly
08-10-2006, 11:17 PM
And here's the fruit of my all-day long labour :)
Prety lame sometimes, but I must admit it works very well...


function getMouse(e) {
if (navigator.appName.indexOf('Netscape') != -1) {
tempX = e.pageX
tempY = e.pageY
} else {
tempX = event.clientX + document.body.scrollLeft
tempY = event.clientY + document.body.scrollTop
}
}

document.onmousemove = getMouse;

function unlockSelect() {
document.onselectstart= function() { return true };
document.onmousedown= function() { return true };
}

function lockSelect() {
document.onselectstart= function() { return false };
document.onmousedown= function() { return false };
}

function relMouse() {
dragging = 0;

unlockSelect();
}

document.onmouseup = relMouse;

function snapMouse(what) {
var what;
pushUp(what);

myWin = document.getElementById(what);
if ((myWin.style.left == "") ||
(parseInt(myWin.style.left) == "NaN")) {
myWin.style.left = "110px";
};
if ((myWin.style.top == "") ||
(parseInt(myWin.style.top) == "NaN")) {
myWin.style.top = "133px";
};
myX = parseInt(myWin.style.left);
myY = parseInt(myWin.style.top);

if (myWin.style.height != "" || parseInt(myWin.style.height) != "NaN")
myWinHeight = parseInt(myWin.style.height);
else myWin.style.height == myWin.offsetHeight;


snapX = tempX;
snapY = tempY;

lockSelect();

dragging = 1;
}

function moveWin(what) {
var what;

if (dragging == 1) {

myWin.style.left = myX + (tempX - snapX) + "px";
myWin.style.top = myY + (tempY - snapY) + "px";

setTimeout("moveWin('" + what +"')", 7);
}
}

function resizeLeft() {
myWin.style.width = (snapRight - tempX + snapX > minWidth) ?
snapRight - tempX + snapX + "px" : minWidth + "px";
myWin.style.left = (snapRight - tempX + snapX > minWidth) ?
tempX + "px" : snapX + (snapRight - minWidth) + "px";
}

function resizeRight() {
myWin.style.width = (tempX - myX > minWidth) ?
tempX - myX + "px" : minWidth + "px";
}

function resizeTop() {
myWin.style.top = (snapHeight + (snapY - tempY) > minHeight) ?
myY + tempY - snapY + "px" : snapHeight - minHeight + snapY + "px";
if (myWinHeight) myWin.style.height = myWinHeight + (snapY - tempY) + "px";
}

function resizeDown() {
myWin.style.height = (tempY - myY > minHeight) ?
tempY - myY + "px" : minHeight + "px";
}

function resizeWin(what, how) {
var what;

if (dragging == 1) {

switch (how) {
case "t" :
resizeTop();
break;
case "tr" :
resizeTop();
resizeRight();
break;
case "r" :
resizeRight();
break;
case "br" :
resizeRight();
resizeDown();
break;
case "b" :
resizeDown();
break;
case "bl" :
resizeLeft();
resizeDown();
break;
case "l" :
resizeLeft();
break;
case "tl" :
resizeTop();
resizeLeft();
break;
}

setTimeout("resizeWin('" + what +"', '"+ how +"')", 7);
}
}

function getDimensions(what) {
var what;

myObj = document.getElementById(what);
snapHeight = parseInt(myObj.style.height);
snapWidth = parseInt(myObj.style.width);
if ((snapHeight < minHeight) || (snapHeight == "NaN"))
snapHeight = 350;
}

function trackSize(what, how) {
var what;
var how;

myObj = document.getElementById(what);

if (dragging == 1) {
if (how == "tl" || how == "t" || how == "tr") {
myObj.style.height = (snapHeight + (snapY - tempY) < minHeight) ?
minHeight + "px" : snapHeight + (snapY - tempY) + "px";
} else myObj.style.height = (snapHeight + tempY - snapY < minHeight) ?
minHeight + "px" : snapHeight + (tempY - snapY) + "px";
setTimeout("trackSize('" + what + "', '" + how + "')", 7);
}
}

function doResize(what, how, keeptrack) {
snapMouse(what);
if (keeptrack) getDimensions(keeptrack, how);
else {
snapHeight = 100;
myWinHeight = 230;
}
snapRight = parseInt(myWin.style.width);
resizeWin(what, how);
if (keeptrack && how != "l" && how != "r") trackSize(keeptrack, how);
}

mburt
08-11-2006, 12:41 AM
Yes, I find offsetLeft, and offsetTop quite handy too, for Drag and Drop scripts, check this out:


<html>
<head>
<script type="text/javascript">
var ie = document.all
var ns = document.getElementById && !ie
function dragbyclass(e) {
var fobj = ns ? e.target : event.srcElement
if (fobj.tagName=="DIV" && fobj.className=="drag") {
var ev=e||event
var offsetx=ev.clientX-fobj.offsetLeft
var offsety=ev.clientY-fobj.offsetTop
document.onmousemove=function() {
fobj.style.left=ev.clientX-offsetx
fobj.style.top=ev.clientY-offsety
return false
}
fobj.onmouseup=function() {
document.onmousemove=null
}
}

}
document.onmousedown=dragbyclass
</script>
<style type="text/css">
.drag {
width:200px;
height:200px;
position:absolute;
border:1px solid black;
background:silver
}
</style>
</head>
<body>
<div class="drag" style="left:40px;top:60px;border:1px solid gray">Drag Box</div>
</body>
</html>

Twey
08-11-2006, 01:02 AM
var ie = document.all
var ns = document.getElementById && !ieUh-uh. No browser detection here please :)
var ev = e || window.event;
var fobj = ev.target || ev.srcElement;

ItsMeOnly
09-11-2006, 08:35 PM
Sorry if anyone finds "bumping" of this thread unappropiate- but I came across "terrifying":) discovery: offset* can lie when contents of element overflow it, OR cause its box to resize. you can observe the effect in "file manager" http://rambo.id.uw.edu.pl/fmanager.html where bottom of the window will "run" when you try resize either down or upwards. it seems to keep the appropiate size, so it's not computation error though.

Checked IEs and FF, happens in both- in IE the effect is more noticable