function reloadAds() {
	$j('iframe').attr( 'src', function ( i, val ) { return val; });
}

$j(document).ready(function(){$j("#carousel > ul, #carousel > ul > li, #carousel > div").removeClass();$j("#carousel").tabs({event:"mouseover"}).tabs("rotate",5E3,"continuing");$j("#carousel li a").click(function(){window.location=$j(".uri",this).html()});$j(".my-home").parent().css("height",300);$j(".sidebar .section-collection .item").each(function(a){(a==2||a==4)&&$j(this).addClass("inner");a>=2&&$j(this).css("margin-bottom","45px")});

$j(document).ready(function() { 
	var SMNS = ["AB", "DD", "HS", "IV", "KW", "PH", "ZE"];
	var SMCS = ["DG", "EH", "FK", "G", "KA", "KY", "ML", "PA", "TD"];
	var SMNI = ["BT"];
	var SMBO = ["CA", "LA"];
	var SMNE = ["DH", "DL", "NE", "SR", "TS"];
	var SMNW = ["BB", "BL", "CH", "CW", "FY", "L", "M", "OL", "PR", "SK", "WA", "WN"];
	var SMYO = ["BD", "DN", "HD", "HG", "HU", "HX", "LN", "LS", "S", "WF", "YO" ];
	var SMWS = ["CF", "LD", "LL", "NP", "SA", "SY"];
	var SMWM = ["B", "CV", "DY", "TF", "WR", "WS", "WV", "DE", "ST", "HR"];
	var SMEM = ["LE", "NG", "NN"];
	var SMEA = ["AL", "CB", "CM", "CO", "HP", "IP", "MK", "NR", "PE"];
	var SMWC = ["DT", "EX", "PL", "TA", "TQ", "TR"];
	var SMWE = ["BA", "BS", "GL", "SP"];
	var SMSO = ["OX", "RG", "SN", "BH", "BN", "PO", "SO"];
	var SMLO = ["BR", "CB", "CM", "DA", "E", "EC", "EN", "GU", "HA", "IG", "KT", "N", "RH", "RM", "SE", "SG", "SM", "SW", "TW", "U", "W", "WD", "WC"];
	var SMSE = ["CT", "ME", "SS", "TN"];
	var XSGL = ['G'];

	//hide check
	if($j.cookie('shortcode') != null) {
		$j('#dialog-modal').hide();
	}
	
	$j(".map-click").hover(function() { 
		$j(this).addClass("hover"); 
	}, function() { 
		$j(this).removeClass("hover") 
	});
        
        
	if ($j.cookie("shortcode") == null || (window.location.hash && window.location.hash == '#map') || $j.cookie('shortcode') == $j.cookie('shortcode').toUpperCase())	{
		$j( "#dialog-modal" ).dialog({
			height: 415,
			width: 940,
			padding: 10,
			modal: true,
			draggable: false,
			resizable: false,
			//position: ["center", 74]
		});
                $j(".ui-dialog").addClass("lightbox-center");
	}
	
	$j( ".map-click" ).click(function(e){
		e.preventDefault();
		area = $j(this).attr("id")
		$j.cookie("shortcode", area, { expires: 1000, path: "/" });
		
		if(window._gaq) { window._gaq.push('_trackEvent', 'regionalisation', 'set-map', area); }
		
		$j( "#dialog-modal" ).dialog( "close" );
		
        if(window.location.hash && window.location.hash == '#map') {
			window.location.href = window.location.href.replace('#map', '');
		} else {
			location.reload();
		}
	});
	
	$j('#change-location').click( function() {
		window.location.href = $j(this).attr('href');
		location.reload();
	});

	$j( "#setLocation" ).click(function(){

		postcode = $j("#postcode").val().toUpperCase();
		if (postcode == "") 
		{
			$j( "#postcode-error" ).empty()
			$j( "#postcode-error" ).append( "Please enter a valid postcode" ); 
		}
		else 
		{
			var postcode = $j("#postcode").val().substr(0, $j("#postcode").val().search(/\d/));
			var postcode = postcode.toUpperCase();
			
			var shortcode = '';
			if($j('#postcode').attr('name') == 'postcode-xs') {
				if(postcode == 'G') {shortcode = 'xsgl';}
				else {shortcode = 'xsuk';}
			} else {
				if ($j.inArray(postcode, SMNS) > -1) {shortcode = "smns";}
				else if ($j.inArray(postcode, SMCS) > -1) {shortcode = "smcs";}
				else if ($j.inArray(postcode, SMBO) > -1) {shortcode = "smbo";}
				else if ($j.inArray(postcode, SMNI) > -1) {shortcode = "smni";}
				else if ($j.inArray(postcode, SMNE) > -1) {shortcode = "smne";}
				else if ($j.inArray(postcode, SMNW) > -1) {shortcode = "smnw";}
				else if ($j.inArray(postcode, SMYO) > -1) {shortcode = "smyo";}
				else if ($j.inArray(postcode, SMWS) > -1) {shortcode = "smws";}
				else if ($j.inArray(postcode, SMWM) > -1) {shortcode = "smwm";}
				else if ($j.inArray(postcode, SMEM) > -1) {shortcode = "smem";}
				else if ($j.inArray(postcode, SMEA) > -1) {shortcode = "smea";}
				else if ($j.inArray(postcode, SMWC) > -1) {shortcode = "smwc";}
				else if ($j.inArray(postcode, SMWE) > -1) {shortcode = "smwe";}
				else if ($j.inArray(postcode, SMSO) > -1) {shortcode = "smso";}
				else if ($j.inArray(postcode, SMLO) > -1) {shortcode = "smlo";}
				else if ($j.inArray(postcode, SMSE) > -1) {shortcode = "smse";}
			}
			$j.cookie("shortcode", shortcode, { expires: 1000, path: '/' });
			
			if(window._gaq) { window._gaq.push('_trackEvent', 'regionalisation', 'set-postcode', shortcode); }
			
			$j( "#dialog-modal" ).dialog( "close" );
            if(window.location.hash && window.location.hash == '#map') {
				window.location.href = window.location.href.replace('#map', '');
			} else {
				location.reload();
			}
		}
		return false;
	});
	
	$j('.ui-dialog .ui-dialog-titlebar-close span').click(function() {
		$j.cookie('shortcode', 'closed', { path: '/' });
		
		if(window._gaq) { window._gaq.push('_trackEvent', 'regionalisation', 'skip-close'); }
		
		$j( "#dialog-modal" ).dialog( "close" );
	});
});

var c=
$j.cookie("mySmoothTopics"),d="news,travel,giftsGadgets,foodDrink,unwind,causes".split(",");$j(".my-signup").hide();$j.cookie("hideMyCheck")==null&&($j.cookie("mySmoothTopics")==null||$j.cookie("mySmoothTopics")=="")?($j(".my-check").show(),$j(".my-list").hide()):($j(".my-check").hide(),$j(".my-list").show());$j(".my-signup #cb-newsletter").is(":checked")||$j(".my-signup .signup-form").hide();$j(".my-signup .topics > ol > li > input").each(function(a){c==null||c==""?$j(this).attr("checked",true):
c.indexOf(d[a])==-1?$j(this).attr("checked",false):$j(this).attr("checked",true)});$j(".my-signup .save").click(function(a){a.preventDefault();var b="";$j(".my-signup .topics > ol > li > input").each(function(a){$j(this).is(":checked")&&(b==""?b=d[a]:b+=","+d[a])});$j.cookie("mySmoothTopics",b,{expires:1E3,path:"/"});window._gaq&&window._gaq.push("_trackEvent","mysmooth","set-subjects",b);window.location.hash&&window.location.hash=="#edit"?window.location.href=window.location.href.replace("#edit",""):location.reload()});
$j(".my-signup #cb-newsletter").change(function(){$j("#cb-newsletter").is(":checked")?$j(".signup-form").slideDown():$j(".signup-form").slideUp()});$j(".my-check .close-box").click(function(a){$j.cookie("hideMyCheck","true",{path:"/"});$j(".my-check").slideUp();$j(".my-list").slideDown();a.preventDefault()});$j(".my-home .heading a, .my-check .button a, .my-list .button a, .my-customise .button a").click(function(a){a.preventDefault();$j(".my-signup").slideDown(800);window._gaq&&window._gaq.push("_trackEvent","mysmooth","explore-panel");$j("body").animate({scrollTop:$j("#on-air").offset().top-$j("body").offset().top})});window.location.hash&&window.location.hash=="#edit"&&($j(".my-signup").slideDown(800),window._gaq&&window._gaq.push("_trackEvent","mysmooth","explore-panel"));$j("a[rel~='radioplayer']").click(function(){;window.open($j(this).attr('href'),"RadioPlayer","width=380,height=665,toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=no,resizable=no");setTimeout("window.location = '/'",3E3);return false});$j(".comments-container article").mouseover(function(){$j(this).find(".link-comment").removeClass("visuallyhidden")}).mouseout(function(){$j(this).find(".link-comment").addClass("visuallyhidden")});$j(".info").each(function(){var a=null,b=false,c=false,d=$j(".info-link",this),e=$j(".info-message",this).css("opacity",0);$j([d.get(0),e.get(0)]).mouseover(function(){
a&&clearTimeout(a);if(!b&&!c)return b=true,e.css({top:40,right:0,display:"block"}).animate({top:"-=10px",opacity:1},250,"swing",function(){b=false;c=true}),false}).mouseout(function(){a&&clearTimeout(a);a=setTimeout(function(){a=null;e.animate({top:"-=10px",opacity:0},250,"swing",function(){c=false;e.css("display","none")})},500);return false})});$j(".ad-gallery").adGallery({width:false,height:false,thumb_opacity:1,description_wrapper:false,slideshow:{enable:false},effect:"fade", callbacks: {afterImageVisible: reloadAds}});var f=window.location.href.split("/"),
f="/"+f[3];$j("#nav").find('a[href="'+f+'"]').each(function(){$j(this).parent().addClass("nav-current")})});

/**
 * Postcode lookup
 */
var _cp_instances = [], 
	_cp_instance_idx = 0,
	_cp_pl = ['FLAT', 'SHOP', 'UNIT', 'BLOCK', 'STALL', 'SUITE', 'APARTMENT', 'MAISONETTE', 'HOUSE NUMBER'];
function CraftyPostcodeCreate() {
	_cp_instance_idx++;
	_cp_instances[_cp_instance_idx] = new CraftyPostcodeClass();
	_cp_instances[_cp_instance_idx].obj_idx = _cp_instance_idx;
	return _cp_instances[_cp_instance_idx];
}

// strip prefix
function _cp_sp(a) {
	var pi = '', ii;
	for (ii=0; ii<_cp_pl.length; ii++) {
		pi = _cp_pl[ii];
		if (pi == a.substr(0,pi.length).toUpperCase()) {
			return (a.substr(pi.length)); // return rest of input string after known prefix
		}
	}
	return ('');
}

// extract house number
function _cp_eh(ha) {
	var hn = '';
	while  (hn = ha.shift()) {
		if (!isNaN(parseInt(hn))) {
			return (parseInt(hn));
		}
	}
	return '';
}

// handle hey press on result box
function _cp_kp(e) {
	var cc;
	if (!e) e = window.event;
	if(e.keyCode) {cc = e.keyCode;}
	else if(e.which) {cc = e.which;}
	if(cc == 13){
		this.onclick();
	}
}

$j(document).ready(function(){
	               
	window.lookup = {
			key : '2da27-b4478-b9983-005e1',
			callback: 'lookup.handleResponse',
			url: 'http://pcls1.craftyclicks.co.uk/js/rapidaddress',
			field: '#mandatory-postcode',
			selector: '#postcode-lookup',
			target: '#mandatory-address',
			org_uppercase	: 1,		// 0 - leading uppercase, 1- all in uppercase
			town_uppercase	: 1,		// 0 - leading uppercase, 1- all in uppercase
			county_uppercase: 0,		// 0 - leading uppercase, 1- all in uppercase
			addr_uppercase	: 0,		// 0 - leading uppercase, 1- all in uppercase
			traditional_county	: 0, 	// 0 - postal county, 1 - traditional county name
			/**
			 * data delimiter
			 */
			delimiter		: ', ',
			/**
			 * address data
			 */
			data: [],
			data_idx : 0,
			/**
			 * messages for use in class
			 */
			messages: {
				notFound: 'We could not find any addresses for this postcode',
				unknown: 'An unknown error occured',
				selectAddress: 'Please select your address'
			},
			/**
			 * find records for a postcode
			 * @param postcode
			 */
			find: function(postcode) {
				var lookupUrl = this.url + '?postcode=' + postcode + '&callback=' + this.callback + '&key=' + this.key;
				$j('body').append($j('<script>').attr('src',lookupUrl));
			},
			
			/**
			 * handle response from crafty clicks 
			 * @param status
			 * @param data array of records found
			 */
			handleResponse: function(status, data) {
				$j(this.selector).html();
				
				if (!status) { // an error
					alert(this.messages.unknown)
				} else {
					this.parse(data);
					this.data = this.data.sort(this.resultCompare);
					
					var options = [];
//					options[0] = this.messages.selectAddress;
					for (var i=0;i<this.data_idx;i++) { 
						var arrayline = this.data[i];
						options[i] = arrayline['org'] + (arrayline['org'] !='' ? this.delimiter : '') + 
												  arrayline['housename2'] + (arrayline['housename2'] != '' ? this.delimiter : '') + 
												  arrayline['housename1'] + (arrayline['housename1'] != '' ? this.delimiter : '') + 
												  arrayline['pobox'] + (arrayline['pobox'] != '' ? this.delimiter : '') + 
												  arrayline['housenumber'] + (arrayline['housenumber'] != '' ? ' ' : '') +
												  arrayline['street2'] + (arrayline['street2'] != '' ? this.delimiter : '') +
												  arrayline['street1'] + (arrayline['street1'] != '' ? this.delimiter : '') +
												  arrayline['locality_dep'] + (arrayline['locality_dep'] != '' ? this.delimiter : '') +
												  arrayline['locality'] + (arrayline['locality'] != '' ? this.delimiter : '') +
												  arrayline['town'];
					}
					
					
					if (0 == this.data_idx) {
						$j(this.selector).html(this.messages.notFound);
					
					} else if (1 == this.data_idx) {
						this.toTarget(1);
						
					} else {
						// assume lots of records
						var select = $j('<select>').addOption(options, false)
												   .bind('change', function() {
													   lookup.toTarget(this.selectedIndex);
												   });
						this.toTarget(0);
						$j(this.selector).html(select);
					}
				}
			},
			
			
			/**
			 * inject data into the target entity
			 * @param data
			 */
			toTarget: function(index) {
				var address = this.data[index];
				var display = address['org'] + (address['org'] !='' ? "\n" : '') + 
							  address['housename2'] + (address['housename2'] != '' ? "\n" : '') + 
							  address['housename1'] + (address['housename1'] != '' ? "\n" : '') + 
							  address['pobox'] + (address['pobox'] != '' ? "\n" : '') + 
							  address['housenumber'] + (address['housenumber'] != '' ? ' ' : '') +
							  address['street2'] + (address['street2'] != '' ? "\n" : '') +
							  address['street1'] + (address['street1'] != '' ? "\n" : '') +
							  address['locality_dep'] + (address['locality_dep'] != '' ? "\n" : '') +
							  address['locality'] + (address['locality'] != '' ? "\n" : '') +
							  address['town'];
				
				$j(this.target).val(display);
				
			},
			
			resultCompare : function(a,b) {
				// sort by street name first, then by number
				if (a['match_quality'] > b['match_quality']) {
					return (1);
				} 
				if (a['match_quality'] < b['match_quality']) {
					return (-1);
				} 
				if (a['street1'] > b['street1']) {
					return (1);
				} 
				if (a['street1'] < b['street1']) {
					return (-1);
				}
				
				if (a['street2'] > b['street2']) {
					return (1);
				}
				if (a['street2'] < b['street2']) {
					return (-1);
				}
				
				// compare house numbers
				var numA;
				if ('' == a['housenumber']) {
					numA = _cp_eh(Array(a['housename1'], a['housename2']));
				} else {
					numA = parseInt(a['housenumber']);
				}
				var numB;
				if ('' == b['housenumber']) {
					numB = _cp_eh(Array(b['housename1'], b['housename2']));
				} else {
					numB = parseInt(b['housenumber']);
				}
				// premises with street numbers go to the top of the list
				if ('' == numA && '' != numB) {
					return (1);
				} else if ('' != numA && '' == numB) {
					return (-1);
				} else {
					if (numA > numB) {
						return (1);
					}
					if (numA < numB) {
						return (-1);
					}
				}
				
				// strip off known prefixes
				var hseA = _cp_sp(a['housename1']);
				if (!isNaN(parseInt(hseA))) {
					hseA = parseInt(hseA);
				}
				var hseB = _cp_sp(b['housename1']);
				if (!isNaN(parseInt(hseB))) {
					hseB = parseInt(hseB);
				}
				if (hseA > hseB) {
					return (1);
				}
				if (hseA < hseB) {
					return (-1);
				}

				var hseA = _cp_sp(a['housename2']);
				if (!isNaN(parseInt(hseA))) {
					hseA = parseInt(hseA);
				}
				var hseB = _cp_sp(b['housename2']);
				if (!isNaN(parseInt(hseB))) {
					hseB = parseInt(hseB);
				}
				if (hseA > hseB) {
					return (1);
				}
				if (hseA < hseB) {
					return (-1);
				}
				
				hseA = a['housename2']+a['housename1'];
				hseB = b['housename2']+b['housename1'];
				if (hseA > hseB) {
					return (1);
				}
				if (hseA < hseB) {
					return (-1);
				}

				if (a['org'] > b['org']) {
					return (1);
				}
				if (a['org'] < b['org']) {
					return (-1);
				}

				return (1);
			},
			
			/**
			 * parse raw data into something more manageable
			 * @param data
			 */
			parse : function (data) {
				// loop over all streets
				for (var str_idx=1; str_idx<=data['thoroughfare_count']; str_idx++) {
					var str1 = data[str_idx]['thoroughfare_name'];
					if ('' != data[str_idx]['thoroughfare_descriptor']) {
						str1 += ' '+data[str_idx]['thoroughfare_descriptor'];
					}
					str1 = this.leading_caps(str1, this.addr_uppercase);
					var str2 = data[str_idx]['dependent_thoroughfare_name'];
					if ('' != data[str_idx]['dependent_thoroughfare_descriptor']) {
						str2 += ' '+data[str_idx]['dependent_thoroughfare_descriptor'];
					}
					str2 = this.leading_caps(str2, this.addr_uppercase);
					if ('delivery_point_count' in data[str_idx]  && 0 < data[str_idx]['delivery_point_count']) {
						// loop over all premises on this street
						for (var p_idx=1; p_idx<=data[str_idx]['delivery_point_count']; p_idx++) {
							var al = this.new_res_line();
							al['street1'] = str1;
							al['street2'] = str2;
							var prem = data[str_idx][p_idx];
							if( 'match_quality' in prem ) {
								// indication of how good this premises matched the search string
								al['match_quality'] = prem['match_quality']; 
							} else {
								al['match_quality'] = 1; 
							}
							al['housenumber'] = prem['building_number'];
							al['housename2'] = this.leading_caps(prem['sub_building_name'], this.addr_uppercase);
							al['housename1'] = this.leading_caps(prem['building_name'], this.addr_uppercase);
							al['org'] = prem['department_name'];
							if ('' != al['org'] && '' != prem['organisation_name']) {
								al['org'] += this.delimiter;
							}
							al['org'] = this.leading_caps(al['org']+prem['organisation_name'], this.org_uppercase);
							al['pobox'] = this.leading_caps(prem['po_box_number'], this.addr_uppercase);
							al['postcode'] = data['postcode'];
							al['town'] = this.leading_caps(data['town'], this.town_uppercase);
							al['locality'] = this.leading_caps(data['dependent_locality'], this.addr_uppercase);;
							al['locality_dep'] = this.leading_caps(data['double_dependent_locality'], this.addr_uppercase);
							if (this.traditional_county) {
								al['county'] = this.leading_caps(data['traditional_county'], this.county_uppercase);
							} else {
								al['county'] = this.leading_caps(data['postal_county'], this.county_uppercase);
							}
							al['udprn'] = prem['udprn'];  
							this.data[this.data_idx] = al;
							this.data_idx++;
						}
					} else {
						// street level data only
						var al = this.new_res_line();
						al['street1'] = str1;
						al['street2'] = str2;
						al['postcode'] = data['postcode'];
						al['town'] = this.leading_caps(data['town'], this.town_uppercase);
						al['locality'] = this.leading_caps(data['dependent_locality'], this.addr_uppercase);;
						al['locality_dep'] = this.leading_caps(data['double_dependent_locality'], this.addr_uppercase);
						if (this.traditional_county) {
							al['county'] = this.leading_caps(data['traditional_county'], this.county_uppercase);
						} else {
							al['county'] = this.leading_caps(data['postal_county'], this.county_uppercase);
						}
						al['match_quality'] = 2; 
						this.data[this.data_idx] = al;
						this.data_idx++;
					}
				}
			},
			
			leading_caps : function(txt, dont_do_it) {
				if (0 != dont_do_it || 2 > txt.length) { return (txt) }
				var out_text = '';
				var words = txt.split(" ");
				for (var i=0; i<words.length; i++) {	// each word in turn
					var word = this.str_trim(words[i]);
					if ('' != word)	{
						if ('' != out_text)	{
							out_text = out_text + ' ';
						}
						out_text = out_text + this.cp_uc(word);
					}
				}
				return (out_text);
			},
			
			str_trim : function(s) {
				var l=0; 
				var r=s.length -1;
				while(l < s.length && s[l] == ' ') { l++; }
				while(r > l && s[r] == ' ') { r-=1;	}
				return s.substring(l, r+1);
			},
			
			new_res_line : function() {
				var al = [];
				al['org'] = ''; 
				al['housename1'] = ''; 
				al['housename2'] = ''; 
				al['pobox'] = '';
				al['housenumber'] = ''; 
				al['street1'] = ''; 
				al['street2'] = '';
				al['locality_dep'] = ''; 
				al['locality'] = ''; 
				al['town'] = '';
				al['county'] = ''; 
				al['postcode'] = ''; 
				al['udprn'] = '';
				return (al);
			},
			
			cp_uc : function(text) {
				if ("PC" == text || "UK" == text || "EU" == text) {return (text);}
				var alpha="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
				var out_text = '';
				var do_uc = 1;
				var all_uc = 0;
				for (var i=0; i<text.length; i++){
					if (-1 != alpha.indexOf(text.charAt(i))) {
						if (do_uc || all_uc) {
							out_text = out_text + text.charAt(i);
							do_uc = 0;
						} else {
							out_text = out_text + text.charAt(i).toLowerCase();
						}
					} else {
						out_text = out_text + text.charAt(i);
						if (i+2 >= text.length && "'" == text.charAt(i)) { // only one more char left, don't capitalise
							do_uc = 0; 
						} else if ("(" == text.charAt(i)) {
							close_idx = text.indexOf(")",i+1);
							if (i+3 < close_idx) { // more than 2 chars
								all_uc = 0; do_uc = 1;
							} else { // no closing bracket or 2 or les chars in brackets, leave uppercase
								all_uc = 1; 
							}				
						} else if (")" == text.charAt(i)) {
							all_uc = 0; do_uc = 1;
						} else if ("-" == text.charAt(i)) {
							close_idx = text.indexOf("-",i+1);
							if ((-1 != close_idx && i+3 >= close_idx) || i+3 >= text.length) { // less than 2 chars
								all_uc = 0; do_uc = 0;
							} else { // 2 or more chars 
								all_uc = 0; do_uc = 1;
							}		
						} else if (i+2 < text.length && "0" <= text.charAt(i) && "9" >= text.charAt(i)) {
							do_uc = 0;
						} else {
							do_uc = 1;
						}
					}
				}
				return (out_text);
			}
			
			
	};
	
	var btn = $j('<button>').attr('type', 'button')
							.html('Find Address')
							.click(function() {
                                var pc = $j('#mandatory-postcode').val();
                                if (pc == '') {
                                    alert('You must enter a postcode');
                                    return;
                                }
                                lookup.find(pc);
                            });
							
	$j('#mandatory-postcode').css('width', '150px')
	                         .after(btn);
			 
    $j('#mandatory-findPostcode').click(function() {
        var pc = $j('#mandatory-postcode').val();
        if (pc == '') {
            alert('You must enter a postcode');
            return;
        }
        lookup.find(pc);
    });
    
});

/**
 * Selectboxes:
 */
/*
 *
 * Copyright (c) 2006-2010 Sam Collett (http://www.texotela.co.uk)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Version 2.2.6
 * Demo: http://www.texotela.co.uk/code/jquery/select/
 *
 *
 */
 
;(function($) {
 
/**
 * Adds (single/multiple) options to a select box (or series of select boxes)
 *
 * @name     addOption
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @example  $("#myselect").addOption("Value", "Text"); // add single value (will be selected)
 * @example  $("#myselect").addOption("Value 2", "Text 2", false); // add single value (won't be selected)
 * @example  $("#myselect").addOption({"foo":"bar","bar":"baz"}, false); // add multiple values, but don't select
 *
 */
$.fn.addOption = function()
{
	var add = function(el, v, t, sO, index)
	{
		var option = document.createElement("option");
		option.value = v, option.text = t;
		// get options
		var o = el.options;
		// get number of options
		var oL = o.length;
		if(!el.cache)
		{
			el.cache = {};
			// loop through existing options, adding to cache
			for(var i = 0; i < oL; i++)
			{
				el.cache[o[i].value] = i;
			}
		}
		if (index || index == 0)
		{
 			// we're going to insert these starting  at a specific index...
			// this has the side effect of el.cache[v] being the 
			// correct value for the typeof check below
			var ti = option;
			for(var ii =index; ii <= oL; ii++)
			{
				var tmp = el.options[ii];
				el.options[ii] = ti;
				o[ii] = ti;
				el.cache[o[ii].value] = ii;
				ti = tmp;
			}
		}
    
		// add to cache if it isn't already
		if(typeof el.cache[v] == "undefined") el.cache[v] = oL;
		el.options[el.cache[v]] = option;
		if(sO)
		{
			option.selected = true;
		}
	};
	
	var a = arguments;
	if(a.length == 0) return this;
	// select option when added? default is true
	var sO = true;
	// multiple items
	var m = false;
	// other variables
	var items, v, t, startindex = 0;
	if(typeof(a[0]) == "object")
	{
		m = true;
		items = a[0];
	}
	if(a.length >= 2)
	{
		if(typeof(a[1]) == "boolean")
		{
			sO = a[1];
			startindex = a[2];
		}
		else if(typeof(a[2]) == "boolean")
		{
			sO = a[2];
			startindex = a[1];
		}
		else
		{
			startindex = a[1];
		}
		if(!m)
		{
			v = a[0];
			t = a[1];
		}
	}
	this.each(
		function()
		{
			if(this.nodeName.toLowerCase() != "select") return;
			if(m)
			{
				for(var item in items)
				{
					add(this, item, items[item], sO, startindex);
					startindex += 1;
				}
			}
			else
			{
				add(this, v, t, sO, startindex);
			}
		}
	);
	return this;
};

/**
 * Add options via ajax
 *
 * @name     ajaxAddOption
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @param    String url      Page to get options from (must be valid JSON)
 * @param    Object params   (optional) Any parameters to send with the request
 * @param    Boolean select  (optional) Select the added options, default true
 * @param    Function fn     (optional) Call this function with the select object as param after completion
 * @param    Array args      (optional) Array with params to pass to the function afterwards
 * @example  $("#myselect").ajaxAddOption("myoptions.php");
 * @example  $("#myselect").ajaxAddOption("myoptions.php", {"code" : "007"});
 * @example  $("#myselect").ajaxAddOption("myoptions.php", {"code" : "007"}, false, sortoptions, [{"dir": "desc"}]);
 *
 */
$.fn.ajaxAddOption = function(url, params, select, fn, args)
{
	if(typeof(url) != "string") return this;
	if(typeof(params) != "object") params = {};
	if(typeof(select) != "boolean") select = true;
	this.each(
		function()
		{
			var el = this;
			$.getJSON(url,
				params,
				function(r)
				{
					$(el).addOption(r, select);
					if(typeof fn == "function")
					{
						if(typeof args == "object")
						{
							fn.apply(el, args);
						} 
						else
						{
							fn.call(el);
						}
					}
				}
			);
		}
	);
	return this;
};

/**
 * Removes an option (by value or index) from a select box (or series of select boxes)
 *
 * @name     removeOption
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @param    String|RegExp|Number what  Option to remove
 * @param    Boolean selectedOnly       (optional) Remove only if it has been selected (default false)   
 * @example  $("#myselect").removeOption("Value"); // remove by value
 * @example  $("#myselect").removeOption(/^val/i); // remove options with a value starting with 'val'
 * @example  $("#myselect").removeOption(/./); // remove all options
 * @example  $("#myselect").removeOption(/./, true); // remove all options that have been selected
 * @example  $("#myselect").removeOption(0); // remove by index
 * @example  $("#myselect").removeOption(["myselect_1","myselect_2"]); // values contained in passed array
 *
 */
$.fn.removeOption = function()
{
	var a = arguments;
	if(a.length == 0) return this;
	var ta = typeof(a[0]);
	var v, index;
	// has to be a string or regular expression (object in IE, function in Firefox)
	if(ta == "string" || ta == "object" || ta == "function" )
	{
		v = a[0];
		// if an array, remove items
		if(v.constructor == Array)
		{
			var l = v.length;
			for(var i = 0; i<l; i++)
			{
				this.removeOption(v[i], a[1]); 
			}
			return this;
		}
	}
	else if(ta == "number") index = a[0];
	else return this;
	this.each(
		function()
		{
			if(this.nodeName.toLowerCase() != "select") return;
			// clear cache
			if(this.cache) this.cache = null;
			// does the option need to be removed?
			var remove = false;
			// get options
			var o = this.options;
			if(!!v)
			{
				// get number of options
				var oL = o.length;
				for(var i=oL-1; i>=0; i--)
				{
					if(v.constructor == RegExp)
					{
						if(o[i].value.match(v))
						{
							remove = true;
						}
					}
					else if(o[i].value == v)
					{
						remove = true;
					}
					// if the option is only to be removed if selected
					if(remove && a[1] === true) remove = o[i].selected;
					if(remove)
					{
						o[i] = null;
					}
					remove = false;
				}
			}
			else
			{
				// only remove if selected?
				if(a[1] === true)
				{
					remove = o[index].selected;
				}
				else
				{
					remove = true;
				}
				if(remove)
				{
					this.remove(index);
				}
			}
		}
	);
	return this;
};

/**
 * Sort options (ascending or descending) in a select box (or series of select boxes)
 *
 * @name     sortOptions
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @param    Boolean ascending   (optional) Sort ascending (true/undefined), or descending (false)
 * @example  // ascending
 * $("#myselect").sortOptions(); // or $("#myselect").sortOptions(true);
 * @example  // descending
 * $("#myselect").sortOptions(false);
 *
 */
$.fn.sortOptions = function(ascending)
{
	// get selected values first
	var sel = $(this).selectedValues();
	var a = typeof(ascending) == "undefined" ? true : !!ascending;
	this.each(
		function()
		{
			if(this.nodeName.toLowerCase() != "select") return;
			// get options
			var o = this.options;
			// get number of options
			var oL = o.length;
			// create an array for sorting
			var sA = [];
			// loop through options, adding to sort array
			for(var i = 0; i<oL; i++)
			{
				sA[i] = {
					v: o[i].value,
					t: o[i].text
				}
			}
			// sort items in array
			sA.sort(
				function(o1, o2)
				{
					// option text is made lowercase for case insensitive sorting
					o1t = o1.t.toLowerCase(), o2t = o2.t.toLowerCase();
					// if options are the same, no sorting is needed
					if(o1t == o2t) return 0;
					if(a)
					{
						return o1t < o2t ? -1 : 1;
					}
					else
					{
						return o1t > o2t ? -1 : 1;
					}
				}
			);
			// change the options to match the sort array
			for(var i = 0; i<oL; i++)
			{
				o[i].text = sA[i].t;
				o[i].value = sA[i].v;
			}
		}
	).selectOptions(sel, true); // select values, clearing existing ones
	return this;
};
/**
 * Selects an option by value
 *
 * @name     selectOptions
 * @author   Mathias Bank (http://www.mathias-bank.de), original function
 * @author   Sam Collett (http://www.texotela.co.uk), addition of regular expression matching
 * @type     jQuery
 * @param    String|RegExp|Array value  Which options should be selected
 * can be a string or regular expression, or an array of strings / regular expressions
 * @param    Boolean clear  Clear existing selected options, default false
 * @example  $("#myselect").selectOptions("val1"); // with the value 'val1'
 * @example  $("#myselect").selectOptions(["val1","val2","val3"]); // with the values 'val1' 'val2' 'val3'
 * @example  $("#myselect").selectOptions(/^val/i); // with the value starting with 'val', case insensitive
 *
 */
$.fn.selectOptions = function(value, clear)
{
	var v = value;
	var vT = typeof(value);
	// handle arrays
	if(vT == "object" && v.constructor == Array)
	{
		var $this = this;
		$.each(v, function()
			{
      				$this.selectOptions(this, clear);
    			}
		);
	};
	var c = clear || false;
	// has to be a string or regular expression (object in IE, function in Firefox)
	if(vT != "string" && vT != "function" && vT != "object") return this;
	this.each(
		function()
		{
			if(this.nodeName.toLowerCase() != "select") return this;
			// get options
			var o = this.options;
			// get number of options
			var oL = o.length;
			for(var i = 0; i<oL; i++)
			{
				if(v.constructor == RegExp)
				{
					if(o[i].value.match(v))
					{
						o[i].selected = true;
					}
					else if(c)
					{
						o[i].selected = false;
					}
				}
				else
				{
					if(o[i].value == v)
					{
						o[i].selected = true;
					}
					else if(c)
					{
						o[i].selected = false;
					}
				}
			}
		}
	);
	return this;
};

/**
 * Copy options to another select
 *
 * @name     copyOptions
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @param    String to  Element to copy to
 * @param    String which  (optional) Specifies which options should be copied - 'all' or 'selected'. Default is 'selected'
 * @example  $("#myselect").copyOptions("#myselect2"); // copy selected options from 'myselect' to 'myselect2'
 * @example  $("#myselect").copyOptions("#myselect2","selected"); // same as above
 * @example  $("#myselect").copyOptions("#myselect2","all"); // copy all options from 'myselect' to 'myselect2'
 *
 */
$.fn.copyOptions = function(to, which)
{
	var w = which || "selected";
	if($(to).size() == 0) return this;
	this.each(
		function()
		{
			if(this.nodeName.toLowerCase() != "select") return this;
			// get options
			var o = this.options;
			// get number of options
			var oL = o.length;
			for(var i = 0; i<oL; i++)
			{
				if(w == "all" || (w == "selected" && o[i].selected))
				{
					$(to).addOption(o[i].value, o[i].text);
				}
			}
		}
	);
	return this;
};

/**
 * Checks if a select box has an option with the supplied value
 *
 * @name     containsOption
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     Boolean|jQuery
 * @param    String|RegExp value  Which value to check for. Can be a string or regular expression
 * @param    Function fn          (optional) Function to apply if an option with the given value is found.
 * Use this if you don't want to break the chaining
 * @example  if($("#myselect").containsOption("val1")) alert("Has an option with the value 'val1'");
 * @example  if($("#myselect").containsOption(/^val/i)) alert("Has an option with the value starting with 'val'");
 * @example  $("#myselect").containsOption("val1", copyoption).doSomethingElseWithSelect(); // calls copyoption (user defined function) for any options found, chain is continued
 *
 */
$.fn.containsOption = function(value, fn)
{
	var found = false;
	var v = value;
	var vT = typeof(v);
	var fT = typeof(fn);
	// has to be a string or regular expression (object in IE, function in Firefox)
	if(vT != "string" && vT != "function" && vT != "object") return fT == "function" ? this: found;
	this.each(
		function()
		{
			if(this.nodeName.toLowerCase() != "select") return this;
			// option already found
			if(found && fT != "function") return false;
			// get options
			var o = this.options;
			// get number of options
			var oL = o.length;
			for(var i = 0; i<oL; i++)
			{
				if(v.constructor == RegExp)
				{
					if (o[i].value.match(v))
					{
						found = true;
						if(fT == "function") fn.call(o[i], i);
					}
				}
				else
				{
					if (o[i].value == v)
					{
						found = true;
						if(fT == "function") fn.call(o[i], i);
					}
				}
			}
		}
	);
	return fT == "function" ? this : found;
};

/**
 * Returns values which have been selected
 *
 * @name     selectedValues
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     Array
 * @example  $("#myselect").selectedValues();
 *
 */
$.fn.selectedValues = function()
{
	var v = [];
	this.selectedOptions().each(
		function()
		{
			v[v.length] = this.value;
		}
	);
	return v;
};

/**
 * Returns text which has been selected
 *
 * @name     selectedTexts
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     Array
 * @example  $("#myselect").selectedTexts();
 *
 */
$.fn.selectedTexts = function()
{
	var t = [];
	this.selectedOptions().each(
		function()
		{
			t[t.length] = this.text;
		}
	);
	return t;
};

/**
 * Returns options which have been selected
 *
 * @name     selectedOptions
 * @author   Sam Collett (http://www.texotela.co.uk)
 * @type     jQuery
 * @example  $("#myselect").selectedOptions();
 *
 */
$.fn.selectedOptions = function()
{
	return this.find("option:selected");
};

})(jQuery);
