// ==UserScript==
// @name Page prefetcher
// @author João Eiras 
// @namespace http://userjs.org/ 
// @version 1.0
// @description  Prefetches page linked to the current one with
//			rel="next","prefetech" or "prev". This
//			behaviour is similar to Gecko's.
// @ujs:category browser: enhancements
// @ujs:published 2006-01-24 09:43
// @ujs:modified 2006-01-25 13:10
// @ujs:documentation http://userjs.org/scripts/browser/enhancements/page-prefetcher 
// @ujs:download http://userjs.org/scripts/download/browser/enhancements/page-prefetcher.js 
//
// Add URLs to exclude here:
// @exclude file://*
//
// ==/UserScript==

/* 
 * Copyright © 2006 by João Eiras
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */


(function(){
/*
    window.prefetched_urls is the variable that allows the script to identify a page being prefetched
    to prevent recursive or duplicate prefetching, prevent scripts from poping up the prefecthed page,
    change the current url, and disable objects and embeds.
    It holds all prefetched urls. It is the only exported symbol to be available between documents.
	
	I've took the care for the script NOT to export any symbol if there are no links to prefetch
*/
	var array_indexOf = function(a,o){for(var k in a)if(a[k]==o)return k;return -1;}
	var this_page_is_prefetched = false;
	try{
		if( window.parent != window && window.parent.prefetched_urls)
			this_page_is_prefetched = array_indexOf(window.parent.prefetched_urls,window.location.href)>=0;
	}catch(ex){
		//if window.parent refers to a page in
		//another server then some cross frame
		//cross domain scripting exception is fired
	}
	
	if( this_page_is_prefetched ){
		//prefetched page
		if(window.opera){
			window.opera.addEventListener("BeforeExternalScript",function(ejs){ejs.preventDefault();},false);
			window.opera.addEventListener("BeforeScript",function(ejs){ejs.preventDefault();},false);
			window.opera.addEventListener("BeforeEventListener",function(ejs){ejs.preventDefault();},false);
			window.opera.addEventListener("BeforeEventListener.load",function(ejs){ejs.preventDefault();},false);
		}
		var clean_n_calls = 0;
		var clean_interval;
		var clean_f = function(){
			//prevent flash, music and others from annoing the user
			for(var k=0,ns=document.getElementsByTagName("object");k<ns.length;k++)
				ns[k].parentNode.removeChild(ns[k]);
			for(var k=0,ns=document.getElementsByTagName("embed");k<ns.length;k++)
				ns[k].parentNode.removeChild(ns[k]);
			for(var k=0,ns=document.getElementsByTagName("applet");k<ns.length;k++)
				ns[k].parentNode.removeChild(ns[k]);
			//the script can't control what happens in pages inside iframes
			for(var k=0,ns=document.getElementsByTagName("iframe");k<ns.length;k++)
				ns[k].parentNode.removeChild(ns[k]);
			
			clean_n_calls++;
			//if the user cancels page loading, the event load isn't fired (sometimes :s probably a bug)
			//or the bandwidth isn't the best
			if( clean_n_calls == 20 )//10 seconds
				clearInterval(clean_interval);
		}

		//make sure the function is called recursively to prevent content
		//from affecting the main page with sound or resources overload
		//before load event
		clean_interval = setInterval(clean_f,500); 
		window.addEventListener('load',function(){clean_f();clearInterval(clean_interval);},false);
		
	}else{
		//this is a regular page - cooperate with frames and iframes
		window.prefetched_urls=((window.parent==window||!window.parent.prefetched_urls)?Array():window.parent.prefetched_urls);
		var resolveurl=function(url){var link=document.createElement("a");link.href=url;url=link.href;delete link;return url;}
		window.addEventListener("load",function(){
			var html = document.getElementsByTagName("body");
			if(html.length<1)
				html = document.getElementsByTagName("html");
			if(html.length<1)
				return;
			html = html[0];
			
			var prefetchdiv;
			var writeiframe = function(url){
				//check it is a external url - quit
				//I don't want cross domain scriptting errors, nor can the script control the page later...
				//This also considers ports appended to the hostname -> 80 is the default port for http so
				// hostname:80 == hostname :)
				if( url.match(/^\w+:\/\/?([^\/]+)/) && window.location.hostname != RegExp.$1.replace(/:80$/,""))
					return;
				window.prefetched_urls.push(url);
				if( !prefetchdiv ){
					//in case the script doesn't reach here, don't append the element to the document tree
					prefetchdiv=document.createElement("div");prefetchdiv.setAttribute("id","ujs_link_prefetcher_iframe_placeholder")
					prefetchdiv.setAttribute("style","display:none;");
					html.appendChild(prefetchdiv);
				}
				var ifr = document.createElement("iframe");
				ifr.setAttribute("src",url);
				ifr.setAttribute("style","display:none;");
				prefetchdiv.appendChild(ifr);
			}
			var k,links = document.getElementsByTagName("link");	
			for(k=0;k<links.length;k++)
				if( links[k].getAttribute("rel").match(/next|prev(ious)?|prefetch/i ) )
					writeiframe( resolveurl(links[k].getAttribute("href")) );
			//no prefetch links found... delete the array
			if( window.prefetched_urls.length==0 )
				delete window.prefetched_urls;
		},false);
	}
})();
