Am not very familiar with CSS, but I have a few comments on strictly the JS related parts:
calcfailback
I would call this calcFailback
or calc_failback
.
one var statement
It's fairly standard practice to only have 1 var statement per scope. This is because JS does hoisting where it essentially pulls all variable declarations to the top of a scope anyway.
function f() {
var x = 5;
if (x == 5) {
var y = 10;
}
}
Is actually silently equivalent to:
function f() {
var x = 5;
var y;
if (x == 5) {
y = 10;
}
}
For this reason (or more particuarly, the odd bugs this can lead to if you forget that it's silently interpretted as this), it's a fairly widespread practice to only use 1 var declaration per scope:
function f() {
var x = 5,
y;
...
}
There's no point in a no-op branch
if (newwidth == "10") {}
That's fairly pointless. There are some border situations where having an empty branch can be useful, but for a trivial one like this, just do:
if (newwidth != "10") { ... }
Variable naming
I would use either underscores or camelCase so that there's some kind of visual separation of words. new_width
and newWidth
are much easier to read and understand than newwidth
.
Functions that call other functions are usually pointless
var x = function () { f(); };
All this does is create a function bound to x
that when called, calls f
.
Unless you specifically want to do this to hide the calling context, it's usually better to just write it as:
var x = f;
In this situation, x()
still calls f
, it just does it without the layer of indirection.
On a technical note though, these are different. A function without a context defaults to the window
object as the context (or undefined
in strict mode).
This means that this
inside of f may be different depending on how x
is called.
For example:
function f() {
console.log(this);
}
var x = function() { f(); },
obj = {foo: "bar"};
x.call(obj); //The console.log will output either window or undefined depending on strict mode
//('this' inside of the wrapper function, however, would be obj)
Compared to:
function f() {
console.log(this);
}
var x = f,
obj = {foo: "bar"};
x.call(obj); //The console.log will output obj (in other words, 'this' inside of 'f' would be 'obj'
Your script clobbers any other scripts
When you assign the window.onload
and window.onresize
properties, you may be over writing old handlers.
"But this is the only script on my page!" You say.
Well, it's the only script for now.
For the sake of avoiding odd future bugs, I might make a simple little function to stack binding instead:
function bindEvt(target, evt, func) {
var prev = target[evt];
if (typeof prev !== "function") {
target[evt] = func;
} else {
target[evt] = function() {
prev.apply(this, Array.prototype.slice.call(arguments));
func.apply(this, Array.prototype.slice.call(arguments));
};
}
return target[evt];
}
It would be used like:
function f() { ... };
bindEvt(window, "onresize", f);
(Note: this really should be used as an idea than an actual implementation. I'm entirely sure that there's at least one major problem with this function.)
Suggested implementation
I might write it something like this:
// CSS calc() replacement
function calcFailback(){
var d = document.createElement('div'),
_body = document.getElementsByTagName('body')[0],
newWidth;
//functions are actually hoisted too, though in a silenty different way
function resize() {
document.getElementById('content').style.height = window.innerHeight - 40 + 'px';
document.getElementById('content').style.width = window.innerWidth - 300 +'px';
document.getElementById('sidebar').style.height = window.innerHeight - 40 + 'px';
}; //You will not usuaully see a ; here. There's nothing wrong with it though.
_body.appendChild(d);
d.style.visibility = 'hidden';
d.style.width = "-webkit-calc(10px)";
d.style.width = "-o-calc(10px)";
d.style.width = "-moz-calc(10px)";
d.style.width = "calc(10px)";
newWidth = d.offsetWidth;
if (newWidth != "10") { //I might use either !== "10" or !== 10 if you know the type
resize();
window.onresize = resize;
//I might consider inlining the function defition since it's a simple function.
//You could use a structure like:
//window.onresize = function() { ... };
//window.onresize();
//This is not the same thing as a legitimate onresize event happening though, so you'd need to be
//careful to make sure that your handler is capable of handling fake events like this.
//A bit more 'authentic' way might be:
//window.onresize.call(window); since the handler is probably (I'm not sure) called with window as the context
//This would still neglect the parameters though.
} //There was no reason for the ; here
_body.removeChild(d); //This should have a ; here (mainly for styling purposes in this context, but it's a good habit for situations where it does matter)
}
Edit
For what it's worth, here's a (very) crude example of using a bindEvt like function: jsfiddle.