Archive

Archive for the ‘Programming’ Category

Easily cache results from Javascript functions

September 21st, 2009 Gunnar Steinn 6 comments

UPDATE: Adrian Quark has a much safer approach for the cache in his comment. I guess I should have tested mine better with other functions than the computational ones I was doing :)

A short Javascript function I made in a project to cache result from functions in Javascript. You can use this function where it makes sense to cache.

The cache method

cacheMethod.cache = {};

function cacheMethod(context, fn) {
	var funcName = fn.toString();
	funcName = funcName.substr('function '.length);
	funcName = funcName.substr(0, funcName.indexOf('('));

	context[funcName] = function() {

		if (cacheMethod.cache[funcName] == null)
			cacheMethod.cache[funcName] = {};

		// Create a unique key of parameters
		var key = Array.slice.call(arguments).join('|');
		if (cacheMethod.cache[funcName][key] == null)
			cacheMethod.cache[funcName][key] = fn.apply(this, arguments);

		return cacheMethod.cache[funcName][key];
	};
}

Usage
If we have a function like isPrime borrowed from John Resig:

function isPrime( num ) {

  var prime = num != 1; // Everything but 1 can be prime
  for ( var i = 2; i < num; i++ ) {
    if ( num % i == 0 ) {
      prime = false;
      break;
    }
  }

  return prime;
}

we can make the isPrime function cache-able with a single line of:

cacheMethod(this, isPrime);

No when we try to call the isPrime 100 times with a large prime number, this first round is calculated and all subsequent rounds use the cache. You can see the difference by removing the cacheMethod line.

for (var i=0; i<100; i++)
		document.write(isPrime(58750291)+'<br/>');

Full example here: cache.html.

Categories: Programming Tags:

How custom HTML tags like Facebook Connect uses work

September 15th, 2009 Gunnar Steinn No comments

While looking at the Facebook Connect API I was curious to see that it uses custom XML tags for it’s elements, for example <fb:login-button/>. After the page is loaded the tag is replaced with <a href="..." ><img src='...' /></a> if the user is not logged in and a profile image and name if the user is already logged in.

So I could better understand how this works I created a little sample were I extracted the important parts from the API. The sample takes in a instance of an User object and displays a profile picture and name of the user with the gs:profile-image and gs:profile-text tags.

First there is the main parser. It starts by defining the objects of the sample API in an array of knownElements. Then the parseDomTree function loops through all of the known elements and find all objects in the document that correspond to that tag.

gsml.js

var GS = {};
GS.GSML = {
	ProfileText : function(el) {
		var span = document.createElement('span');
		span.innerHTML = GS.user.username;
		el.innerHTML = "";
		el.appendChild(span);

	},
	ProfileImage : function(el) {
		// Some logic to create the image from the logged in user
		var img = document.createElement('img');
		img.setAttribute('src', GS.user.img);
		img.setAttribute('onclick', el.getAttribute('clickhandler'));
		el.innerHTML = "";
		el.appendChild(img);
	}
};

GS = {
	knownElements : [
		{key:'profile-image', class:GS.GSML.ProfileImage},
		{key:'profile-text',  class:GS.GSML.ProfileText}],
	user : null,

	init : function(user) {
		this.user = user;
	},

	parseDomTree : function(context) {

		// Loop through all known elements in our namespace
		for (var i=0; i<this.knownElements.length; i++) {

			// Find all tags for current known element
			var elements = context.getElementsByTagName("GS:"+ this.knownElements[i]['key']);
			for (var j=0; j<elements.length; j++) {

				// Call the associated function to parse this tag
				this.knownElements[i]['class'](elements[j]);
			}
		}
	}
};

In the HTML that uses the sample API there are four elements of interest; include of the sample javascript api, define the User object, tell the API to parse the DOM and add the custom API tags to the HTML body.

thefile.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:gs="http://www.gunnarsteinn.com/2009/gsml">
<head>
<script type="text/javascript" src="gsml.js"></script>
<script type="text/javascript">
	var user = {
		username : 'Click Image',
		img : 'http://www.gunnarsteinn.com/wp-content/uploads/tf.jpg'
	};

	function imgClicked() {
		user.username = 'Tobias Funke';
		GS.parseDomTree(document);
	}
</script>
</head>
<body onload="GS.init(user); GS.parseDomTree(document)">

<gs:profile-image clickhandler="imgClicked();"></gs:profile-image>
<gs:profile-text></gs:profile-text>
</body>
</html>

And the results:

Categories: Programming Tags:

JavaScript magic

September 15th, 2009 Gunnar Steinn No comments
Function.prototype.bind = function(){
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
  return function(){
    return fn.apply(object,
      args.concat(Array.prototype.slice.call(arguments)));
  };
};

If you want to spent an hour studying how this one function in JavaScript works there is an excellent demonstration at John Resig’s blog.

The code uses three types of method invocation in just a couple of lines (shift(), apply and call). Isn’t JavaScript too complex?

Categories: Programming Tags:

Blogg

September 3rd, 2009 Gunnar Steinn 4 comments

Ég finn alltaf fyrir mikill bloggþörf þó ég hafi margoft byrjað og nákvæmlega jafn oft hætt (ef við teljum þessa færslu ekki með, ennþá).

Klassíska vandamálið, þegar það er nóg að blogga um hef ég ekki tíma til að blogga um það, og þess á milli, þegar ég hef nægan tíma, hef ég ekkert að blogga um…

Categories: Programming Tags: