/**
 * Flash (http://jquery.lukelutman.com/plugins/flash)
 * A jQuery plugin for embedding Flash movies.
 * 
 * Version 1.0
 * November 9th, 2006
 *
 * Copyright (c) 2006 Luke Lutman (http://www.lukelutman.com)
 * Dual licensed under the MIT and GPL licenses.
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.opensource.org/licenses/gpl-license.php
 * 
 * Inspired by:
 * SWFObject (http://blog.deconcept.com/swfobject/)
 * UFO (http://www.bobbyvandersluis.com/ufo/)
 * sIFR (http://www.mikeindustries.com/sifr/)
 * 
 * IMPORTANT: 
 * The packed version of jQuery breaks ActiveX control
 * activation in Internet Explorer. Use JSMin to minifiy
 * jQuery (see: http://jquery.lukelutman.com/plugins/flash#activex).
 *
 **/ 
;(function(){
	
var $$;

/**
 * 
 * @desc Replace matching elements with a flash movie.
 * @author Luke Lutman
 * @version 1.0.1
 *
 * @name flash
 * @param Hash htmlOptions Options for the embed/object tag.
 * @param Hash pluginOptions Options for detecting/updating the Flash plugin (optional).
 * @param Function replace Custom block called for each matched element if flash is installed (optional).
 * @param Function update Custom block called for each matched if flash isn't installed (optional).
 * @type jQuery
 *
 * @cat plugins/flash
 * 
 * @example $('#hello').flash({ src: 'hello.swf' });
 * @desc Embed a Flash movie.
 *
 * @example $('#hello').flash({ src: 'hello.swf' }, { version: 8 });
 * @desc Embed a Flash 8 movie.
 *
 * @example $('#hello').flash({ src: 'hello.swf' }, { expressInstall: true });
 * @desc Embed a Flash movie using Express Install if flash isn't installed.
 *
 * @example $('#hello').flash({ src: 'hello.swf' }, { update: false });
 * @desc Embed a Flash movie, don't show an update message if Flash isn't installed.
 *
**/
$$ = jQuery.fn.flash = function(htmlOptions, pluginOptions, replace, update) {
	
	// Set the default block.
	var block = replace || $$.replace;
	
	// Merge the default and passed plugin options.
	pluginOptions = $$.copy($$.pluginOptions, pluginOptions);
	
	// Detect Flash.
	if(!$$.hasFlash(pluginOptions.version)) {
		// Use Express Install (if specified and Flash plugin 6,0,65 or higher is installed).
		if(pluginOptions.expressInstall && $$.hasFlash(6,0,65)) {
			// Add the necessary flashvars (merged later).
			var expressInstallOptions = {
				flashvars: {  	
					MMredirectURL: location,
					MMplayerType: 'PlugIn',
					MMdoctitle: jQuery('title').text() 
				}					
			};
		// Ask the user to update (if specified).
		} else if (pluginOptions.update) {
			// Change the block to insert the update message instead of the flash movie.
			block = update || $$.update;
		// Fail
		} else {
			// The required version of flash isn't installed.
			// Express Install is turned off, or flash 6,0,65 isn't installed.
			// Update is turned off.
			// Return without doing anything.
			return this;
		}
	}
	
	// Merge the default, express install and passed html options.
	htmlOptions = $$.copy($$.htmlOptions, expressInstallOptions, htmlOptions);
	
	// Invoke $block (with a copy of the merged html options) for each element.
	return this.each(function(){
		block.call(this, $$.copy(htmlOptions));
	});
	
};
/**
 *
 * @name flash.copy
 * @desc Copy an arbitrary number of objects into a new object.
 * @type Object
 * 
 * @example $$.copy({ foo: 1 }, { bar: 2 });
 * @result { foo: 1, bar: 2 };
 *
**/
$$.copy = function() {
	var options = {}, flashvars = {};
	for(var i = 0; i < arguments.length; i++) {
		var arg = arguments[i];
		if(arg == undefined) continue;
		jQuery.extend(options, arg);
		// don't clobber one flash vars object with another
		// merge them instead
		if(arg.flashvars == undefined) continue;
		jQuery.extend(flashvars, arg.flashvars);
	}
	options.flashvars = flashvars;
	return options;
};
/*
 * @name flash.hasFlash
 * @desc Check if a specific version of the Flash plugin is installed
 * @type Boolean
 *
**/
$$.hasFlash = function() {
	// look for a flag in the query string to bypass flash detection
	if(/hasFlash\=true/.test(location)) return true;
	if(/hasFlash\=false/.test(location)) return false;
	var pv = $$.hasFlash.playerVersion().match(/\d+/g);
	var rv = String([arguments[0], arguments[1], arguments[2]]).match(/\d+/g) || String($$.pluginOptions.version).match(/\d+/g);
	for(var i = 0; i < 3; i++) {
		pv[i] = parseInt(pv[i] || 0);
		rv[i] = parseInt(rv[i] || 0);
		// player is less than required
		if(pv[i] < rv[i]) return false;
		// player is greater than required
		if(pv[i] > rv[i]) return true;
	}
	// major version, minor version and revision match exactly
	return true;
};
/**
 *
 * @name flash.hasFlash.playerVersion
 * @desc Get the version of the installed Flash plugin.
 * @type String
 *
**/
$$.hasFlash.playerVersion = function() {
	// ie
	try {
		try {
			// avoid fp6 minor version lookup issues
			// see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
			var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
			try { axo.AllowScriptAccess = 'always';	} 
			catch(e) { return '6,0,0'; }				
		} catch(e) {}
		return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
	// other browsers
	} catch(e) {
		try {
			if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
				return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
			}
		} catch(e) {}		
	}
	return '0,0,0';
};
/**
 *
 * @name flash.htmlOptions
 * @desc The default set of options for the object or embed tag.
 *
**/
$$.htmlOptions = {
	height: 240,
	flashvars: {},
	pluginspage: 'http://www.adobe.com/go/getflashplayer',
	src: '#',
	type: 'application/x-shockwave-flash',
	width: 320		
};
/**
 *
 * @name flash.pluginOptions
 * @desc The default set of options for checking/updating the flash Plugin.
 *
**/
$$.pluginOptions = {
	expressInstall: false,
	update: true,
	version: '6.0.65'
};
/**
 *
 * @name flash.replace
 * @desc The default method for replacing an element with a Flash movie.
 *
**/
$$.replace = function(htmlOptions) {
	this.innerHTML = '<div class="alt">'+this.innerHTML+'</div>';
	jQuery(this)
		.addClass('flash-replaced')
		.prepend($$.transform(htmlOptions));
};
/**
 *
 * @name flash.update
 * @desc The default method for replacing an element with an update message.
 *
**/
$$.update = function(htmlOptions) {
	var url = String(location).split('?');
	url.splice(1,0,'?hasFlash=true&');
	url = url.join('');
	var msg = '<p>This content requires the Flash Player. <a href="http://www.adobe.com/go/getflashplayer">Download Flash Player</a>. Already have Flash Player? <a href="'+url+'">Click here.</a></p>';
	this.innerHTML = '<span class="alt">'+this.innerHTML+'</span>';
	jQuery(this)
		.addClass('flash-update')
		.prepend(msg);
};
/**
 *
 * @desc Convert a hash of html options to a string of attributes, using Function.apply(). 
 * @example toAttributeString.apply(htmlOptions)
 * @result foo="bar" foo="bar"
 *
**/
function toAttributeString() {
	var s = '';
	for(var key in this)
		if(typeof this[key] != 'function')
			s += key+'="'+this[key]+'" ';
	return s;		
};
/**
 *
 * @desc Convert a hash of flashvars to a url-encoded string, using Function.apply(). 
 * @example toFlashvarsString.apply(flashvarsObject)
 * @result foo=bar&foo=bar
 *
**/
function toFlashvarsString() {
	var s = '';
	for(var key in this)
		if(typeof this[key] != 'function')
			s += key+'='+encodeURIComponent(this[key])+'&';
	return s.replace(/&$/, '');		
};
/**
 *
 * @name flash.transform
 * @desc Transform a set of html options into an embed tag.
 * @type String 
 *
 * @example $$.transform(htmlOptions)
 * @result <embed src="foo.swf" ... />
 *
 * Note: The embed tag is NOT standards-compliant, but it 
 * works in all current browsers. flash.transform can be
 * overwritten with a custom function to generate more 
 * standards-compliant markup.
 *
**/
$$.transform = function(htmlOptions) {
	htmlOptions.toString = toAttributeString;
	if(htmlOptions.flashvars) htmlOptions.flashvars.toString = toFlashvarsString;
	return '<embed ' + String(htmlOptions) + '/>';		
};

/**
 *
 * Flash Player 9 Fix (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
 *
**/
if (window.attachEvent) {
	window.attachEvent("onbeforeunload", function(){
		__flash_unloadHandler = function() {};
		__flash_savedUnloadHandler = function() {};
	});
}
	
})();

/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		//alert(jQuery.easing.default);
		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158; 
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});

/*
 *
 * TERMS OF USE - EASING EQUATIONS
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2001 Robert Penner
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
 */
 
 
 /*
  * jQuery Address Plugin v1.3.1
  * http://www.asual.com/jquery/address/
  *
  * Copyright (c) 2009-2010 Rostislav Hristov
  * Dual licensed under the MIT or GPL Version 2 licenses.
  * http://jquery.org/license
  *
  * Date: 2010-11-29 11:54:20 +0200 (Mon, 29 Nov 2010)
  */
 (function ($) {

     $.address = (function () {

         var _trigger = function(name) {
                 $($.address).trigger(
                     $.extend($.Event(name), 
                         (function() {
                             var parameters = {},
                                 parameterNames = $.address.parameterNames();
                             for (var i = 0, l = parameterNames.length; i < l; i++) {
                                 parameters[parameterNames[i]] = $.address.parameter(parameterNames[i]);
                             }
                             return {
                                 value: $.address.value(),
                                 path: $.address.path(),
                                 pathNames: $.address.pathNames(),
                                 parameterNames: parameterNames,
                                 parameters: parameters,
                                 queryString: $.address.queryString()
                             };
                         }).call($.address)
                     )
                 );
             },
             _bind = function(value, data, fn) {
                 $($.address).bind(value, data, fn);
                 return $.address;
             },
             _supportsState = function() {
                 return (_h.pushState && _opts.state !== UNDEFINED);
             },
             _hrefState = function() {
                 return ('/' + _l.pathname.replace(new RegExp(_opts.state), '') + 
                     _l.search + (_hrefHash() ? '#' + _hrefHash() : '')).replace(_re, '/');
             },
             _hrefHash = function() {
                 var index = _l.href.indexOf('#');
                 return index != -1 ? _crawl(_l.href.substr(index + 1), FALSE) : '';
             },
             _href = function() {
                 return _supportsState() ? _hrefState() : _hrefHash();
             },
             _window = function() {
                 try {
                     return top.document !== UNDEFINED ? top : window;
                 } catch (e) { 
                     return window;
                 }
             },
             _js = function() {
                 return 'javascript';
             },
             _strict = function(value) {
                 value = value.toString();
                 return (_opts.strict && value.substr(0, 1) != '/' ? '/' : '') + value;
             },
             _crawl = function(value, direction) {
                 if (_opts.crawlable && direction) {
                     return (value != '' ? '!' : '') + value;
                 }
                 return value.replace(/^\!/, '');
             },
             _cssint = function(el, value) {
                 return parseInt(el.css(value), 10);
             },
             _search = function(el) {
                 var url, s;
                 for (var i = 0, l = el.childNodes.length; i < l; i++) {
                     if (el.childNodes[i].src) {
                         url = String(el.childNodes[i].src);
                     }
                     s = _search(el.childNodes[i]);
                     if (s) {
                         url = s;
                     }
                 }
                 return url;
             },
             _listen = function() {
                 if (!_silent) {
                     var hash = _href(),
                         diff = _value != hash;
                     if (_webkit && _version < 523) {
                         if (_length != _h.length) {
                             _length = _h.length;
                             if (_stack[_length - 1] !== UNDEFINED) {
                                 _value = _stack[_length - 1];
                             }
                             _update(FALSE);
                         }
                     } else if (diff) {
                         if (_msie && _version < 7) {
                             _l.reload();
                         } else {
                             if (_msie && _version < 8 && _opts.history) {
                                 _st(_html, 50);
                             }
                             _value = hash;
                             _update(FALSE);
                         }
                     }
                 }
             },
             _update = function(internal) {
                 _trigger(CHANGE);
                 _trigger(internal ? INTERNAL_CHANGE : EXTERNAL_CHANGE);
                 _st(_track, 10);
             },
             _track = function() {
                 if (_opts.tracker !== 'null' && _opts.tracker !== null) {
                     var fn = $.isFunction(_opts.tracker) ? _opts.tracker : _t[_opts.tracker],
                         value = (_l.pathname + _l.search + 
                                 ($.address && !_supportsState() ? $.address.value() : ''))
                                 .replace(/\/\//, '/').replace(/^\/$/, '');
                     if ($.isFunction(fn)) {
                         fn(value);
                     } else if ($.isFunction(_t.urchinTracker)) {
                         _t.urchinTracker(value);
                     } else if (_t.pageTracker !== UNDEFINED && $.isFunction(_t.pageTracker._trackPageview)) {
                         _t.pageTracker._trackPageview(value);
                     } else if (_t._gaq !== UNDEFINED && $.isFunction(_t._gaq.push)) {
                         _t._gaq.push(['_trackPageview', value]);
                     }
                 }
             },
             _html = function() {
                 var src = _js() + ':' + FALSE + ';document.open();document.writeln(\'<html><head><title>' + 
                     _d.title.replace('\'', '\\\'') + '</title><script>var ' + ID + ' = "' + encodeURIComponent(_href()) + 
                     (_d.domain != _l.host ? '";document.domain="' + _d.domain : '') + 
                     '";</' + 'script></head></html>\');document.close();';
                 if (_version < 7) {
                     _frame.src = src;
                 } else {
                     _frame.contentWindow.location.replace(src);
                 }
             },
             _options = function() {
                 if (_url && _qi != -1) {
                     var param, params = _url.substr(_qi + 1).split('&');
                     for (i = 0; i < params.length; i++) {
                         param = params[i].split('=');
                         if (/^(autoUpdate|crawlable|history|strict|wrap)$/.test(param[0])) {
                             _opts[param[0]] = (isNaN(param[1]) ? /^(true|yes)$/i.test(param[1]) : (parseInt(param[1], 10) !== 0));
                         }
                         if (/^(state|tracker)$/.test(param[0])) {
                             _opts[param[0]] = param[1];
                         }
                     }
                     _url = null;
                 }
                 _value = _href();
             },
             _load = function() {
                 if (!_loaded) {
                     _loaded = TRUE;
                     _options();
                     var complete = function() {
                             _enable.call(this);
                             _unescape.call(this);
                         },
                         body = $('body').ajaxComplete(complete);
                     complete();
                     if (_opts.wrap) {
                         var wrap = $('body > *')
                             .wrapAll('<div style="padding:' + 
                                 (_cssint(body, 'marginTop') + _cssint(body, 'paddingTop')) + 'px ' + 
                                 (_cssint(body, 'marginRight') + _cssint(body, 'paddingRight')) + 'px ' + 
                                 (_cssint(body, 'marginBottom') + _cssint(body, 'paddingBottom')) + 'px ' + 
                                 (_cssint(body, 'marginLeft') + _cssint(body, 'paddingLeft')) + 'px;" />')
                             .parent()
                             .wrap('<div id="' + ID + '" style="height:100%;overflow:auto;position:relative;' + 
                                 (_webkit ? (window.statusbar.visible && !/chrome/i.test(_agent) ? '' : 'resize:both;') : '') + '" />');
                         $('html, body')
                             .css({
                                 height: '100%',
                                 margin: 0,
                                 padding: 0,
                                 overflow: 'hidden'
                             });
                         if (_webkit) {
                             $('<style type="text/css" />')
                                 .appendTo('head')
                                 .text('#' + ID + '::-webkit-resizer { background-color: #fff; }');
                         }
                     }
                     if (_msie && _version < 8) {
                         var frameset = _d.getElementsByTagName('frameset')[0];
                         _frame = _d.createElement((frameset ? '' : 'i') + 'frame');
                         if (frameset) {
                             frameset.insertAdjacentElement('beforeEnd', _frame);
                             frameset[frameset.cols ? 'cols' : 'rows'] += ',0';
                             _frame.noResize = TRUE;
                             _frame.frameBorder = _frame.frameSpacing = 0;
                         } else {
                             _frame.style.display = 'none';
                             _frame.style.width = _frame.style.height = 0;
                             _frame.tabIndex = -1;
                             _d.body.insertAdjacentElement('afterBegin', _frame);
                         }
                         _st(function() {
                             $(_frame).bind('load', function() {
                                 var win = _frame.contentWindow;
                                 _value = win[ID] !== UNDEFINED ? win[ID] : '';
                                 if (_value != _href()) {
                                     _update(FALSE);
                                     _l.hash = _crawl(_value, TRUE);
                                 }
                             });
                             if (_frame.contentWindow[ID] === UNDEFINED) {
                                 _html();
                             }
                         }, 50);
                     } else if (_webkit) {
                         if (_version < 418) {
                             $(_d.body).append('<form id="' + ID + '" style="position:absolute;top:-9999px;" method="get"></form>');
                             _form = _d.getElementById(ID);
                         }
                         if (_l[ID] === UNDEFINED) {
                             _l[ID] = {};
                         }
                         if (_l[ID][_l.pathname] !== UNDEFINED) {
                             _stack = _l[ID][_l.pathname].split(',');
                         }
                     }

                     _st(function() {
                         _trigger('init');
                         _update(FALSE);
                     }, 1);

                     if (!_supportsState()) {
                         if ((_msie && _version > 7) || (!_msie && ('on' + HASH_CHANGE) in _t)) {
                             if (_t.addEventListener) {
                                 _t.addEventListener(HASH_CHANGE, _listen, FALSE);
                             } else if (_t.attachEvent) {
                                 _t.attachEvent('on' + HASH_CHANGE, _listen);
                             }
                         } else {
                             _si(_listen, 50);
                         }
                     }
                 }
             },
             _enable = function() {
                 var el, 
                     elements = $('a'), 
                     length = elements.size(),
                     delay = 1,
                     index = -1;
                 _st(function() {
                     if (++index != length) {
                         el = $(elements.get(index));
                         if (el.is('[rel*=address:]')) {
                             el.address();
                         }
                         _st(arguments.callee, delay);
                     }
                 }, delay);
             },
             _popstate = function() {
                 if (_value != _href()) {
                     _value = _href();
                     _update(FALSE);
                 }
             },
             _unload = function() {
                 if (_t.removeEventListener) {
                     _t.removeEventListener(HASH_CHANGE, _listen, FALSE);
                 } else if (_t.detachEvent) {
                     _t.detachEvent('on' + HASH_CHANGE, _listen);
                 }
             },
             _unescape = function() {
                 if (_opts.crawlable) {
                     var base = _l.pathname.replace(/\/$/, ''),
                         fragment = '_escaped_fragment_';
                     if ($('body').html().indexOf(fragment) != -1) {
                         $('a[href]:not([href^=http]), , a[href*=' + document.domain + ']').each(function() {
                             var href = $(this).attr('href').replace(/^http:/, '').replace(new RegExp(base + '/?$'), '');
                             if (href == '' || href.indexOf(fragment) != -1) {
                                 $(this).attr('href', '#' + $.address.decode(href.replace(new RegExp('/(.*)\\?' + fragment + '=(.*)$'), '!$2')));
                             }
                         });
                     }
                 }
             },
             _encode = function(value) {
                 return _ec(_dc(value)).replace(/%20/g, '+');
             }, 
             _path = function(value) {
                 return value.split('#')[0].split('?')[0];
             },
             _pathNames = function(value) {
                 var path = _path(value),
                     names = path.replace(_re, '/').split('/');
                 if (path.substr(0, 1) == '/' || path.length === 0) {
                     names.splice(0, 1);
                 }
                 if (path.substr(path.length - 1, 1) == '/') {
                     names.splice(names.length - 1, 1);
                 }
                 return names;
             },
             _queryString = function(value) {
                 var arr = value.split('?');
                 return arr.slice(1, arr.length).join('?').split('#')[0];
             },
             _parameter = function(name, value) {
                 value = _queryString(value);
                 if (value) {
                     params = value.split('&');
                     var r = [];
                     for (i = 0; i < params.length; i++) {
                         var p = params[i].split('=');
                         if (p[0] == name || $.address.decode(p[0]) == name) {
                             r.push(p.slice(1).join('='));
                         }
                     }
                     if (r.length !== 0) {
                         return r.length != 1 ? r : r[0];
                     }
                 }
             },
             _parameterNames = function(value) {
                 var qs = _queryString(value),
                     names = [];
                 if (qs && qs.indexOf('=') != -1) {
                     var params = qs.split('&');
                     for (var i = 0; i < params.length; i++) {
                         var name = params[i].split('=')[0];
                         if ($.inArray(name, names) == -1) {
                             names.push(name);
                         }
                     }
                 }
                 return names;
             },
             _hash = function(value) {
                 var arr = value.split('#');
                 return arr.slice(1, arr.length).join('#');
             },
             UNDEFINED,
             ID = 'jQueryAddress',
             STRING = 'string',
             HASH_CHANGE = 'hashchange',
             INIT = 'init',
             CHANGE = 'change',
             INTERNAL_CHANGE = 'internalChange',
             EXTERNAL_CHANGE = 'externalChange',
             TRUE = true,
             FALSE = false,
             _opts = {
                 autoUpdate: TRUE, 
                 crawlable: FALSE,
                 history: TRUE, 
                 strict: TRUE,
                 wrap: FALSE
             },
             _browser = $.browser, 
             _version = parseFloat($.browser.version),
             _mozilla = _browser.mozilla,
             _msie = _browser.msie,
             _opera = _browser.opera,
             _webkit = _browser.webkit || _browser.safari,
             _supported = FALSE,
             _t = _window(),
             _d = _t.document,
             _h = _t.history, 
             _l = _t.location,
             _si = setInterval,
             _st = setTimeout,
             _ec = encodeURIComponent,
             _dc = decodeURIComponent,
             _re = /\/{2,9}/g,
             _agent = navigator.userAgent,            
             _frame,
             _form,
             _url = _search(document),
             _qi = _url ? _url.indexOf('?') : -1,
             _title = _d.title, 
             _length = _h.length, 
             _silent = FALSE,
             _loaded = FALSE,
             _justset = TRUE,
             _juststart = TRUE,
             _updating = FALSE,
             _stack = [], 
             _listeners = {}, 
             _value = _href();

         if (_msie) {
             _version = parseFloat(_agent.substr(_agent.indexOf('MSIE') + 4));
             if (_d.documentMode && _d.documentMode != _version) {
                 _version = _d.documentMode != 8 ? 7 : 8;
             }
             $(document).bind('propertychange', function() {
                 if (_d.title != _title && _d.title.indexOf('#' + _href()) != -1) {
                     _d.title = _title;
                 }
             });
         }

         _supported = 
             (_mozilla && _version >= 1) || 
             (_msie && _version >= 6) ||
             (_opera && _version >= 9.5) ||
             (_webkit && _version >= 312);

         if (_supported) {
             for (var i = 1; i < _length; i++) {
                 _stack.push('');
             }
             _stack.push(_value);
             if (_opera) {
                 history.navigationMode = 'compatible';
             }
             if (document.readyState == 'complete') {
                 var interval = setInterval(function() {
                     if ($.address) {
                         _load();
                         clearInterval(interval);
                     }
                 }, 50);
             } else {
                 _options();
                 $(_load);
             }
             var hrefState = _hrefState();
             if (_opts.state !== UNDEFINED) {
                 if (_h.pushState) {
                     if (hrefState.substr(0, 3) == '/#/') {
                         _l.replace(_opts.state.replace(/^\/$/, '') + hrefState.substr(2));
                     }
                 } else if (hrefState != '/' && hrefState.replace(/^\/#/, '') != _hrefHash()) {
                     _l.replace(_opts.state.replace(/^\/$/, '') + '/#' + hrefState);
                 }
             }
             $(window).bind('popstate', _popstate).bind('unload', _unload);
         } else if ((!_supported && _hrefHash() != '') || 
             (_webkit && _version < 418 && _hrefHash() != '' && _l.search != '')) {
             _l.replace(_l.href.substr(0, _l.href.indexOf('#')));
         } else {
             _track();
         }

         return {
             bind: function(type, data, fn) {
                 return _bind(type, data, fn);
             },
             init: function(fn) {
                 return _bind(INIT, fn);
             },
             change: function(fn) {
                 return _bind(CHANGE, fn);
             },
             internalChange: function(fn) {
                 return _bind(INTERNAL_CHANGE, fn);
             },
             externalChange: function(fn) {
                 return _bind(EXTERNAL_CHANGE, fn);
             },
             baseURL: function() {
                 var url = _l.href;
                 if (url.indexOf('#') != -1) {
                     url = url.substr(0, url.indexOf('#'));
                 }
                 if (/\/$/.test(url)) {
                     url = url.substr(0, url.length - 1);
                 }
                 return url;
             },
             autoUpdate: function(value) {
                 if (value !== UNDEFINED) {
                     _opts.autoUpdate = value;
                     return this;
                 }
                 return _opts.autoUpdate;
             },
             crawlable: function(value) {
                 if (value !== UNDEFINED) {
                     _opts.crawlable = value;
                     return this;
                 }
                 return _opts.crawlable;
             },
             history: function(value) {
                 if (value !== UNDEFINED) {
                     _opts.history = value;
                     return this;
                 }
                 return _opts.history;
             },
             state: function(value) {
                 if (value !== UNDEFINED) {
                     _opts.state = value;
                     return this;
                 }
                 return _opts.state;
             },
             strict: function(value) {
                 if (value !== UNDEFINED) {
                     _opts.strict = value;
                     return this;
                 }
                 return _opts.strict;
             },
             tracker: function(value) {
                 if (value !== UNDEFINED) {
                     _opts.tracker = value;
                     return this;
                 }
                 return _opts.tracker;
             },
             wrap: function(value) {
                 if (value !== UNDEFINED) {
                     _opts.wrap = value;
                     return this;
                 }
                 return _opts.wrap;
             },
             update: function() {
                 _updating = TRUE;
                 this.value(_value);
                 _updating = FALSE;
                 return this;
             },
             encode: function(value) {
                 var pathNames = _pathNames(value),
                     parameterNames = _parameterNames(value),
                     queryString = _queryString(value),
                     hash = _hash(value),
                     first = value.substr(0, 1),
                     last = value.substr(value.length - 1),
                     encoded = '';
                 $.each(pathNames, function(i, v) {
                     encoded += '/' + _encode(v);
                 });
                 if (queryString !== '') {
                     encoded += '?';
                     if (parameterNames.length === 0) {
                         encoded += queryString;
                     } else {
                         $.each(parameterNames, function(i, v) {
                             var pv = _parameter(v, value);
                             if (typeof pv !== STRING) {
                                 $.each(pv, function(ni, nv) {
                                     encoded += _encode(v) + '=' + _encode(nv) + '&';
                                 });
                             } else {
                                 encoded += _encode(v) + '=' + _encode(pv) + '&';
                             }
                         });
                         encoded = encoded.substr(0, encoded.length - 1);
                     }
                 }
                 if (hash !== '') {
                     encoded += '#' + _encode(hash);
                 }
                 if (first != '/' && encoded.substr(0, 1) == '/') {
                     encoded = encoded.substr(1);
                 }
                 if (first == '/' && encoded.substr(0, 1) != '/') {
                     encoded = '/' + encoded;
                 }
                 if (/#|&|\?/.test(last)) {
                     encoded += last;
                 }
                 return encoded;
             },
             decode: function(value) {
                 if (value !== UNDEFINED) {
                     var result = [],
                         replace = function(value) {
                             return _dc(value.toString().replace(/\+/g, '%20'));
                         };
                     if (typeof value == 'object' && value.length !== UNDEFINED) {
                         for (var i = 0, l = value.length; i < l; i++) {
                             result[i] = replace(value[i]);
                         }
                         return result;
                     } else {
                         return replace(value);
                     }
                 }
             },
             title: function(value) {
                 if (value !== UNDEFINED) {
                     _st(function() {
                         _title = _d.title = value;
                         if (_juststart && _frame && _frame.contentWindow && _frame.contentWindow.document) {
                             _frame.contentWindow.document.title = value;
                             _juststart = FALSE;
                         }
                         if (!_justset && _mozilla) {
                             _l.replace(_l.href.indexOf('#') != -1 ? _l.href : _l.href + '#');
                         }
                         _justset = FALSE;
                     }, 50);
                     return this;
                 }
                 return _d.title;
             },
             value: function(value) {
                 if (value !== UNDEFINED) {
                     value = this.encode(_strict(value));
                     if (value == '/') {
                         value = '';
                     }
                     if (_value == value && !_updating) {
                         return;
                     }
                     _justset = TRUE;
                     _value = value;
                     if (_opts.autoUpdate || _updating) {
                         _update(TRUE);
                         if (_supportsState()) {
                             _h[_opts.history ? 'pushState' : 'replaceState']({}, '', 
                                     _opts.state.replace(/\/$/, '') + (_value == '' ? '/' : _value));
                         } else {
                             _silent = TRUE;
                             _stack[_h.length] = _value;
                             if (_webkit) {
                                 if (_opts.history) {
                                     _l[ID][_l.pathname] = _stack.toString();
                                     _length = _h.length + 1;
                                     if (_version < 418) {
                                         if (_l.search == '') {
                                             _form.action = '#' + _crawl(_value, TRUE);
                                             _form.submit();
                                         }
                                     } else if (_version < 523 || _value == '') {
                                         var evt = _d.createEvent('MouseEvents');
                                         evt.initEvent('click', TRUE, TRUE);
                                         var anchor = _d.createElement('a');
                                         anchor.href = '#' + _crawl(_value, TRUE);
                                         anchor.dispatchEvent(evt);                
                                     } else {
                                         _l.hash = '#' + _crawl(_value, TRUE);
                                     }
                                 } else {
                                     _l.replace('#' + _crawl(_value, TRUE));
                                 }
                             } else if (_value != _href()) {
                                 if (_opts.history) {
                                     _l.hash = '#' + _crawl(_value, TRUE);
                                 } else {
                                     _l.replace('#' + _crawl(_value, TRUE));
                                 }
                             }
                             if ((_msie && _version < 8) && _opts.history) {
                                 _st(_html, 50);
                             }
                             if (_webkit) {
                                 _st(function(){ _silent = FALSE; }, 1);
                             } else {
                                 _silent = FALSE;
                             }
                         }
                     }
                     return this;
                 }
                 if (!_supported) {
                     return null;
                 }
                 return this.decode(_strict(_value));
             },
             path: function(value) {
                 if (value !== UNDEFINED) {
                     var qs = _queryString(_strict(_value)),
                         hash = _hash(_strict(_value));
                     this.value(value + (qs ? '?' + qs : '') + (hash ? '#' + hash : ''));
                     return this;
                 }
                 return this.decode(_path(_strict(_value)));
             },
             pathNames: function() {
                 return this.decode(_pathNames(_strict(_value)));
             },
             queryString: function(value) {
                 if (value !== UNDEFINED) {
                     var hash = _hash(_strict(_value));
                     this.value(this.path() + (value ? '?' + value : '') + (hash ? '#' + hash : ''));
                     return this;
                 }
                 return this.decode(_queryString(_strict(_value)));
             },
             parameter: function(name, value, append) {
                 var i, params;
                 if (value !== UNDEFINED) {
                     var names = this.parameterNames();
                     params = [];
                     value = value ? _ec(value) : '';
                     for (i = 0; i < names.length; i++) {
                         var n = names[i],
                             v = this.parameter(n);
                         if (typeof v == STRING) {
                             v = [v];
                         }
                         if (n == name) {
                             v = (value === null || value === '') ? [] : 
                                 (append ? v.concat([value]) : [value]);
                         }
                         for (var j = 0; j < v.length; j++) {
                             params.push(n + '=' + _encode(v[j]));
                         }
                     }
                     if ($.inArray(name, names) == -1 && value !== null && value !== '') {
                         params.push(name + '=' + _encode(value));
                     }
                     this.queryString(params.join('&'));
                     return this;
                 }
                 return this.decode(_parameter(name, _strict(_value)));
             },
             parameterNames: function() {
                 return this.decode(_parameterNames(_strict(_value)));
             },
             hash: function(value) {
                 if (value !== UNDEFINED) {
                     this.value(_strict(_value).split('#')[0] + (value ? '#' + value : ''));
                     return this;
                 }
                 return this.decode(_hash(_strict(_value)));
             }
         };
     })();

     $.fn.address = function(fn) {
         if (!$(this).attr('address')) {
             var f = function(e) {
                 if ($(this).is('a')) {
                     var value = fn ? fn.call(this) : 
                         /address:/.test($(this).attr('rel')) ? $(this).attr('rel').split('address:')[1].split(' ')[0] : 
                         $.address.state() !== undefined && $.address.state() != '/' ? 
                                 $(this).attr('href').replace(new RegExp('^(.*' + $.address.state() + '|\\.)'), '') : 
                                 $(this).attr('href').replace(/^(#\!?|\.)/, '');
                     $.address.value(value);
                     e.preventDefault();
                 }
             };
             $(this).click(f).live('click', f).submit(function(e) {
                 if ($(this).is('form')) {
                     var value = fn ? fn.call(this) : $(this).attr('action') + '?' + $.address.decode($(this).serialize());
                     $.address.value(value);
                     e.preventDefault();
                 }
             }).attr('address', true);
         }
         return this;
     };

 }(jQuery));
