In my current Silverlight project the amount of JavaScript is growing exponentially. Everything that I took for granted in Flash which took years to build and “perfect” now needed to be converted to JavaScript.

For the first beta release which is looming next week, the amount is about 130k. “Compressing” it with JSMin yields a file of 75kb in size. Yesterday I tried YUI Compressor which managed to squeeze it down to 65kb.

I’m very happy I no longer have to look at JSMin code which induces gag reflex and makes my eyes bleed. The amount of effort and self restraint it took not to rewrite it can not be described in words.

http://www.prototypejs.org/api/element/show

Documentation says:

Element.show cannot display elements hidden via CSS stylesheets. Note that this is not a Prototype limitation but a consequence of how the CSS display property works.

That’s completely false, because setStyle({ display: 'block' }) works just fine on elements hidden via CSS.

I was shocked to discover that finding a JavaScript library to work with browser cookies isn’t as easy as I expected. So I’m rolling my own solution.

This code allows to access cookies directly by name or an alias.

var Cookies = {
	aliases: {},

	alias: function(alias, name, defaultValue)
	{
		Cookies.aliases[alias] = name;

		Cookies[alias] = function(value, days)
		{
			if(value == null)
				return Cookies.get(name, defaultValue);
			else
				Cookies.set(name, value, days);
		}
	},

	set: function(name, value, days)
	{
		name = Cookies.aliases[name] || name;

		var expires = '';

		if(!isNaN(days))
		{
			var date = new Date();
			date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
			expires = "; expires=" + date.toGMTString();
		}

		document.cookie = name + "=" + escape(value) + expires + "; path=/";
	},

	get: function(name, defaultValue)
	{
		name = Cookies.aliases[name] || name;

		var regex = new RegExp(name + "s*=s*(.*?)(;|$)");
		var cookies = document.cookie.toString();
		var match = cookies.match(regex);

		if(match)
			return unescape(match[1]);

		return defaultValue;
	},

	erase: function(name)
	{
		Cookies.set(name, '', -1);
	}
}

// Create an alias for a cookie named 'a'
Cookies.alias('greeting', 'a', 0);

// Set the value
Cookies.greeting(parseInt(Cookies.greeting()) + 1);

// Display the value
alert(
	Cookies.greeting() + 'n' +
	Cookies.get('a') + 'n' +
	Cookies.get('greeting')
);

Sometimes you just want to store some data on the client to access it later. Sometimes you don’t even want to send it to the server. In this case, you can use something called ‘local storage’.

In Firefox it utilizes window.globalStorage which is a part of HTML 5 draft. Internet Explorer, unsurprisingly had this ability since version 5 using #default#userData behavior and unsurprisingly it’s somewhat awkward. Unfortunately, Safari/Webkit don’t seem to support local storage at all as of now, so this is more of a demo.

<html>
<body>

<script>
LockBox = {
	ensureStorage: function()
	{
		if(LockBox.storage != null)
			return;

		var storage;

		if(document.all)
		{
			storage = document.createElement("span");
			storage.style.behavior = "url(#default#userData)";

			if(document.body)
				document.body.appendChild(storage);
			else
				throw new Error("DomStorage works only after dom loaded");

			storage.load("lockbox");
		}
		else
		{
			storage = globalStorage[location.hostname];
		}

		LockBox.storage = storage;
	},

	set: function(name, value)
	{
		LockBox.ensureStorage();

		if(document.all)
		{
			LockBox.storage.setAttribute(name, value);
			LockBox.storage.save("lockbox");
		}
		else
		{
			LockBox.storage[name] = value;
		}
	},

	get: function(name, defaultValue)
	{
		LockBox.ensureStorage();

		var result = document.all
			? LockBox.storage.getAttribute(name)
			: LockBox.storage[name]
		;

		return result || defaultValue;
	}
}

//
// Here's a little demo.
//
var value = parseInt(LockBox.get('count', 0));
alert(value);
LockBox.set('count', value + 1);
</script>

</body>
</html>

This issue allows an attacker to insert inject random JavaScript code which could potentialy be very harmful. It’s the same exploit that was used by the MySpace Worm. If you are using sanitize(), this is something to be aware of.

sanitize("<div style=\"width: expression(alert('gotcha'))\">pure innocence</div>")

Causes an infinite loop alert box in IE 7. Currently applies to Ruby on Rails 1.2.2.