
/* IE6 flickering */
try {
 document.execCommand("BackgroundImageCache", false, true);
} catch(err) {}



/* Submenu */

/*
 * Superfish v1.4.8 - jQuery menu widget
 * Copyright (c) 2008 Joel Birch
 *
 * Dual licensed under the MIT and GPL licenses:
 * 	http://www.opensource.org/licenses/mit-license.php
 * 	http://www.gnu.org/licenses/gpl.html
 *
 * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
 */

(function($){
	/* hoverIntent by Brian Cherne */
	$.fn.hoverIntent = function(f,g) {
		// default configuration options
		var cfg = {
			sensitivity: 7,
			interval: 100,
			timeout: 0
		};
		// override configuration options with user supplied object
		cfg = $.extend(cfg, g ? { over: f, out: g } : f );

		// instantiate variables
		// cX, cY = current X and Y position of mouse, updated by mousemove event
		// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
		var cX, cY, pX, pY;

		// A private function for getting mouse position
		var track = function(ev) {
			cX = ev.pageX;
			cY = ev.pageY;
		};

		// A private function for comparing current and previous mouse position
		var compare = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			// compare mouse positions to see if they've crossed the threshold
			if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
				$(ob).unbind("mousemove",track);
				// set hoverIntent state to true (so mouseOut can be called)
				ob.hoverIntent_s = 1;
				return cfg.over.apply(ob,[ev]);
			} else {
				// set previous coordinates for next time
				pX = cX; pY = cY;
				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
				ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
			}
		};

		// A private function for delaying the mouseOut function
		var delay = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			ob.hoverIntent_s = 0;
			return cfg.out.apply(ob,[ev]);
		};

		// A private function for handling mouse 'hovering'
		var handleHover = function(e) {
			// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
			while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
			if ( p == this ) { return false; }

			// copy objects to be passed into t (required for event object to be passed in IE)
			var ev = jQuery.extend({},e);
			var ob = this;

			// cancel hoverIntent timer if it exists
			if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

			// else e.type == "onmouseover"
			if (e.type == "mouseover") {
				// set "previous" X and Y position based on initial entry point
				pX = ev.pageX; pY = ev.pageY;
				// update "current" X and Y position based on mousemove
				$(ob).bind("mousemove",track);
				// start polling interval (self-calling timeout) to compare mouse coordinates over time
				if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}

			// else e.type == "onmouseout"
			} else {
				// unbind expensive mousemove event
				$(ob).unbind("mousemove",track);
				// if hoverIntent state is true, then call the mouseOut function after the specified delay
				if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
			}
		};

		// bind the function to the two event listeners
		return this.mouseover(handleHover).mouseout(handleHover);
	};
	
})(jQuery);

;(function($){
	$.fn.superfish = function(op){

		var sf = $.fn.superfish,
			c = sf.c,
			$arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
			over = function(){
				var $$ = $(this), menu = getMenu($$);
				clearTimeout(menu.sfTimer);
				$$.showSuperfishUl().siblings().hideSuperfishUl();
			},
			out = function(){
				var $$ = $(this), menu = getMenu($$), o = sf.op;
				clearTimeout(menu.sfTimer);
				menu.sfTimer=setTimeout(function(){
					o.retainPath=($.inArray($$[0],o.$path)>-1);
					$$.hideSuperfishUl();
					if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
				},o.delay);	
			},
			getMenu = function($menu){
				var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
				sf.op = sf.o[menu.serial];
				return menu;
			},
			addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); };
			
		return this.each(function() {
			var s = this.serial = sf.o.length;
			var o = $.extend({},sf.defaults,op);
			o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
				$(this).addClass([o.hoverClass,c.bcClass].join(' '))
					.filter('li:has(ul)').removeClass(o.pathClass);
			});
			sf.o[s] = sf.op = o;
			
			$('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
				if (o.autoArrows) addArrow( $('>a:first-child',this) );
			})
			.not('.'+c.bcClass)
				.hideSuperfishUl();
			
			var $a = $('a',this);
			$a.each(function(i){
				var $li = $a.eq(i).parents('li');
				$a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
			});
			o.onInit.call(this);
			
		}).each(function() {
			var menuClasses = [c.menuClass];
			if (sf.op.dropShadows  && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
			$(this).addClass(menuClasses.join(' '));
		});
	};

	var sf = $.fn.superfish;
	sf.o = [];
	sf.op = {};
	sf.IE7fix = function(){
		var o = sf.op;
		if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
			this.toggleClass(sf.c.shadowClass+'-off');
		};
	sf.c = {
		bcClass     : 'sf-breadcrumb',
		menuClass   : 'sf-js-enabled',
		anchorClass : 'sf-with-ul',
		arrowClass  : 'sf-sub-indicator',
		shadowClass : 'sf-shadow'
	};
	sf.defaults = {
		hoverClass	: 'sfHover',
		pathClass	: 'overideThisToUse',
		pathLevels	: 1,
		delay		: 800,
		animation	: {opacity:'show'},
		speed		: 'fast',
		autoArrows	: true,
		dropShadows : true,
		disableHI	: false,		// true disables hoverIntent detection
		onInit		: function(){}, // callback functions
		onBeforeShow: function(){},
		onShow		: function(){},
		onHide		: function(){}
	};
	$.fn.extend({
		hideSuperfishUl : function(){
			var o = sf.op,
				not = (o.retainPath===true) ? o.$path : '';
			o.retainPath = false;
			var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
					.find('>ul').hide().css('visibility','hidden');
			o.onHide.call($ul);
			return this;
		},
		showSuperfishUl : function(){
			var o = sf.op,
				sh = sf.c.shadowClass+'-off',
				$ul = this.addClass(o.hoverClass)
					.find('>ul:hidden').css('visibility','visible');
			sf.IE7fix.call($ul);
			o.onBeforeShow.call($ul);
			$ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
			return this;
		}
	});

})(jQuery);


/**
 * jQuery Maxlength plugin
 * @version		$Id: jquery.maxlength.js 18 2009-05-16 15:37:08Z emil@anon-design.se $
 * @package		jQuery maxlength 1.0.5
 * @copyright	Copyright (C) 2009 Emil Stjerneman / http://www.anon-design.se
 * @license		GNU/GPL, see LICENSE.txt
 */
 (function(A){A.fn.maxlength=function(B){var C=jQuery.extend({events:[],maxCharacters:10,status:true,statusClass:"status",statusText:"character left",notificationClass:"notification",showAlert:false,alertText:"You have typed too many characters.",slider:false},B);A.merge(C.events,["keyup"]);return this.each(function(){var G=A(this);var J=A(this).val().length;function D(){var K=C.maxCharacters-J;if(K<0){K=0}G.next("div").html(K+" "+C.statusText)}function E(){var K=true;if(J>=C.maxCharacters){K=false;G.addClass(C.notificationClass);G.val(G.val().substr(0,C.maxCharacters));I()}else{if(G.hasClass(C.notificationClass)){G.removeClass(C.notificationClass)}}if(C.status){D()}}function I(){if(C.showAlert){alert(C.alertText)}}function F(){var K=false;if(G.is("textarea")){K=true}else{if(G.filter("input[type=text]")){K=true}else{if(G.filter("input[type=password]")){K=true}}}return K}if(!F()){return false}A.each(C.events,function(K,L){G.bind(L,function(M){J=G.val().length;E()})});if(C.status){G.after(A("<div/>").addClass(C.statusClass).html("-"));D()}if(!C.status){var H=G.next("div."+C.statusClass);if(H){H.remove()}}if(C.slider){G.next().hide();G.focus(function(){G.next().slideDown("fast")});G.blur(function(){G.next().slideUp("fast")})}})}})(jQuery);
 
 
 /* 
 * Spinbox plugin for jQuery
 * http://www.softwareunity.com/jquery/JQuerySpinBtn/
 *
 * Adds bells and whistles to any ordinary textbox to
 * make it look and feel like a SpinBox Control.
 *
 * Copyright (c) 2006-2010 Software Unity Ltd
 * Dual licensed under the MIT and GPL licenses:
 * http://www.softwareunity.com/jquery/MIT-LICENSE.txt
 * http://www.softwareunity.com/jquery/GPL-LICENSE.txt
 *
 * Originally written by George Adamson, Software Unity (george.jquery@softwareunity.com) August 2006.
 * Modifications made by Mark Gibson, (mgibson@designlinks.net) September 2006.
 * Rewritten and enhanced by George Adamson, Software Unity (george.jquery@softwareunity.com) October 2009.
 *
 * Tested in IE6, Opera9, Firefox 3.5.3
 * v1.0  11 Aug 2006 - George Adamson	- First release
 * v1.1     Aug 2006 - George Adamson	- Minor enhancements
 * v1.2  27 Sep 2006 - Mark Gibson		- Major enhancements
 * v1.3a 28 Sep 2006 - George Adamson	- Minor enhancements
 * v2.0	 20 Oct 2009 - George Adamson	- Major refactor with breaking changes to options.
 
 Sample usage:
 
	// Create group of settings to initialise spinbutton(s). (Optional)
	var myOptions = {
		min: 0,							// Set lower limit or null for no limit.
		max: 100,						// Set upper limit or null for no limit.
		step: 0.5,						// Set increment size.
		spinboxClass: "mySpinBoxClass",	// CSS class to style the spinbutton. (Class also specifies url of the up/down button image.)
		upClass: "mySpinUpClass",		// CSS class for style when mouse over up button.
		downClass: "mySpinDnClass"		// CSS class for style when mouse over down button.
	}
 
	jQuery(document).ready(function($){

		// Initialise INPUT elements as SpinBoxes: (passing options if desired)
		$("INPUT.spinbox").spinbox(myOptions);

	});
 
 */

(function($){

$.fn.spinbox = function(options){

	// Tidy up when spinbox('destroy') is called:
	if( options && typeof(options)==="String" && options==="destroy" )
		return this.unbind(".spinbox")
			.removeClass(options.spinboxClass)
			.removeClass(options.upClass).removeClass(options.downClass)
			.removeClass(options.upHoverClass).removeClass(options.downHoverClass)
			.removeData("spinboxMin").removeData("spinboxMax").removeData("spinboxReset")
			.removeData("spinboxStep").removeData("spinboxBigStep")
	;


	// Apply specified options or defaults:
	var undefined;		
	options = $.extend( {}, $.fn.spinbox.defaults, options );


	// Store min, max & reset values for each element: (Reset defaults to element's initial value if option undefined)
	this.each(function(){

		var $box	= $(this),
			min		= classData( "spinboxMin", this ),
			max		= classData( "spinboxMax", this ),
			step	= classData( "spinboxStep", this ),
			bigStep	= classData( "spinboxBigStep", this ),
			reset	= classData( "spinboxReset", this ),
			scale	= classData( "spinboxScale", this );	// AKA: Number of decimal places.

		if( min===undefined )	min		= firstNum( $box.attr("min"), options.min );
		if( max===undefined )	max		= firstNum( $box.attr("max"), options.max );
		if( !step )				step	= firstNum( $box.attr("step"), options.step );
		if( !bigStep )			bigStep	= firstNum( $box.attr("bigStep"), options.bigStep );
		if( reset===undefined )	reset	= firstNum( options.reset, $box.val(), min, max );
		if( scale===undefined )	scale	= $box.data("spinboxScale"); scale = ( scale || isNum(scale) ) ? scale : options.scale;

		// When scale option is true, auto derive the number of decimalPlaces to round to:
		if( scale === true ) scale = ( step.toString().split(".")[1] || "" ).length;

		$box.data( "spinboxMin", min );
		$box.data( "spinboxMax", max );
		$box.data( "spinboxStep", step );
		$box.data( "spinboxBigStep", bigStep );
		$box.data( "spinboxReset", reset );
		$box.data( "spinboxScale", scale );

	});


	return this.each(function(){

		// Flags used while mouse is being moved or pressed:
		var hoverUp, hoverDown, delayId, repeatId;
		var $box = $(this);

		// Bind event handlers for the spinbox:
		$box.bind("mousemove.spinbox",function(e){

			// Change css class when mouse is over an up/down button:
			var $box	= $(this);			
			var offset	= $box.offset();		// Calculate element left & top;
			var middle	= $box.height() / 2;	// Calculate midpoint between top and bottom of element;
			var hover	= ( e.pageX > offset.left + $box.width() - options.buttonWidth );
			hoverUp		= hover && ( e.pageY <= offset.top + middle );
			hoverDown	= hover && ( e.pageY >  offset.top + middle );

			$box.toggleClass( options.upHoverClass, hoverUp )
				.toggleClass( options.downHoverClass, hoverDown );
			// TODO: Stop autorepeat when mouse moves away from button?

		})

		.bind("mouseout.spinbox",function(){

			// Reset up/down buttons to their normal state when mouse moves away:
			stopAutorepeat();
			$(this).removeClass( [ options.upClass, options.downClass, options.upHoverClass, options.downHoverClass ].join(" ") );
			hoverUp = hoverDown = null;

		})

		.bind("mousedown.spinbox",function(e){

			// Update the spinbox value and set up autorepeat to start after a short delay:
			if( hoverUp || hoverDown ){

				$(this).toggleClass( options.upClass, hoverUp ).toggleClass( options.downClass, hoverDown );
				adjustValue.apply( this, [e] );
				startAutorepeat(this,e);

			};
		})

		.bind("mouseup.spinbox", function(e){
			stopAutorepeat();
			$(this).removeClass(options.upClass).removeClass(options.downClass);
		})

		//.bind("dblclick", function(e) {
		//	if ($.browser.msie)
		//		adjustValue.apply( this, [e, options.step, 1] );
		//})

		.bind("keydown.spinbox",function(e){

			// Filter key press by allowable options.keys if specified:
			if( !options.keys ||
				$.grep(options.keys, function(key){
					return key === e.keyCode || ( key instanceof RegExp && key.test( String.fromCharCode(e.keyCode) ) );
				}).length ){

				// Define arry key codes and decide whether to use options.bigStep when Shift is pressed:
				var $box	= $(this);
				var key		= { up:38, down:40, pageUp:33, pageDown:34 };
				var bigStep	= $box.data("spinboxBigStep");
				var step	= e.shiftKey ? bigStep : $box.data("spinboxStep");

				// Respond to up/down arrow keys and pageUp/pageDown:
				switch(e.keyCode){
					case key.up: adjustValue.apply( this, [e, step, 1] );  break;
					case key.down: adjustValue.apply( this, [e, step, -1] ); break;
					case key.pageUp: adjustValue.apply( this, [e, bigStep, 1] );  break;
					case key.pageDown: adjustValue.apply( this, [e, bigStep, -1] ); break;
				};
			}
			else
				// Cancel event if keys filter was specified but pressed key is not on the list:
				return !options.keys;
		})

		.bind("change.spinbox", function(e){
			adjustValue.apply( this, [e,0] );
		})

		.addClass(options.spinboxClass);



		// React to mousewheel if desired:
		if( options.mousewheel ){

			$(this).bind("mousewheel.spinbox DOMMouseScroll.spinbox", function(e){

				var step = e.shiftKey ? $(this).data("spinboxBigStep") : $(this).data("spinboxStep");

				// Respond to mouse wheel: (Allow for IE/Opera e.wheelDelta and W3C e.detail)
				if ( e.detail < 0 || e.wheelDelta >= 120 )
					adjustValue.apply( this, [e, step, 1] );
				else if ( e.detail > 0 || e.wheelDelta <= -120 )
					adjustValue.apply( this, [e, step, -1] );

				return false;
			});

		}


		// Initialise the current value, ensuring it is within min/max etc:
		adjustValue.apply( this, [$.Event(),0] );



		// Helper called in response to click or mousewheel etc to apply step change:
		function adjustValue(e,step,direction){

			var $box	= $(this); if( options.ignore && $box.is(options.ignore) ) return;
			step		= firstNum( step, $box.data("spinboxStep"), 1 );
			direction	= direction || (hoverDown ? -1 : 1);
			var oldVal	= $box.val();
			var val		= firstNum( oldVal, $box.data("spinboxReset"), 0 );
			var min		= firstNum( $box.data("spinboxMin") );
			var max		= firstNum( $box.data("spinboxMax") );
			var data	= [val,step,min,max,direction,oldVal,options];

			if( direction > 0 ) val = options.increment.apply( this,data ); else
			if( direction < 0 ) val = options.decrement.apply( this,data );
			if( isNum($box.data("spinboxScale")) && options.round ) val = options.round(val,$box.data("spinboxScale"));
			if( isNum(min) ) val = Math.max(val,min);
			if( isNum(max) ) val = Math.min(val,max);

			var data	= [val,step,min,max,direction,oldVal,options];
			if( val != oldVal && $box.triggerHandler("beforeSpin",data) !== false ){
				$box.val(val);
				if( options.change ) $box.trigger("change",data);
				$box.triggerHandler("spin",data);
			};
		};


		// Helper to begin autorepeat when mouse is held down:
		function startAutorepeat(elem,e){
			stopAutorepeat();
			// Start timer for initial delay:
			delayId = window.setTimeout(function(){
				adjustValue.apply( elem, [e] );
				// Start timer for repeating:
				repeatId = window.setInterval(function(){
					adjustValue.apply( elem, [e] );
				},options.repeat);
			},options.delay);
		};

		// Helper to end autorepeat when mouse is released:
		function stopAutorepeat(){
			window.clearTimeout(delayId);
			window.clearInterval(repeatId);
		};

	});

};



// Helper functions:

	// More reliable alternative to isNaN and isFinite:
	function isNum(num){
		return !isNaN(parseFloat(num))
	}

	// Helper to return the first parameter that is a valid number:
	function firstNum(args){
		for( var i=0; i<arguments.length; i++ ){
			if( isNum(arguments[i]) ) return Number( parseFloat(arguments[i]) );
		};
		return;
	};

	// Helper to extract settings stored in css class attribute string: (Eg: when class="spinbox spinboxStep0.5")
	function classData(attr,elem){

		var classes	= $(elem||this).attr("class"),
			match	= new RegExp( "(\\b" + attr + ")(\\S*)" ).exec(classes),
			lookupBoolean = { "true":true, "True":true, "false":false, "False":false };

		// Convert "True" or "False" string to boolean:
		if( match && match.length >= 3 && lookupBoolean[match[3]] !== undefined )
			match[3] = lookupBoolean[ match[3] ];

		return	!match ? undefined :			// attr not found in class string.
				match.length >= 3 ? match[2] :	// Specific value.
				null;							// attr specified but value deliberately blank.
	};





$.fn.spinbox.defaults = {
	min				: 0,						// Lower limit or null.
	max				: null,						// Upper limit or null.
	step			: 1,						// Size of standard increment.
	bigStep			: 10,						// Size of increment when Shift key is held down or when pageUp/pagedown is pressed.
	keys			: [ /[0-9]/,9,13,8,46,33,34,37,38,39,40,109,188,190 ],	// Array of regular expressions and/or char codes to restrict key input. Default: 0-9, Tab, Enter, Backspace, Delete, PageUp, PageDown, Left, Up, Right, Down, Minus, Comma, Dot.
	ignore			: "[readonly],[disabled]",	// Spinbox will not respond on elements matching this CSS selector.
	spinboxClass	: 'spinbox-active',			// Added to element when spinbox is initialised. Typically used to apply button image through css.
	upClass			: 'spinbox-up',				// Added to element while mouse is depressed on the Up button.
	downClass		: 'spinbox-down',			// Added to element while mouse is depressed on the Down button.
	upHoverClass	: 'spinbox-up-hover',		// Added to element while mouse is over the Up button.
	downHoverClass	: 'spinbox-down-hover',		// Added to element while mouse is over the Down button.
	mousewheel		: true,						// When true, spinbox will react to mousehweel.
	change			: true,						// When true, spinbox will trigger change event as it spins. (Otherwise change event is fired in the same ways as any normal textbox)
	increment		: function(val,step,min,max,options){ return val + step; },	// Custom function to calculate the value increment.
	decrement		: function(val,step,min,max,options){ return val - step; },	// Custom function to calculate the value decrement.
	reset			: null,						// Value used when element value is invalid. Specify null to default to element's initial value;
	delay			: 500,						// Initial delay before auto-repeat when mouse button held down. (Milliseconds)
	repeat			: 100,						// Interval between auto-repeats when mouse button held down. (Milliseconds)
	buttonWidth		: 20,						// Width of the button sprite image (so we can decide when mouse is over it).
	scale			: true,						// Specify number of DP, or true to auto derive from options.step (Eg: when step is 0.125 then DP will be 3)
	round			: function round(num,dp) {	// Specify your own decimalPlaces rounding function if you don't like this default one.
		return Math.round( num * Math.pow(10,dp) ) / Math.pow(10,dp);
	}
};

})(jQuery);


/**
 * Cookie plugin
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a cookie with the given name and value and other optional parameters.
 *
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Set the value of a cookie.
 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
 * @desc Create a cookie with all available options.
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Create a session cookie.
 * @example $.cookie('the_cookie', null);
 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
 *       used when the cookie was set.
 *
 * @param String name The name of the cookie.
 * @param String value The value of the cookie.
 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
 *                             when the the browser exits.
 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
 *                        require a secure protocol (like HTTPS).
 * @type undefined
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Get the value of a cookie with the given name.
 *
 * @example $.cookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};



//   adtag client v6.46 2009-10-23 JavaScript


// Setup
	var adServer, dartSite, dartZone, subSection, subSection1, subSection2, pageType, aTitle, adTag, blnTestMode, strTestZone;
	var pageURL = self.location.href;
	var strhttps = /https:/i;
	var pnum = 0;
	var tnum = 0;
	var rndNum = getRandomNum();
	var strHome = "index.html index.htm index.php index.py default.html default.htm default.php default.asp";
	var sizeParams = new Object();
	var chkDomain = true;
	var dcoptDisp = true;
	var blnTicker = true;
	var blnAdTagTest = false;
	var prout="0";
	var msnExclude = false;

// Check for https and set ad server
	if (strhttps.test(pageURL)) {
		adServer = "https://ad.doubleclick.net/adj/";
		(urlStart = 7);
		}
	else {
		adServer = "http://ad.doubleclick.net/adj/";
		(urlStart = 6);
	}


//*************************************************** Handling lesaffaires.com ONLY ********************************************************
// Exception handling - Les Affaires
	var siteAff = new RegExp("lesaffaires.com");
	var siteAffReplace = ".fr";
	if ( siteAff.test(pageURL) ) {
		pageURL = pageURL.replace(siteAffReplace,'');
		var siteAffReplace = new RegExp("article\/[0-9]\/");
		pageURL = pageURL.replace(siteAffReplace,'');

		zonechanged = false;
		
		
	}
	
// Exception handling - Les Affaires - DEV server
	var siteAff2 = new RegExp("dev-mm.com");
	var siteAff2Replace = "/lesaffaires/web";
	if ( siteAff2.test(pageURL)) pageURL = pageURL.replace(siteAff2Replace,'');
	


//*************************************************** Handling lesaffaires.com END ********************************************************	




//*************************************************** Handling Exceptions for multiple sites **********************************************


// Exception handling - MSN exclusion variable
	var siteMsn = new RegExp("/msn");
	var MsnReplace = "/msn";
	if (siteMsn.test(pageURL)) {
		pageURL = pageURL.replace(MsnReplace,'');
		msnExclude = true;
	}

// Exception handling - Visiondurable test
	var siteExOld = new RegExp("mignon-media.com/vd");
	var siteExNew = "visiondurable.com";
	if (siteExOld.test(pageURL)) {
		pageURL = pageURL.replace(siteExOld,siteExNew);
		chkDomain = false;
		urlDomain = "mignon-media.com";
		if (document.domain != urlDomain) document.domain = urlDomain;
	}

// Exception handling - Thats the Spirit
	var siteTts = new RegExp("thatsthespirit.com");
	var TtsReplace = "/en/";
	if (siteTts.test(pageURL)) pageURL = pageURL.replace(TtsReplace,'/');

// Exception handling - Thats the Spirit
	var siteTts = new RegExp("thatsthespirit.ca");
	var TtsReplace = "/en/";
	if (siteTts.test(pageURL)) pageURL = pageURL.replace(TtsReplace,'/');

// Exception handling - Coup de Pouce
	var siteCdeP = new RegExp(/coupdepouce.com/);
	if (siteCdeP.exec(pageURL)) {
		var artCdePRxp = new RegExp(/\/[a-z]\/[1-9]/);
		var artCdeP = artCdePRxp.exec(pageURL);
		if (artCdeP) pageURL = pageURL.substring(0, artCdePRxp.exec(pageURL).index);
	}

// Exception handling - jardinage.net
	var siteTts = new RegExp("jardinage.net");
	var TtsReplace = "/?id=";
	//Because we have no subsection (ss) we add a none value so the article doesn't go in a ss key-value.
	if (siteTts.test(pageURL)) pageURL = pageURL.replace(TtsReplace,'/none/');
	
	
	if(document.domain == "ca.askmen.com"){
		pageURL = pageURL.replace('/blogs/','/');
	}
	
	
// Exception handling - swbooster.com
	/*var siteSW = new RegExp("swbooster.com");
	var siteSWReplace = "2009-";
	prout = "1";
	if ( siteSW.test(pageURL) ) {
		alert();
		prout = "2";
		pageURL = pageURL.replace(siteSWReplace,'');
	}*/
	

//*************************************************** Handling Exceptions for multiple sites END **********************************************



// Strip out query string and anchor from URL
	var urlQ = pageURL.split('?');
	var urlQUery = urlQ[0].split('#');
	
	
	
//****************************************************** Handling Test Mode **************************************************************
// Check for Test Mode
	if (urlQ.length > 1) {
		var urlQAmp = urlQ[1].split('&');
		var i = 0;

		while (i < urlQAmp.length) {
			var urlQAmpSpt = urlQAmp[i].split('=');

			if (urlQAmpSpt[0]=="adtagtest") {
				blnAdTagTest = true;
				alert('** Adtag Script TEST MODE **');
			}


			if (urlQAmpSpt[0]=="tcadtest") {
				blnTestMode = true;
				if (urlQAmpSpt[1] == undefined) {
					strTestZone = 'test';

				} else {
					strTestZone = urlQAmpSpt[1];
				}
				alert('** AD TEST MODE **  Zone: ' + strTestZone);
			}
			i += 1;
		}
	}
//****************************************************** Handling Test Mode End **************************************************************

// Get URL parameters
	var urlString = urlQUery[0].substring(urlStart+1);
	var urlParams = urlString.split('/');

// Define ad tag URL parameter vars
// URL Site
	var urlSite = urlParams[0].split('.');
	var urlDomain = urlSite[urlSite.length-2] + "." + urlSite[urlSite.length-1];
	
// Set document domain for security
	if( document.domain == 'ca.askmen.com' ) chkDomain = false;
	else if ( document.domain == 'ellecanada.com' ) chkDomain = false;
	else if ( document.domain == 'www.ellecanada.com' ) chkDomain = false;
	else if ( document.domain == 'ellequebec.com' ) chkDomain = false;
	else if ( document.domain == 'www.ellequebec.com' ) chkDomain = false;
	
  if (document.domain != urlDomain && chkDomain) document.domain = urlDomain;



//****************************************** Dart tag sites, zones and subzones affectations *********************************************
// DART Site
	(urlSite[urlSite.length-2] == undefined) ? (dartSite = "") : (dartSite = "tc." + urlSite[urlSite.length-2]);

// DART Zone
	if ((urlParams[1] == undefined) || (strHome.indexOf(urlParams[1]) > -1)) {
		dartZone = "homepage";
		subSection = "";
		subSection1 = "";
		subSection2 = "";
		aTitle = "";
		pageType = "homepage";

	} else {
		if ((urlParams[2] == undefined) && (urlParams[1].indexOf(".") > -1)) {
				if(urlDomain != "lesaffaires.com"){
					dartZone = "homepage";
					subSection = "";
					aTitle = pageReplace(urlParams[1]);
					pageType = "content";
				} else {
					dartZone = pageReplace(urlParams[1]);
					subSection = "";
					aTitle = "";
					pageType = "sectionhome";
					}
					
		} else {

			dartZone = urlParams[1];

// sub Section
			if ((urlParams[2] == undefined) || (strHome.indexOf(urlParams[2]) > -1)) {
			
					subSection = "";
					aTitle = "";
					pageType = "sectionhome";
				
			} else {

				if ((urlParams[3] == undefined) && (urlParams[2].indexOf(".") > -1)) {
					
					if(urlDomain != "lesaffaires.com"){
						if (strHome.indexOf(urlParams[3]) > -1) {
							subSection = "";
							aTitle = "";
							pageType = "sectionhome";
						} else {
							subSection = "";
							aTitle = pageReplace(urlParams[2]);
							pageType = "content";
						}

					} else {
						subSection = pageReplace(urlParams[2]);
						aTitle = "";
						pageType = "subhome";
					}

				} else {

					subSection = pageReplace(urlParams[2]);

// article title	
					
					if ((urlParams[3] == undefined) || (strHome.indexOf(urlParams[3]) > -1)) {
						aTitle = "";
						pageType = "subhome";

					} else {

						// Coup de Pouce Recettes exception
						if ( (dartSite=="tc.coupdepouce" && dartZone=="recettes-cuisine") && urlParams[3] != undefined) {
							if (urlParams[4] != undefined) {
								// sub-sub section functionality
								subSection1 = pageReplace(urlParams[3]);

								if (artCdeP) {
									pageType = "content";
									if (urlParams[5] != undefined) {
										subSection2 = pageReplace(urlParams[4]);
										aTitle = pageReplace(urlParams[5]);

									} else {
										aTitle = pageReplace(urlParams[4]);
										pageType = "content";
									}

								} else {
									pageType = "subhome";
									subSection2 = pageReplace(urlParams[4]);
									aTitle = "";
								}

							} else {
								if (artCdeP) {
									aTitle = pageReplace(urlParams[3]);
									pageType = "content";

								} else {
									subSection1 = pageReplace(urlParams[3]);
									pageType = "subhome";
									aTitle = "";
								}
							}

						} else {

						// standard functionality
						aTitle = pageReplace(urlParams[3]);
						pageType = "content";
						}
					}
				}
			}
		}
	}
//****************************************** Dart tag sites, zones and subzones affectations END *********************************************



function pageReplace(strPage) {
	strPage = strPage.replace(/.html/, "");
	strPage = strPage.replace(/.htm/, "");
	strPage = strPage.replace(/.php/, "");
	strPage = strPage.replace(/.asp/, "");
	return strPage;
}

// timestamp
function getRandomNum() {
  var now = new Date();
  var num = now.getTime();
  return num;
}

function printAdTag(adSize, adSite, adZone, adArgs) {
// Check for adSize required entry
	if (adSize == undefined || adSize == '') return 0;

// Insert test mode parameters
	if (blnTestMode) adZone = strTestZone;
	if (blnTestMode) adSite = 'dart.test.site';


// Exception handling
	var siteListStr = "tc.en.wmn.cl|tc.en.wmn.cl.health.healthyweigh|tc.en.wmn.cl.crafts|tc.en.wmn.cl.family|tc.en.wmn.cl.food|tc.en.wmn.cl.free_stuff|tc.en.wmn.cl.health|tc.en.wmn.cl.homepage|tc.en.wmn.cl.life|tc.en.wmn.cl.relationships|tc.en.wmn.cl.style|tc.en.wmn.cl.videos|";
	if (adSite != undefined && adSite != '') {
		if (siteListStr.indexOf(adSite) > -1) {
			adSite = adZone = undefined;
		}
	}

	if (adZone != undefined && adZone != '') {
		//
	}

	if (adSite != undefined && adSite != '' && adZone != undefined && adZone != '') {
		if (adSite == "tc.canadianliving"  && adZone == "recipes") {
			adZone = "food";
			adArgs = (adArgs == undefined) ? ("pg=recipe") : (adArgs + ";pg=recipe");
		}


		//Globeinvestor.com for Les Affaries
		var siteAff2Globe = new RegExp("actions.lesaffaires.com");
		if ( adSite == "tc.lesaffaires" && adZone == "actions" && siteAff2Globe.test(pageURL) ) {
			adZone = "investir";
			adArgs = "ss=actions;pg=content";
		}

		var siteAff2Globe = new RegExp("fonds.lesaffaires.com");
		if ( adSite == "tc.lesaffaires" && adZone == "fonds" && siteAff2Globe.test(pageURL) ) {
			adZone = "investir";
			adArgs = "ss=fonds;pg=content";
		}
	}


// Tile display
	var noTileListStr = "1x50|50x50";
	var tileDisp = true;
	var adSizeSingle = adSize.split(',');
	var i = 0;
	while ( i < adSizeSingle.length) {
		if (noTileListStr.indexOf(adSizeSingle[i]) > -1) (tileDisp = false);
		i += 1;
	}


// Build ad tag with arguments from URL

	
	if (adArgs != undefined) {
		adTag = "" +
		((subSection != "" && adArgs.indexOf("ss=") == -1) ? ("ss=" + subSection + ";"):"") +
		((aTitle != "" && adArgs.indexOf("atitle=") == -1) ? ("atitle=" + aTitle + ";"):"") +
		((msnExclude) ? ("pnr=msn;!category=msn;"):"") +
		((pageType != "" && adArgs.indexOf("pg=") == -1) ? ("pg=" + pageType + ";"):"");
		// dcopt display
		if (adArgs.indexOf("dcopt=no") > -1) {
			(dcoptDisp = false);
			adArgs = adArgs.replace("dcopt=no", "");
		}
		if (adArgs.indexOf("dcopt=yes") > -1) {
			(dcoptDisp = true);
			adArgs = adArgs.replace("dcopt=yes", "");
		}
		// tile display
		if (adArgs.indexOf("tile=no") > -1) {
			(tileDisp = false);
			adArgs = adArgs.replace("tile=no", "");
		}
		if (adArgs.indexOf("tile=yes") > -1) {
			(tileDisp = true);
			adArgs = adArgs.replace("tile=yes", "");
		}
		adTag = adTag + adArgs + ";";
		adTag = adTag .replace(/;;/gi, ";");
	} else {
		adTag = ((subSection != "") ? ("ss=" + subSection + ";"):"") +
		((subSection1 != undefined && subSection1 != "") ? ("ss1=" + subSection1 + ";"):"") +
		((subSection2 != undefined && subSection2 != "") ? ("ss2=" + subSection2 + ";"):"") +
		((aTitle != "") ? ("atitle=" + aTitle + ";"):"") +
		((msnExclude) ? ("pnr=msn;!category=msn;"):"") +
		((pageType != "") ? ("pg=" + pageType + ";"):"");
	}



// Calculated tag values
	if (tileDisp) tnum += 1;
	pnum = getPos(adSize);


// Build ad tag with calculated tag arguments
	adTag = adTag +
		(dcoptDisp ? ("dcopt=ist;") : "") +
		"pos=but" + pnum + ";" +
		(tileDisp ? ("tile=" + tnum + ";") : "") +
		"sz=" + adSize + ";" +
             	"ord=" + rndNum + "?";


// Complete ad tag with required parameters
//	adTag = '<SCRIPT language="JavaScript1.1" charset="ISO-8859-1" src="' +
	adTag = '<SCRIPT language="JavaScript1.1" src="' +
		adServer +
// Check for manually defined site
		((adSite == undefined || adSite == '') ? (dartSite) : (adSite)) + '/' +
// Check for manually defined zone
		((adZone == undefined || adZone == '') ? (dartZone) : (adZone)) + ';' +
		adTag +
		'"><\/SCRIPT>';


// Write out ad call all lowercase
	adTag = adTag.toLowerCase();
	
	var patt1 = /dev-mm.com/;
	
	if (pageURL.search(patt1)){
	    //alert(adTag);
	}
	
	if ( siteAff2.test(pageURL) ) {
	    //alert(adTag);
	    adTag = adTag.replace(/ss=web;/,'');
	}
	document.write(adTag);
	//return  adTag;
	
//	document.getElementById('eee').innerHTML = adTag;



// Ticker
	var tickerListStrFr = "tc.coupdepouce|";
	var tickerSiteStr = ((adSite == undefined || adSite == '') ? (dartSite) : (adSite));
	if ((tickerSiteStr.indexOf(tickerSiteStr) > -1) && (adSize.indexOf('300x250') > -1) && blnTicker && blnAdTagTest) {
//		document.write('<div id="ticker"</div>');
//		var newdiv=document.createElement("div");
//		var newtext=document.createTextNode("A new div");
//		newdiv.appendChild(newtext) //append text to new div
//		document.getElementById('adtile' + tnum).appendChild(newdiv) //append new div to another div
//		document.write('<div id="ticker"><iframe src="http://tcadops.coupdepouce.com/ticker.html" height="200" scrolling="no" frameborder="0" width="300"></iframe></div>');
		blnTicker = false;
	}


// One time only operations
	dcoptDisp = false;
}


// pos value
function getPos(adSize){
	var sizeFind
	var posvalue = 0;
	var posParams = adSize.split(',');
	var i = 0;
	while (i < posParams.length) {
		if (sizeParams[posParams[i]] == undefined) {
			sizeParams[posParams[i]] = 1;
			if (posvalue == 0) (posvalue = 1);
		}
		else {
			sizeParams[posParams[i]] +=1;
			if (posvalue < sizeParams[posParams[i]]) (posvalue = sizeParams[posParams[i]]);
		}
	    	i += 1;
	}
	return posvalue;
}

function setAdTagCookie(name, value) {
  var argv = setAdTagCookie.arguments;
  var argc = setAdTagCookie.arguments.length;
  var expires = (argc > 2) ? argv[2] : null;
  var path = (argc > 3) ? argv[3] : null;
  var domain = (argc > 4) ? argv[4] : null;
  var secure = (argc > 5) ? argv[5] : false;
  document.cookie = name + "=" + escape (value) +
    ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
    ((path == null) ? "" : ("; path=" + path)) +
    ((domain == null) ? "" : ("; domain=" + domain)) +
    ((secure == true) ? "; secure" : "");
}

function getAdTagCookie(name) {
  var arg = name + "=";
  var alen = arg.length;
  var clen = document.cookie.length;
  var cval = null;
  var i = 0;
  while (i < clen) {
    var j = i + alen;
    if (document.cookie.substring(i, j) == arg) {
      cval = getAdTagCookieVal(j);
    }
    i = document.cookie.indexOf(" ", i) + 1;
    if (i == 0) break;
  }
  return cval;
}

function getAdTagCookieVal(offset) {
  var endstr = document.cookie.indexOf (";", offset);
  if (endstr == -1) endstr = document.cookie.length;
  return unescape(document.cookie.substring(offset, endstr));
}


function transPrintAd(returnURL, adSite, adZone){
	return 0;
}

function transPrintAdOld(returnURL, adSite, adZone){
	var tagUrl = "http://ad.doubleclick.net/adi/" +
// Check for manually defined site
		((adSite == undefined || adSite == '') ? (dartSite) : (adSite)) + '/' +
// Check for manually defined zone
		((adZone == undefined || adZone == '') ? (dartZone) : (adZone)) + ';' +
		"rtitle=" + escape(document.title) + ";" +
		"rurl=" + pageURL + ";" +
		"rtime=10;" +
		"sz=3x3;" +
		"ord=" + rndNum + "?";
	var cookieName = 'transAd';
	var exp = new Date(); 
	exp.setTime(exp.getTime() + (8*60*60*1000));
	var showed = getAdTagCookie(cookieName);
	if (showed == null) {
		setAdTagCookie (cookieName, 'served', exp, '/', urlDomain);
		var showed = getAdTagCookie(cookieName);
		if (showed != null) {
			if (document.images) {
				window.location.replace(tagUrl.toLowerCase());
			}
			else {
				window.location.href = tagUrl.toLowerCase();
			}
		}
	}
}



/*
 ### jQuery Star Rating Plugin v3.12 - 2009-04-16 ###
 * Home: http://www.fyneworks.com/jquery/star-rating/
 * Code: http://code.google.com/p/jquery-star-rating-plugin/
 *
	* Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 ###
*/

/*# AVOID COLLISIONS #*/
;if(window.jQuery) (function($){
/*# AVOID COLLISIONS #*/
	
	// IE6 Background Image Fix
	if ($.browser.msie) try { document.execCommand("BackgroundImageCache", false, true)} catch(e) { };
	// Thanks to http://www.visualjquery.com/rating/rating_redux.html
	
	// plugin initialization
	$.fn.rating = function(options){
		if(this.length==0) return this; // quick fail
		
		// Handle API methods
		if(typeof arguments[0]=='string'){
			// Perform API methods on individual elements
			if(this.length>1){
				var args = arguments;
				return this.each(function(){
					$.fn.rating.apply($(this), args);
    });
			};
			// Invoke API method handler
			$.fn.rating[arguments[0]].apply(this, $.makeArray(arguments).slice(1) || []);
			// Quick exit...
			return this;
		};
		
		// Initialize options for this call
		var options = $.extend(
			{}/* new object */,
			$.fn.rating.options/* default options */,
			options || {} /* just-in-time options */
		);
		
		// Allow multiple controls with the same name by making each call unique
		$.fn.rating.calls++;
		
		// loop through each matched element
		this
		 .not('.star-rating-applied')
			.addClass('star-rating-applied')
		.each(function(){
			
			// Load control parameters / find context / etc
			var control, input = $(this);
			var eid = (this.name || 'unnamed-rating').replace(/\[|\]/g, '_').replace(/^\_+|\_+$/g,'');
			var context = $(this.form || document.body);
			
			// FIX: http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=23
			var raters = context.data('rating');
			if(!raters || raters.call!=$.fn.rating.calls) raters = { count:0, call:$.fn.rating.calls };
			var rater = raters[eid];
			
			// if rater is available, verify that the control still exists
			if(rater) control = rater.data('rating');
			
			if(rater && control)//{// save a byte!
				// add star to control if rater is available and the same control still exists
				control.count++;
				
			//}// save a byte!
			else{
				// create new control if first star or control element was removed/replaced
				
				// Initialize options for this raters
				control = $.extend(
					{}/* new object */,
					options || {} /* current call options */,
					($.metadata? input.metadata(): ($.meta?input.data():null)) || {}, /* metadata options */
					{ count:0, stars: [], inputs: [] }
				);
				
				// increment number of rating controls
				control.serial = raters.count++;
				
				// create rating element
				rater = $('<span class="star-rating-control"/>');
				input.before(rater);
				
				// Mark element for initialization (once all stars are ready)
				rater.addClass('rating-to-be-drawn');
				
				// Accept readOnly setting from 'disabled' property
				if(input.attr('disabled')) control.readOnly = true;
				
				// Create 'cancel' button
				rater.append(
					control.cancel = $('<div class="rating-cancel"><a title="' + control.cancel + '">' + control.cancelValue + '</a></div>')
					.mouseover(function(){
						$(this).rating('drain');
						$(this).addClass('star-rating-hover');
						//$(this).rating('focus');
					})
					.mouseout(function(){
						$(this).rating('draw');
						$(this).removeClass('star-rating-hover');
						//$(this).rating('blur');
					})
					.click(function(){
					 $(this).rating('select');
					})
					.data('rating', control)
				);
				
			}; // first element of group
			
			// insert rating star
			var star = $('<div class="star-rating rater-'+ control.serial +'"><a title="' + (this.title || this.value) + '">' + this.value + '</a></div>');
			rater.append(star);
			
			// inherit attributes from input element
			if(this.id) star.attr('id', this.id);
			if(this.className) star.addClass(this.className);
			
			// Half-stars?
			if(control.half) control.split = 2;
			
			// Prepare division control
			if(typeof control.split=='number' && control.split>0){
				var stw = ($.fn.width ? star.width() : 0) || control.starWidth;
				var spi = (control.count % control.split), spw = Math.floor(stw/control.split);
				star
				// restrict star's width and hide overflow (already in CSS)
				.width(spw)
				// move the star left by using a negative margin
				// this is work-around to IE's stupid box model (position:relative doesn't work)
				.find('a').css({ 'margin-left':'-'+ (spi*spw) +'px' })
			};
			
			// readOnly?
			if(control.readOnly)//{ //save a byte!
				// Mark star as readOnly so user can customize display
				star.addClass('star-rating-readonly');
			//}  //save a byte!
			else//{ //save a byte!
			 // Enable hover css effects
				star.addClass('star-rating-live')
				 // Attach mouse events
					.mouseover(function(){
						$(this).rating('fill');
						$(this).rating('focus');
					})
					.mouseout(function(){
						$(this).rating('draw');
						$(this).rating('blur');
					})
					.click(function(){
						$(this).rating('select');
					})
				;
			//}; //save a byte!
			
			// set current selection
			if(this.checked)	control.current = star;
			
			// hide input element
			input.hide();
			
			// backward compatibility, form element to plugin
			input.change(function(){
    $(this).rating('select');
   });
			
			// attach reference to star to input element and vice-versa
			star.data('rating.input', input.data('rating.star', star));
			
			// store control information in form (or body when form not available)
			control.stars[control.stars.length] = star[0];
			control.inputs[control.inputs.length] = input[0];
			control.rater = raters[eid] = rater;
			control.context = context;
			
			input.data('rating', control);
			rater.data('rating', control);
			star.data('rating', control);
			context.data('rating', raters);
  }); // each element
		
		// Initialize ratings (first draw)
		$('.rating-to-be-drawn').rating('draw').removeClass('rating-to-be-drawn');
		
		return this; // don't break the chain...
	};
	
	/*--------------------------------------------------------*/
	
	/*
		### Core functionality and API ###
	*/
	$.extend($.fn.rating, {
		// Used to append a unique serial number to internal control ID
		// each time the plugin is invoked so same name controls can co-exist
		calls: 0,
		
		focus: function(){
			var control = this.data('rating'); if(!control) return this;
			if(!control.focus) return this; // quick fail if not required
			// find data for event
			var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
   // focus handler, as requested by focusdigital.co.uk
			if(control.focus) control.focus.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
		}, // $.fn.rating.focus
		
		blur: function(){
			var control = this.data('rating'); if(!control) return this;
			if(!control.blur) return this; // quick fail if not required
			// find data for event
			var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
   // blur handler, as requested by focusdigital.co.uk
			if(control.blur) control.blur.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
		}, // $.fn.rating.blur
		
		fill: function(){ // fill to the current mouse position.
			var control = this.data('rating'); if(!control) return this;
			// do not execute when control is in read-only mode
			if(control.readOnly) return;
			// Reset all stars and highlight them up to this element
			this.rating('drain');
			this.prevAll().andSelf().filter('.rater-'+ control.serial).addClass('star-rating-hover');
		},// $.fn.rating.fill
		
		drain: function() { // drain all the stars.
			var control = this.data('rating'); if(!control) return this;
			// do not execute when control is in read-only mode
			if(control.readOnly) return;
			// Reset all stars
			control.rater.children().filter('.rater-'+ control.serial).removeClass('star-rating-on').removeClass('star-rating-hover');
		},// $.fn.rating.drain
		
		draw: function(){ // set value and stars to reflect current selection
			var control = this.data('rating'); if(!control) return this;
			// Clear all stars
			this.rating('drain');
			// Set control value
			if(control.current){
				control.current.data('rating.input').attr('checked','checked');
				control.current.prevAll().andSelf().filter('.rater-'+ control.serial).addClass('star-rating-on');
			}
			else
			 $(control.inputs).removeAttr('checked');
			// Show/hide 'cancel' button
			control.cancel[control.readOnly || control.required?'hide':'show']();
			// Add/remove read-only classes to remove hand pointer
			this.siblings()[control.readOnly?'addClass':'removeClass']('star-rating-readonly');
		},// $.fn.rating.draw
		
		select: function(value){ // select a value
			var control = this.data('rating'); if(!control) return this;
			// do not execute when control is in read-only mode
			if(control.readOnly) return;
			// clear selection
			control.current = null;
			// programmatically (based on user input)
			if(typeof value!='undefined'){
			 // select by index (0 based)
				if(typeof value=='number')
 			 return $(control.stars[value]).rating('select');
				// select by literal value (must be passed as a string
				if(typeof value=='string')
					//return 
					$.each(control.stars, function(){
						if($(this).data('rating.input').val()==value) $(this).rating('select');
					});
			}
			else
				control.current = this[0].tagName=='INPUT' ? 
				 this.data('rating.star') : 
					(this.is('.rater-'+ control.serial) ? this : null);
			
			// Update rating control state
			this.data('rating', control);
			// Update display
			this.rating('draw');
			// find data for event
			var input = $( control.current ? control.current.data('rating.input') : null );
			// click callback, as requested here: http://plugins.jquery.com/node/1655
			if(control.callback) control.callback.apply(input[0], [input.val(), $('a', control.current)[0]]);// callback event
		},// $.fn.rating.select
		
		readOnly: function(toggle, disable){ // make the control read-only (still submits value)
			var control = this.data('rating'); if(!control) return this;
			// setread-only status
			control.readOnly = toggle || toggle==undefined ? true : false;
			// enable/disable control value submission
			if(disable) $(control.inputs).attr("disabled", "disabled");
			else     			$(control.inputs).removeAttr("disabled");
			// Update rating control state
			this.data('rating', control);
			// Update display
			this.rating('draw');
		},// $.fn.rating.readOnly
		
		disable: function(){ // make read-only and never submit value
			this.rating('readOnly', true, true);
		},// $.fn.rating.disable
		
		enable: function(){ // make read/write and submit value
			this.rating('readOnly', false, false);
		}// $.fn.rating.select
		
 });
	
	/*--------------------------------------------------------*/
	
	/*
		### Default Settings ###
		eg.: You can override default control like this:
		$.fn.rating.options.cancel = 'Clear';
	*/
	$.fn.rating.options = { //$.extend($.fn.rating, { options: {
			cancel: 'Cancel Rating',   // advisory title for the 'cancel' link
			cancelValue: '',           // value to submit when user click the 'cancel' link
			split: 0,                  // split the star into how many parts?
			
			// Width of star image in case the plugin can't work it out. This can happen if
			// the jQuery.dimensions plugin is not available OR the image is hidden at installation
			starWidth: 16//,
			
			//NB.: These don't need to be pre-defined (can be undefined/null) so let's save some code!
			//half:     false,         // just a shortcut to control.split = 2
			//required: false,         // disables the 'cancel' button so user can only select one of the specified values
			//readOnly: false,         // disable rating plugin interaction/ values cannot be changed
			//focus:    function(){},  // executed when stars are focused
			//blur:     function(){},  // executed when stars are focused
			//callback: function(){},  // executed when a star is clicked
 }; //} });
	
	/*--------------------------------------------------------*/
	
	/*
		### Default implementation ###
		The plugin will attach itself to file inputs
		with the class 'multi' when the page loads
	*/
	$(function(){
	 $('input[type=radio].star').rating();
	});
	
	
	
/*# AVOID COLLISIONS #*/
})(jQuery);
/*# AVOID COLLISIONS #*/




/*
 * Autocomplete - jQuery plugin 1.1pre
 *
 * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, J�rn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.autocomplete.js 5785 2008-07-12 10:37:33Z joern.zaefferer $
 *
 */

;(function($) {
	
$.fn.extend({
	autocomplete: function(urlOrData, options) {
		var isUrl = typeof urlOrData == "string";
		options = $.extend({}, $.Autocompleter.defaults, {
			url: isUrl ? urlOrData : null,
			data: isUrl ? null : urlOrData,
			delay: isUrl ? $.Autocompleter.defaults.delay : 10,
			max: options && !options.scroll ? 10 : 150
		}, options);
		
		// if highlight is set to false, replace it with a do-nothing function
		options.highlight = options.highlight || function(value) { return value; };
		
		// if the formatMatch option is not specified, then use formatItem for backwards compatibility
		options.formatMatch = options.formatMatch || options.formatItem;
		
		return this.each(function() {
			new $.Autocompleter(this, options);
		});
	},
	result: function(handler) {
		return this.bind("result", handler);
	},
	search: function(handler) {
		return this.trigger("search", [handler]);
	},
	flushCache: function() {
		return this.trigger("flushCache");
	},
	setOptions: function(options){
		return this.trigger("setOptions", [options]);
	},
	unautocomplete: function() {
		return this.trigger("unautocomplete");
	}
});

$.Autocompleter = function(input, options) {

	var KEY = {
		UP: 38,
		DOWN: 40,
		DEL: 46,
		TAB: 9,
		RETURN: 13,
		ESC: 27,
		COMMA: 188,
		PAGEUP: 33,
		PAGEDOWN: 34,
		BACKSPACE: 8
	};

	// Create $ object for input element
	var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass);

	var timeout;
	var previousValue = "";
	var cache = $.Autocompleter.Cache(options);
	var hasFocus = 0;
	var lastKeyPressCode;
	var config = {
		mouseDownOnSelect: false
	};
	var select = $.Autocompleter.Select(options, input, selectCurrent, config);
	
	var blockSubmit;
	
	// prevent form submit in opera when selecting with return key
	$.browser.opera && $(input.form).bind("submit.autocomplete", function() {
		if (blockSubmit) {
			blockSubmit = false;
			return false;
		}
	});
	
	// only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
	$input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
		// track last key pressed
		lastKeyPressCode = event.keyCode;
		switch(event.keyCode) {
		
			case KEY.UP:
				event.preventDefault();
				if ( select.visible() ) {
					select.prev();
				} else {
					onChange(0, true);
				}
				break;
				
			case KEY.DOWN:
				event.preventDefault();
				if ( select.visible() ) {
					select.next();
				} else {
					onChange(0, true);
				}
				break;
				
			case KEY.PAGEUP:
				event.preventDefault();
				if ( select.visible() ) {
					select.pageUp();
				} else {
					onChange(0, true);
				}
				break;
				
			case KEY.PAGEDOWN:
				event.preventDefault();
				if ( select.visible() ) {
					select.pageDown();
				} else {
					onChange(0, true);
				}
				break;
			
			// matches also semicolon
			case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
			case KEY.TAB:
			case KEY.RETURN:
				if( selectCurrent() ) {
					// stop default to prevent a form submit, Opera needs special handling
					event.preventDefault();
					blockSubmit = true;
					return false;
				}
				break;
				
			case KEY.ESC:
				select.hide();
				break;
				
			default:
				clearTimeout(timeout);
				timeout = setTimeout(onChange, options.delay);
				break;
		}
	}).focus(function(){
		// track whether the field has focus, we shouldn't process any
		// results if the field no longer has focus
		hasFocus++;
	}).blur(function() {
		hasFocus = 0;
		if (!config.mouseDownOnSelect) {
			hideResults();
		}
	}).click(function() {
		// show select when clicking in a focused field
		if ( hasFocus++ > 1 && !select.visible() ) {
			onChange(0, true);
		}
	}).bind("search", function() {
		// TODO why not just specifying both arguments?
		var fn = (arguments.length > 1) ? arguments[1] : null;
		function findValueCallback(q, data) {
			var result;
			if( data && data.length ) {
				for (var i=0; i < data.length; i++) {
					if( data[i].result.toLowerCase() == q.toLowerCase() ) {
						result = data[i];
						break;
					}
				}
			}
			if( typeof fn == "function" ) fn(result);
			else $input.trigger("result", result && [result.data, result.value]);
		}
		$.each(trimWords($input.val()), function(i, value) {
			request(value, findValueCallback, findValueCallback);
		});
	}).bind("flushCache", function() {
		cache.flush();
	}).bind("setOptions", function() {
		$.extend(options, arguments[1]);
		// if we've updated the data, repopulate
		if ( "data" in arguments[1] )
			cache.populate();
	}).bind("unautocomplete", function() {
		select.unbind();
		$input.unbind();
		$(input.form).unbind(".autocomplete");
	});
	
	
	function selectCurrent() {
		var selected = select.selected();
		if( !selected )
			return false;
		
		var v = selected.result;
		previousValue = v;
		
		if ( options.multiple ) {
			var words = trimWords($input.val());
			if ( words.length > 1 ) {
				v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v;
			}
			v += options.multipleSeparator;
		}
		
		$input.val(v);
		hideResultsNow();
		$input.trigger("result", [selected.data, selected.value]);
		return true;
	}
	
	function onChange(crap, skipPrevCheck) {
		if( lastKeyPressCode == KEY.DEL ) {
			select.hide();
			return;
		}
		
		var currentValue = $input.val();
		
		if ( !skipPrevCheck && currentValue == previousValue )
			return;
		
		previousValue = currentValue;
		
		currentValue = lastWord(currentValue);
		if ( currentValue.length >= options.minChars) {
			$input.addClass(options.loadingClass);
			if (!options.matchCase)
				currentValue = currentValue.toLowerCase();
			request(currentValue, receiveData, hideResultsNow);
		} else {
			stopLoading();
			select.hide();
		}
	};
	
	function trimWords(value) {
		if ( !value ) {
			return [""];
		}
		var words = value.split( options.multipleSeparator );
		var result = [];
		$.each(words, function(i, value) {
			if ( $.trim(value) )
				result[i] = $.trim(value);
		});
		return result;
	}
	
	function lastWord(value) {
		if ( !options.multiple )
			return value;
		var words = trimWords(value);
		return words[words.length - 1];
	}
	
	// fills in the input box w/the first match (assumed to be the best match)
	// q: the term entered
	// sValue: the first matching result
	function autoFill(q, sValue){
		// autofill in the complete box w/the first match as long as the user hasn't entered in more data
		// if the last user key pressed was backspace, don't autofill
		if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) {
			// fill in the value (keep the case the user has typed)
			$input.val($input.val() + sValue.substring(lastWord(previousValue).length));
			// select the portion of the value not typed by the user (so the next character will erase)
			$.Autocompleter.Selection(input, previousValue.length, previousValue.length + sValue.length);
		}
	};

	function hideResults() {
		clearTimeout(timeout);
		timeout = setTimeout(hideResultsNow, 200);
	};

	function hideResultsNow() {
		var wasVisible = select.visible();
		select.hide();
		clearTimeout(timeout);
		stopLoading();
		if (options.mustMatch) {
			// call search and run callback
			$input.search(
				function (result){
					// if no value found, clear the input box
					if( !result ) {
						if (options.multiple) {
							var words = trimWords($input.val()).slice(0, -1);
							$input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
						}
						else
							$input.val( "" );
					}
				}
			);
		}
		if (wasVisible)
			// position cursor at end of input field
			$.Autocompleter.Selection(input, input.value.length, input.value.length);
	};

	function receiveData(q, data) {
		if ( data && data.length && hasFocus ) {
			stopLoading();
			select.display(data, q);
			autoFill(q, data[0].value);
			select.show();
		} else {
			hideResultsNow();
		}
	};

	function request(term, success, failure) {
		if (!options.matchCase)
			term = term.toLowerCase();
		var data = cache.load(term);
		// recieve the cached data
		if (data && data.length) {
			success(term, data);
		// if an AJAX url has been supplied, try loading the data now
		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
			
			var extraParams = {
				timestamp: +new Date()
			};
			$.each(options.extraParams, function(key, param) {
				extraParams[key] = typeof param == "function" ? param() : param;
			});
			
			$.ajax({
				// try to leverage ajaxQueue plugin to abort previous requests
				mode: "abort",
				// limit abortion to this input
				port: "autocomplete" + input.name,
				dataType: options.dataType,
				url: options.url,
				data: $.extend({
					q: lastWord(term),
					limit: options.max
				}, extraParams),
				success: function(data) {
					var parsed = options.parse && options.parse(data) || parse(data);
					cache.add(term, parsed);
					success(term, parsed);
				}
			});
		} else {
			// if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match
			select.emptyList();
			failure(term);
		}
	};
	
	function parse(data) {
		var parsed = [];
		var rows = data.split("\n");
		for (var i=0; i < rows.length; i++) {
			var row = $.trim(rows[i]);
			if (row) {
				row = row.split("|");
				parsed[parsed.length] = {
					data: row,
					value: row[0],
					result: options.formatResult && options.formatResult(row, row[0]) || row[0]
				};
			}
		}
		return parsed;
	};

	function stopLoading() {
		$input.removeClass(options.loadingClass);
	};

};

$.Autocompleter.defaults = {
	inputClass: "ac_input",
	resultsClass: "ac_results",
	loadingClass: "ac_loading",
	minChars: 1,
	delay: 400,
	matchCase: false,
	matchSubset: true,
	matchContains: false,
	cacheLength: 10,
	max: 100,
	mustMatch: false,
	extraParams: {},
	selectFirst: true,
	formatItem: function(row) { return row[0]; },
	formatMatch: null,
	autoFill: false,
	width: 0,
	multiple: false,
	multipleSeparator: ", ",
	highlight: function(value, term) {
		return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
	},
    scroll: true,
    scrollHeight: 180
};

$.Autocompleter.Cache = function(options) {

	var data = {};
	var length = 0;
	
	function matchSubset(s, sub) {
		if (!options.matchCase) 
			s = s.toLowerCase();
		var i = s.indexOf(sub);
		if (options.matchContains == "word"){
			i = s.toLowerCase().search("\\b" + sub.toLowerCase());
		}
		if (i == -1) return false;
		return i == 0 || options.matchContains;
	};
	
	function add(q, value) {
		if (length > options.cacheLength){
			flush();
		}
		if (!data[q]){ 
			length++;
		}
		data[q] = value;
	}
	
	function populate(){
		if( !options.data ) return false;
		// track the matches
		var stMatchSets = {},
			nullData = 0;

		// no url was specified, we need to adjust the cache length to make sure it fits the local data store
		if( !options.url ) options.cacheLength = 1;
		
		// track all options for minChars = 0
		stMatchSets[""] = [];
		
		// loop through the array and create a lookup structure
		for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
			var rawValue = options.data[i];
			// if rawValue is a string, make an array otherwise just reference the array
			rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
			
			var value = options.formatMatch(rawValue, i+1, options.data.length);
			if ( value === false )
				continue;
				
			var firstChar = value.charAt(0).toLowerCase();
			// if no lookup array for this character exists, look it up now
			if( !stMatchSets[firstChar] ) 
				stMatchSets[firstChar] = [];

			// if the match is a string
			var row = {
				value: value,
				data: rawValue,
				result: options.formatResult && options.formatResult(rawValue) || value
			};
			
			// push the current match into the set list
			stMatchSets[firstChar].push(row);

			// keep track of minChars zero items
			if ( nullData++ < options.max ) {
				stMatchSets[""].push(row);
			}
		};

		// add the data items to the cache
		$.each(stMatchSets, function(i, value) {
			// increase the cache size
			options.cacheLength++;
			// add to the cache
			add(i, value);
		});
	}
	
	// populate any existing data
	setTimeout(populate, 25);
	
	function flush(){
		data = {};
		length = 0;
	}
	
	return {
		flush: flush,
		add: add,
		populate: populate,
		load: function(q) {
			if (!options.cacheLength || !length)
				return null;
			/* 
			 * if dealing w/local data and matchContains than we must make sure
			 * to loop through all the data collections looking for matches
			 */
			if( !options.url && options.matchContains ){
				// track all matches
				var csub = [];
				// loop through all the data grids for matches
				for( var k in data ){
					// don't search through the stMatchSets[""] (minChars: 0) cache
					// this prevents duplicates
					if( k.length > 0 ){
						var c = data[k];
						$.each(c, function(i, x) {
							// if we've got a match, add it to the array
							if (matchSubset(x.value, q)) {
								csub.push(x);
							}
						});
					}
				}				
				return csub;
			} else 
			// if the exact item exists, use it
			if (data[q]){
				return data[q];
			} else
			if (options.matchSubset) {
				for (var i = q.length - 1; i >= options.minChars; i--) {
					var c = data[q.substr(0, i)];
					if (c) {
						var csub = [];
						$.each(c, function(i, x) {
							if (matchSubset(x.value, q)) {
								csub[csub.length] = x;
							}
						});
						return csub;
					}
				}
			}
			return null;
		}
	};
};

$.Autocompleter.Select = function (options, input, select, config) {
	var CLASSES = {
		ACTIVE: "ac_over"
	};
	
	var listItems,
		active = -1,
		data,
		term = "",
		needsInit = true,
		element,
		list;
	
	// Create results
	function init() {
		if (!needsInit)
			return;
		element = $("<div/>")
		.hide()
		.addClass(options.resultsClass)
		.css("position", "absolute")
		.appendTo(document.body);
	
		list = $("<ul/>").appendTo(element).mouseover( function(event) {
			if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
	            active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
			    $(target(event)).addClass(CLASSES.ACTIVE);            
	        }
		}).click(function(event) {
			$(target(event)).addClass(CLASSES.ACTIVE);
			select();
			// TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus
			input.focus();
			return false;
		}).mousedown(function() {
			config.mouseDownOnSelect = true;
		}).mouseup(function() {
			config.mouseDownOnSelect = false;
		});
		
		if( options.width > 0 )
			element.css("width", options.width);
			
		needsInit = false;
	} 
	
	function target(event) {
		var element = event.target;
		while(element && element.tagName != "LI")
			element = element.parentNode;
		// more fun with IE, sometimes event.target is empty, just ignore it then
		if(!element)
			return [];
		return element;
	}

	function moveSelect(step) {
		listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
		movePosition(step);
        var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
        if(options.scroll) {
            var offset = 0;
            listItems.slice(0, active).each(function() {
				offset += this.offsetHeight;
			});
            if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
                list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight());
            } else if(offset < list.scrollTop()) {
                list.scrollTop(offset);
            }
        }
	};
	
	function movePosition(step) {
		active += step;
		if (active < 0) {
			active = listItems.size() - 1;
		} else if (active >= listItems.size()) {
			active = 0;
		}
	}
	
	function limitNumberOfItems(available) {
		return options.max && options.max < available
			? options.max
			: available;
	}
	
	function fillList() {
		list.empty();
		var max = limitNumberOfItems(data.length);
		for (var i=0; i < max; i++) {
			if (!data[i])
				continue;
			var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
			if ( formatted === false )
				continue;
			var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
			$.data(li, "ac_data", data[i]);
		}
		listItems = list.find("li");
		if ( options.selectFirst ) {
			listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
			active = 0;
		}
		// apply bgiframe if available
		if ( $.fn.bgiframe )
			list.bgiframe();
	}
	
	return {
		display: function(d, q) {
			init();
			data = d;
			term = q;
			fillList();
		},
		next: function() {
			moveSelect(1);
		},
		prev: function() {
			moveSelect(-1);
		},
		pageUp: function() {
			if (active != 0 && active - 8 < 0) {
				moveSelect( -active );
			} else {
				moveSelect(-8);
			}
		},
		pageDown: function() {
			if (active != listItems.size() - 1 && active + 8 > listItems.size()) {
				moveSelect( listItems.size() - 1 - active );
			} else {
				moveSelect(8);
			}
		},
		hide: function() {
			element && element.hide();
			listItems && listItems.removeClass(CLASSES.ACTIVE);
			active = -1;
		},
		visible : function() {
			return element && element.is(":visible");
		},
		current: function() {
			return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
		},
		show: function() {
			var offset = $(input).offset();
			element.css({
				width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(),
				top: offset.top + input.offsetHeight,
				left: offset.left
			}).show();
            if(options.scroll) {
                list.scrollTop(0);
                list.css({
					maxHeight: options.scrollHeight,
					overflow: 'auto'
				});
				
                if($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
					var listHeight = 0;
					listItems.each(function() {
						listHeight += this.offsetHeight;
					});
					var scrollbarsVisible = listHeight > options.scrollHeight;
                    list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight );
					if (!scrollbarsVisible) {
						// IE doesn't recalculate width when scrollbar disappears
						listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) );
					}
                }
                
            }
		},
		selected: function() {
			var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);
			return selected && selected.length && $.data(selected[0], "ac_data");
		},
		emptyList: function (){
			list && list.empty();
		},
		unbind: function() {
			element && element.remove();
		}
	};
};

$.Autocompleter.Selection = function(field, start, end) {
	if( field.createTextRange ){
		var selRange = field.createTextRange();
		selRange.collapse(true);
		selRange.moveStart("character", start);
		selRange.moveEnd("character", end);
		selRange.select();
	} else if( field.setSelectionRange ){
		field.setSelectionRange(start, end);
	} else {
		if( field.selectionStart ){
			field.selectionStart = start;
			field.selectionEnd = end;
		}
	}
	field.focus();
};

})(jQuery);

