As far back as I can remember, Web 2.0 has been synonymous with Table-less layout. And table-less layout has been limited by one major, major problem:
There is no way to set the width of two elements that are placed side by side.
The div is a 'block level' element. This means that it can receive a width and height. But it also means it cannot share a line inside its parent with any other element.
Ditto for the H1 - H6, Pre, P, and all other block level elements.
The span is an 'inline element'. This means that you can place as many spans as you need side by side on the same line. However, you cannot set a width on an inline-element and expect that width to be kept cross-browser.
Ditto here for the a, em, strong, and other inline elements.
The img and button elements exist they way we need - their dimensions can be set, but they do not need their own line. However, there is no easy way to put content inside these elements.
The CSS specs do have a solution: a style called inline-block. But inline block in IE is only kept by the span and a, and even thre it is buggy. In Firefox it is not kept at all.
(Note: inline-block works great in FF3, which is expected out in mid February. It is also up to par in IE8, expected out in mid 2009. Don't hold your breadth.)
There does exist one "easy" solution - floats. A floated div can have other divs alongside it in the same row, and they can have their widths and height set. But, they have plenty of their own baggage. If you are not familiar with floats I suggest you go learn them (at w3schools). Trust me that they are not the panacea you need to move into a table free environment.
Floats aside, there are three techniques that exist around the web (If someone knows another, please let me know).
1) Amending the button. [credit: Mozilla]
As said above, there are two elements that are inline-block by default: the img and the button. There exists no way to put anything into the img tag other other than an image or alternate text, so there is no real way to use it.
The button element does accept inner html, so as long as you clean up all the default css it can be used quite simply. Below is the neccessary code:css type="text/css"
button.fix{border:none; background:inherit; font:inherit; color:inherit; vertical-align: bottom;}
example usage (it seems blogger eats all the carrots):
button class="fix" style="WIDTH: 150px"
User
/button
input name="user"/
button class="fix" style="WIDTH: 150px"
Password
/button
input name="pass" type="password" /
This is a great technique for when you just have a little bit of text that needs a certain width, such as in the form above.
However it is semantically a sin, so for the same effort you might as well use tables.
Especially if you will be using it to house a large section of your html.
Also, the text inside the button is not selectable (after all, it is a button) so for anything more than a little text it is usually useless.
2) Filling out the span
3) Wrapping the div:
By far the most popular method for dealing with this problem is by wrapping the block element with an inline element (ie. put the div into a span). To paraphrase the w3c: The inside div is formatted as a block box, and the outer element is formatted as an inline replaced element.
Since this doesn't work out of the box, there are a few hacks:
a) The fieldset:
Set a fieldset's display to inline and remove the default css border and margin and wrap it around your div (or around a span, etc. that you set to display:block). Width and height properties should remain on the div.
Example:
fieldset.fix{display:inline; margin:0; border:0}
fieldset class="fix"
div style="width:200px; background-color:red"
Woot!
/div
/fieldset
fieldset class="fix"
div style="width:200px; background-color:red"
Woot the second!
/div
/fieldset
b) The table
Exactly the same as the fieldset, but using a table instead (If you are using this, you should consider using a *gasp* table):
table.fix{display:inline; margin:0; padding:0}
table class="fix" tr td
div style="width:200px; background-color:red"
Woot!
/div
/td /tr /table
table class="fix" tr td
div style="width:200px; background-color:red"
Woot the second!
/div
/td /tr /table
These have the advantage of not throwing any error by the w3c validator, as they are both originally block elements, and may contain a div.
c) the span
IE recognises display-block on a span, so the real hack is needed for FF. While the following solution works, and may someday be considered better code, it currently does not validate.
Set a span's display to both -moz-inline-box and inline-block and wrap it around your div (or around a span, etc. that you set to display:block). Width and height properties should remain on the div. Note that you can use -moz-inline-stack or -moz-groupbox instead of -moz-inline-box, I could not find a difference.
Note that theoretically, you should be able to use any inline block as the wrapping span, as long as it is set to display:inline or is naturally inline. However, Caveat Emptor! Quirky things happen in strict mode! For example, you can use a strong, but not an em. And when the entire span/div is inside pres, it acts different than when inside Hs.
span.fix{display:-moz-inline-box; display:inline-block}
span class="fix"
div style="width:200px; background-color:red"
Woot!
/div
/span
span class="fix"
div style="width:200px; background-color:red"
Woot the second!
/div
/span
There are several drawbacks to all of these techniques.
The first is that you have a block inside an inline element which should not be valid (even if the parser does not catch it).
The second is that there is no way to set a percentage based width. (IE actually renders the width of the inner div the way we would like it, even when using a percentage based width. This is not technically correct, as any percentage of the parent - which has no set width - should be 0, but it would've been useful if the FF team would've granted us this infraction.)
The third is that the browsers treat these div as being truly inline. Which means that when you put the two divs on separate lines in your code, you get a space between the inline-blocked divs. Just as when you put text on two lines in your code, they appear in the browser with a space between them.
This is hard to describe, but when you try to implement the code it shows up right away. We are used to opening and closing divs each on their own lines and having them show up seamlessly in the browser.
It is also avoidable; as long as the fieldsets/spans are closed and reopened on the same lines, it doesn't matter whether or not the divs inside them are on separate lines. But don't take it lightly or it will bite you.
d) the Div
Wrapping the div with a div solves all of the problems mentioned above, but requires a bit more markup. Kudos to Suzy at WebmasterWorld for first pointing it out (I have since seen it elsewhere.)
The extra markup here is several fold:
i. two(!) outside wrapping divs.
ii. on one line {display:-moz-inline-stack; display:inline-block}
iv. on a separate line, but only for IE {display:inline}
v. the width must be on every one of the divs, or if percentage, the inner widths need 100%.
vi. Even with all this, it doesn't work. but I working on getting it, I must be missing something obvious.
Monday, January 7, 2008
Setting flags
A flag in most languages is a variable that is only used to tell the state of a different object.
For example, you can have a button change alternate a flag every time it is pressed to know if it's state should be on or off.
var flag:Boolean = false;
function btnPress(){
if(flag == false) {
flag = true;
//code to make the thing move around the stage
} else{
flag = true;
//code to make the thing stop moving
}
By far the most common flags need only two states (such as in the code above), true and false.
While the code above is not entirely uncommon, it is entirely inefficient. Here are some better techniques:
1) Use the Bang (!) operator: [flag = !flag;]
The bang means 'not', the opposite of false is true, and not true is false
var flag:Boolean = false;
function btnPress(){
flag = !flag;
if(flag == false) {
//code to make the thing move around the stage
} else{
//code to make the thing stop moving
}
3) Use a modulized number [flag = ++flag%2;]:
While a bit messier than the last method, this has a huge advantage - you can set a flag for an unlimited number of states. Eg. If you want to keep track of which row in a table you are in, change the limit to match.
This works as follows:
++ before a variable increments the value by one.
% means that when it reaches the number after the '%', it should start again from zero.
The first time this is called, flag becomes '1'. The second time, flag is made into a '2', which is than modulized into a zero. The third time it is moved back to '1', etc.
var flag:Number = 0;
var rows:Number = 5;
function tblFill(){
flag = ++flag%rows;
if(flag == 0) {
border-left:solid;
} else if(flag==5){
border-right:solid;
} else{
border:none;
}
3) Use a ternary [flag = flag ? false : true;]:
This is not as neat as the first method, but has an advantage (I might post about later).
var flag:Boolean = false;
function btnPress(){
flag = flag ? false : true;
if(flag == false) {
//code to make the thing move around the stage
} else{
//code to make the thing stop moving
}
4) Use absolute numbers: [flag = Math.absolute(--flag);]
I cannot think of any advantage to this method, 'cept that it's really ingenious, and came from a programmer I respect.
The math.absolute function converts a number to a positive value. So that absolute -5 is the same as absolute 5.
-- decrements a value, so the second time this is run, flag becomes -1, and is than made into a 1 via the absolute. The second time it becomes a 0. The third time, back to 1, etc.
var flag:Number = 0;
function btnPress(){
flag = Math.absolute(--flag);
if(flag == false) {
//code to make the thing move around the stage
} else{
//code to make the thing stop moving
}
The first two are very, very, useful.
For example, you can have a button change alternate a flag every time it is pressed to know if it's state should be on or off.
var flag:Boolean = false;
function btnPress(){
if(flag == false) {
flag = true;
//code to make the thing move around the stage
} else{
flag = true;
//code to make the thing stop moving
}
By far the most common flags need only two states (such as in the code above), true and false.
While the code above is not entirely uncommon, it is entirely inefficient. Here are some better techniques:
1) Use the Bang (!) operator: [flag = !flag;]
The bang means 'not', the opposite of false is true, and not true is false
var flag:Boolean = false;
function btnPress(){
flag = !flag;
if(flag == false) {
//code to make the thing move around the stage
} else{
//code to make the thing stop moving
}
3) Use a modulized number [flag = ++flag%2;]:
While a bit messier than the last method, this has a huge advantage - you can set a flag for an unlimited number of states. Eg. If you want to keep track of which row in a table you are in, change the limit to match.
This works as follows:
++ before a variable increments the value by one.
% means that when it reaches the number after the '%', it should start again from zero.
The first time this is called, flag becomes '1'. The second time, flag is made into a '2', which is than modulized into a zero. The third time it is moved back to '1', etc.
var flag:Number = 0;
var rows:Number = 5;
function tblFill(){
flag = ++flag%rows;
if(flag == 0) {
border-left:solid;
} else if(flag==5){
border-right:solid;
} else{
border:none;
}
3) Use a ternary [flag = flag ? false : true;]:
This is not as neat as the first method, but has an advantage (I might post about later).
var flag:Boolean = false;
function btnPress(){
flag = flag ? false : true;
if(flag == false) {
//code to make the thing move around the stage
} else{
//code to make the thing stop moving
}
4) Use absolute numbers: [flag = Math.absolute(--flag);]
I cannot think of any advantage to this method, 'cept that it's really ingenious, and came from a programmer I respect.
The math.absolute function converts a number to a positive value. So that absolute -5 is the same as absolute 5.
-- decrements a value, so the second time this is run, flag becomes -1, and is than made into a 1 via the absolute. The second time it becomes a 0. The third time, back to 1, etc.
var flag:Number = 0;
function btnPress(){
flag = Math.absolute(--flag);
if(flag == false) {
//code to make the thing move around the stage
} else{
//code to make the thing stop moving
}
The first two are very, very, useful.
Hitting the frogs (VaEra)
The Medrash, quoted by Rashi, says that only one large frog came out of the water. When someone tried to kill it, it split into two. Each of these in turn also split into two when attacked, as did each of the new ones, until there were many, many, frogs.
The question is asked, when they saw that their attempts to kill the frogs were working against them, why did they continue hitting the frogs?
The Baalei Mussar use this as the quintessential example of how people act irrationally while in a rage.
However, when I was in high school, they taught us a different explanation:
It wasn't the Egyptians hitting the frogs, it was the Jews.
The Jews could safely leave to Goshen as soon as things got out of control, but think of the fun hitting the frogs and letting them multiply again and again.
The question is asked, when they saw that their attempts to kill the frogs were working against them, why did they continue hitting the frogs?
The Baalei Mussar use this as the quintessential example of how people act irrationally while in a rage.
However, when I was in high school, they taught us a different explanation:
It wasn't the Egyptians hitting the frogs, it was the Jews.
The Jews could safely leave to Goshen as soon as things got out of control, but think of the fun hitting the frogs and letting them multiply again and again.
Before going on to the next thought we should apply the principals from the last post to ternaries:
Simply, just as
if(val = true) alert(val);
first sets val to true, than evaluates 'val' [and calls the alert].
Similarly,
(val = true) ? alert('val') : null;
also sets val to true, and than evaluates val [and calls the alert].
However, this leads us into an interesting scenario (which has tripped up many a developer) which should be better explained.
In JS & related languages, the ternary can be used to assign a value as well as to run functions. So that the following are both legal, and both assign "less" to val:
var val = (5<6 ? "less" : "more");
(5 < 6) ? val = "less" : val = "more";
It is usually pretty clear which statement it should calculate, but not always:
main = false ? val = 0 : val = 1;
Watch out there - I didn't use two equals (main == true)! We are not evaluating main, we are assigning it a value!
This can mean either:
(main = false) ? val = 0 : val = 1;
ie:
if (main = false) val = 0;
else val = 1;
which will first assign false to main, then will evaluate main, and run the second half of the function, which assigns 1 to val
Or:
main = (false ? val = 0 : val = 1);
ie:
main = (
if(false) val = 0;
else val = 1;
)
which will evaluate the false, and assign 1 to val, than assign val to main, in which case they both become 1.
The answer is.......
The second way: which results in main = val = 1!
Unless clearly evaluating a statement, it will assume that it is setting a value.
Once at it:
val1 = val2 = false ? val = 0 : val = 1;
is the same as: val1 = (val2 = (false ? val = 0 : val = 1));
Which obviously will translate with all the values being equal to 1.
And the following if will run conditional and alert "1". (main = val = 1):
if (main = false ? val = 0 : val = 1;) alert (main) ;
Whereas if we would put the condition in parenthesis it will run, but will alert "false":
if ((main = false) ? val = 0 : val = 1;) alert (main) ;
It will still run, since by the time it has finished dealing with the ternary it's as though it says:
if (val = 1;) alert (main) ;
or even if (val) alert(main);
However, main is set to false in the midst of the assigning.
Simply, just as
if(val = true) alert(val);
first sets val to true, than evaluates 'val' [and calls the alert].
Similarly,
(val = true) ? alert('val') : null;
also sets val to true, and than evaluates val [and calls the alert].
However, this leads us into an interesting scenario (which has tripped up many a developer) which should be better explained.
In JS & related languages, the ternary can be used to assign a value as well as to run functions. So that the following are both legal, and both assign "less" to val:
var val = (5<6 ? "less" : "more");
(5 < 6) ? val = "less" : val = "more";
It is usually pretty clear which statement it should calculate, but not always:
main = false ? val = 0 : val = 1;
Watch out there - I didn't use two equals (main == true)! We are not evaluating main, we are assigning it a value!
This can mean either:
(main = false) ? val = 0 : val = 1;
ie:
if (main = false) val = 0;
else val = 1;
which will first assign false to main, then will evaluate main, and run the second half of the function, which assigns 1 to val
Or:
main = (false ? val = 0 : val = 1);
ie:
main = (
if(false) val = 0;
else val = 1;
)
which will evaluate the false, and assign 1 to val, than assign val to main, in which case they both become 1.
The answer is.......
The second way: which results in main = val = 1!
Unless clearly evaluating a statement, it will assume that it is setting a value.
Once at it:
val1 = val2 = false ? val = 0 : val = 1;
is the same as: val1 = (val2 = (false ? val = 0 : val = 1));
Which obviously will translate with all the values being equal to 1.
And the following if will run conditional and alert "1". (main = val = 1):
if (main = false ? val = 0 : val = 1;) alert (main) ;
Whereas if we would put the condition in parenthesis it will run, but will alert "false":
if ((main = false) ? val = 0 : val = 1;) alert (main) ;
It will still run, since by the time it has finished dealing with the ternary it's as though it says:
if (val = 1;) alert (main) ;
or even if (val) alert(main);
However, main is set to false in the midst of the assigning.
Sunday, January 6, 2008
First Post on blogger.
The blog on jewishmusic.net is down for a bit, and I figured if I don't write stuff down they'll be forgotten, so we'll start with a thought on evaluations:
When evaluating terms inside a parenthesis, JS (or any other language) looks for a true or false value. For example, in the following conditional, the browser will alert 'true':
if (true) alert ('true');
Where the value is not a Boolean, JS must convert it to one. Generally, anything besides false, 0, and an undefined variable evaluates to true.
so (4), (-1), and ('potatoes') are the same as (true).
There is a common mis-belief that when given a statement, JS will return true if it successfully carries out the statement, and false if it does not. This is NOT correct. Instead JS will carry out the statement, and than evaluate the results.
So that in truth (2+4) will return true, since it is the same as (6).
(4-4) will return false, since it is the same as (0).
if (val = false) will evaluate to false and not run, since it is read the same as:
val = false; if(val)...
JS first assigns false to the val variable, and then evaluates the val variable.
Many, many a programmer gets stuck on this, so file it somewhere useful, when the code acts unexpectedly.
The blog on jewishmusic.net is down for a bit, and I figured if I don't write stuff down they'll be forgotten, so we'll start with a thought on evaluations:
When evaluating terms inside a parenthesis, JS (or any other language) looks for a true or false value. For example, in the following conditional, the browser will alert 'true':
if (true) alert ('true');
Where the value is not a Boolean, JS must convert it to one. Generally, anything besides false, 0, and an undefined variable evaluates to true.
so (4), (-1), and ('potatoes') are the same as (true).
There is a common mis-belief that when given a statement, JS will return true if it successfully carries out the statement, and false if it does not. This is NOT correct. Instead JS will carry out the statement, and than evaluate the results.
So that in truth (2+4) will return true, since it is the same as (6).
(4-4) will return false, since it is the same as (0).
if (val = false) will evaluate to false and not run, since it is read the same as:
val = false; if(val)...
JS first assigns false to the val variable, and then evaluates the val variable.
Many, many a programmer gets stuck on this, so file it somewhere useful, when the code acts unexpectedly.
Subscribe to:
Comments (Atom)