/**
 * @fileoverview
 *
 * AjaxWp - An AJAX enchancement for Wordpress blogs
 * Copyright (c) 2006, Gianni Milanesi <gianni@giannim.com>
 * 
 * AjaxWp is freely distributable under the terms of an MIT-style license.
 * For details, see the AjaxWp web site: http://www.giannim.com/projects/ajax-wp
 * 
 * @author Gianni Milanesi <gianni@giannim.com>
 */

/**
 * Static instance object that handles AJAXification of a Wordpress blog.
 * 
 * @version 0.7 27-jul-2006
 */
var AjaxWp = function() {
	/*=========================================
			    AjaxWp Constants
	===========================================*/
	/**
	 * Enumeration of the two possible permalink structures
	 * used for internal links
	 */
	var Permalink = {
		QUERYSTRING : 'querystring',
		MOD_REWRITE : 'mod-rewrite'
	};
	/**
	 * Enumeration of the two possible update modes to use when 
	 * requesting updates to the server.
	 * -  QUICK is slower and has a bigger payload because it requires
	 *    the client to request the full page from the server and parse it 
	 *    to look for the updatable area.
	 * -  OPTIMIZED is faster and most efficient but it requires separate
	 *    AJAX only pages of your blog. These pages only contain the needed
	 * 	  HTML code. These pages shouldn't contain redundant HTML like header
	 *    and footer and should have the same filename of the full pages with
	 *    the 'ajax-wp-' prefix.
	 * 
	 * Please refer to the online documentation at 
	 * http://www.giannim.com/projects/ajax-wp for more information on update
	 * modes.
	 */
	var UpdateMode = {
		QUICK : 'quick',
		OPTIMIZED : 'optimized'
	};
	
	/*=========================================
			AjaxWp Utility Functions
	===========================================*/
	/**
	 * Utility object that contains common functions used throughout the 
	 * AjaxWp object.
	 */
	var Utility = {
		/**
		 * Evaluates the correct AJAX command based on the link based on the blog 
		 * permalink structure.
		 * @param {String} link The link to evaluate
		 * 
		 * @return {String} The AJAX command to send to the server
		 */
		evaluateCommand : function(link, title) {
			if (!link) {
				throw 'AjaxWp Error: Unexpected link passed to the evaluateCommand function.';
			}
			
			// Prepare the link
			link = link.strip();
			
			// Absolutize the link if necessary
			if (link.indexOf(window.location.protocol + '//') != 0) {
				// check if the link points to the current folder
				if (link.indexOf(window.location.pathname) == 0) {
					link = this.getHost() + link;
				} else {
					link = this.getHostAndPath() + link;
				}
			}
			
			// Fill the command object
			var command = {};
			command.url = link;
			command.title = title;
			
			// remove the protocol prefix
			link = link.replace(window.location.protocol + '//', '');
			switch(_permalinkStructure) {
				case Permalink.QUERYSTRING:
					if (link.indexOf('?') > 0) {
						command.parameters = link.substring(link.indexOf('?') + 1);
					} else {
						command.parameters = link.substring(link.indexOf('/'));
						command.isDirectCallback = true;
					}
					break;
				default:
					command.parameters = link.substring(link.indexOf('/'));
					break;
			}			
			return command;
		},
		/**
		 * Helper function that determines if an AJAX callback is currently
		 * in progress.
		 * @param {XMLHttpRequest} xmlhttp An instance of an XMLHttpRequest to be checked
		 * 
		 * @return {bool} true if the given XMLHttpRequest is still in progress, false otherwise.
		 */			
		callInProgress : function(xmlhttp) {
			switch (xmlhttp.readyState) {
				case 1: case 2: case 3:
					return true;
				// Case 4 and 0
				default:
					return false;
			}
		},
		/**
		 * Helper function that evaluates a link and determines if it points
		 * to a page or subpage of the blog based on the _blogBasePath
		 * @param {String} link The link to evaluate
		 * 
		 * @return {bool} true if the link is internal to the blog, false otherwise.
		 */
		isBlogLink : function(link, blogPath) {
			if (!link) {
				return false;
			}
			link = link.strip();
			
			// Determine if it's an absolute or relative link
			if (link.indexOf(window.location.protocol + '//') == 0) {
				blogPath = this.getHost() + blogPath;				
			} else {
				// The link is relative, check if it points to the current folder
				if (link.charAt(0) != '/') {
					return true;
				}
			}
			// The link could be absolute or relative, check if
			// it starts with either the absolute blog path or the relative blog path
			if (link.indexOf(blogPath) == 0)
				return true;
			else 
				return false;
		},
		/**
		 * Helper function that cleans up the given path removing excess slashes (like double slashes or 
		 * trailing slashes) 
		 * in the format /path1/path2 
		 * @param {String} path The path to normalize
		 * 
		 * @return {String} A normalized path 
		 */
		cleanUpPath : function(path) {
			path = path.strip();
			if (!path) {
				path = '/';
			} else {
				while(path.substr(0, 1) == '/')
					path = path.substring(1);
				path = '/' + path;
				while (path.substr(path.length - 2, 1) == '/') 
					path = path.substring(0, path.length - 2);
			}
			return path;
		},
		/**
		 * Helper function that evaluates the current host URL.
		 * For example http://www.myhost.com
		 * 
		 * @return {String} The string representation of the current host
		 */
		getHost : function() {
			return window.location.protocol + '//' + window.location.host;
		},
		/**
		 * Helper function that evaluates the current host URL and pathname without the
		 * trailing querystring or hash.
		 * For example http://www.myhost.com/pathname
		 * 
		 * @return {String} The string representation of the current host and pathname
		 */
		getHostAndPath : function() {
			return window.location.protocol + '//' + window.location.host + window.location.pathname;
		},
		/**
		 * Helper function that evaluates the current hash without the hash sign.
		 * For example anchor
		 * 
		 * @return {String} The string representation of the hash if set, otherwise an
		 * empty string.
		 */
		getHash : function() {
			if (window.location.hash) {
				return window.location.hash.substring(1);
			} else {
				return '';
			}
		},
		/**
		 * Helper function that evaluates the current URL and title encoded in the 
		 * hash value of the window.location.href property.
		 * 
		 * @return {Object} An object with two properties: title and url if the hash value
		 * is set, otherwise null.
		 */
		getPageInfo : function() {
			if (window.location.hash) {
				var parts = window.location.hash.substring(1).split('|');
				// If malformed return null
				if (!parts || parts.length < 2)
					return null;			
				var url = decodeURIComponent(parts[0]);
				var title = decodeURIComponent(parts[1]);
				var cleanUrl = url;
				if (url.indexOf('#') != -1)
					cleanUrl = url.substring(0, url.indexOf('#'));
				
				return {title:title, url:url, cleanUrl:cleanUrl};
			} else {
				return null;
			}
		},
		/**
		 * Helper function that evaluates the current querystring of the given link without the 
		 * question mark.
		 * For example val1=x&val2=y
		 * 
		 * @return {String} The string representation of the querystring if set, otherwise an
		 * empty string.
		 */
		getQueryString : function() {
			if (window.location.search) {
				return window.location.search.substring(1);
			} else {
				return '';
			}
		},
		/**
		 * Helper function that scrolls the viewport to the given element.
		 * If no element is specified, the viewport will scroll to the top of the document.
		 * 
		 * @param {Element} element The reference or ID of the DOM element to scroll to. 
		 * If the element is invalid or null the viewport will scroll to the top.
		 */
		scrollTo : function(element) {
			if ($(element)) {
				new Effect.ScrollTo(element, {duration:0.4});
			} else {
				new Effect.ScrollTo(document.getElementsByTagName('body')[0], {duration:0.4});
			}
		},
		/**
		 * Helper function to set a cookie.
		 */
		setCookie: function(name, value) {
			var date = new Date();
			// Expires in one year
			date.setTime(date.getTime()+(365*24*60*60*1000)); 
			var expires = '; expires='+date.toGMTString();
			document.cookie = name+'='+value+expires+'; path=/';
		},	
		/**
		 * Helper function to read a cookie.
		 */
		readCookie: function(name) {
			var nameEQ = name + "=";
			var cookies = document.cookie.split(';');
			for(var i = 0; c = cookies[i]; i++) {
				while (c.charAt(0)==' ') 
					c = c.substring(1, c.length);
				if (c.indexOf(nameEQ) == 0) 
					return c.substring(nameEQ.length, c.length);
			}
			return false;
		}		
	};
	
	/*=========================================
			AjaxWp Member Variables
	===========================================*/
	/**
	 * The title of the blog. Needed for dynamic window title change.
	 */
	var _blogTitle = 'My Blog';
	/**
	 * The root path of your blog 
	 */
	var _blogBasePath = '/blog';
	/**
	 * The ID of the DOM element that will be updated
	 * dynamically.
	 */
	var _updatableAreaId = 'content';
	/**
	 * Specify the Permalink structure used in your blog from 
	 * one of the allowed values of the Permalink enumeration:
	 * 	  - QUERYSTRING
	 * 	  - MOD_REWRITE
	 */
	var _permalinkStructure = Permalink.QUERYSTRING;
	/**
	 * Animation type to use in the transitions from a page to the other
	 * Allowed values: 'appear', 'slide', 'blind' 
	 */
	var _animationType = 'appear';
	/**
	 * The tag type of the updatable area
	 */
	var _updatableAreaTag = 'div';
	/**
	 * The update mode to be used when requesting the pages.
	 */
	var _updateMode = UpdateMode.QUICK;
	/**
	 * The name of the PHP page that will handle AJAX
	 * callbacks.
	 */
	var _callbackPage = 'ajax-wp.php';
	/**
	 * The loading indicator that will be shown while the new content is being loaded.
	 * If null or empty, no image will not be used.
	 */
	var _loadingIndicator = '/img/loading.gif';
	/**
	 * This array specified the links within the blog base path
	 * that shouldn't be loaded dinamycally (for example your
	 * Wordpress admin page).
	 */
	var _ignoreLinks = [
		'wp-admin',
		'wp-logout'
	];	
	/**
	 * This array specified the filetypes that should be loaded 
	 * dinamycally (for example htm and txt files).
	 */
	var _allowedFileTypes = [
		'htm',
		'html',
		'aspx',
		'jsp',
		'php'
	];
	/**
	 * The timeout value for AJAX callbacks (in milliseconds)
	 */
	var _ajaxTimeout = 7500;
	/**
	 * Variable that avoids multiple simultaneous updates
	 */
	var _isLoadingContent = null;
	/**
	 * The current AJAX command
	 */
	var _currentCommand = null;
	/**
	 * The current AJAX request method
	 */
	var _requestMethod = 'get';
	/**
	 * The page to post the data to in case of a POST request
	 */
	var _postPage = null;
	/**
	 * AjaxWp toggle flag
	 */
	var _disableAjaxWp = false;
	var _disablePostForms = false;
	var _disableGetForms = false;
	var _disableBookmarkLinks = false;
	var _enableGoogleAnalytics = false;
	/*=========================================
			AjaxWp Core Private Functions
	===========================================*/
	/**
	 * When the content has been loaded and successfully injected
	 * crawl the DOM, refresh onclick event handlers and show the 
	 * newly loaded data.
	 */
	var updateHandlersAndShowContent = function() {
		AjaxWp.updateLinkHandlers();
		AjaxWp.updateFormHandlers();
		if (_enableGoogleAnalytics 
			&& _currentCommand.url 
			&& typeof urchinTracker != 'undefined'){
			var url = _currentCommand.url.replace('://', '');
			urchinTracker(url.substring(url.indexOf('/')));			
		}
		if (_animationType == 'appear') {
			Element.setOpacity(_updatableAreaId, 0);
		}
		
		new Effect.toggle(_updatableAreaId, _animationType, {
			duration:0.45,
			afterFinish: function() {
				// Reset the loading flag 
				_isLoadingContent = false;
				// If the clicked link had an anchor hash, scroll the viewport
				// to the correct location
				if (Utility.getPageInfo()) {
					var link = document.createElement('a');
					link.href = Utility.getPageInfo().url;
					if(link.hash) {
						Utility.scrollTo(link.hash.substring(1));
					}
				}
			}
		});
	};
	
	/**
	 * Makes the asynchronous request to the AjaxWp callback page
	 * to retrieve the optimized version of the requested page.
	 * If an unexpected error occurs (like a 404) the user is redirected
	 * normally to the requested page, instead of updating the current page.
	 */
	var loadFromServer = function() {
		var requestUrl = _blogBasePath + '/' + _callbackPage;
		var fallbackUrl = Utility.getHostAndPath();
		var pars = '';
		
		if (_requestMethod == 'get') {
			if (_permalinkStructure == Permalink.QUERYSTRING) {
				if (_currentCommand.isDirectCallback) {
					requestUrl = Utility.getHost() + _currentCommand.parameters;
					fallbackUrl = Utility.getHost() + _currentCommand.parameters;
				} else {
					requestUrl += '?' + _currentCommand.parameters;
					fallbackUrl = Utility.getHostAndPath() + '?' + _currentCommand.parameters;
				}
			} else {
				if (Utility.getQueryString()) {
					var parameters = Utility.getQueryString();
					pars += '&' + parameters;
					fallbackUrl = Utility.getHostAndPath() + '?' + parameters;
				} else {
					requestUrl = Utility.getHost() + _currentCommand.parameters;
					fallbackUrl = requestUrl;
				}
			}
		} else {
			if (Utility.getPageInfo()) {
				fallbackUrl = Utility.getPageInfo().url;
			}
			pars += '&' + _currentCommand.parameters;
			if (_postPage) {
				requestUrl = _postPage;
			}
		}
		if (requestUrl.indexOf('#') != -1)
			requestUrl = requestUrl.substring(0, requestUrl.indexOf('#'));
					
		// Request the data from the server
		new Ajax.Request(requestUrl, {
			method: _requestMethod, 
			parameters: 'ajax-wp=' + _updateMode + pars,
			onCreate: function(request) {
				request.timeoutId = window.setTimeout(
					function() {
						// If we have hit the timeout and the AJAX request is active, abort it and let the user know
						if (Utility.callInProgress(request.transport)) {
							request.transport.abort();
							// Run the onFailure method if we set one up when creating the AJAX object
							if (request.options.onFailure) {
								request.options.onFailure();
							}
						}
					},
					_ajaxTimeout
				);
			},
			onFailure:function() {
				// An error occured while making the request, navigate to the page
				// normally
				window.location.href = fallbackUrl;
			},
			onSuccess:function(request) {
				// Clear the timeout, the request completed ok
				window.clearTimeout(request.timeoutId);				
				
				// Hide the updatable area and reset it's state
				$(_updatableAreaId).style.display = 'none';
				$(_updatableAreaId).style.height = 'auto';				
				if (_loadingIndicator) {
					$(_updatableAreaId).style.backgroundImage = '';
					$(_updatableAreaId).style.backgroundPosition = '';
					$(_updatableAreaId).style.backgroundRepeat = '';
				}
				Element.removeClassName(_updatableAreaId, 'ajax-wp-loading');
				// Make a quick and dirty check if the received document has a body tag, 
				// if so look for the correct <div> because it is probably 
				// a full page, otherwise inject the result into the updatable area	
				var hasBody = request.responseText.toLowerCase().indexOf('<body') != -1;
				if (hasBody || _updateMode == UpdateMode.QUICK || _postPage) {				
					var elementFound = false;
					var buffer = document.createElement('div');
					buffer.innerHTML = request.responseText;
					// Look for all the tags of the type specified in the
					// configuration and check if the ID matches the one
					// of the _updatableAreaId, if so inject the HTML.
					var elements = buffer.getElementsByTagName(_updatableAreaTag);	
					for (var i = 0; i < elements.length; i++) {
						if (elements[i].id == _updatableAreaId) {
							$(_updatableAreaId).innerHTML = elements[i].innerHTML;
							elementFound = true;
							break;
						}
					}
					// Clean up
					buffer.innerHTML = '';
					buffer = null;
					
					// If no matching element is found redirect the page
					// to the requested page
					if (!elementFound) {
						var text = request.responseText.strip();
						if (text) {
							$(_updatableAreaId).innerHTML = request.responseText;
						} else {
							window.location.href = fallbackUrl;
						}
					}				
				} else {
					$(_updatableAreaId).innerHTML = request.responseText;
				}					
				window.setTimeout(updateHandlersAndShowContent, 15);
			}
		});
	};
	/**
	 * Updates the content of the page with the data fetched from the given URL
	 * address
	 * @param {String} command The command type used for the AJAX request
	 * @param {String} url The URL of the requested page 
	 * @param {String} title The title of the requested page 
	 * @param {bool} saveHistory Flag that indicates if the history should be saved or not
	 */
	var updateContent = function(command, saveHistory) {
		// make sure that the updatable area exists
		if (!$(_updatableAreaId)) {
			throw 'AjaxWp Error: The updatable area specified in the JavaScript ("'
				+ _updatableAreaId
				+ '") could not be found in the current page';
		}
		
		// Check if an update is already in progress
		if (_isLoadingContent) {
			return;
		} else {
			_isLoadingContent = true;
		}
		
		// Update the title bar of the browser
		document.title = _blogTitle;
		if (command.title) {
			command.title = new String(command.title).stripTags().strip();
			if (command.title != _blogTitle) {
				document.title += ' > ' + command.title;
			}
		} else {
			command.title = '';
		}
		
		// If needed, store the new location to the history
		if (saveHistory) {
			var historyHash = encodeURIComponent(command.url) 
				+ '|' + encodeURIComponent(command.title);
			unFocus.History.addHistory(historyHash);
		}
		_currentCommand = command;
		
		// Scroll to the top of the page
		Utility.scrollTo(null);
		
		// Toggle the updatable area and clear it when the animation is done
		new Effect.toggle(_updatableAreaId, _animationType, {
			duration:0.45,
			afterFinish: function() {
				$(_updatableAreaId).innerHTML = '&nbsp;';
				$(_updatableAreaId).style.display = 'block';
				$(_updatableAreaId).style.height = '200px';
				Element.setOpacity(_updatableAreaId, 1);
				Element.addClassName(_updatableAreaId, 'ajax-wp-loading');
				if (_loadingIndicator) {
					$(_updatableAreaId).style.backgroundImage = 'url('+ _loadingIndicator + ')';
					$(_updatableAreaId).style.backgroundPosition = '50% 50%';
					$(_updatableAreaId).style.backgroundRepeat = 'no-repeat';					  
				}
				// Wait a few milliseconds to allow browsers to refresh DOM
				window.setTimeout(loadFromServer, 10);
			}
		});		
	};
	
	/**
	 * Evaluate the type of permalink and call the update method
	 */
	var updateFromLink = function(e) {
		if (_disableAjaxWp) 
			return;
			
		// Stop the event propagation so that the browser wont
		// follow the link.
		Event.stop(e);
		
		// Set the title of the document
		var title = this.innerHTML;		
		var link = this.href;		
		var command = Utility.evaluateCommand(link, title);
		
		updateContent(command, true);
	};
	
	/**
	 * Called whenever the userpresses the back or forward buttons. 
	 * This function will be passed the newLocation,
	 * as well as any history data we associated
	 * with the location. 
	 */
	var historyListener = function (historyHash) {
		var parts = historyHash.split('|');
		if (!parts || parts.length < 2)
			return;
			
		var historyLink = decodeURIComponent(parts[0]);
		var title = decodeURIComponent(parts[1]);	
		var command = Utility.evaluateCommand(historyLink, title);
		
		updateContent(command, false);
	};	
	/**
	 * Function that traps blog forms onsubmit events. 
	 */
	var formSubmit = function(e) {			
		if (_disableAjaxWp || this.onsubmit) 
			return;
		
		_requestMethod = this.method.toLowerCase();
		if (_requestMethod == 'get' && _disableGetForms)
			return;
		if (_requestMethod == 'post' && _disablePostForms)
			return;		
		
		Event.stop(e);	
				
		var url = Utility.getHostAndPath();
		var command = Utility.evaluateCommand(url);		
		_postPage = this.action;
		if (_requestMethod == 'get') {
			url = Utility.getHostAndPath() + '?' + Form.serialize(this);
			command = Utility.evaluateCommand(url);		
		} else {
			if (Utility.getPageInfo()) {
				url = Utility.getPageInfo().url;
				command = Utility.evaluateCommand(url);
			}
			command.parameters = Form.serialize(this) + '&redirect_to=' + command.url;
		}
	
		updateContent(command, true);
	};
	
	/**
	 * Public functions and properties
	 */
	return {
		/**
		 * Initializes AjaxWp by loading options from the document and adding 
		 * event handlers to the links and forms
		 */
		init : function() {
			var cookieDisabled = Utility.readCookie('ajax-wp-disabled');
			// Check if AjaxWp has been disabled for the current page or in the cookies
			if (cookieDisabled == 'true' || window.ajax_wp_disable) {
				_disableAjaxWp = true;
				// Check if the user has come here from a bookmark
				var initialLocation = unFocus.History.getCurrent();	
				if (initialLocation) {
	  				var parts = initialLocation.split('|');
					if (parts && parts.length == 2) {
						window.location.href = decodeURIComponent(parts[0]);
					}
				}
				return;
			}
				
			// The updatabale area ID and tag
			// If the ID is not found in the DOM terminate execution
			_updatableAreaId = window.ajax_wp_updatable_element || _updatableAreaId;
			_updatableAreaTag = window.ajax_wp_updatable_element_tag || _updatableAreaTag;
			if (!$(_updatableAreaId)) {
				throw 'AjaxWp Error: You must specify a valid ID for the updatable element';
			}
			
			// The title of the blog
			_blogTitle = window.ajax_wp_blog_title || _blogTitle;
			
			// Blog path: Clean up and normalize the base URL of the blog
			_blogBasePath = window.ajax_wp_blog_base_path || _blogBasePath;
			_blogBasePath = Utility.cleanUpPath(_blogBasePath);
			
			// AJAX timeout
			if (!isNaN(parseInt(window.ajax_wp_ajax_timeout)))
				_ajaxTimeout = parseInt(window.ajax_wp_ajax_timeout);
			
			// Ignore links
			if (window.ajax_wp_ignore_links) {
				var links = window.ajax_wp_ignore_links.split(',');
				if (links && links.length) {
					for (var i = 0; i < links.length; i++)
						_ignoreLinks.push(links[i].strip());
				}
			}	
			// Allowed File types	
			if (window.ajax_wp_allowed_file_types) {
				var filetypes = window.ajax_wp_allowed_file_types.split(',');
				if (filetypes && filetypes.length) {
					for (var i = 0; i < filetypes.length; i++)
						_allowedFileTypes.push(filetypes[i].strip());
				}
			}			
			
			// Forms
			if (window.ajax_wp_disable_get_forms)
				_disableGetForms = true;
			if (window.ajax_wp_disable_post_forms)
				_disablePostForms = true;
			
			// Rel Bookmark links
			if (window.ajax_wp_disable_bookmark_links)
				_disableBookmarkLinks = true;
			
			// Google Analytics
			if (!window.ajax_wp_enable_google_analytics)
				_enableGoogleAnalytics = true;			
			
			// Permalink structure used by the blog
			if (window.ajax_wp_permalink) {
				window.ajax_wp_permalink = window.ajax_wp_permalink.toLowerCase();
				if (window.ajax_wp_permalink == 'querystring')
					_permalinkStructure = Permalink.QUERYSTRING;
				else
					_permalinkStructure = Permalink.MOD_REWRITE;					
			}
			if (window.ajax_wp_update_mode) {
				window.ajax_wp_update_mode = window.ajax_wp_update_mode.toLowerCase();
				if (window.ajax_wp_update_mode == 'optimized')
					_updateMode = UpdateMode.OPTIMIZED;
				else
					_updateMode = UpdateMode.QUICK;
			}
			_callbackPage = window.ajax_wp_callback_page || _callbackPage;
			_loadingIndicator = window.ajax_wp_loading_image || _loadingIndicator;	
			
			// Initialize the history
			unFocus.History.addEventListener('historyChange', historyListener);
			var initialLocation = unFocus.History.getCurrent();	
			if (initialLocation) {
  				historyListener(initialLocation, null, false);
			}				
			// Add the event handlers
			AjaxWp.updateFormHandlers();
			AjaxWp.updateLinkHandlers();
		},
		/**
		 * Binds onsubmit event handler to the search form in the page
		 */
		updateFormHandlers :function() {				
			// Reset the request method to the default
			_requestMethod = 'get';
			_postPage = null;
			
			var forms = document.getElementsByTagName('form');
			$A(forms).each(function(form){
				if (Utility.isBlogLink(form.action, _blogBasePath)) {
					Event.observe(form, 'submit', formSubmit.bindAsEventListener(form));
				}
			});
		},
		/**
		 * Navigates through the DOM looking for links and binds
		 * onclick event handlers the links are internal to the blog.
		 */
		updateLinkHandlers : function() {
			var baseHost = window.location.host;
			var baseUrl = Utility.getHostAndPath();
			var currentUrl = Utility.getHostAndPath();
			if (Utility.getPageInfo())
				currentUrl = Utility.getPageInfo().cleanUrl;
					
			var anchors = document.getElementsByTagName('a');
			$A(anchors).each(function(anchor){
				// check that the link is not an ignore link
				var isIgnoreLink = true;
				
				try {
					if (!anchor.pathname || anchor.pathname.charAt(anchor.pathname.length - 1) == '/') {
						isIgnoreLink = false;
					} else {
						$A(_allowedFileTypes).each(function(filetype){
							filetype = filetype.replace('.', '');
							var pattern = new RegExp('\.' + filetype + '$', 'im');
							if (anchor.href.match(pattern))
								isIgnoreLink = false;
						});
					}
				} catch(ex) {
					isIgnoreLink = false;
				}
				$A(_ignoreLinks).each(function(link){
					if (anchor.href.match(link))
						isIgnoreLink = true;
				});
				
				// Check that the link is not a bookmark link
				if (_disableBookmarkLinks && anchor.rel && anchor.rel.toLowerCase() == 'bookmark') {
					isIgnoreLink = true;
				}
				
				// Some magic to evaluate if the current link 
				// points to an inpage anchor or if points to an anchor
				// in another page
				var isInternalAnchor = false;
				if (anchor.href.indexOf('#') > 0) {
					var anchorHTML = anchor.parentNode.innerHTML;
					var regex = new RegExp('href=["\']?'+ anchor.hash + '["\']?[^>]+>'+anchor.innerHTML+'<', 'gi');
					if(anchorHTML.match(regex))
						isInternalAnchor = true;
				}				
				
				// Check that it points to an internal page						
				if (!isIgnoreLink && anchor.href.match(baseHost)){
					// Clean up the target and current url 
					var targetUrl = anchor.href.replace(anchor.hash, '');
					// If the target URL and the current URL match, than 
					// we don't need to load the page.
					if (isInternalAnchor || targetUrl == currentUrl || targetUrl == baseUrl) {
						Element.addClassName(anchor, 'ajax-wp-current-page');
						Event.observe(anchor, 'click', function(e) {	
							if (_disableAjaxWp) 
								return;
							// Stop the event propagation so that the browser wont
							// follow the link.
							Event.stop(e);
							// Check if the user clicked on an internal anchor if so jump
							// to that portion of the page, otherwise reload the content
							if (anchor.hash && anchor.hash.length > 1) {
								Utility.scrollTo(anchor.hash.substring(1));
							} else {
								var command = Utility.evaluateCommand(anchor.href, anchor.innerHTML);
								updateContent(command, true);
							}
						});
					} else {
						Element.removeClassName(anchor, 'ajax-wp-current-page');
						Event.observe(anchor, 'click', updateFromLink.bindAsEventListener(anchor));
					}
				}
			});
		},
		disable : function() {
			_disableAjaxWp = true;
			Utility.setCookie('ajax-wp-disabled', true);
		},
		enable : function() {
			_disableAjaxWp = false;
			Utility.setCookie('ajax-wp-disabled', false);
			AjaxWp.init();
		},
		isDisabled : function() {
			return _disableAjaxWp;
		}
	};
}();

// Initialize AjaxWp
Event.observe(window, 'load', AjaxWp.init);
