  $(document).ready(function() {
    addDisabledClassToDisabledElements();  
    
    concealAndReveal();
    
    //undisable disabled shadowbox links
    $("a[rel*=shadowbox][href^=#]").each(function(){ $(this).attr('href',$(this).attr('href').replace(/^#/,'')) });
    //initiate the shadowbox player
    Shadowbox.init({
      players:  ['html', 'iframe']
    });
    activeFilters();
    
    jQuery("a.closeShadowbox").click(function(){
      closeShadowboxAndGoTo($(this).attr('href'));
    });
    
    // $('html').addClass('jQ');
    
    loadHelpIfCookie();
    trackFileDownloads();
    
    // prevent form price monkey business
    $('.auto-generated input').focus(function() { this.blur(); });            
    
  }); 

//old version  
//  function initSchoolPriceCalculation(arr){
//    $("input#school_order_number_of_teachers").change(function(){
//      var teacherNum = parseInt($("input#school_order_number_of_teachers").val()); 
//      for(var i = 0; i < arr.length; i++){
//        subarr = arr[i];
//        if(teacherNum >= subarr[0] && teacherNum <= subarr[1]){
//          var teacherPrice = subarr[2];
//          var totalPrice = teacherNum * teacherPrice;
//          $("input#school_order_price_per_teacher").val("£"+teacherPrice);
//          $("input#school_order_total_price").val("£"+totalPrice);
//        }
//      }
//    });
//  }
  
  function initSchoolPriceBandCalculation(teacherPriceBands, pupilPriceBands){
    $("#school_order_number_of_teachers").change(function(){
      var teacherNum = parseInt($("#school_order_number_of_teachers").val()); 
      var newVal = priceFromPriceBands(teacherNum, teacherPriceBands);
      $("#teachers_school_order_total_price").val("£"+newVal);  
      $("#school_order_total_price").val("£"+newVal);                           
    });
    
    $("#school_order_number_of_pupils").keyup(function(){
      var pupilVal = $("#school_order_number_of_pupils").val().replace(/[£,\.]/g,"");
      var pupilNum = parseInt(pupilVal);
      //test if > 0 - this handles the NaN case as well, eg letters not numbers in pupil number field
      if(pupilNum > 0){
        var newVal = priceFromPriceBands(pupilNum, pupilPriceBands);  
        //need to make sure minimum price is £30
        var totalPrice = newVal * pupilNum;
        if(totalPrice < 30)
          totalPrice = 30;
        //need to make total price into a string with £ and two decimal places
        var newVal = "£"+totalPrice.toFixed(2);
      } else { 
        var newVal ='';
      }   
      $("#pupils_school_order_total_price").val(newVal); 
      $("#school_order_total_price").val(newVal);             
    });    
  }  
  
  function priceFromPriceBands(num, arr){
    for(var i = 0; i < arr.length; i++){
      subarr = arr[i];
      if(num <= subarr[0]){
        return subarr[1];
      } else {
      }
    }
  }

  function trackFileDownloads(){
    jQuery("a.ga-trackable").click(function(){
      if(location.href.match(/^http\:\/\/(www\.)?millionaireforschools\.co\.uk/)){
        _gaq.push(['_trackPageview',$(this).attr('href')]);
      }
    });
  }
  
  function helpSelector(){
    return "#helpSection";
  }
  
  function helpContentCookie(){
    return 'help_content';
  }
  
  function initJobRoleSelect(){
    $("#job_role_all").hide();            
    $("#job_role_short").show();
    hideUnhideJobRoleSelect()
    $("#user_job_role_id_short").change(function(){
      hideUnhideJobRoleSelect()
    });
  }
  
  function hideUnhideJobRoleSelect(){
    if($("#user_job_role_id_short").val() == 'teacher'){
      $("#job_role_other").hide();                
      $("#job_role_teacher").show();
    } else if($("#user_job_role_id_short").val() == 'other'){
      $("#job_role_teacher").hide();     
      $("#job_role_other").show(); 
    } else {
      $("#job_role_teacher").hide(); 
      $("#job_role_other").hide();            
    }  
  }
  
  
  
  function loadHelp(article, options){
    article = typeof(article) != 'undefined' ? article : '';
    options = typeof(options) != 'undefined' ? options : {};
    if(/\/help\//.test(article)){
      var url = article;
    } else {
      var url = "/help/" + article;
    }
    var defaults = {
//      title: "Help",
//        autoOpen: false,
      height: 566,
      width: 702,
      resizable: false,
      draggable: true,
      open: function() { 
        populateHelp(url);
      },
      close: function() {
        deleteHelpContentCookie();
      }
    };
    options = jQuery.extend(defaults, options);
    if($(helpSelector()).dialog("isOpen") == true){
      populateHelp(url);        
    } else {
      $(helpSelector()).dialog(options);   
    }
  }
  
  // a basic show/hide function
  function concealAndReveal(){	
    $(".concealed").css("display","none");
    $(".revealToggle").toggle(function(){
		$(this).next(".concealed").slideDown(400);
	  },function(){
		$(this).next(".concealed").slideUp(250);
    });
  }
  
  function populateHelp(url){
    $("#helpSection").load(url, {}, function(){
      saveHelpContentCookie(url); 
      //get hash part of the url and scrollTo it (if present)
      var sections = url.split("#");
      if(sections.length == 2){
        var section =  "#"+sections[1];
        $("#helpPane").scrollTo( section, 800);
        $("#helpNavMain").find("li.topLevel").find("li").removeClass("current");
        $("#helpNavMain").find("li.topLevel").find("li"+section+"_nav").addClass("current");
      }    
      initHelpNav();
    }); 
  }
  
  function initHelpNav(){
    if ($.browser.msie){
      $("#helpNavMain").addClass("ieFix");
    } else {
      $("#helpNavMain").treeview({
        animated: "fast",
        persist: "cookie"//,    
        //unique: true, 
        //collapsed: true
      });
    }
    trackFileDownloads();
  }
  
  function closeHelp(){
    $(helpSelector()).dialog("close");
  }
  
  function saveHelpContentCookie(url){
    $.cookie(helpContentCookie(), url);
  }

  //setting cookie to null started failing so setting to "" now  
  function deleteHelpContentCookie(){
    $.cookie(helpContentCookie(), "");
  }
  
  function loadHelpContentCookie(){
    try {
      return $.cookie(helpContentCookie());
    } catch (error) {    
      return "";
    }
  }  
  
  function loadHelpIfCookie(){
    url = loadHelpContentCookie();
    if(url && url != ""){
      loadHelp(url);
    }
  }
  
  function closeShadowboxAndGoTo(url){
    window.parent.location.href = url;
  }
  
  function closeShadowboxAndReopenInMainWindow(){
    if(window.parent.location != window.location){
      closeShadowboxAndGoTo(window.location);
    }  
  }
  
  function initStyleChangeWarnings(){
    var styleSelect = $("#quiz_style");
    var changing = false;
    styleSelect.change(function(){
      var selected = styleSelect.val(); 
      if(changing != true){
        if(selected == "classic" && !confirm(I18n.t('quiz.style.changing_to_classic'))) {
              changing = true;                                                          
              styleSelect.val('sequential');
              $("#selectstyle").html(I18n.t('quiz.style.sequential'));
              alert(I18n.t('quiz.style.cancelled_change')); 
              changing = false;                                         
              return false;
        } else if(selected == "sequential" && !confirm(I18n.t('quiz.style.changing_to_sequenced'))) {
              changing = true;                                                              
              styleSelect.val('classic');
              $("#selectstyle").html(I18n.t('quiz.style.classic'));
              alert(I18n.t('quiz.style.cancelled_change')); 
              changing = false;
              return false;
        }
      }
    });
  }
  
  function initQuizLadderSwapping(){
    jQuery("form#new_quiz").find("select").change(function(){
      swapQuizLadderImage();
      swapQuizLadderTitle();    
    });
    swapQuizLadderImage();
    swapQuizLadderTitle();        
  }
  
  function swapQuizLadderImage(){
    var new_image = '/images/ladder/' + $("#quiz_style").val() + "_" +  $("#quiz_size").val() + ".jpg";
    jQuery("#ladderImage").attr('src', new_image);
  }
  
  function swapQuizLadderTitle(){
    if($("select#quiz_style").val() == "classic"){
      $(".LadderImageTitles-Sequential").hide();
      $(".LadderImageTitles-Classic").show();      
    } else {
      $(".LadderImageTitles-Sequential").show();
      $(".LadderImageTitles-Classic").hide();      
    }
  }
  
  function maskElement(selector){
    elem = $(selector);
    
  }
  
  //note - i've changed the way this works a bit.  Now, the link which opens the menu doesn't have to be an a
  //tag, in fact it's better if it's not as then we don't have to stop it going somewhere.  Just use a span.  
  //The rule, though, is that if the menu itself has the id 'something_123' then the span (or whatever) that you
  //click to open it has to have the id "show_somethng_123".  Ie, 'show_' is taken off the start of the id of the 
  //open link to get the id of the thing it opens.
  function enableMiniPopUpMenu(){
  	
  	// ie rubbish starts here
  	
  	$(function() {
     if($.browser.msie){
     	
       // IE can only handle hovers on a tags and we are using form elements like links	
       $('.popupMenu *').hover(function() {
          $(this).addClass('hover');
        }, function() {
          $(this).removeClass('hover');
        });
                
       // Z-index fix 
       $('td div').each(function(i) {
         if($(this).css('position')!='absolute') $(this).css('zIndex', 1500 - (i * 10));
       });
       
     }
    });
    
    // !! ie rubbish ends here
    
    //add a mask, unless we have one already, then make sure it's hidden
    if($("#wrapper").siblings("div#mask").size() == 0){
      $('#wrapper').after('<div id="mask"></div>');  
    }
    $('#mask').hide();

	// opening the menu
    $('.otherActions').click(function(e) {
      closeAllPopupMenus();
      //Get the id of the menu from the id of the otherActions element that was clicked
      var id = $(this).attr('id').replace(/^show_/,'');
      //Get the screen height and width
      var maskHeight = $(document).height();
      var maskWidth = $(window).width();
	  
	  $(this).parent().parent().addClass('iePopupHelper'); //kludge
	  
      //Set height and width to mask to fill up the whole screen
      $('#mask').css({'width':maskWidth,'height':maskHeight,'color':'#ffffff'}).fadeIn(0);
      $('#' + id).fadeIn(200); 
    });
    
    // closing the window
    $('.popupMenu .closePopupMenu, #mask').click(function (e) {
      closeAllPopupMenus();
    }); 
    
  };   
  
  function closeAllPopupMenus(e){
    if(e){
      e.preventDefault();
    }
	$('#mask, .popupMenu').hide();
    $('.iePopupHelper').removeClass('iePopupHelper'); //kludge
  }
  
  function enableSelect(selectId){
    jQuery(selectId).removeAttr('disabled');
    jQuery(selectId).siblings("span").removeClass('disabled');
  }  
  
  function disableSelect(selectId){
    jQuery(selectId).attr('disabled','disabled');
    jQuery(selectId).siblings("span").addClass('disabled');
  }
  
  function addDisabledClassToDisabledElements(){
    jQuery(':disabled').each(function(){
      if(jQuery(this).attr('disabled')  == "disabled"){
        jQuery(this).addClass("disabled");
      }
    });
  }
  
  function initializeCurriculumCoverageButtons(){
    $("div#tabs ul.tabnav a").click(function(){
      var anchor = $(this).attr('href').split('#')[1];
      var tab = $("#curriculum_coverage_tab");
      tab.addClass("loading");
      //take active class off clicked parents siblings and put it on clicked parent        
      var parentLi = $(this).parent();
      parentLi.siblings("[class$='active']").removeClass('active');
      parentLi.addClass('active');      
      jQuery.ajax({
        async:true, 
        data: anchor,
        dataType:'script', 
        type:'get', 
        url:"/explore/tab"
      });
    });
  }
  
  function add_tag(){
    //if we got a taggable_id then just go ahead and make a new tagging
    //if we didn't then we're dealing with a new record - so make a new tagging, rather than create one
    var tag_name = jQuery("#tagging_tag_name").val();
    if(tag_name.length < 2){
      alert("Keywords must be at least two characters long");
    } else {
      var user_id = jQuery("#tagging_user_id").val();
      var taggable_type = jQuery("#tagging_taggable_type").val();
      var taggable_id = jQuery("#tagging_taggable_id").val();
      if(taggable_id == ""){
        jQuery.ajax({
          async:true, 
          data:{"tagging[tag_name]": tag_name,
                "tagging[user_id]": user_id,
                "tagging[taggable_type]": taggable_type,
                "tagging[taggable_id]": taggable_id
          }, 
          dataType:'script', 
          type:'get', 
          url:"/taggings/new"
        });        
      } else {
        jQuery.ajax({
          async:true, 
          data:{"tagging[tag_name]": tag_name,
                "tagging[user_id]": user_id,
                "tagging[taggable_type]": taggable_type,
                "tagging[taggable_id]": taggable_id
          }, 
          dataType:'script', 
          type:'post', 
          url:"/taggings"
        });     
      }
    }
  }
   
  function submitQuizForm(extraParams){
    var quizSearchForm = jQuery(".quiz_edit_form");
    var formParams = quizSearchForm.serializeArray();
    var quizId = quizSearchForm.attr("id").split("_")[2]    
    var paramString = jQuery.param(formParams);
    if(extraParams){
      for(attrName in extraParams) {
//        formParams.push({name:attrName, value:extraParams[attrName]});
        paramString += "&" + attrName + "=" + extraParams[attrName];
      }
    }    
    jQuery.ajax({
      async: true, 
      data: paramString, 
      dataType: 'script', 
      type: 'put', 
      url: '/quizzes/'+quizId, 
//      success: function(msg){ 
//        setPublishButtonStatus();
//      },
      error:function(request, textStatus, errorThrown) {
        //403 is the signal that we had a controlled failure at the back end, eg data validation failure
        //So, use the returned message for a 403, or a generic failure message for a 500
        var message = (request.status == 403) ? request.responseText : "Sorry, we couldn't automatically save your quiz as the request was interrupted.  Any further changes will be saved automatically, and you can also save it manually with the Save button.";
        alert(message);
//        quizSaved = false;
      }
    });  
//    setPublishButtonStatus();
//    return quizSaved;   
  }
  
//  function disableTabsForUnsavedQuiz(){
//    jQuery("#navSecondary").find("a").
//  }
//  
  //also does preview button as this is subject to the same logic
  function setPublishButtonStatus(){
    var publishButton = jQuery("#makeMyQuiz");
    var previewButton = jQuery("#previewQuiz");
    //don't do anything if there's no publish button
    if(publishButton.size() > 0){
      //look in a hidden div for the quiz's status
      if(jQuery("#publishable_status").html() == "true"){
//        alert("Enabling publish");            
        publishButton.removeAttr("disabled");
        publishButton.removeClass("disabled");   
        previewButton.removeAttr("disabled");
        previewButton.removeClass("disabled");          
      } else {
//        alert("Disabling publish");      
        publishButton.attr("disabled","disabled");
        publishButton.addClass("disabled");      
        previewButton.attr("disabled","disabled");
        previewButton.addClass("disabled");         
      }
    }
  }
  
  function initializeQuizForm(){
    var timer1;
    jQuery(".autosave").change(function(){
      clearTimeout(timer1);
      timer1 = setTimeout("submitQuizForm()",100);
    });
    //if target age range is reset, reset difficulty for target age range too
     $("#quiz_age_group_id").change(function(){
       if($(this).val() == "") {
         var difficulty = $("#quiz_difficulty_id");
         difficulty.val("");
         deactivateSelect(difficulty);     
       }             
     });
  }
  
  function initializeQuizQuestions(){
    initializeMoveQuizQuestionSelects();
    initializeDeleteQuizQuestionSelects();
    initializeHideShowToggles();
    initializeDragHandles();
    setPublishButtonStatus();
  }
  
  function initializeHideShowToggles(){
    $("#quiz_questions table thead").addClass("active");
    $("#quiz_questions table thead").click().toggle(
      function () { 
        $(this).removeClass("active");
        $(this).next("tbody").fadeOut("fast"); 
      },
      function () { 
        $(this).addClass("active");
        $(this).next("tbody").fadeIn("slow"); 
      }
    );  
    $(".colQuestionTitle dl dt").click().toggle(
      function () { 
        $(this).parent().addClass("active").parent().addClass("active");
        $(this).next("dd").fadeIn("slow"); 
      },
      function () { 
        $(this).parent().removeClass("active").parent().removeClass("active");
        $(this).next("dd").fadeOut("fast"); 
      }
    );
  }

  function initializeDifficultySelects(){
    $("select.difficulty").change(function(){
      cursorWait();
      var difficulty = $(this).val();
      var rowId = jQuery(this).parents(".question").attr("id");
      var splitId = rowId.split("-");
      var quizId = splitId[0].replace(/quiz_/,"");
      var questionId = splitId[1].replace(/question_/,"");

      if(difficulty == ""){
        deleteQuestionFromQuiz(questionId, quizId);
      } else if(difficulty == "next") {
        addQuestionToQuiz(questionId, quizId);        
      } else {
        addQuestionToQuiz(questionId, quizId, difficulty);
      }
    });
  }
  
  function deleteQuestionFromQuiz(questionId, quizId){
    jQuery.ajax({
      async:true, 
      //'_method':'delete' is secret rails signal for the unsupported delete request
      data:{"question_id":questionId, "_method":"delete"}, 
      dataType:'script', 
      type:'post', 
      url:"/quizzes/"+quizId+"/quiz_questions/remove_question", 
      success: function(msg){ 
//        $("#searchResultsTable").trigger("update"); 
        jQuery("tr[id*='question_"+questionId+"']").removeClass('selected');     
        cursorNormal();   
      },
      error: function(msg){
        alert("error:" + msg);
        cursorNormal();
      }      
    });     
  }
  
  function addQuestionToQuiz(questionId, quizId, difficulty){
    if(difficulty == null){
      var data = {"question_id":questionId}
    } else {
      var data = {"question_id":questionId, "quiz_question[difficulty_value]":difficulty}
    }
    jQuery.ajax({
      async:true, 
      data: data, 
      dataType:'script', 
      type:'post', 
      url:"/quizzes/"+quizId+"/quiz_questions", 
      success: function(msg){ 
//        $("#searchResultsTable").trigger("update"); 
        //add selected class to row 
        jQuery("tr[id*='question_"+questionId+"']").addClass('selected');
        cursorNormal();
      },
      error: function(msg){
        alert("error:" + msg);
        cursorNormal();
      }      
    });     
  }  
  
  function initializeDeleteQuizQuestionSelects(){
    jQuery("tr.quiz_question").find(".discard").click(function(){
      if(confirm("Remove this question from your quiz?")){
        cursorWait();      
        var splitId = jQuery(this).parents("tr").attr("id").split("-");
        var quizId = splitId[0].replace(/quiz_/,"");
        var quizQuestionId = splitId[1].replace(/quiz_question_/,"");
        deleteQuizQuestion(quizQuestionId, quizId);       
      }
    });
  }
  
  function deleteQuizQuestion(quizQuestionId, quizId){
    //send ajax call to back end to change the difficulty of the quiz question
    //back end will then refresh the relevant parts of the page (progress bars, flashes, quiz status)
    jQuery.ajax({
      async: true, 
      dataType: 'script',
      data: {"_method":"delete"}, 
      type: 'post', 
      url: "/quizzes/"+quizId+"/quiz_questions/"+quizQuestionId,
      success: function(msg){ 
        initializeQuizQuestions();
        jQuery("tr[id*='quiz_question_"+quizQuestionId+"']").removeClass('selected');     
        cursorNormal();
      },
      error: function(msg){
        alert("error:" + msg);
        cursorNormal();
      }
    });     
  }
  
  function cursorNormal(){
    document.body.style.cursor = "default";   
  }
  
  function cursorWait(){
    document.body.style.cursor = "wait";
  }
  
  function initializeMoveQuizQuestionSelects(){
    jQuery("select.moveQuizQuestion").change(function(){
//      alert("changed");
      cursorWait();
      var splitId = jQuery(this).parents("tr").attr("id").split("-");
      var quizId = splitId[0].replace(/quiz_/,"");
      var quizQuestionId = splitId[1].replace(/quiz_question_/,"");
      updateQuizQuestion(quizQuestionId, quizId, {"quiz_question[difficulty_value]":jQuery(this).val()}); 
    });
  } 
  
  function initializeDragHandles(){
    $('#draggable').tableDnD({
        onDragClass: "dragging",
        dragHandle: "dragHandle",       
        onDropClass: "dragged", 
        onDrop: function(table, row) {
          position = $("#draggable").find("tr").index(jQuery("#"+row.id)[0]) + 1;
          splitId = row.id.split("-");
          quizId = splitId[0].replace(/quiz_/,"");
          quizQuestionId = splitId[1].replace(/quiz_question_/,"");          
          updateQuizQuestion(quizQuestionId, quizId, {"quiz_question[sequence_step]":position});           
        }
    });
  }
  
  function updateQuizQuestion(quizQuestionId, quizId, data){
    jQuery.ajax({
      async:true, 
      data:data, 
      dataType:'script', 
      type:'put', 
      url:"/quizzes/"+quizId+"/quiz_questions/"+quizQuestionId,
      success: function(msg){ 
        initializeQuizQuestions();
        setPublishButtonStatus();
        cursorNormal();
      },
      error: function(msg){
        alert("error:" + msg);
        cursorNormal();
      }
    });     
  }
  
function initQuizSearchForm(searchUrl){
  jQuery("#searchForm").find("#filterBank").find("select").change(function(){
    submitQuizSearchForm(searchUrl);
  });
  jQuery("#searchForm").find("#filterBank").find("input").change(function(){
    submitQuizSearchForm(searchUrl);
  });  
  jQuery("#clearAll").click(function(){
    clearSearchForm();
    submitQuizSearchForm(searchUrl);
  });
  
  $("#search_by_term").click(function(){
    $(".hidden_sortfield#order").val();
  });
}

function clearSearchForm(){
  //reset fields 
  jQuery("#searchForm").find("#search, #order, #search_page").val("");
  jQuery("label[for='search']").find("span.reset").hide();
  //deactivate selects
  jQuery("#searchForm").find("#filterBank").find("select").each(function(){
    $(this).val("");
    deactivateSelect($(this));  
  });
  if($("select#difficulty_id").size > 0){
    //disable difficulty select (since age is now reset to blank and we don't want a search just on difficulty without age)
    toggleDifficultyIdEnabled();
  }
}

function setPageFieldAndSubmitQuizSearchForm(page){
  jQuery('#search_page').val(page);
  submitQuizSearchForm(); 
} 

function submitQuizSearchForm(){
  //disable empty fields so they don't clutter up the url
  var empty_fields = jQuery("#searchForm").find(':input[value=""][type!="radio"]');
  empty_fields.attr('disabled', true);
  jQuery("#searchForm").submit();
}
  
//when one of the non-page fields is changed, we want to always start with page 1 of the results
//so we need to clear the hidden page field which is set by will_paginate 
function initQuestionSearchForm(){
  jQuery("#searchForm").find("#filterBank").find("select").change(function(){
    clearPageFieldAndSubmitQuestionSearchForm();    
  });
  jQuery("#searchForm").find("#filterBank").find("input").change(function(){
    clearPageFieldAndSubmitQuestionSearchForm();    
  });  
  jQuery("#clearAll").click(function(){
    clearSearchForm();
    clearPageFieldAndSubmitQuestionSearchForm();
  });  
  jQuery("select#age_group_id").change(function(){
    toggleDifficultyIdEnabled();
  });
  toggleDifficultyIdEnabled();
  initializeHideShowToggles();
}

function toggleDifficultyIdEnabled(){
  if($("select#age_group_id").val() == ""){
    jQuery("select#difficulty_id").val("");    
    jQuery("select#difficulty_id").attr("disabled", "disabled");
    deactivateSelect(jQuery("select#difficulty_id"));      
    jQuery("span#selectdifficulty_id").addClass("disabled");
  } else {
    jQuery("select#difficulty_id").removeAttr("disabled");
    jQuery("span#selectdifficulty_id").removeClass("disabled");    
  }
}

function clearPageFieldAndSubmitQuestionSearchForm(){
  jQuery('#search_page').val('');
  submitQuestionSearchForm(); 
} 

function setPageFieldAndSubmitQuestionSearchForm(page){
  jQuery('#search_page').val(page);
  submitQuestionSearchForm(); 
} 

function submitQuestionSearchForm(){
  var empty_fields = jQuery("#searchForm").find(':input[value=""][type!="radio"]');
  empty_fields.attr('disabled', true);
  jQuery("#searchForm").submit();
}
  
function initEnableQuestionSubmitButton(){
  //when a form element is changed we need to decide whether we have enough info and disable/enable the save button accordingly
  jQuery("form.edit_question,form.new_question").find("select").change(function(){ 
    enableDisableQuestionSubmitButton();
  });
  jQuery("form.edit_question,form.new_question").find("input,textarea").keyup(function(){ 
    enableDisableQuestionSubmitButton();
  }); 
  jQuery("#addTag, #removeTag").click(function(){
    enableDisableQuestionSubmitButton();  
  });
}

function enableDisableQuestionSubmitButton(){
  if(questionFormSubmittable()){
    //enable button
    $("#question_submit").removeClass("disabled").removeAttr("disabled");
  } else {
    $("#question_submit").addClass("disabled").attr("disabled","disabled");
  }
}

function questionFormSubmittable(){
  //ok - before we can let the user submit we need a question, four answers, a subject, and either (an age group
  //and a difficulty level) or (an age group/difficulty level)
  var submittable = true;
  //standard fields that are on all versions of the form, which must be completed
  if($("#question_text").val() == "" || 
     $("#answer1").val() == "" || 
     $("#answer2").val() == "" || 
     $("#answer3").val() == "" || 
     $("#answer4").val() == "" || 
     $("#question_subject_name").val() == "" ||
     $("#question_privacy").val() == "" ||
     ($('#subject_short_list').val()+$('#subject_long_list').val()) == '')
     {
   submittable = false;
  }
  //two different cases for age group/difficulty depending on the user type.  If we have age group and difficulty, we need both
  //if we have a list of difficulty selects (content admin version of the form), we just need one of them
  var selects = jQuery("fieldset#contentAdminOnly").find("select");
  if(selects.size() > 0){
    //we just need one so add values and see if it's ""
    var str = "";
    selects.each(function(){ str += $(this).val() });
    if(str.replace(/undefined/g,"") == ""){
      submittable = false;
    }
  } else {
    //we need both of these
    if($("#question_target_age_group_id").val() == "" || $("#question_target_age_group_difficulty_id").val() == ""){
      submittable = false;
    }
  } 
  return submittable;
}

function checkUsernameAvailability(userId){
  var loginField = $("#user_login");
  var loginStatus = $("#login_status");
  loginField.keyup(function(){
    loginStatus.removeClass("available").removeClass("unavailable").addClass("checking").html("Checking availability...");
    if(loginField.val().length > 2){
      afterDelayedKeyup("#user_login", "updateUsernameAvailability('"+userId+"')", 1000);
    }
  });
}

function updateUsernameAvailability(userId){
  var loginField = $("#user_login");
  var loginStatus = $("#login_status");
  $.get("/users/check_availability", {login: loginField.val(), user_id: userId}, function(data){ 
    if(data == "available"){
      loginStatus.removeClass("checking").addClass("available").html("username available");    
    } else {
      loginStatus.removeClass("checking").addClass("unavailable").html("username already taken");        
    }
  });
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        function afterDelayedKeyup(selector, action, delay){
  jQuery(selector).keyup(function(){
    if(typeof(window['inputTimeout']) != "undefined"){
      clearTimeout(inputTimeout);
    }  
    inputTimeout = setTimeout(action, delay);
  });
}

function initTable(table_id){
    // show hide keyword lists
  showHideKeywords();
  showHideIndex();  
  enableMiniPopUpMenu();  
  //jQuery("#search").example('Search', {
  //  className: 'example'
  //});
  
  jQuery("#search").focus( function(){
    jQuery(this).addClass("tv-focused");
  });
  
  jQuery("#search").blur( function(){
    jQuery(this).removeClass("tv-focused");
  });      
  
//  $("#search").keyup(function() {
//    filterRows();
//  });
//  
}

function toggleFormFields(){
  $("input[type='text'], input[type='password'],select").change(function(){ 
    $(this).addClass("tv-changed");
  });
  var passField = $("#user_password");
  passField.val('');
  var passConfField = $("#user_password_confirmation");    
  passConfField.keyup(function() {
    if(passConfField.val() == passField.val()){
      passConfField.addClass("tv-changed");
    } else {
      passConfField.removeClass("tv-changed");
    }
  });
}

function resetForms(){  
  // reset forms on page load to avoid mystery filteryness
  $("form").each(function(){
    $(this).reset();
  });
}
 
//this works with the 'hidden select and overlaid span' hack for styling selects.
//when the select changes, we need to add the activeFilter class to the span and change it's content to to be the same as 
//the *content* of the selected option - NOT the value!!  
//function activeFilters(){
//  unhideClearButtons();
//  initClearButtons();
//  initSearchBox();
//  $("select.withspan").change(function() {
//    var comboVal = $(this).val();
//    if(comboVal != ""){
//      activateSelect($(this));
//    } else {
//      deactivateSelect($(this));
//    }
//  });
//}  

function activeFilters(){
  unhideClearButtons();
  initClearButtons();
  initSearchBox();
  $("select.withspan").each(function(){
    setSpan($(this));
  });
  $("select.withspan").change(function(){
    setSpan($(this));
  });  
}  

function setSpan(element){
  var comboVal = element.val();
  if(comboVal != ""){
    activateSelect(element);
  } else {
    deactivateSelect(element);
  }
}

function activateSelect(select){
  var comboContent = select.find(":selected").html();
  //get corresponding span 
  var span = select.prev(".select");
  if(span.size() == 0)
    span = select.parent().prev(".select");
  select.addClass("activeFilter");
  span.addClass("activeFilter").html(comboContent);
  jQuery("label[for='"+select.attr('id').replace('select','')+"']").find("span.reset").show();
  $("span#clearAll").show();
}

function deactivateSelect(select){
  var comboContent = select.find(":selected").html();
  //get corresponding span 
  var span = select.prev(".select");
  if(span.size() == 0)
    span = select.parent().prev(".select");
  select.removeClass("activeFilter");
  span.removeClass("activeFilter").html(comboContent);
  jQuery("label[for='"+select.attr('id').replace('select','')+"']").find("span.reset").css("display","none");
//  hideClearAllIfFormIsBlank();
}

//function hideClearAllIfFormIsBlank(){
//  if 
//  $("span#clearAll").hide(); 
//}

function unhideClearButtons(){
  jQuery("span.activeFilter").each(function(){
    jQuery("label[for='"+$(this).attr('id').replace('select','')+"']").find("span.reset").css("display", "inline");
  });
}   

function initSearchBox(){
  showHideSearchReset();
  $("input#search").change(function(){
    $("#clearAll").show();
    showHideSearchReset();
  });
}

function showHideSearchReset(){
  if($("input#search").val() == "") {
    $("label[for='search']").find("span.reset").addClass("hidden");           
  } else {
    $("label[for='search']").find("span.reset").removeClass("hidden");          
  }
}

function initClearButtons(){
  jQuery("span.reset").click(function(){
    //change associated val to ""
    var input = $("#"+$(this).parent().attr('for'));
    //if we're on a search term field we want to we want to clear the order field
    if($(this).attr('id') == "search"){    
      $(".hidden_sortfield").val("");
    }
    input.val("");
    input.trigger('change');
    jQuery("#searchBoxSubmit").click().submit();
  });
}

function initColumnSorting(func) {  
  //set up keyword links to amend a hidden sortfield and then call the given function
  $(".keyword_sort").click(function(){
    var hiddenSortfield = $(".hidden_sortfield");        
    if(hiddenSortfield.size() != 0){
//      //set radio button to search by term rather than keyword (which will wipe out any keywords)
//      $("#search_by_term").click();
      //want to go to page one so delete page option
      $("#search_page").val("");      
      //hide 
      hiddenSortfield.val("keyword-"+$(this).parents(".keywords").find(".keyword").text());
      if(func != null)
        func();
    }  
  });
  
  $(".keyword_search").click(function(){
    //clear all fields
    clearSearchForm();
    //write keyword into search field
    $("#search").val($(this).parents(".keywords").find(".keyword").text());    
    $("#search_by_keyword").attr('checked', true);
    if(func != null){
      func();
    }
  });  
  
  //Set up columns to amend a hidden sortfield and then call the given function 
  $("table th.sortable").click(function(){
    //if we have activeAsc class already, then sort descending, otherwise sort ascending
    if($(this).attr('class').indexOf('activeAsc') != -1) {
      $("table th.activeAsc").attr("class","inactive");
      $("table th.activeDesc").attr("class","inactive");
      $(this).attr("title","Sorted descending").attr("class","activeDesc");
      var hiddenSortfield = $(".hidden_sortfield");      
      if(hiddenSortfield.size() != 0){
        hiddenSortfield.val($(this).find(".sort_attribute").text() + " desc");
        if(func != null)
          func();
      }  
    } else {
      $("table th.activeAsc").attr("class","inactive");
      $("table th.activeDesc").attr("class","inactive");
      $(this).attr("title","Sorted Ascending").attr("class","activeAsc");
      var hiddenSortfield = $(".hidden_sortfield");
      if(hiddenSortfield.size() != 0){
        hiddenSortfield.val($(this).find(".sort_attribute").text());
        if(func != null)
          func();
      }    
    }
  });
}

function showHideKeywords(){    
//  $("#keywordBox .expandCollapse").addClass("hidden"); 
  // main interaction thing
  $("#keywordBox .expandCollapseToggle").toggle(
    function () {
      $(this).toggleClass("active");
      $("#keywordBox .expandCollapse").fadeIn("slow");
    },
    function () {
      $(this).toggleClass("active");
      $("#keywordBox .expandCollapse").fadeOut("slow");
    }
  );
  
  //  show/hide keyword list
  $("#keywordListTrigger").click(function () { 
  $("#keywordList").attr("class","visible");
  $("#keywordAlphabetChooser").attr("class","visible");
  
  $("#indexList").attr("class","hidden");
  $("#indexAlphabetChooser").attr("class","hidden");
  });
}

function showHideIndex(){  
  //  show/hide index list
  $("#indexListTrigger").click(function () { 
  $("#indexList").attr("class","visible");
  $("#indexAlphabetChooser").attr("class","visible");
  $("#keywordList").attr("class","hidden");
  $("#keywordAlphabetChooser").attr("class","hidden");
  });
} 

function filterRows(){
  var filter = jQuery("#search").val(), count = 0;
  $("tbody.filtered tr").each(function () {
      if ($(this).find(".keywords").text().search(new RegExp(filter, "i")) < 0) {
          $(this).addClass("hidden");
      } else {
          $(this).removeClass("hidden");
          count++;
      }
  });
}

function initSubjectSelect(){
  $(".subject_short_long_list").change(function(){
    updateSubjectSelect();
  });
  updateSubjectSelect();
}

function updateSubjectSelect(){
  if($(".subject_short_long_list:checked").attr('id') == "subject_long_list_radio")
  {
    $("#subject_short_list").each(function(){
      $(this).val("");
      deactivateSelect($(this));
    });
    $("#subject_short_list").attr('disabled', true).addClass("disabled");
    $("#subject_long_list").attr('disabled', false).removeClass("disabled");    
    $("#short_list").hide();
    $("#long_list").show();

  } else {
    $("#subject_long_list").each(function(){
      $(this).val("");
      deactivateSelect($(this));
    });  
    $("#subject_long_list").attr('disabled', true).addClass("disabled");
    $("#subject_short_list").attr('disabled', false).removeClass("disabled");   
    $("#long_list").hide();
    $("#short_list").show();
  }
  enableDisableQuestionSubmitButton();
}

function initSwitchableAutocomplete(field, button1_id, button2_id, values1, values2){
  $(button1_id+","+button2_id).change(function(){
    updateSwitchableAutocomplete(field, button1_id, button2_id, values1, values2);
  });
  updateSwitchableAutocomplete(field, button1_id, button2_id, values1, values2);
}

function updateSwitchableAutocomplete(field, button1_id, button2_id, values1, values2){
  if($(button1_id+":checked").size() > 0){  
    $(field).autocomplete("close");  
    $(field).unbind();
    initAutocomplete(field, values1);
  } else if($(button2_id+":checked").size() > 0){
    $(field).autocomplete("close");    
    $(field).unbind();
    initAutocomplete(field, values2, {preserveOrder: true});
    $("#long_list_select").val("");
    $("#long_list").hide();
    $("#short_list").show();    
   }
 }

function initAutocomplete(field, values, options){
  //override defaults with supplied options, if any
  defaults = {
    minChars: 1,
    max: 2000,
    scrollHeight: 300,
    matchContains: false,
    selectFirst: false
  };
  options = jQuery.extend(defaults, options);
  jQuery(field).autocomplete(values, options);   
}

function goBack(){
  //read var off page
  url = goBackUrl;
  //if we got something in that var then go back to it, otherwise try to use browser history or fall back to homepage
  if(url == null || url == ''){
    if (window.history.length >= 2) {
      window.history.go(-1);
    } else {
      location.href = "/";
    }
  } else {
    location.href = url;
  }
}

/* -------------------------------------------------- *
 * ToggleVal 2.1  
 * Updated: 1/16/09
 * -------------------------------------------------- *
 * Author: Aaron Kuzemchak
 * URL: http://aaronkuzemchak.com/
 * Copyright: 2008-2009 Aaron Kuzemchak
 * License: MIT License
** -------------------------------------------------- */
function initToggleVal(){
  (function($){$.fn.toggleVal=function(theOptions){if(!theOptions||typeof(theOptions)=="object"){theOptions=$.extend({focusClass:"tv-focused",changedClass:"tv-changed",populateFrom:"default",text:null,removeLabels:false},theOptions)}else if(typeof(theOptions)=="string"&&theOptions.toLowerCase()=="destroy"){var destroy=true}return this.each(function(){if(destroy){$(this).unbind("focus.toggleval").unbind("blur.toggleval").removeData("defText");return false}var defText="";switch(theOptions.populateFrom){case"alt":defText=$(this).attr("alt");$(this).val(defText);break;case"label":defText=$("label[for='"+$(this).attr("id")+"']").text();$(this).val(defText);break;case"custom":defText=theOptions.text;$(this).val(defText);break;default:defText=$(this).val()}$(this).addClass("toggleval").data("defText",defText);if(theOptions.removeLabels==true){$("label[for='"+$(this).attr("id")+"']").remove()}$(this).bind("focus.toggleval",function(){if($(this).val()==$(this).data("defText")){$(this).val("")}$(this).addClass(theOptions.focusClass).removeClass(theOptions.changedClass)}).bind("blur.toggleval",function(){if($(this).val()==""){$(this).val($(this).data("defText"))}$(this).removeClass(theOptions.focusClass);if($(this).val()!=$(this).data("defText")){$(this).addClass(theOptions.changedClass)}else{$(this).removeClass(theOptions.changedClass)}})})}})(jQuery);
}

  function animateTicker() {
    var oldPositionText = $("div.number span:last-child").css("backgroundPosition");
    if(oldPositionText != "" && oldPositionText != null) {
      var oldX = oldPositionText.split(" ")[0].replace(/px/,"");
      var oldY = parseInt(oldPositionText.split(" ")[1].replace(/px/,""));
      var newY = oldY + 10;
      var newPositionText = oldX+"px "+newY+"px";
      $("div.number").animate({ opacity: 1 }, 500);
      $("div.number span:last-child").css("backgroundPosition",newPositionText);
      $("div.number span:last-child")
        .css("backgroundPosition",newPositionText)
        .animate({ 
          backgroundPosition: oldPositionText
        }, 1000 );
    }
  }

  function twitterCallback2(twitters) {
    var statusHTML = [];
    for (var i=0; i<twitters.length; i++){
      var username = twitters[i].user.screen_name;
      var status = twitters[i].text.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\<\>]*[^.,;'">\:\s\<\>\)\]\!])/g, function(url) {
        return '<a href="'+url+'">'+url+'</a>';
      }).replace(/\B@([_a-z0-9]+)/ig, function(reply) {
        return  reply.charAt(0)+'<a href="http://twitter.com/'+reply.substring(1)+'">'+reply.substring(1)+'</a>';
      });
      statusHTML.push('<li><span>'+status+'</span> <span class="when")>'+relative_time(twitters[i].created_at)+'</span></li>');
    }
       document.getElementById('latestNews').innerHTML = statusHTML.join('');    
  }

  function relative_time(time_value) {
    var values = time_value.split(" ");
    time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
    var parsed_date = Date.parse(time_value);
    var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
    var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
    delta = delta + (relative_to.getTimezoneOffset() * 60);

    if (delta < 60) {
      return ' &hellip; less than a minute ago';
    } else if(delta < 120) {
      return ' &hellip; about a minute ago';
    } else if(delta < (60*60)) {
      return (parseInt(delta / 60)).toString() + ' minutes ago';
    } else if(delta < (120*60)) {
      return ' &hellip; about an hour ago';
    } else if(delta < (24*60*60)) {
      return ' &hellip; about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
    } else if(delta < (48*60*60)) {
      return ' &hellip; 1 day ago';
    } else {
      return (parseInt(delta / 86400)).toString() + ' days ago';
    }
  }
  

    
  function initialiseSignpost() {
    
    // $('tbody').html('<tr class=\"NoQuestion\"><td colspan=\"4\">You don\'t have any .....very easy..... questions yet.<br><a class=\"findQuestions\" href=\"?goto=step_2\">Find questions</a> in the question library or <a class=\"makeQuestions\" href=\"?goto=step_3\">create questions</a> to include in your quiz</td></tr>');
    
    $('td a.findQuestions').hover(function() {
      $('#cq-Nav2 a').addClass('signpost');
    }, function() {
      $('#cq-Nav2 a').removeClass('signpost');
    });

    $('td a.makeQuestions').hover(function() {
      $('#cq-Nav3 a').addClass('signpost');
    }, function() {
      $('#cq-Nav3 a').removeClass('signpost');
    });
    
  }
  
  function checkQuestionImportProgress(){
    var qids = [];
    $("span.incomplete").each(function(){
      qids.push($(this).html()); 
    });
    if(qids.length > 0){
      jQuery.ajax({ 
        async:true, 
        type: "POST", 
        url: ("/admin/questions/import_progress"), 
        data: {"qids": qids.join("-")},
        dataType: "json",
        success: function(msg){
          $.each(msg.imported_qids, function(index, value){
            $("#qid_"+value).removeClass("incomplete");
          });
          if($("span.incomplete").size() > 0){
            setTimeout('checkQuestionImportProgress()',5000);
          } else {
            alert("All questions have been imported");
          }
        },
        error: function(msg){
          alert("An error occurred while checking import progress");
        }        
      });
    } else {
      alert("All questions have been imported");
    }
  }
 
 function loggedOutHomePageScripts(){
 	fadeInHoverState();
 }
  
 function fadeInHoverState(){

	// this just handles the fad in of the video hover effect. If we need similar effects then we should abstact further
	$(".fadeInHoverState").fadeTo(0, 0);
	$(".fadeInHoverState").hoverIntent(function(){
			$(this).fadeTo(1000, 0.85);
		},function(){
			$(this).fadeTo("fast", 0);
	});
 
  }
  
  

/**
* hoverIntent is similar to jQuery's built-in "hover" function except that
* instead of firing the onMouseOver event immediately, hoverIntent checks
* to see if the user's mouse has slowed down (beneath the sensitivity
* threshold) before firing the onMouseOver event.
* 
* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
* 
* hoverIntent is currently available for use in all personal or commercial 
* projects under both MIT and GPL licenses. This means that you can choose 
* the license that best suits your project, and use it accordingly.
* 
* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions
* $("ul li").hoverIntent( showNav , hideNav );
* 
* // advanced usage receives configuration object only
* $("ul li").hoverIntent({
*	sensitivity: 7, // number = sensitivity threshold (must be 1 or higher)
*	interval: 100,   // number = milliseconds of polling interval
*	over: showNav,  // function = onMouseOver callback (required)
*	timeout: 0,   // number = milliseconds delay before onMouseOut function call
*	out: hideNav    // function = onMouseOut callback (required)
* });
* 
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne <brian@cherne.net>
*/
(function($) {
	$.fn.hoverIntent = function(f,g) {
		// default configuration options
		var cfg = {
			sensitivity: 7,
			interval: 100,
			timeout: 0
		};
		// override configuration options with user supplied object
		cfg = $.extend(cfg, g ? { over: f, out: g } : f );

		// instantiate variables
		// cX, cY = current X and Y position of mouse, updated by mousemove event
		// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
		var cX, cY, pX, pY;

		// A private function for getting mouse position
		var track = function(ev) {
			cX = ev.pageX;
			cY = ev.pageY;
		};

		// A private function for comparing current and previous mouse position
		var compare = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			// compare mouse positions to see if they've crossed the threshold
			if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
				$(ob).unbind("mousemove",track);
				// set hoverIntent state to true (so mouseOut can be called)
				ob.hoverIntent_s = 1;
				return cfg.over.apply(ob,[ev]);
			} else {
				// set previous coordinates for next time
				pX = cX; pY = cY;
				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
				ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
			}
		};

		// A private function for delaying the mouseOut function
		var delay = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			ob.hoverIntent_s = 0;
			return cfg.out.apply(ob,[ev]);
		};

		// A private function for handling mouse 'hovering'
		var handleHover = function(e) {
			// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
			while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
			if ( p == this ) { return false; }

			// copy objects to be passed into t (required for event object to be passed in IE)
			var ev = jQuery.extend({},e);
			var ob = this;

			// cancel hoverIntent timer if it exists
			if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

			// else e.type == "onmouseover"
			if (e.type == "mouseover") {
				// set "previous" X and Y position based on initial entry point
				pX = ev.pageX; pY = ev.pageY;
				// update "current" X and Y position based on mousemove
				$(ob).bind("mousemove",track);
				// start polling interval (self-calling timeout) to compare mouse coordinates over time
				if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}

			// else e.type == "onmouseout"
			} else {
				// unbind expensive mousemove event
				$(ob).unbind("mousemove",track);
				// if hoverIntent state is true, then call the mouseOut function after the specified delay
				if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
			}
		};

		// bind the function to the two event listeners
		return this.mouseover(handleHover).mouseout(handleHover);
	};
})(jQuery);

