//
// Custom plugins for jQuery
//
// Put additional plugins and fixes for jQuery here, not in jquery files to allow easy updating of jQuery.
//

/***
*  jMP3 v0.2.1 - 10.10.2006 (w/Eolas fix & jQuery object replacement)
* an MP3 Player jQuery Plugin (http://www.sean-o.com/jquery/jmp3)
* by Sean O
*
* An easy way make any MP3 playable directly on most any web site (to those using Flash & JS),
* using the sleek Flash Single MP3 Player & the fantabulous jQuery.
*
* SIMPLE USAGE Example:
* $(youridorclass).jMP3();
*
* ADVANCED USAGE Example:
* $("#sounddl").jmp3({
*   showfilename: "false",
*   backcolor: "000000",
*   forecolor: "00ff00",
*   width: 200,
*   showdownload: "false"
* });
*
* HTML:
* <span class="mp3">sound.mp3</span>
*
* NOTE: filename must be enclosed in tag.  Various file paths can be set using the filepath option.
*
* Copyright (c) 2006 Sean O (http://www.sean-o.com)
* Licensed under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
***//*
jQuery.fn.jmp3 = function(passedOptions){
	// hard-wired options
	var playerpath = "/jscript/workgroup/mediabank_workgroup/swf/";					// SET THIS FIRST: path to singlemp3player.swf

	// passable options
	var options = {
		"filepath": "",										// path to MP3 file (default: current directory)
		"backcolor": "",									// background color
		"forecolor": "ffffff",								// foreground color (buttons)
		"width": "25",										// width of player
		"repeat": "no",										// repeat mp3?
		"volume": "50",										// mp3 volume (0-100)
		"autoplay": "false",								// play immediately on page load?
		"showdownload": "true",								// show download button in player
		"showfilename": "false"								// show .mp3 filename after player
	};
	
	// use passed options, if they exist
	if (passedOptions) {
		jQuery.extend(options, passedOptions);
	}
	
	// iterate through each object
	return this.each(function(){
		// filename needs to be enclosed in tag (e.g. <span class='mp3'>mysong.mp3</span>)
		var filename = options.filepath + jQuery(this).html();
		// do nothing if not an .mp3 file
		var validfilename = filename.indexOf(".mp3");
		if (validfilename == -1) { return false; }
		// build the player HTML
		var mp3html = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
		mp3html += 'width="' + options.width + '" height="20" ';
		mp3html += 'codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">';
		mp3html += '<param name="movie" value="' + playerpath + 'singlemp3player.swf?';
		mp3html += 'showDownload=' + options.showdownload + '&file=' + filename + '&autoStart=' + options.autoplay;
		mp3html += '&backColor=' + options.backcolor + '&frontColor=' + options.forecolor;
		mp3html += '&repeatPlay=' + options.repeat + '&songVolume=' + options.volume + '" />';
		mp3html += '<param name="wmode" value="transparent" />';
		mp3html += '<embed wmode="transparent" width="' + options.width + '" height="20" ';
		mp3html += 'src="' + playerpath + 'singlemp3player.swf?'
		mp3html += 'showDownload=' + options.showdownload + '&file=' + filename + '&autoStart=' + options.autoplay;
		mp3html += '&backColor=' + options.backcolor + '&frontColor=' + options.forecolor;
		mp3html += '&repeatPlay=' + options.repeat + '&songVolume=' + options.volume + '" ';
		mp3html += 'type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />';
		mp3html += '</object>';
		// don't display filename if option is set
		if (options.showfilename == "false") { jQuery(this).html(""); }
		jQuery(this).prepend(mp3html+"&nbsp;");
		
		// Eolas workaround for IE (Thanks Kurt!)
		if(jQuery.browser.msie){ this.outerHTML = this.outerHTML; }
	});
};*/

/*
 * ContextMenu - jQuery plugin for right-click context menus
 *
 * Author: Chris Domigan
 * Parts of this plugin are inspired by Joern Zaefferer's Tooltip plugin
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Version: r1
 *
 * For documentation visit http://www.trendskitchens.co.nz/jquery/contextmenu/
 *
 */

(function($) {

 	var menu, trigger, content, hash;
  var defaults = {
    menuStyle : {
      listStyle : "none",
      padding : "1px",
      margin : "0px",
      backgroundColor : "#fff",
      border : "1px solid #999",
      width : "100px"
    },
    itemStyle : {
      margin : "0px",
      color : "#000",
      display : "block",
      cursor : "default",
      padding : "3px",
      border : "1px solid #fff",
      backgroundColor : "#fff"
    },
    itemHoverStyle : {
      border : "1px solid #0a246a",
      backgroundColor : "#b6bdd2"
    }
	};

  $.fn.contextMenu = function(id, options) {
    options = options || defaults;
    if (!menu) {
      menu = $("<div id='jqContextMenu'></div>")
               .hide()
               .css({position:"absolute", zIndex:"500"})
               .appendTo("body")
               .bind("click", function(e) {
                 e.stopPropagation();
               });
    }
    hash = hash || [];
    hash.push({
      id : id,
      menuStyle : $.extend({}, defaults.menuStyle, options.menuStyle || {}),
      itemStyle : $.extend({}, defaults.itemStyle, options.itemStyle || {}),
      itemHoverStyle : $.extend({}, defaults.itemHoverStyle, options.itemHoverStyle || {}),
      bindings : options.bindings || {}
    });
    var index = hash.length - 1;
    $(this).bind("contextmenu", function(e) {
      display(index, this, e);
      return false;
    });
    return this;
  };

  function display(index, trigger, e) {
    cur = hash[index];
    content = $(cur.id).find("ul:first").clone(true);
    content.css(cur.menuStyle).find("li").css(cur.itemStyle).hover(
      function() {
        $(this).css(cur.itemHoverStyle);
      },
      function(){
        $(this).css(cur.itemStyle);
      }
    ).find("img").css({verticalAlign:"middle",paddingRight:"2px"});
    menu.html(content);
    $.each(cur.bindings, function(id, func) {
      $(id, menu).bind("click", function() {
        hide();
        func(trigger);
      });
    });
    menu.css({"left":e.pageX,"top":e.pageY}).show();
    $(document).one("click", hide);
  }

  function hide() {
    menu.hide();
  }

 	$.contextMenu = {
    defaults : function(userDefaults) {
      $.each(userDefaults, function(i) {
        $.extend(defaults[i], this);
      });
    }
  };

})(jQuery);
$(function() {
  $("div.contextMenu").hide();
});

//. **************************** jMediaPlayer by Johan van Tongeren ************************************ .//

jQuery.fn.jmediaplayer = function(passedOptions){
	var playerpath = "http://home.insiders.nl/johan/jMediaPlayer/";					  // SET THIS FIRST: path to mediaplayer.swf
	
	var options = {
		"filepath": "",										// path to file [path]
        "width": "320",                   // width [int]
		"height": "240",                  // height [int]
		"fgcolor": "",                    // foreground color (buttons, slider, etc) [hex]
		"bgcolor": "",                    // background color (toolbar, etc) [hex]
		"hlcolor": "",                    // highlight color (hovercolor for elements) [hex]
		"largecontrols": "false",         // double size controls [true/false]
		"logo": "",                       // logo (like on television) [url]
		"showeq": "false",                // show an equalizer over the video/audio/image [true/false]
		"autostart": "false",             // automatically start playing [true/false]
		"bufferlength": "5",              // seconds to buffer before playing [int]
		"repeat": "false",                // repeat the video/audio [true/false]
		"image": "",                      // still image to begin the video with or display with audio [url]
		"volume": "80"                    // volume at start [int]
	};

		

	if (passedOptions) {
		jQuery.extend(options, passedOptions);
	}
	
	return this.each(function(){
		var filename = options.filepath + jQuery(this).html();
		if(filename.substring(filename.length - 3) ==  'swf'){
			var s1 = new SWFObject(filename,"audioplayer",options.width,options.height,"8");
		}else{
			var s1 = new SWFObject(playerpath+"mediaplayer.swf","audioplayer",options.width,options.height,"8");
			s1.addParam("allowfullscreen","true");
			s1.addVariable("file",filename);
			s1.addVariable("frontcolor",'0x' + options.fgcolor);
			s1.addVariable("backcolor",'0x' + options.bgcolor);
			s1.addVariable("lightcolor",'0x' + options.hlcolor);
			s1.addVariable("largecontrols",options.largecontrols);
			s1.addVariable("logo",options.logo);
			s1.addVariable("showeq",options.showeq);
			s1.addVariable("autostart",options.autostart);
			s1.addVariable("bufferlength",options.bufferlength);
			s1.addVariable("repeat",options.repeat);
			s1.addVariable("volume",options.volume);
			s1.addVariable("javascriptid","audioplayer"); 
			s1.addVariable("image",options.image);
		}
        
		s1.addVariable("height",options.height);		
		s1.addVariable("width",options.width);
	    s1.write(this.id);
	});
	
};

/**
 * 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.
 *
 * @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
        }
        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;
    }
};

/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-06-20 01:13:48 -0500 (Wed, 20 Jun 2007) $
 * $Rev: 2113 $
 *
 * Version: 1.0b2
 */

(function($){

// store a copy of the core height and width methods
var height = $.fn.height,
    width  = $.fn.width;

$.fn.extend({
	/**
	 * If used on document, returns the document's height (innerHeight)
	 * If used on window, returns the viewport's (window) height
	 * See core docs on height() to see what happens when used on an element.
	 *
	 * @example $("#testdiv").height()
	 * @result 200
	 *
	 * @example $(document).height()
	 * @result 800
	 *
	 * @example $(window).height()
	 * @result 400
	 *
	 * @name height
	 * @type Object
	 * @cat Plugins/Dimensions
	 */
	height: function() {
		if ( this[0] == window )
			return self.innerHeight ||
				$.boxModel && document.documentElement.clientHeight || 
				document.body.clientHeight;
		
		if ( this[0] == document )
			return Math.max( document.body.scrollHeight, document.body.offsetHeight );
		
		return height.apply(this, arguments);
	},
	
	/**
	 * If used on document, returns the document's width (innerWidth)
	 * If used on window, returns the viewport's (window) width
	 * See core docs on height() to see what happens when used on an element.
	 *
	 * @example $("#testdiv").width()
	 * @result 200
	 *
	 * @example $(document).width()
	 * @result 800
	 *
	 * @example $(window).width()
	 * @result 400
	 *
	 * @name width
	 * @type Object
	 * @cat Plugins/Dimensions
	 */
	width: function() {
		if ( this[0] == window )
			return self.innerWidth ||
				$.boxModel && document.documentElement.clientWidth ||
				document.body.clientWidth;

		if ( this[0] == document )
			return Math.max( document.body.scrollWidth, document.body.offsetWidth );

		return width.apply(this, arguments);
	},
	
	/**
	 * Returns the inner height value (without border) for the first matched element.
	 * If used on document, returns the document's height (innerHeight)
	 * If used on window, returns the viewport's (window) height
	 *
	 * @example $("#testdiv").innerHeight()
	 * @result 800
	 *
	 * @name innerHeight
	 * @type Number
	 * @cat Plugins/Dimensions
	 */
	innerHeight: function() {
		return this[0] == window || this[0] == document ?
			this.height() :
			this.is(':visible') ?
				this[0].offsetHeight - num(this, 'borderTopWidth') - num(this, 'borderBottomWidth') :
				this.height() + num(this, 'paddingTop') + num(this, 'paddingBottom');
	},
	
	/**
	 * Returns the inner width value (without border) for the first matched element.
	 * If used on document, returns the document's Width (innerWidth)
	 * If used on window, returns the viewport's (window) width
	 *
	 * @example $("#testdiv").innerWidth()
	 * @result 1000
	 *
	 * @name innerWidth
	 * @type Number
	 * @cat Plugins/Dimensions
	 */
	innerWidth: function() {
		return this[0] == window || this[0] == document ?
			this.width() :
			this.is(':visible') ?
				this[0].offsetWidth - num(this, 'borderLeftWidth') - num(this, 'borderRightWidth') :
				this.width() + num(this, 'paddingLeft') + num(this, 'paddingRight');
	},
	
	/**
	 * Returns the outer height value (including border) for the first matched element.
	 * Cannot be used on document or window.
	 *
	 * @example $("#testdiv").outerHeight()
	 * @result 1000
	 *
	 * @name outerHeight
	 * @type Number
	 * @cat Plugins/Dimensions
	 */
	outerHeight: function() {
		return this[0] == window || this[0] == document ?
			this.height() :
			this.is(':visible') ?
				this[0].offsetHeight :
				this.height() + num(this,'borderTopWidth') + num(this, 'borderBottomWidth') + num(this, 'paddingTop') + num(this, 'paddingBottom');
	},
	
	/**
	 * Returns the outer width value (including border) for the first matched element.
	 * Cannot be used on document or window.
	 *
	 * @example $("#testdiv").outerHeight()
	 * @result 1000
	 *
	 * @name outerHeight
	 * @type Number
	 * @cat Plugins/Dimensions
	 */
	outerWidth: function() {
		return this[0] == window || this[0] == document ?
			this.width() :
			this.is(':visible') ?
				this[0].offsetWidth :
				this.width() + num(this, 'borderLeftWidth') + num(this, 'borderRightWidth') + num(this, 'paddingLeft') + num(this, 'paddingRight');
	},
	
	/**
	 * Returns how many pixels the user has scrolled to the right (scrollLeft).
	 * Works on containers with overflow: auto and window/document.
	 *
	 * @example $("#testdiv").scrollLeft()
	 * @result 100
	 *
	 * @name scrollLeft
	 * @type Number
	 * @cat Plugins/Dimensions
	 */
	/**
	 * Sets the scrollLeft property and continues the chain.
	 * Works on containers with overflow: auto and window/document.
	 *
	 * @example $("#testdiv").scrollLeft(10).scrollLeft()
	 * @result 10
	 *
	 * @name scrollLeft
	 * @param Number value A positive number representing the desired scrollLeft.
	 * @type jQuery
	 * @cat Plugins/Dimensions
	 */
	scrollLeft: function(val) {
		if ( val != undefined )
			// set the scroll left
			return this.each(function() {
				if (this == window || this == document)
					window.scrollTo( val, $(window).scrollTop() );
				else
					this.scrollLeft = val;
			});
		
		// return the scroll left offest in pixels
		if ( this[0] == window || this[0] == document )
			return self.pageXOffset ||
				$.boxModel && document.documentElement.scrollLeft ||
				document.body.scrollLeft;
				
		return this[0].scrollLeft;
	},
	
	/**
	 * Returns how many pixels the user has scrolled to the bottom (scrollTop).
	 * Works on containers with overflow: auto and window/document.
	 *
	 * @example $("#testdiv").scrollTop()
	 * @result 100
	 *
	 * @name scrollTop
	 * @type Number
	 * @cat Plugins/Dimensions
	 */
	/**
	 * Sets the scrollTop property and continues the chain.
	 * Works on containers with overflow: auto and window/document.
	 *
	 * @example $("#testdiv").scrollTop(10).scrollTop()
	 * @result 10
	 *
	 * @name scrollTop
	 * @param Number value A positive number representing the desired scrollTop.
	 * @type jQuery
	 * @cat Plugins/Dimensions
	 */
	scrollTop: function(val) {
		if ( val != undefined )
			// set the scroll top
			return this.each(function() {
				if (this == window || this == document)
					window.scrollTo( $(window).scrollLeft(), val );
				else
					this.scrollTop = val;
			});
		
		// return the scroll top offset in pixels
		if ( this[0] == window || this[0] == document )
			return self.pageYOffset ||
				$.boxModel && document.documentElement.scrollTop ||
				document.body.scrollTop;

		return this[0].scrollTop;
	},
	
	/** 
	 * Returns the top and left positioned offset in pixels.
	 * The positioned offset is the offset between a positioned
	 * parent (absolute, relative or fixed) and the element itself.
	 *
	 * @example $("#testdiv").position()
	 * @result { top: 100, left: 100, scrollTop: 10, scrollLeft: 10 }
	 *
	 * @example $("#testdiv").position({ scroll: false })
	 * @result { top: 90, left: 90 }
	 *
	 * @example var position = {}
	 * $("#testdiv").position({ scroll: false }, position)
	 * @result position = { top: 90, left: 90 }
	 * 
	 * @name position
	 * @param Map options Optional settings to configure the way the offset is calculated.
	 * @option Boolean margin Should the margin of the element be included in the calculations? True by default.
	 * @option Boolean border Should the border of the element be included in the calculations? False by default.
	 * @option Boolean padding Should the padding of the element be included in the calculations? False by default.
	 * @option Boolean scroll Should the scroll offsets of the parent elements be included in the calculations? True by default.
	 *                        When true it adds the totla scroll offets of all parents to the total offset and also adds two properties
	 *                        to the returned object, scrollTop and scrollLeft.
	 * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
	 *                            chain will not be broken and the result will be assigned to this object.
	 * @type Object
	 * @cat Plugins/Dimensions
	 */
	position: function(options, returnObject) {
		var elem = this[0], parent = elem.parentNode, op = elem.offsetParent,
		    options = $.extend({ margin: true, border: false, padding: false, scroll: true }, options || {}),
			x = elem.offsetLeft,
			y = elem.offsetTop, 
			sl = elem.scrollLeft, 
			st = elem.scrollTop;
			
		// Mozilla and IE do not add the border
		if ($.browser.mozilla || $.browser.msie) {
			// add borders to offset
			x += num(elem, 'borderLeftWidth');
			y += num(elem, 'borderTopWidth');
		}

		if (options.scroll || $.browser.mozilla) {
			do {
				if (options.scroll) {
					// get scroll offsets
					sl += parent.scrollLeft;
					st += parent.scrollTop;
				}

				// Mozilla does not add the border for a parent that has overflow set to anything but visible
				if ($.browser.mozilla && parent != elem && $.css(parent, 'overflow') != 'visible') {
					x += num(parent, 'borderLeftWidth');
					y += num(parent, 'borderTopWidth');
				}

				if (parent == op) break; // break if we are already at the offestParent
				parent = parent.parentNode;
			} while (op && (parent.tagName.toLowerCase() != 'body' || parent.tagName.toLowerCase() != 'html'));
		}
		
		var returnValue = handleOffsetReturn(elem, options, x, y, sl, st);
		
		if (returnObject) { $.extend(returnObject, returnValue); return this; }
		else              { return returnValue; }
	},
	
	/**
	 * Returns the location of the element in pixels from the top left corner of the viewport.
	 *
	 * For accurate readings make sure to use pixel values for margins, borders and padding.
	 * 
	 * Known issues:
	 *  - Issue: A div positioned relative or static without any content before it and its parent will report an offsetTop of 0 in Safari
	 *    Workaround: Place content before the realtive div ... and set height and width to 0 and overflow to hidden
	 *
	 * @example $("#testdiv").offset()
	 * @result { top: 100, left: 100, scrollTop: 10, scrollLeft: 10 }
	 *
	 * @example $("#testdiv").offset({ scroll: false })
	 * @result { top: 90, left: 90 }
	 *
	 * @example var offset = {}
	 * $("#testdiv").offset({ scroll: false }, offset)
	 * @result offset = { top: 90, left: 90 }
	 *
	 * @name offset
	 * @param Map options Optional settings to configure the way the offset is calculated.
	 * @option Boolean margin Should the margin of the element be included in the calculations? True by default.
	 * @option Boolean border Should the border of the element be included in the calculations? False by default.
	 * @option Boolean padding Should the padding of the element be included in the calculations? False by default.
	 * @option Boolean scroll Should the scroll offsets of the parent elements be included in the calculations? True by default.
	 *                        When true it adds the totla scroll offets of all parents to the total offset and also adds two properties
	 *                        to the returned object, scrollTop and scrollLeft. 
	 * @options Boolean lite Will use offsetLite instead of offset when set to true. False by default.
	 * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
	 *                            chain will not be broken and the result will be assigned to this object.
	 * @type Object
	 * @cat Plugins/Dimensions
	 */
	offset: function(options, returnObject) {
		var x = 0, y = 0, sl = 0, st = 0,
		    elem = this[0], parent = this[0], op, parPos, elemPos = $.css(elem, 'position'),
		    mo = $.browser.mozilla, ie = $.browser.msie, sf = $.browser.safari, oa = $.browser.opera,
		    absparent = false, relparent = false, 
		    options = $.extend({ margin: true, border: false, padding: false, scroll: true, lite: false }, options || {});
		
		// Use offsetLite if lite option is true
		if (options.lite) return this.offsetLite(options, returnObject);
		
		if (elem.tagName.toLowerCase() == 'body') {
			// Safari is the only one to get offsetLeft and offsetTop properties of the body "correct"
			// Except they all mess up when the body is positioned absolute or relative
			x = elem.offsetLeft;
			y = elem.offsetTop;
			// Mozilla ignores margin and subtracts border from body element
			if (mo) {
				x += num(elem, 'marginLeft') + (num(elem, 'borderLeftWidth')*2);
				y += num(elem, 'marginTop')  + (num(elem, 'borderTopWidth') *2);
			} else
			// Opera ignores margin
			if (oa) {
				x += num(elem, 'marginLeft');
				y += num(elem, 'marginTop');
			} else
			// IE does not add the border in Standards Mode
			if (ie && jQuery.boxModel) {
				x += num(elem, 'borderLeftWidth');
				y += num(elem, 'borderTopWidth');
			}
		} else {
			do {
				parPos = $.css(parent, 'position');
			
				x += parent.offsetLeft;
				y += parent.offsetTop;

				// Mozilla and IE do not add the border
				if (mo || ie) {
					// add borders to offset
					x += num(parent, 'borderLeftWidth');
					y += num(parent, 'borderTopWidth');

					// Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
					if (mo && parPos == 'absolute') absparent = true;
					// IE does not include the border on the body if an element is position static and without an absolute or relative parent
					if (ie && parPos == 'relative') relparent = true;
				}

				op = parent.offsetParent;
				if (options.scroll || mo) {
					do {
						if (options.scroll) {
							// get scroll offsets
							sl += parent.scrollLeft;
							st += parent.scrollTop;
						}
				
						// Mozilla does not add the border for a parent that has overflow set to anything but visible
						if (mo && parent != elem && $.css(parent, 'overflow') != 'visible') {
							x += num(parent, 'borderLeftWidth');
							y += num(parent, 'borderTopWidth');
						}
				
						parent = parent.parentNode;
					} while (parent != op);
				}
				parent = op;

				if (parent.tagName.toLowerCase() == 'body' || parent.tagName.toLowerCase() == 'html') {
					// Safari and IE Standards Mode doesn't add the body margin for elments positioned with static or relative
					if ((sf || (ie && $.boxModel)) && elemPos != 'absolute' && elemPos != 'fixed') {
						x += num(parent, 'marginLeft');
						y += num(parent, 'marginTop');
					}
					// Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
					// IE does not include the border on the body if an element is positioned static and without an absolute or relative parent
					if ( (mo && !absparent && elemPos != 'fixed') || 
					     (ie && elemPos == 'static' && !relparent) ) {
						x += num(parent, 'borderLeftWidth');
						y += num(parent, 'borderTopWidth');
					}
					break; // Exit the loop
				}
			} while (parent);
		}

		var returnValue = handleOffsetReturn(elem, options, x, y, sl, st);

		if (returnObject) { $.extend(returnObject, returnValue); return this; }
		else              { return returnValue; }
	},
	
	/**
	 * Returns the location of the element in pixels from the top left corner of the viewport.
	 * This method is much faster than offset but not as accurate. This method can be invoked
	 * by setting the lite option to true in the offset method.
	 *
	 * @name offsetLite
	 * @param Map options Optional settings to configure the way the offset is calculated.
	 * @option Boolean margin Should the margin of the element be included in the calculations? True by default.
	 * @option Boolean border Should the border of the element be included in the calculations? False by default.
	 * @option Boolean padding Should the padding of the element be included in the calculations? False by default.
	 * @option Boolean scroll Should the scroll offsets of the parent elements be included in the calculations? True by default.
	 *                        When true it adds the totla scroll offets of all parents to the total offset and also adds two properties
	 *                        to the returned object, scrollTop and scrollLeft. 
	 * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
	 *                            chain will not be broken and the result will be assigned to this object.
	 * @type Object
	 * @cat Plugins/Dimensions
	 */
	offsetLite: function(options, returnObject) {
		var x = 0, y = 0, sl = 0, st = 0, parent = this[0], op, 
		    options = $.extend({ margin: true, border: false, padding: false, scroll: true }, options || {});
				
		do {
			x += parent.offsetLeft;
			y += parent.offsetTop;

			op = parent.offsetParent;
			if (options.scroll) {
				// get scroll offsets
				do {
					sl += parent.scrollLeft;
					st += parent.scrollTop;
					parent = parent.parentNode;
				} while(parent != op);
			}
			parent = op;
		} while (parent && parent.tagName.toLowerCase() != 'body' && parent.tagName.toLowerCase() != 'html');

		var returnValue = handleOffsetReturn(this[0], options, x, y, sl, st);

		if (returnObject) { $.extend(returnObject, returnValue); return this; }
		else              { return returnValue; }
	}
});

/**
 * Handles converting a CSS Style into an Integer.
 * @private
 */
var num = function(el, prop) {
	return parseInt($.css(el.jquery?el[0]:el,prop))||0;
};

/**
 * Handles the return value of the offset and offsetLite methods.
 * @private
 */
var handleOffsetReturn = function(elem, options, x, y, sl, st) {
	if ( !options.margin ) {
		x -= num(elem, 'marginLeft');
		y -= num(elem, 'marginTop');
	}

	// Safari and Opera do not add the border for the element
	if ( options.border && ($.browser.safari || $.browser.opera) ) {
		x += num(elem, 'borderLeftWidth');
		y += num(elem, 'borderTopWidth');
	} else if ( !options.border && !($.browser.safari || $.browser.opera) ) {
		x -= num(elem, 'borderLeftWidth');
		y -= num(elem, 'borderTopWidth');
	}

	if ( options.padding ) {
		x += num(elem, 'paddingLeft');
		y += num(elem, 'paddingTop');
	}
	
	// do not include scroll offset on the element
	if ( options.scroll ) {
		sl -= elem.scrollLeft;
		st -= elem.scrollTop;
	}

	return options.scroll ? { top: y - st, left: x - sl, scrollTop:  st, scrollLeft: sl }
	                      : { top: y, left: x };
};

})(jQuery);


/****
 *
 * frameReady: Remote function calling for jQuery
 *
 * Version 1.2.0
 *
 * Copyright (c) 2007 Daemach (John Wilson) <daemach@gmail.com>, http://ideamill.synaptrixgroup.com
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 * 
 *	Credit John Resig and his excellent book for the ready function concepts.
 *
 * ============================================================================================
 * Usage:  	$.frameReady(function (function),target (string)[,options (map/object)]);
 * 
 * Function: (function/required) An anonymous function to be run within the target frame.
 *
 * Target: (string/required) The target frame.  This must be a window object name (in quotes), 
 *		so work from the top down.  If you have 3 frames named topFrame, navFrame, mainFrame, and 
 *		an iframe inside of mainframe named iFrame, use "top.topFrame", "top.navFrame", 
 *		"top.mainFrame", "top.mainFrame.iFrame" respectively.
 *
 *	Options: (object/optional) Map of options in object literal form.  Options include:
 *
 * 		remote: (boolean/ default true)  Run the function in the context of the target frame. 
 *				If true, jQuery will be loaded in the target frame automatically and you can run 
 *				jQuery selectors in the target frame as if they were local. ie: $("p") instead of 
 *				$("p",top.mainFrame.document).  If false, jQuery will not be loaded automatically 
 *				and you must use a context in jquery selectors.
 *				
 *			load: (array or object)  jquery is loaded by default. You can pass a single object to 
 *				frameReady, or an array of objects that will be loaded and tested in order.  2 types 
 *				of files can be loaded.  Scripts	and stylesheets:
 *				
 *				scripts: {type:"script", src:"/js/myscript.js", id:"_ms", test:"afunction"}
 *				stylesheets: {type:"stylesheet", src:"/css/mycss.css", id:"_ss"}
 *				
 *					type: (string/required) "script" for script files, "stylesheet" for stylesheets.
 *					src: (string/required)  The source of the file, ie: /js/myscript.js.
 *					id: (string/optional)  An id for the id attribute.  If one isn't provided it 
 *						will be generated.
 *					test: (sting/optional) The name of a function that should exist once the script 
 *						is loaded properly.  Until this function becomes available, the script will 
 *						be considered not ready and no other files will be loaded.  If a test is not 
 *						provided, the next file will be loaded immediately.  Tests are not useful 
 *						with stylesheets.
 *
 *	One gotcha: You must have something other than space characters within the body tags of 
 * 	target frame documents for frameReady to work properly.  A single character is enough.  
 *		The reason for this is a workaround for an iFrame bug in Firefox, of all things.
 * ==============================================================================================
 *
 * Example: 
 *
 *		$.frameReady(function(){
 *		  $("<div>I am a div element</div>").prependTo("body");
 *		}, "top.mainFrame", 
 *		{ load: [ 
 *			{type:"script",id:"_fr",src:"/js/jquery.frameReady.js",test: "$.frameReady"},
 *			{type:"stylesheet",id:"_ss",src:"frameReady.css"} 
 *			] } 
 *		); 
 *
 *
 * Release Notes:
 *	
 *	1.2.0 - Added provision for a local callback function;
 *	        Added functionality to reset frame information if frame unloads for any reason;
 *			  
 *	1.1.0 - Added the ability to load scripts and stylesheets inside the target frame before
 *					processing function stack;
 *	
 ****/
 
if (typeof $daemach == "undefined") { 
	$daemach = {}; 
	$daemach.debug = false;  // set this to true to enable logging
	$daemach.log = function() {
		if (!top.window.console || !top.window.console.log || !$daemach.debug) { 
			return;
		} else { 
			top.window.console.log([].join.call(arguments,'')); 
		}
	}
}

if (typeof $daemach["frameReady"] == "undefined") { 
	$daemach["frameReady"] = {}; 
}
 
jQuery.frameReady = function(f,t,r,j) {
	
	/************************************************************
		You must specify the path to your jquery.js file below!	
	*************************************************************/
	
	var jQueryPath = "/js/jQuery.js";
	
	var u = "undefined";	
	var $fr = $daemach["frameReady"];
	var fn = t.split(".").join("_");	
	// create a branch
	if (typeof $fr[fn] == u) { 
		$fr[fn] = {}; 
		$fr[fn]["settings"] = {	
			remote: true,
			jquery: true,
			load: [ {type:"script",id:"_jq", src:jQueryPath, test:"jQuery"} ],
			bLoaded: false,
			loadInit: [],
			callback: false
		};
		$fr[fn]["target"] = t;
	}
	var fr = $fr[fn];	
	var frs = fr["settings"];
	
	if (fr.done) { 
		$daemach.log(fr.target + " is ready.  Running functions now.");
		return (frs.remote) ? eval(fr.target).eval("(" + f.toString() + ")()") : f(); 
	};
	
	// process arguments

	for (var a=2;a<arguments.length;a++){
		var arg = arguments[a];
		
		if ($.isFunction(arg)){
			frs.callback = arg;
		} else if (typeof arg == "object") {
			if (typeof arg.remote !== u) { 
				frs.remote = arg.remote;
			};
			if (typeof arg.jquery !== u) { 
				frs.jquery = arg.jquery;
			};
			
			// if we're not running functions in the remote frame itself, no need for jQuery
			if (!frs.remote || !frs.jquery) { 
				frs.load.pop(); 
			}
			
			if (typeof arg.load !== u) {
				var bl = true;
				if (arg.load.constructor == Array && arg.load.length){
					for (var i=0;i<arg.load.length;i++){
						bl = true;
						for (var h=0;h<frs.load.length;h++){
							if (frs.load[h].src == arg.load[i].src) { bl=false; };
						}
						if (bl) { frs.load.push(arg.load[i]); }
					}
				} else if (typeof arg.load == "object") {
					for (var h=0;h<frs.load.length;h++){
						if (frs.load[h].src == arg.load.src) { bl=false; };
					}
					if (bl) { frs.load.push(arg.load); }
				}
			}
		}
	}

	if (fr.timer) {
		fr.ready.push(f);
	} else {
		fr.ready=[f];
		if (typeof addEvent !== "undefined"){ addEvent(window,"load",function(){ jQuery.isFrameReady(fn); }); };
		fr.timer = setInterval(function(){ jQuery.isFrameReady(fn); },13);
	}
}

jQuery.isFrameReady = function(fn){
	var u = "undefined";	
	var $d = $daemach;
	var fr = $d["frameReady"][fn];
	var frs = fr["settings"];
	
	if (fr.done) { return false; };

	var fx = eval(fr.target);
	$d.log(fn, ": New Pass. Checking target");
	// make sure we have a target
	if (typeof fx !== "undefined") {
		$d.log(fn, ": Found target.  Checking DOM");
		var fd = fx.document;
		
		// make sure we have a DOM
		if (fd && fd.getElementsByTagName && fd.getElementById && fd.body && fd.body.innerHTML.length) {
			
			$d.log(fn, ": Found DOM");
			
			if (frs.load.length && !frs.bLoaded){
				for (var i=0;i<frs.load.length;i++){
					var s = frs.load[i];
					var _test;
					try { _test = eval('typeof fx.'+s.test+ ' !== "undefined"'); } 
					catch(ex){ _test = false;}
					finally { $d.log(fn, ": Running test for script ",i,". ", (_test || !s.test) ? "Passed.":"Failed."); }

					if ((_test || !s.test) && frs.loadInit[i]) {
						frs.bLoaded = (typeof s.test == u) ? true : _test; 
						continue; 
					} else {
						frs.bLoaded = false;
						if (typeof frs.loadInit[i] == u){
							var id = s.id || "frs_"+i;
							switch (s.type) {
								case "script" :
									$d.log(fn, ": Loading script "+ i + " (" + s.src + ")");
									var ele=fd.createElement('script');
									ele.setAttribute('id', id);
									ele.setAttribute('src', s.src);
									fd.getElementsByTagName("body")[0].appendChild(ele);
									void(ele);
									frs.loadInit[i] = true;
									break
								case "stylesheet" :
									$d.log(fn, ": Loading stylesheet "+ i + " (" + s.src + ")");
									var ele=fd.createElement('link');
									ele.setAttribute('id', id);
									ele.setAttribute('href', s.src);
									ele.setAttribute('rel', "stylesheet");
									ele.setAttribute('type', "text/css");
									fd.getElementsByTagName("body")[0].appendChild(ele);
									void(ele);
									frs.loadInit[i] = true;
								break
								default :
									$d.log(fn, ": Script "+i+" has a bad or missing type attribute..." );
							}
						}
						break;
					}
				}
			} else {
				clearInterval(fr.timer);	
				fr.timer = null;

				fr.ready.push(function(){ window.frameReadyUnload = function(root, fn){ $(window).bind("unload",function(){ root.jQuery.frameReady.unload(fn); }); } });
				
				$d.log(fn, ": Processing function stack:");
				for (var i=0; i<fr.ready.length;i++){
					(frs.remote) ? fx.eval("(" + fr.ready[i].toString() + ")()") : fr.ready[i]();
				}
				
				fx.frameReadyUnload(window,fn);
				
				$d.log(fn, ": Function stack processing complete.");
				
				// we're done here.  let's have a beer.
				fr.ready = null;
				fr.done=true;
				
				if (frs.callback){ 
					$d.log(fn, ": Found a callback.  Executing...");
					frs.callback(); 
				}
			}
		}
	} 

	$d.log(fn, ":");
}

jQuery.frameReady.unload = function(fn){
	$daemach.log("Frame " + fn + " is unloading.  Resetting state.")
	$daemach["frameReady"][fn].done = false;
	$daemach["frameReady"][fn]["settings"].bLoaded = false;
	$daemach["frameReady"][fn]["settings"].loadInit = [];
}



/**
 * Create an accordion from a HTML structure
 *
 * @example $('#myAccordion').Accordion(
 *				{
 *					headerSelector	: 'dt',
 *					panelSelector	: 'dd',
 *					activeClass		: 'myAccordionActive',
 *					hoverClass		: 'myAccordionHover',
 *					panelHeight		: 200,
 *					speed			: 300
 *				}
 *			);
 * @desc Converts definition list with id 'myAccordion' into an accordion width dt tags as headers and dd tags as panels
 * 
 * @name Accordion
 * @description Create an accordion from a HTML structure
 * @param Hash hash A hash of parameters
 * @option Integer panelHeight the pannels' height
 * @option String headerSelector selector for header elements
 * @option String panelSelector selector for panel elements
 * @option String activeClass (optional) CSS Class for active header
 * @option String hoverClass (optional) CSS Class for hovered header
 * @option Function onShow (optional) callback called whenever an pannel gets active
 * @option Function onHide (optional) callback called whenever an pannel gets incative
 * @option Function onClick (optional) callback called just before an panel gets active
 * @option Mixed speed (optional) animation speed, integer for miliseconds, string ['slow' | 'normal' | 'fast']
 * @option Integer crrentPanel (otional) the active panel on initialisation
 *
 * @type jQuery
 * @cat Plugins/Interface
 * @author Stefan Petre
 */
jQuery.iAccordion = {
	build : function(options)
	{
		return this.each(
			function()
			{
				if (!options.headerSelector || !options.panelSelector)
					return;
				var el = this;
				el.accordionCfg = {
					panelHeight			: options.panelHeight||300,
					headerSelector	: options.headerSelector,
					panelSelector		: options.panelSelector,
					activeClass			: options.activeClass||'fakeAccordionClass',
					hoverClass			: options.hoverClass||'fakeAccordionClass',
					onShow				  : options.onShow && typeof options.onShow == 'function' ? options.onShow : false,
					onHide				  : options.onShow && typeof options.onHide == 'function' ? options.onHide : false,
					onClick				  : options.onClick && typeof options.onClick == 'function' ? options.onClick : false,
					headers				  : jQuery(options.headerSelector, this),
					panels				  : jQuery(options.panelSelector, this),
					speed				    : options.speed||400,
					currentPanel		: options.currentPanel||0
				};
				el.accordionCfg.panels
					.hide()
					.css('height', '0px')
					.css('padding', '0px')
					.css('border', '0px')
					.eq(options.currentPanel)
					.css(
						{
							height: el.accordionCfg.panelHeight + 'px',
							display: 'block'
						}
					)
					.end();
			  el.accordionCfg.headers
				.each(
					function(nr)
					{
						this.accordionPos = nr;
					}
				)
				.hover(
					function()
					{
						jQuery(this).addClass(el.accordionCfg.hoverClass);
					},
					function()
					{
						jQuery(this).removeClass(el.accordionCfg.hoverClass);
					}
				)
				.bind(
					'click',
					function(e) {					  
						if (el.accordionCfg.currentPanel == this.accordionPos) {
							return;
						}
						el.accordionCfg.headers
							.eq(el.accordionCfg.currentPanel)
							.removeClass(el.accordionCfg.activeClass)
							.end()
							.eq(this.accordionPos)
							.addClass(el.accordionCfg.activeClass)
							.end();
						el.accordionCfg.panels
						.eq(el.accordionCfg.currentPanel)
							.animate(
								{height:0},
								el.accordionCfg.speed,
								function()
								{
									this.style.display = 'none';
									if (el.accordionCfg.onHide) {
										el.accordionCfg.onHide.apply(el, [this]);
									}
								}
							)
						.end()
						.eq(this.accordionPos)
							.show()
							.animate (
								{height:el.accordionCfg.panelHeight},
								el.accordionCfg.speed,
								function()
								{
									this.style.display = 'block';
									if (el.accordionCfg.onShow) {
										el.accordionCfg.onShow.apply(el, [this]);
									}
								}
							)
						.end();
						
						if (el.accordionCfg.onClick) {
							el.accordionCfg.onClick.apply(
								el, 
								[
									this, 
									el.accordionCfg.panels.get(this.accordionPos),
									el.accordionCfg.headers.get(el.accordionCfg.currentPanel),
									el.accordionCfg.panels.get(el.accordionCfg.currentPanel)
								]
							);
						}
						el.accordionCfg.currentPanel = this.accordionPos;
					}
				)				
				.eq(0)
				.addClass(el.accordionCfg.activeClass)
				.end();
				jQuery(this)
					.css('height', jQuery(this).css('height'))
					.css('overflow', 'hidden');
			}
		);
	}
};

jQuery.fn.Accordion = jQuery.iAccordion.build;


/* jQuery autocomplete Copyright Dylan Verheul 
 * Licensed like jQuery, see http://docs.jquery.com/License
 */

$.autocomplete = function(input, options) {
	// Create a link to self
	var me = this;

	// Create jQuery object for input element
	var $input = $(input).attr("autocomplete", "off");;

	// Apply inputClass if necessary
	if (options.inputClass) $input.addClass(options.inputClass);

	// Create results
	var results = document.createElement("div");
	// Create jQuery object for results
	var $results = $(results);
	// Set default values for results
	var pos = findPos(input);
	$results.hide().addClass(options.resultsClass).css({
		position: "absolute",
		top: (pos.y + input.offsetHeight) + "px",
		left: pos.x + "px"
	});
	// Add to body element
	$("body").append(results);

	input.autocompleter = me;
	input.lastSelected = $input.val();

	var timeout = null;
	var prev = "";
	var active = -1;
	var cache = {};
	var keyb = false;

	$input
	.keydown(function(e) {
		switch(e.keyCode) {
			case 38: // up
				e.preventDefault();
				moveSelect(-1);
				break;
			case 40: // down
				e.preventDefault();
				moveSelect(1);
				break;
			case 9:  // tab
			case 13: // return
				if (selectCurrent()) {
					e.preventDefault();
				}
				break;
			default:
				active = -1;
				if (timeout) clearTimeout(timeout);
				timeout = setTimeout(onChange, options.delay);
				break;
		}
	})
	.blur(function() {
		hideResults();
	});

	hideResultsNow();

	function onChange() {
		var v = $input.val();
		if (v == prev) return;
		prev = v;
		if (v.length >= options.minChars) {
			$input.addClass(options.loadingClass);
			requestData(v);
		} else {
			$input.removeClass(options.loadingClass);
			$results.hide();
		}
	};

 	function moveSelect(step) {

		var lis = $("li", results);
		if (!lis) return;

		active += step;

		if (active < 0) {
			active = 0;
		} else if (active >= lis.size()) {
			active = lis.size() - 1;
		}

		lis.removeClass("over");

		$(lis[active]).addClass("over");

		// Weird behaviour in IE
		// if (lis[active] && lis[active].scrollIntoView) {
		// 	lis[active].scrollIntoView(false);
		// }

	};

	function selectCurrent() {
		var li = $("li.over", results)[0];
		if (!li) {
			var $li = $("li", results);
			if (options.selectOnly) {
				if ($li.length == 1) li = $li[0];
			} else if (options.selectFirst) {
				li = $li[0];
			}
		}
		if (li) {
			selectItem(li);
			return true;
		} else {
			return false;
		}
	};

	function selectItem(li) {
		if (!li) {
			li = document.createElement("li");
			li.extra = [];
			li.selectValue = "";
		}
		var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML);
		input.lastSelected = v;
		prev = v;
		$results.html("");
		$input.val(v);
		hideResultsNow();
		if (options.onItemSelect) setTimeout(function() { options.onItemSelect(li) }, 1);
	};

	function hideResults() {
		if (timeout) clearTimeout(timeout);
		timeout = setTimeout(hideResultsNow, 200);
	};

	function hideResultsNow() {
		if (timeout) clearTimeout(timeout);
		$input.removeClass(options.loadingClass);
		if ($results.is(":visible")) {
			$results.hide();
		}
		if (options.mustMatch) {
			var v = $input.val();
			if (v != input.lastSelected) {
				selectItem(null);
			}
		}
	};

	function receiveData(q, data) {
		if (data) {
			$input.removeClass(options.loadingClass);
			results.innerHTML = "";
			if ($.browser.msie) {
				// we put a styled iframe behind the calendar so HTML SELECT elements don't show through
				// INSIDERS
				var iframeTmp = document.createElement('iframe');
				iframeTmp.style.display = 'none';
				// END INSIDERS
				$results.append(iframeTmp);
			}
			results.appendChild(dataToDom(data));
			$results.show();
		} else {
			hideResultsNow();
		}
	};

	function parseData(data) {
		if (!data) return null;
		var parsed = [];
		var rows = data.split(options.lineSeparator);
		for (var i=0; i < rows.length; i++) {
			var row = $.trim(rows[i]);
			if (row) {
				parsed[parsed.length] = row.split(options.cellSeparator);
			}
		}
		return parsed;
	};

	function dataToDom(data) {
		var ul = document.createElement("ul");
		var num = data.length;
		for (var i=0; i < num; i++) {
			var row = data[i];
			if (!row) continue;
			var li = document.createElement("li");
			if (options.formatItem) {
				li.innerHTML = options.formatItem(row, i, num);
				li.selectValue = row[0];
			} else {
				li.innerHTML = row[0];
			}
			var extra = null;
			if (row.length > 1) {
				extra = [];
				for (var j=1; j < row.length; j++) {
					extra[extra.length] = row[j];
				}
			}
			li.extra = extra;
			ul.appendChild(li);
			$(li).hover(
				function() { $("li", ul).removeClass("over"); $(this).addClass("over"); },
				function() { $(this).removeClass("over"); }
			).click(function(e) { e.preventDefault(); e.stopPropagation(); selectItem(this) });
		}
		return ul;
	};

	function requestData(q) {
		if (!options.matchCase) q = q.toLowerCase();
		var data = options.cacheLength ? loadFromCache(q) : null;
		if (data) {
			receiveData(q, data);
		} else {
			$.get(makeUrl(q), function(data) {
				data = parseData(data)
				addToCache(q, data);
				receiveData(q, data);
			});
		}
	};

	function makeUrl(q) {
		var url = options.url + "?q=" + q;
		for (var i in options.extraParams) {
			url += "&" + i + "=" + options.extraParams[i];
		}
		return url;
	};

	function loadFromCache(q) {
		if (!q) return null;
		if (cache[q]) return cache[q];
		if (options.matchSubset) {
			for (var i = q.length - 1; i >= options.minChars; i--) {
				var qs = q.substr(0, i);
				var c = cache[qs];
				if (c) {
					var csub = [];
					for (var j = 0; j < c.length; j++) {
						var x = c[j];
						var x0 = x[0];
						if (matchSubset(x0, q)) {
							csub[csub.length] = x;
						}
					}
					return csub;
				}
			}
		}
		return null;
	};

	function matchSubset(s, sub) {
		if (!options.matchCase) s = s.toLowerCase();
		var i = s.indexOf(sub);
		if (i == -1) return false;
		return i == 0 || options.matchContains;
	};

	this.flushCache = function() {
		cache = {};
	};

	this.setExtraParams = function(p) {
		options.extraParams = p;
	};
//INSIDERS
	this.findValue = function(li) {			
			if( !!li.extra ){
				var sValue = li.extra[0];				
			}else{
				var sValue = li.selectValue;		
			}	
			return 	sValue;	
		}
//END INSIDERS
	function addToCache(q, data) {
		if (!data || !q || !options.cacheLength) return;
		if (!cache.length || cache.length > options.cacheLength) {
			cache = {};
			cache.length = 1; // we know we're adding something
		} else if (!cache[q]) {
			cache.length++;
		}
		cache[q] = data;
	};

	function findPos(obj) {
		var curleft = obj.offsetLeft || 0;
		var curtop = obj.offsetTop || 0;
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
		}
		return {x:curleft,y:curtop};
	}
}

$.fn.autocomplete = function(url, options) {
	// Make sure options exists
	options = options || {};
	// Set url as option
	options.url = url;
	// Set default values for required options
	options.inputClass = options.inputClass || "ac_input";
	options.resultsClass = options.resultsClass || "ac_results";
	options.lineSeparator = options.lineSeparator || "\n";
	options.cellSeparator = options.cellSeparator || "|";
	options.minChars = options.minChars || 1;
	options.delay = options.delay || 100;
	options.matchCase = options.matchCase || 0;
	options.matchSubset = options.matchSubset || 1;
	options.matchContains = options.matchContains || 0;
	options.cacheLength = options.cacheLength || 0;
	options.mustMatch = options.mustMatch || 0;
	options.extraParams = options.extraParams || {};
	options.loadingClass = options.loadingClass || "ac_loading";
	options.selectFirst = options.selectFirst || false;
	options.selectOnly = options.selectOnly || false;

	this.each(function() {
		var input = this;
		new $.autocomplete(input, options);
	});

	// Don't break the chain
	return this;
}