Element.addMethods('IMG', {
	lazyload: function (element, options) {
		/**
		What does it do?
			It delays loading of images in (long) pages. Images below "the fold" (far down in the
			page) won't be loaded before the user scrolls down. This is exact opposite of image
			preloading. With long pages containing heavy image content end user result is the
			same. Page feels snappier. Browser is in ready state after loading visible images.
			No need to wait for n pictures to load.
			
		From Wikipedia:
			Lazy loading is a design pattern commonly used in computer programming to defer
			initialization of an object until the point at which it is needed. It can contribute
			to efficiency in the program's operation if properly and appropriately used.
		
		Inspired by:
			http://www.appelsiini.net/2007/9/lazy-load-images-jquery-plugin
			
		Requires:
			Prototype.js version 1.6.0 or later
			Element.Storage.API.js
			A page with lots of big images below "the fold" (optional)
			
		Bugs:
			Does not work in Safari 2 due to http://bugs.webkit.org/show_bug.cgi?id=6656
		
		Potential Issues:
			Each image below the fold starts a 100ms timer. This timer ends when the image is restored
			but I'm not sure how much of an impact this will have. I maintain that it's better this
			way than to run this entire function on every page scroll/resize.
		*/
		
		element = $(element);
		
		function restore(image) {
			// this function restores the original image source; called when above "the fold"
			var source = image.retrieve('source');
			if (source) {
				image.writeAttribute({
					src: source
				});
				
				image.eliminate('source');
			}
			
			return image;
		}
		
		function scroll() {
			// this function returns the amount the page is scrolled vertically
			var offset = document.viewport.getScrollOffsets();
			
			return {
				x: offset[0],
				y: offset[1]
			};
		}
		
		function size() {
			// this function returns the height of the viewport
			var dimensions = document.viewport.getDimensions();
			
			return {
				width: dimensions.width,
				height: dimensions.height
			};
		}
		
		options = Object.extend({
			threshold : 0,
			placeholder : '/images/grey.gif',
			event : 'scroll',
			frequency : 0.1
		}, options || {});

		var offset = element.cumulativeOffset();
		var activate_on = {
			x: (offset[0] - options.threshold) - size().width,
			y: (offset[1] - options.threshold) - size().height
		};

		var old_source = element.readAttribute('src');
		var new_source = options.placeholder;
		
		// only replace the image if it is below "the fold"
		if ((activate_on.y >= scroll().y) || (activate_on.x >= scroll().x)) {
			
			element.writeAttribute({
				src : new_source
			});
			
			element.store('source', old_source);
			
		}
		
		if ('scroll' === options.event) {
			/*
			 * I have decided to create many peridodical executers as opposed to observing
			 * the (window).onscroll because the executers will get removed when the image
			 * is in view, as opposed to every image being processed on every scroll.
			 * 
			 */
			
			var action = new PeriodicalExecuter(function (executor) {
				if ((activate_on.y < scroll().y) && (activate_on.x < scroll().x)) {
					restore(element);
					executor.stop();
				}
			}, options.frequency);
			
		} else {
			
			element.observe(options.event, function () {
				restore(this);
				element.stopObserving();
			});
			
		}

		return element;
	}
});