/**
* :path (http://devkick.com/lab/path/)
*
* :path is a useful jquery selector. 
* It filters out anchors that matches their href attribute with the window location and their ancestor's trail.
*
* Adding active classes is very common in navigational elements in order to style an 'active state'. This is normally added server-side. 
* Instead of adding classes server-side using complicated logic, the :path selector uses javascript to parse the window.location and match it with href attributes. 
* The plugin works recursively, meaning it can take the entire path to your page and return navigational anchors that points to the page's ancestors as well as itself.
* Use CSS or jQuery to parse and style the active element properly.
*
* :path is a pseudo-class selector so you can continue the chain for easy manipulation
*
* FEATURES
*   Works on all relative href paths (including '../') as well as absolute paths
*   Returns empty if the href points to root
*   Ignores a custom array of file names, such as index.html
*   Works on query strings, such as ?s1=home&s2=blog
*   includes a :current pseudo-class so you can style the anchor that links to the current page location
*   Tested in Safari 3, Firefox 2, MSIE 6, MSIE 7, Opera 9
*
* Version 1.0
* April 28, 2008
*
* Copyright (c) 2008 David Hellsing (http://monc.se)
* Licensed under the GPL licenses.
* http://www.gnu.org/licenses/gpl.txt
**/

(function($) {

	/**
	* 
	* @desc Filters out anchors that matches the window.location trail
	* @author David Hellsing
	* @version 1.0
	*
	* @name :path
	* @type jQuery
	*
	* @cat plugins/Utilities
	* 
	* @example $('ul a:path').parent().addClass('active');
	* @desc Adds an 'active' class to the filtered anchors parent inside every <ul>
	*
	* @options
	*   strictQuery: Boolean if you want the query string to be strict (ex: a=b&b=a equals b=a&a=b). Defaults true.
	*   ignoreFiles: Array of file names to ignore. ['index.htm','index.html','index.shtml','index.cgi','index.php']
	*
	**/

	$.extend({ path: {

		// array of files to ignore
		//ignoreFiles: ['index.php', 'index.htm', 'index.html'],
		ignoreFiles: [],

		// strict mode boolean
		strictQuery: true,

		// regexp for ignored file names
		ignore: function() {
			return new RegExp('(' + $.path.ignoreFiles.join('|') + ')', 'i');
		},

		// grab and parse the location
		window: function() {

			// define window.location as a short variable
			var _l = window.location;

			// grab the window path, split & and parse
			var _w = null;
			if (_l.port) {
				_w = (_l.protocol + '//' + _l.hostname + ':' + _l.port + _l.pathname + _l.hash).cleanPath($.path.ignore()).split('/');
			} else {
				_w = (_l.protocol + '//' + _l.hostname + _l.pathname + _l.hash).cleanPath($.path.ignore()).split('/');
			}

			// grab the query string, split & sort if not in strict mode
			var _q = _l.search.substring(1).length > 0 ? _l.search.substring(1).split('&') : [];
			if (!$.path.strictQuery) { _q.sort(); }

			// merge the arrays
			return _w.concat(_q);
		},

		// grab and parse the anchor
		anchor: function(_this) {

			// grab the hrefs
			var _org = _this.getAttribute('href', 1);

			// return false if node is not anchor or href is not present
			if (!_org || _this.nodeName != 'A') { return false; }

			var _l = window.location;

			// parse href
			var _href = _org.absUrl().cleanPath($.path.ignore());

			// return if href is root
			if (_href === (_l.protocol + '//' + _l.hostname).replace(/www\./, '').noSlash() ||
				_href === (_l.protocol + '//' + _l.hostname + '//' + _l.port).replace(/www\./, '').noSlash()) {
				return [];
			}

			// split href into path & query
			var _s = _href.split("?");
			var _a = _s[0].noSlash().split('/');
			var _q = _s.length > 1 ? _s[1].split('&') : [];

			// sort query if not in strict mode
			if (!$.path.strictQuery) { _q.sort(); }

			// merge the arrays
			return _a.concat(_q);

		},

		// match the anchor with window
		match: function(_this) {

			var _a = $.path.anchor(_this);
			var _w = $.path.window();

			// compare and return
			return _w.length < _a.length ? false : _w.slice(0, _a.length).compare(_a);
		},

		current: function(_this) {

			var _a = $.path.anchor(_this);
			var _w = $.path.window();
			
			//alert("Anchor: " + _a + " | Window: " + _w);

			// NOTE fixed bug in this comparison
			// James Churchill 10/2009

			// compare and return
			//return _w.length == _a.length ? true : false;
			return _w.join('-') == _a.join('-');
		}
	}
	});

	// NOTE the following calls to jQuery.extend were changed from the original source code
	// instead of passing a string for the function to call for the new selector an anonymous
	// function is setup that calls the necessary function
	// James Churchill 10/2009

	// Extend jQuery with the :path selector
	//$.extend($.expr[":"], { path: 'jQuery.path.match(a);' });
	$.extend($.expr[":"], { path: function(a) { return $.path.match(a); } });

	// Extend jQuery with the :current selector
	//$.extend($.expr[":"], { current: 'jQuery.path.current(a);' });
	$.extend($.expr[":"], { current: function(a) { return $.path.current(a); } });

	/*
	* @name noSlash()
	* @desc String prototype that removes ending slashes
	**/

	String.prototype.noSlash = function() {
		return this.lastIndexOf('/') === this.length - 1 ? this.substr(0, this.length - 1) : this.toString();
	};

	/*
	* @name absUrl()
	* @desc String prototype that returns the absolute URL
	**/

	String.prototype.absUrl = function() {
		var l = window.location, h, p, f, i;
		if (/^\w+:/.test(this)) {
			return this.toString();
		}
		h = l.protocol + '//' + l.host;
		if (this.indexOf('/') === 0) {
			return h + this.toString();
		}
		p = l.pathname.replace(/\/[^\/]*$/, '');
		f = this.match(/\.\.\//g);
		if (f) {
			var n = this.substring(f.length * 3);
			for (i = f.length; i--; ) {
				p = p.substring(0, p.lastIndexOf('/'));
			}
		} else {
			n = this.toString();
		}
		return h + p + '/' + n;
	};

	/*
	* @name cleanPath()
	* @desc String prototype that cleans up the URL path
	**/

	String.prototype.cleanPath = function(ignore) {
		return this.replace(/www\./i, '').replace(ignore, '').replace(/\.\//, '').noSlash().toString();
	};

	/*
	* @name compare()
	* @desc Array prototype that compares two arrays and returns a boolean
	**/

	Array.prototype.compare = function(t) {
		if (this.length != t.length) { return false; }
		for (var i = 0; i < t.length; i++) {
			if (this[i] !== t[i]) {
				return false;
			}
		}
		return true;
	};

})(jQuery);