// Core RateMyPlacement JS Class
// V1.0.0

// INITIALISATION

var RMP = {
    // Checks if we're running on Apple iOS
    is_iOS: function() {
        return navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/iPad/i) ? true : false;
    },
    // Checks if the site is running as a standalone (installed/iOS) app
    is_standalone_app: function() {
        return navigator.standalone ? true : false;
    },
    // Finds all placeholders and renders them as dissappearing text/using value
    placeholder_replacement: function() {
        $('input[placeholder]').each(function(){
			var input = $(this);
            var pha_class = 'placeholder-active';
            var phr_class = 'placeholder-replaced';
            var ph = $(this).attr('placeholder');
			if ($(this).val()==''){
            $(this).removeAttr('placeholder').addClass(pha_class).addClass(phr_class).val(ph)
            .focus(function(){
                if($(this).val()==ph) $(this).val('').removeClass(pha_class);
            })
            .blur(function(){
                if(jQuery.trim($(this).val()) =='')	$(this).val(ph).addClass(pha_class);
            });
		}
		$(this).closest('form').submit(function(){
			if ($(input).val() == ph)
				$(input).val('');
        	});
		});	    
	},
    // Enables drop down menus in the navigation
    navigation_dropdowns: function() {
		$('#navigation li a.write-review').parent('li').remove();
        $('#navigation li>ul')
        .parent('li')
        .prepend(
            $('<span>',{"class":'sub-arrow'}) // Create arrows
        ).each(function(){
		$(this).hoverIntent({
			over: function(){
                $(this).find('ul').slideDown(200);
			},
			out: function(){
                $(this).find('ul').slideUp(200);
            }
			});
        });
        $('#navigation li>ul').each(function(){
            var w = parseFloat($(this).parent().width())+6;
            $(this).css({'min-width':w+'px'});
		
        }).find('li').click(function(){ //$('#navigation li>ul').hide(); 
	});
    },
    // Enables the dropdown to change the focus of the site search in the navigation
    search_dropdown: function() {
        $('#site_search_scope')
        .append($('<ul>',{id:'site_search_scope_list'}))
        .find('input').each(function(){
            $('#site_search_scope_list').append(
                $('<li />',
                        {
                         html: $(this).attr('title'),
                         title: $(this).attr('title'),
                         click: function() {
                             $(this).addClass('first').parent().prepend($(this));
                             $(this).siblings().hide().removeClass('first');
                             $('#site_search input').removeAttr('checked')
                             .filter('[title="'+$(this).attr('title')+'"]').attr('checked','checked');
                         }
             })).toggle(function(){
                 $(this).children().show();
             },function(){
                 $(this).children(':gt(0)').hide();
             });
        });
        $('#site_search_scope_list li:first-child').addClass('first');
    },
    // Makes embed codes auto-select
    embed_codes: function(){
        $('#content .embed-code textarea').click(function(){
            $(this).focus().select();
        });
    },
    // Makes messages deletable
    deleteable_messages: function(){
        $('#content_wrapper .notices-display li, #content_wrapper .errors-display li, #content_wrapper .alert-display li').live('click',function(){
            var parent = $(this).parent();
            $(this).remove();
     
            if(parent.children().length<1) parent.slideUp(200,function() { $(this).remove(); });
        });
    },
    // Load the Class
    run: function(){
        if (this.is_standalone_app()) document.getElementsByTagName('html')[0].className += ' standalone';
        else document.getElementsByTagName('html')[0].className += ' not-standalone';
        // iOS app
        if (this.is_iOS()) {
            document.title = "Placements";
            document.getElementsByTagName('html')[0].className += ' is-iOS';
        } else document.getElementsByTagName('html')[0].className += ' not-iOS';
        // Placeholder Replacement
        this.placeholder_replacement();
        // Navigation Dropdown Support
        this.navigation_dropdowns();
        // Search Scope Support
        this.search_dropdown();
        // Embed Code Selection Support
        this.embed_codes();
        // Make messages deletable when clicked
        this.deleteable_messages();
    }
};

$(function(){ RMP.run(); }); // Go!

// VALIDATION

//Removes Error Messages
jQuery.fn.removeErrorMessage = function() {
	$('#err_'+this.attr('id')).remove();
	this.removeClass('error');
}

//Adds Inline Error Message
jQuery.fn.addErrorMessage = function(msg) {
	msg = msg?msg:'You must complete this';
	this.addClass('error');
	var count_errors = $('.error').length;
	if(count_errors>1) $('.error').first().focus();
	this.after('<div class="error-message" id="err_'+this.attr('id')+'">'+msg+'</div>');
}
// Adds top-of-page errors wrapper
jQuery.fn.addMainNoticeMessage = function(msg){
	if ($('ul.notices-display').length){
		var li = $('<li />',{ html:  msg  });
		//$('ul.notices-display').append(li).slideDown();	
	} else {
		var ul = $('<ul />',{
			'class' : 'notices-display',
			 html : '<li>' + msg + '</li>'
		});

		$('#content_wrapper').prepend(ul).slideDown();
	}
}

// Adds top-of-page error message
jQuery.fn.addMainErrorMessage = function(msg){
	if ($('ul.errors-display').length){
		var li = $('<li />',{
			'html': msg
		});
		$('ul.errors-display').append(li).slideDown();	
	} else {
		var ul = $('<ul />',{
			'class' : 'errors-display',
			 'html' : '<li>' + msg + '</li>'
		});
		$('#content_wrapper').prepend(ul).slideDown();
	}
}

//Checks if textfield is blank
jQuery.fn.validateNotBlank = function(msg) {
	msg = msg?msg:'This cannot be left blank';
	if(jQuery.trim(this.val())=='') {
		if (!$('#err_'+this.attr('id')).length>0) {
			this.addErrorMessage(msg);
		} return false; // Fail
	} else this.removeErrorMessage();
	return true;
}

// Queries the select to find nearest select to see if this appears in the drop down.
jQuery.fn.validateIsInSelect = function(msg){
	this.removeErrorMessage();
	value = $(this).val();
	id = $(this).attr('id').replace('_other','');
	found = false;
	$('#'+id+ ' option').each(function(){
		if ($(this).text() == value) found = true;
	});
	if (!found) this.addErrorMessage(msg);
	else this.removeErrorMessage();
	return found;
}

//Checks if select is not value="0"
jQuery.fn.validateIsSelected = function(msg) {
	msg = msg?msg:'You must make a selection'
	val = $('option:selected',this).val();
	if(val =='0' || val == '' ){
	//if(this.val()=='0' || this.val()=='') {
		if (!$('#err_'+this.attr('id')).length>0) {
			this.addErrorMessage(msg);
		} return false; // Fail
	} else this.removeErrorMessage();
	return true;
}

//Checks if select is not value="0"
jQuery.fn.validateAutoComplete = function(msg) {
	if (window.console && window.console.log) console.log(this);
	msg = msg?msg:'You must make a selection'
	auto_parent = $(this).closest('div.autocomplete-select');
	type = $(auto_parent).attr('data-auto-type');
	switch(type){
		case "1":
				this.validateIsSelected(msg);
		break;
		case"2":
			$('#' + this.attr('id') + '_other').validateNotBlank(msg);
		break;
		case "3":
				return true;
		break;
		
	}	
}
//Checks if select is not value="0"
jQuery.fn.validateOptionPickerSelected = function(msg) {
	msg = msg?msg:'You must make a selection'
	val = $('option:selected',this).val();
	$(this).closest('div.optionpicker').children('ul.optionpicker').attr('id',$(this).attr('id') + '_option');
	id =	$(this).closest('div.optionpicker').children('ul.optionpicker').attr('id');
	if(val =='0' || val == '' ){
		if (!$('#err_'+ id).length>0) {
			$(this).closest('div.optionpicker').children('ul.optionpicker').addErrorMessage(msg);
		} return false; // Fail
	} else 	$(this).closest('div.optionpicker').children('ul.optionpicker').removeErrorMessage();
	return true;
}
//Checks if a radio button has been selected
jQuery.fn.validateRadioIsChecked = function(msg) {
	msg = msg?msg:'You must make a selection';
	if(this.find('input:radio:checked').length==0) {
		if (!$('#err_'+this.attr('id')).length>0) {
			this.find('div.radio:last').addErrorMessage(msg);
		} return false; // Fail
	} else this.find('div.radio:last').removeErrorMessage();
	return true;
}

//Checks if a checkbox has been selected (apply to wrapper)
jQuery.fn.validateCheckboxIsChecked = function(msg) {
	msg = msg?msg:'You must make at least one selection';
	if(this.find('input:checkbox:checked').length==0) {
		if (!$('#err_'+this.attr('id')).length>0) {		
			this.addErrorMessage(msg);
		} return false; // Fail
	} else this.removeErrorMessage();
	return true;
}
//Checks if a checkbox has been selected (apply to wrapper)
jQuery.fn.validateMultiSelectorIsChecked = function(msg) {
	msg = msg?msg:'You must make at least one selection';
	if(this.find('input:checkbox:checked').length==0) {
		if (!$('#err_'+ $(this).attr('id') + '_list').length>0) {
			$(this).closest('div.multiselector').children('ul.multiselector-display').addErrorMessage(msg);
		} return false; // Fail
	} else 		$(this).closest('div.multiselector').children('ul.multiselector-display').removeErrorMessage();
	return true;
}
//Checks if email is valid
jQuery.fn.validateEmail = function(msg) {
	msg = msg?msg:'This email address is not valid';
	if(!/^[!-'*+=?{-~\/-9A-Z^-z-]+(\.[!-'*+=?{-~\/-9A-Z^-z-]+)*@[!-'*+=?{-~\/-9A-Z^-z-]+\.[!-'*+=?{-~\/-9A-Z^-z-]{2,}/.test(this.val())) {
		if (!$('#err_'+this.attr('id')).length>0) {
			this.addErrorMessage(msg);
		} return false; // Fail
	} else this.removeErrorMessage();
	return true;
}

//Checks if the firstname/lastname is valid
jQuery.fn.validateName = function(msg) {
	msg = msg?msg:'This name is not valid';
	if(!/^[A-Za-z\ -]{1,50}$/.test(this.val())) {
		if (!$('#err_'+this.attr('id')).length>0) {
			this.addErrorMessage(msg);
		} return false; // Fail
	} else this.removeErrorMessage();
	return true;
}

//Checks if password is valid
jQuery.fn.validatePassword = function(msg) {
	msg = msg?msg:'This password is not valid';
	if(!/^[a-zA-Z0-9]{4,20}$/.test(this.val())) {
		if (!$('#err_'+this.attr('id')).length>0) {
			this.addErrorMessage(msg);
		} return false; // Fail
	} else this.removeErrorMessage();
	return true;
}

//Checks if forum username is valid
jQuery.fn.validateForumName = function(msg) {
	msg = msg?msg:'This username is not valid';
	if(!/^([A-Za-z0-9\.\_]){1,50}$/.test(this.val())) {
		if (!$('#err_'+this.attr('id')).length>0) {
			this.addErrorMessage(msg);
		} return false; // Fail
	} else this.removeErrorMessage();
	return true;
}

//Validates two elements against each other
jQuery.fn.validateMatch = function(compare_to_this,msg) {
	msg = msg?msg:"Your passwords don't match";
	if(this.val()!=compare_to_this.val()) {
		if (!$('#err_'+this.attr('id')).length>0) {
			this.addErrorMessage(msg);
		} return false; // Fail
	} else this.removeErrorMessage();
	return true;
}

//Validates if one element is greater value than another
jQuery.fn.validateGreaterThan = function(compare_to_this,msg) {
	msg = msg?msg:"The value is too small";
	if(this.val()>compare_to_this.val()) {
		if (!$('#err_'+this.attr('id')).length>0) {
			this.addErrorMessage(msg);
		} return false; // Fail
	} else this.removeErrorMessage();
	return true;
}

//Validates if date is (today or) in the future
jQuery.fn.validateFutureDay = function(today_is_acceptable,msg) {
	msg = msg?msg:"This date is not valid";
	if(!checkDateIsAfterNow(this.val(),$('#'+this.attr('id').replace('day','month')).val(),$('#'+this.attr('id').replace('day','year')).val(),today_is_acceptable)) {
		if (!$('#err_'+this.attr('id').replace('day','year')).length>0) {
			$('#'+this.attr('id').replace('day','year')).addErrorMessage(msg);
		} return false; // Fail
	} else $('#'+this.attr('id').replace('day','year')).removeErrorMessage();
	return true;
}


// FUNCTIONALITY

jQuery.fn.videoThumbnailOverlays = function() {
	var play_mask = $('<div class="play" />');
	this.each(function(){
	    var elem = $(this).find('.gallery-item div');
	    var width = elem.closest('li').width();
	    play_mask.css({width:width+'px'});
		elem.append(play_mask);
	});
}

jQuery.fn.createPrintLinkInList = function(msg,position) {
    msg = msg ? msg : 'Print this page';
    var print_link_i = $('<img src="/assets/img/stream-icons/icon-print.png" width="20" height="20">');
	var print_link_a = $('<a />',{html:' '+msg,href:'#',click:function(e){ e.preventDefault(); window.print(); }});
	print_link_a.prepend(print_link_i);
	var print_link = $('<li />',{html:print_link_a});
	if(position=='prepend') this.prepend(print_link);
	else this.append(print_link);
}

// Limit Text in A Textarea
jQuery.fn.addCharacterCounter = function(max_char_limit) {
	max_char_limit = max_char_limit ? max_char_limit : 500 ;
	this.after('<p class="textarea-counter"><input value="'+(max_char_limit-$(this).val().length)+'" type="text" size="3" style="width:3em;" readonly="readonly"> Characters Remaining (Maximum '+max_char_limit+')</p>');
	function limiter() {
		$(this).next().children().val((max_char_limit-$(this).val().length<1?0:max_char_limit-$(this).val().length));
		if(max_char_limit-$(this).val().length<=1) {
			$(this).val($(this).val().substring(0,max_char_limit));
			$(this).next().children().addClass('limit-reached');
		} 
		if (max_char_limit-$(this).val().length>=1) $(this).next().children().removeClass('limit-reached');
	}
	this.keyup(limiter);
	this.keydown(limiter);
}

// Creates T&Cs Popup using Apprise (apprise must be included on page!)
jQuery.fn.termsPopup = function() {
    if(window.console && window.console.log) {
        if(typeof apprise != 'function') console.log('Apprise.js has not been included (needed for termsPopup)');
    }
	this.each(function(){
		$(this).click(function(e){
			var url = $(this).attr('href');
			var content;
			$.get('terms-slim.php',function(data){ content = data; })
			.error(function(){ window.location.href = url; })
			.success(function(){ 
				if (typeof apprise == 'function') apprise(content,{'textOk':'Done'});
				else { window.location.href = url;}
			});
			e.preventDefault();
		});
	});
}

//Form Annotations
//Removes Error Messages
jQuery.fn.formNote = function(remove) {
	if(remove) this.unbind('focus');
	else {
		this.focus(function(){
		    var note = $('<div />',{
		                          id: 'note_'+$(this).attr('id'),
		                          'class': 'note',
		                          style: 'display:none;',
		                          html: '<div>'+$(this).attr('title')+'</div>'
		                      });
			$(this).parent('.field').append(note);
			$('#note_'+$(this).attr('id')).slideDown();
		}).blur(function(){
			$('#note_'+$(this).attr('id')).slideUp('slow',function(){ $(this).remove() });
		});
	}
}

//Generic
function checkDateIsAfterNow(day,month,year,today_is_acceptable) {
	var currentDate = new Date();
	var yearNow = currentDate.getFullYear();
	var monthNow = currentDate.getMonth()+1;
	var dayNow = currentDate.getDate();
	
	var year_check = (year < yearNow) ? true : false;
	var month_check = (month < monthNow && year == yearNow) ? true : false;
	if (today_is_acceptable) var day_check = (day < dayNow && month == monthNow && year == yearNow) ? true : false; 
	else var day_check = (day <= dayNow && month == monthNow && year == yearNow) ? true : false;
	
	if (year_check) return false;
	if (month_check) return false;
	if (day_check) return false;
	return true;
}




/////// NEW OR NEEDED

// Checks if there have been any changes before leaving page
jQuery.fn.checkBeforeLeavingPage = function() {
	function setConfirmUnload(on) { window.onbeforeunload = (on) ? unloadMessage : null; }
	function unloadMessage() { return 'You have made some changes. Are you sure you wish to leave this page without saving?';}
	this.find(':input').bind("change", function() { setConfirmUnload(true); }); // Prevent accidental navigation away
	this.bind("submit", function() { setConfirmUnload(false); }); // Prevent accidental navigation away
}
//Rotates Homepage Mini Adverts
jQuery.fn.rotateTrackerBenefits = function() {
    var tracker_ad_rotation_enabled = false;
    var delay = 2000;
    var speed = 2000;
    $(this).find('li:gt(0)').css('opacity',0.1);
    function removeNext(list) {
        
        if(list.is(':visible')) tracker_ad_rotation_enabled=true;
        else tracker_ad_rotation_enabled=false;
        
    	if(tracker_ad_rotation_enabled) {
    		var elem = list.children('li:first');
    		var next = elem.next();
    		next.delay(delay).animate({opacity:1},speed/2);
    		elem.delay(delay).animate({marginLeft:-$(this).width()+'px'},
    		    speed,
    		    function() {
    		    	list.children('li:last').after(elem);
    		    	elem.css({marginLeft:'0',opacity:0.1});
    		    	removeNext(list);
    		    }
    	    );
    	} else {
    		// Just a delaying tactic - nothing useful
    		$(list.last()).animate({opacity:'1'},
    		delay,
    		function(){removeNext(list);});
    	}
    }
    removeNext(this); // Start
}

//Rotates Homepage Mini Adverts
jQuery.fn.rotateMiniAds = function() {
	var mini_ad_rotation_enabled = true;
	var delay = 1000;
	var speed = 1000;
	function removeNext(list) {
		if(mini_ad_rotation_enabled) {
			var elem = list.children('li:first');
			elem.delay(delay).animate({marginLeft:'-160px'},
			speed,
			function() {
				list.children('li:last').after(elem);
				elem.css({marginLeft:'0'});
				removeNext(list);
			});
		} else {
			// Just a delaying tactic - nothing useful
			$(list.last()).animate({opacity:'1'},
			delay,
			function(){removeNext(list);});
		}
	}
	removeNext(this); // Start
	this.hover( // Pause on hover
		function(){ mini_ad_rotation_enabled = false; },
		function(){ mini_ad_rotation_enabled = true; }
	);
}

// Shakes a item left and right
jQuery.fn.shake = function(){ 
     this.each(function(init){ 
          var jqNode = $(this); 
          jqNode.css({position: 'relative'}); 
          for (var x = 1; x<=3; x++) { 
               jqNode.animate({ left: -5 },10) 
               .animate({ left: 0 },10) 
               .animate({ left: 5 },10) 
               .animate({ left: 0 },10); 
          } 
     }); 
     return this; 
}

jQuery.fn.headerTicker = function(replace_text, original_text){
	this.each(function(init){
			var header = this;
			$(header).delay(2000).animate({'margin-right':'-750px'},1000,function(){
				$(header).html(replace_text).addClass('advert');
				$(header).delay(1000).animate({'margin-right':'0px'},1000,function(){
					$(header).delay(10000).animate({'margin-right':'-750px'},1000,function(){
						$(header).removeClass('advert');
						$(header).text(original_text).delay(1000).animate({ 'margin-right':'0px'},1000);
						$(header).headerTicker(replace_text,original_text);
						});
				});
			});
	});
	return this;
}

// Takes a <select> (non multiple) element and replaces it with a clickable list selector
jQuery.fn.optionpicker = function(){ 
     this.each(function(init){
        var original_select = $(this).css({position:'absolute',top:'0',left:'-9999px',overflow:'hidden'});
        var selected = $(this).find(':selected').index();
		//this line is because webkit doesnt apply "select" to default state 
		if (selected == 0){ $(this).find('option:first').attr('selected','selected')};
        var str = '';
        $(this).find('option').each(function(){
            str += '<li class="'+(selected==$(this).index()?'selected':'')+' '+($(this).index()===0?'first':'')+'" data-value="' + $(this).val() + '"><span>'+$(this).text()+'</span></li>'+"\n";
        });
        var replacement = $('<ul />',{"class": 'optionpicker', html: str });
        replacement.find('span').click(function(e){
            e.preventDefault();
            $(this).parent().addClass('selected').siblings().removeClass('selected');
           
			id = $(original_select).attr('id');
		
			$('#' + id + ' option').attr('selected',false);
			$('#' + id + ' option[value="' + $(this).parent('li').attr('data-value') + '"]').attr('selected','selected').val($(this).parent('li').attr('data-value'));
        });
        $(this).after(replacement);
     });
     return this; 
}

// Takes a set of checkboxes (wrapped) and converts it to a multiselector popup
// + Bug: for some reason if you select then deselect an item, it is no longer attacked using select all/deselect all
jQuery.fn.multiselector = function(){ 
	
     this.each(function(init){
            
            var max_visible_items = 10;
			var elem = $(this);
			
			// Functions
			// Show the current modal
			function change_multi_selection(e) {
			    $('.multiselector-contents').hide(); // Hide others first
					if ($('#content_wrapper > ul:first-child')){
					ul = $('#content_wrapper > ul:first-child');
					ul_top = ($(ul).outerHeight());
				} else 
					ul_top = 0;
			
		  		elem.find('.multiselector-contents, .checkboxes').css({ 'top': (e.pageY-e.clientY- ul_top + 100)}).show();
		  	}
		  	
		  	// Update the selection list
		  	function update_display() {
			    
			    var checkbox_count = elem.find(':checkbox').length;
			    var checked = elem.find(':checked');
			    var checked_count = checked.length;
			    
			    if(checked_count>=checkbox_count) { // Selected everything
			        $(multiselector_display).html(all_selected);  
			    } else if(checked_count==0) { // Selected nothing at all
			        $(multiselector_display).html(nothing_selected);
			    } else if(checked_count>=max_visible_items) { // Selected more than the max allowed visible
			        $(multiselector_display).html(multiple_selected);
			    } else { // Selected less than the max allowed visible
                    $(multiselector_display).html('');
			        for(var i=0;i<checked_count;i++) {
    					var checkbox = $('#'+checked[i].id);
    					var label_text = checkbox.siblings('label').html();
    					multiselector_display.append($('<li />',{html:label_text}).attr('data-id',checkbox.val()));
    				}
                }
		    }

            // New Elements
            var title = $(this).find('.label:first');
			var elem_input_id = $(this).find(':checkbox:first').attr('name').replace('[]','');
			var multiselector_display = $('<ul />',{
														'class':'multiselector-display',
														'click': function (e) { change_multi_selection(e); e.preventDefault(); }
													}).attr('data-related-to',elem_input_id).attr('id',elem_input_id + "_list");
			var multiselector_contents = $('<div />',{'class':'multiselector-contents'});
			var multiselector_title = $('<h3 />',{html:title.html()});
			var multiselector_fields = $('<div />',{'class':'multiselector-fields'});
			var multiselector_controls = $('<button />',{ 
														'click': function(e) { 
															$(this).closest('.multiselector-contents').hide();
															e.preventDefault();
														},
														'html': '<span>Done</span>',
														'class': 'blue-button'
													});
			var nothing_selected = $('<li />',{text:'Nothing selected', 'class':'nothing-selected'});
			var all_selected = $('<li />',{text:'Everything selected', 'class':'all-selected'});
			var multiple_selected = $('<li />',{text:'More than '+max_visible_items+' selected', 'class':'multiple-selected'});
			var select_all = $('<a>',   {
			                            text:'Select All', href: '#', 
			                            click: function(e) {
			                                e.preventDefault();
			                                elem.find(':checkbox').attr('checked','checked');
			                                update_display();
			                            }
			                            });
			var deselect_all = $('<a>',{
			                            text:'Deselect All', href: '#', 
			                            click: function(e) {
			                                e.preventDefault();
			                                elem.find(':checkbox').removeAttr('checked');
			                                update_display();
			                            }
			                            });
			var change_selection_a = $('<a />',{
											text: 'Change Selection', href: '#',
											click: function (e) { change_multi_selection(e); e.preventDefault(); }
										});
            var change_selection = $('<p />',{html:change_selection_a});
            var multiselector_header = multiselector_title.after($('<div />',{
                                            'class': 'select-controls',
                                            'html': select_all.after(deselect_all)
                                        }));
			
			// Existing Elements						
            var checkboxes = $(this).find(':checkbox');
			var selected = checkboxes.filter(':checked');
			
			// Defaults
			if(selected.length>=checkboxes.length) {
			    multiselector_display.append(all_selected);
			} else if(selected.length>=max_visible_items) {
			    multiselector_display.append(multiple_selected);
			} else if(selected.length>0) {
				for(var i=0;i<selected.length;i++) {
					var checkbox = $('#'+selected[i].id);
					var label_text = checkbox.siblings('label').html();
					multiselector_display.append($('<li />',{html:label_text}).attr('data-id',checkbox.val()));
				}
			} else multiselector_display.append(nothing_selected);
		
		// Build
      	$(this).wrapInner(multiselector_fields).wrapInner(multiselector_contents);
      	$(this).prepend(title).append(multiselector_display).append(change_selection)
		.find('.multiselector-fields').before(multiselector_header).first().after(multiselector_controls);
		
		// On Change, Update Displayed Selections
		elem.find(':checkbox').live('change',function(){update_display();});

     });
     return this; 
}

jQuery.fn.autocomplete = function(){
	this.each(function(){
	    
	    var id = $(this).attr('id').replace('_wrapper','');
	    var data_URL = $(this).attr('data-url');
	    var data_limit = $(this).attr('data-limit')>-1 ? $(this).attr('data-limit') : 10;
		var realtime_results = $('<div />', { "class":'realtime-results' } );
		var realtime_result_elem;
		var autocomplete_select = $('#' + id);
		//$(autocomplete_select).find('option:first').attr('selected','selected');
		if ($(this).attr('data-other')){
			other = $(this).attr('data-other');
		}else
			other = ''
		var autocomplete_textbox = $('<input />', { "class":'autocomplete-textbox', 
													name: id+'_other',
													id: id+'_other',
													autocomplete:'off',
													type: 'text',
													value : other,
													keyup: function(e) {
														autocomplete = $(this);
														$.get(data_URL,{'s':encodeURI($(this).val()),'l':data_limit},
														 function(data) { 
														        var all_li = realtime_results.find('li');
														 		var total_results = all_li.size();
														 		var current_selection = all_li.filter('.hover:first');
														 		
														 		if(e.keyCode==40 || e.keyCode==38) { // Up or Down
														 			
																	//Remove Existing Hover Classes
														 			all_li.removeClass('hover');
														 			if(e.keyCode==40) { // Down
														 				if ((current_selection.index()+1)==total_results || current_selection.index()==-1) all_li.first().addClass('hover');
														 				else current_selection.next('li').addClass('hover');
														 			} else { // Up
														 				if (current_selection.index()<0) all_li.last().addClass('hover');
														 				else current_selection.prev('li').addClass('hover');
														 			}
														
														 		} else if(e.keyCode==13) { // Enter
														 		    e.preventDefault();
																	$('#' + id + '_other').removeErrorMessage();
														 		    if(current_selection.text()!='') {
																		autocomplete.val(current_selection.text());
																		$('#' + id + ' option[value='+current_selection.attr('data-id')+']').attr('selected','selected')
																		.siblings('option').removeAttr('selected');
																	}		
																  $('div.realtime-results').fadeOut('fast');
														 		  
														 		} else {
														 		    
														 			$('div.realtime-results').html(data).find('li').live('click',function(e){
														 				e.preventDefault();
														 			 	autocomplete.val($(this).text());
																		$('#' + id + ' option[value='+$(this).attr('data-id')+']').attr('selected','selected')
																		.siblings('option').removeAttr('selected');
																			
														   		    });
														   		    
														 		}
														 		
															});
														 
														 	if(autocomplete.val()=='') realtime_results.fadeOut('fast');																			 																					 	
															else if(autocomplete.val()!='' && realtime_results.html().length<1) realtime_results.fadeOut('fast');
															else realtime_results.fadeIn('fast');
													},
													blur: function() {
														$('#' + id + '_other').removeErrorMessage();
														realtime_results.fadeOut('fast'); // MAY NOT WORK BECAUSE OF REFERENCE?????!
														
													}
												});
		                                        
										 		
		var autocomplete_elements = autocomplete_textbox.before(realtime_results);
	    $(this).find('select:first')
	        .css({position:'absolute',left:'-9999px',overflow:'hidden'}).attr('tabindex','-1') // Using display:none would stop things working!
	        .before(autocomplete_elements); // Setup autocomplete
	    realtime_result_elem = $(this).find('.realtime-results:first');
	    realtime_result_elem.find('li').live('mouseover',function(){ $(this).addClass('hover'); }).live('mouseout',function(){ $(this).removeClass('hover'); });
        
        $(this).closest('form').keypress(function(e) {
              if (e.keyCode == 13 // Enter Key
                  && $(this).find('input.autocomplete-textbox:focus').length>0 // Focussed on an autocomplete field
                  && realtime_result_elem.is(':visible') // And the results are still visible
              ) return false;
        });

     });
		

	return this;
}

// Video Carousel

jQuery.fn.RMPVideoCarousel = function(){
	this.each(function(){
		var carousel_wrapper = $('<div />',{'class':"carousel-layout-wrapper"});
		var back_button = $('<a />',{
			'class':'carousel-nav go-back',
			html:'&#x25C0;',
			click:function(e){
				e.preventDefault()
				var carousel = $(this).closest('.carousel-layout-wrapper').find('.carousel-layout:first');
				var last_carousel_item = carousel.find('li:last');
				var last_carousel_item_width = last_carousel_item.width();
				last_carousel_item.css({width:'0'}).prependTo(carousel);
				last_carousel_item.animate({width:last_carousel_item_width},1000,function(){
					$('.gallery-control p strong').text(carousel.find('li:first').attr('data-original-order'));
				});
			}
		});
		var fwd_button = $('<a />',{
			'class':'carousel-nav go-forward',
			html:'&#x25B6;',
			click:function(e){
				e.preventDefault()
				var carousel = $(this).closest('.carousel-layout-wrapper').find('.carousel-layout:first');
				var first_carousel_item = carousel.find('li:first');
				var first_carousel_item_width = first_carousel_item.width();
				first_carousel_item.animate({width:'0'},1000,function(){
					$(this).appendTo($(this).parent()).css({width:first_carousel_item_width});
					$('.gallery-control p strong').text(carousel.find('li:first').attr('data-original-order'));
				});
			}
		});
		$(this).wrap(carousel_wrapper)
		.after(back_button).after(fwd_button);
	});
};

// New tabbing (introduced July 2011)
// e.g. $('.tabbing').RMPtabs();
// 1. <div class="tab">...<h2 class="tab-title">One Thing...
// 2. <div class="tab" data-tab-title="One Thing">...<h2>Another...
jQuery.fn.RMPtabs = function(){
	this.each(function(){
		var f = false;
		if (window.location.hash){
			f = true;
	    	var hash = window.location.hash;
			hash = '#' + hash.substring(5);
		    var index = $(hash).index();
		    if(index>=1) var tab = (index); 
		    else var tab = 0;
		    var hash_regex_pattern=new RegExp("#tab_");
		    if(hash_regex_pattern.test(window.location.hash)) $('html, body').animate({scrollTop: '0px'}, 300);		
		}
		var tablist_ul = $('<ul />',{'id':$(this).attr('id')+'_navigation','class':'tabbed','role':'navigation'});
		var tabs = $(this).find('.tab[data-tab-title], .tab-title');
		tabs.each(function(i){
			var elem = $(this);
			var fill_html;
			if(elem.is('[data-tab-title]')) fill_html = elem.data('tab-title');
			else fill_html = elem.html();
			tablist_ul.append($('<li />',{
				'class': (i==0?'this-tab':''),
				'id': elem.closest('.tab').attr('id')+'_tab',
				'html': $('<a />',{
					href:'#'+elem.closest('.tab').attr('id'),
					html: fill_html,
					click: function(e) {
						e.preventDefault();
						var href_elem = $(this).attr('href');
						$(this).parent().siblings('.this-tab').removeClass('this-tab');
						$(this).parent().addClass('this-tab');
						$(href_elem).show().siblings('.tab').hide();
						if (f){
							var n = href_elem.substring(1);
							window.location.hash = 'tab_' + n;
							$('html, body').animate({scrollTop: '0px'}, 300)
						}
					
					}
				})
			}));
		});
		tabs = $(this).find('.tab');
		if (f){
			tabs.eq(tab).show();
			tabs.not(':eq('+tab+')').hide();
			$('li',tablist_ul).removeClass('this-tab');		
			$('li',tablist_ul).eq(tab).addClass('this-tab');
		} else{
			tabs.first().addClass('first-tab').siblings().hide();
		}	
		$(this).prepend(tablist_ul);
	});
	return this;
};
