For fun I asked a few friends for ideas on a random color generator in a single line of javascript. You know, these guys: #0afec0, #c9f2d0, #9b923e.
Here's what we came up in about two minutes (in chronological order)…
'#' + (function co(lor){ return (lor +=
[0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'][Math.floor(Math.random()*16)])
&& (lor.length == 6) ? lor : co(lor); })('');
Similar recursive technique, but using a string instead of an array and aliasing the Math object:
(function(m,s,c){return (c ? arguments.callee(m,s,c-1) : '#') +
s[m.floor(m.random() * s.length)]})(Math,'0123456789ABCDEF',5)
Using a named function expression instead of arguments.callee.
'#'+(function lol(m,s,c){return s[m.floor(m.random() * s.length)] +
(c && lol(m,s,c-1));})(Math,'0123456789ABCDEF',4)
If we assume JavaScript 1.6, then we could just use Array.map():
'#'+'0123456789abcdef'.split('').map(function(v,i,a){
return i>5 ? null : a[Math.floor(Math.random()*16)] }).join('');
But then, the magic of Math struck (16777215 == ffffff in decimal):
'#'+Math.floor(Math.random()*16777215).toString(16);
Thx to ben alman, nlogax, and temp01 for their smarts.
Paul Irish javascript
There are a few things that a console.log wrapper can and should do:
- Prevent errors if a console isn't around (i.e. IE)
- Maintain a history of logs, so you can look in the past if your console is added afterwards (e.g. firebug lite)
- Normalize the browser differences in console integration (e.g. when passing multiple arguments into
console.log())
- For something you type regularly, make it quicker to type for the lazy among us.
But there are a few considerations…
Console.log.apply doesn't handle multiple arguments in Safari 3 or Chrome 1.1
Firebug, Chrome, and Safari have a clearer presentation for strings when inside an array: 
However while the improved array-wrapped presentation is nice, nested arrays get truncated: 
Truncation is no good, so here we avoid array-wrapping when we can.
Extra features
- A reverse-chronological history, accessible as an array at
log.history
- I have also included a shorthand
logargs() function that is useful when you're inside a function and want to know the context and arguments passed in. I use it a lot in ajax callbacks. Worth noting that it uses arguments.callee.caller, which will be deprecated in ECMAScript 5 Strict mode. :(
The code:
window.log = function(){
// store logs to an array for reference
log.history = log.history || [];
log.history.push(arguments);
window.console && console.log[console.firebug ?
'apply' : 'call'](console,Array.prototype.slice.call(arguments));
}
// logargs(this); == console.log(this,arguments);
window.logargs = function(context){
// grab the calling functions arguments
log(context,arguments.callee.caller.arguments);
}
And if you'd like it minified:
window.log=function(){var a="history";log[a]=log[a]||[];log[a].push(arguments);window.console&&console.log[console.firebug?"apply":"call"](console,Array.prototype.slice.call(arguments))};window.logargs=function(a){log(a,arguments.callee.caller.arguments)};
Interestingly, the minified version of this script is smaller (262 bytes), and arguably more useful, than the minified firebugx.js, which I've covered before. Plus it has quite a few more features.
Demo?
log() and logargs() demo
Plus Firebug lite?
You got it. This bookmarklet will add firebug lite, and then output the logged history when it's ready:
>>> Fbug Lite+log <<<
Want more power?
After writing this, I worked with Ben Alman on a more comprehensive and robust logging script. It's excellent if you take full advantage of the console API. And you should be aware that Safari 4 and Chrome 2 have most of that API supported. Make full use of it and don't you dare type another alert()!
Paul Irish javascript
There are a few cases where you want to know if the user is idle. Namely:
- You want to preload more assets
- You want to grab their attention to pull them back
- You want close their banking session after 5 minutes of inactivity. (Jerk!)
- You want the site to sneak off the screen and see if they notice ;-)
Nick Zakas wrote a script for YUI3 to handle these cases. His writeup has a great description of the architecture approach he took to the script.
In my jQuery adaptation, I did a few different things:
- Leveraged event namespaces for easy unbinding
- Considered mousewheel as activity, in addition to keyboard and mouse movement.
- Gave it a bit more jQuery-ish of an API
To use:
// idleTimer() takes an optional argument that defines the idle timeout
// timeout is in milliseconds; defaults to 30000
$.idleTimer(10000);
$(document).bind("idle.idleTimer", function(){
// function you want to fire when the user goes idle
});
$(document).bind("active.idleTimer", function(){
// function you want to fire when the user becomes active again
});
// pass the string 'destroy' to stop the timer
$.idleTimer('destroy');
Get the source on github (4.6k unminified)
View the demo
Note: If you want to change the timeout interval, you'll have to destroy the existing timer first.
2009.09.22: I've updated the idleTimer script for a few more features…
// you can query if the user is idle or not with data()
$.data(document,'idleTimer'); // 'idle' or 'active'
// you can get time elapsed since user when idle/active
$.idleTimer('getElapsedTime'); // time since state change in ms
You can get the latest code, naturally, on github.
Paul Irish jquery