// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults


//Setup function for adding context menus and setting the height of the main
//body window to fill available space but leave a little on the bottom
function setup(offset) {				
  new Draggable('translationDialogBorder');
  if($('mainBody').getHeight() < document.documentElement.clientHeight - $('mainBar').getHeight() - 77) {
    $('mainBody').style.height = (document.documentElement.clientHeight - $('mainBar').getHeight() - $('copyrightNotice').getHeight() - 77) + "px";
  }
  SimpleContextMenu.setup({'preventDefault':false, 'preventForms':true});
  SimpleContextMenu.attach('translation', 'translationMenu');
}

//Resizes the empty image viewer in the extract view when the browser window is
//resized
function resizeEmptyViewer() {
  $('emptyImageViewer').style.height = (document.documentElement.clientHeight - $('record_form').style.height - $('extractMainBarItems').style.height - 200) + 'px';
  $('emptyImageViewer').style.width = (document.documentElement.clientWidth - 160) + 'px';
  $('record_form').style.width = (document.documentElement.clientWidth - 20) + 'px';
  $('viewerContainer').style.height = (document.documentElement.clientHeight - 140) + "px";
  $('viewerContainer').style.width = (document.documentElement.clientWidth - 150) + "px";
  $('viewerContainer').style.overflow = 'hidden'; 
}

//Setup function for adding context menus and setting the size of the
//extraction window in the extract view 
function setupExtract() {				
  new Draggable('translationDialogBorder', {zindex:3000});
  new Draggable('fieldEditor', {zindex:3000});
  $('extractBody').style.height= (document.documentElement.clientHeight) + "px";
  $('imageListContainer').style.height = (parseInt($('extractBody').style.height) - 200) + 'px';
  $('record_form').style.width = (document.documentElement.clientWidth - 20) + 'px';
  $('recordFormDragHandle').style.width = (document.documentElement.clientWidth - 20) + 'px';
  SimpleContextMenu.setup({'preventDefault':false, 'preventForms':true});
  SimpleContextMenu.attach('translation', 'translationMenu');
}

//Constructor for the imageViewer
function imageViewer(height, width) {
  this.height = height;
  this.width = width;
  this.viewer = $('viewer');		
  this.viewerImage = $('viewerImage');
  if (this.viewerImage == null) return;
  var aspectRatio = parseInt(this.viewerImage.height)/parseInt(this.viewerImage.width);		
  this.viewerImage.width = this.width;
  this.viewerImage.height = (this.viewerImage.width * aspectRatio);
  this.currentZoom = 1;
  this.originalHeight = this.viewerImage.height;
  this.originalWidth = this.viewerImage.width;
  this.topOffset = 0;
  this.leftOffset = 0;
  this.leftCorner = 20;
  this.topCorner = 39;
  this.startImageDrag = startImageDrag;
  this.endImageDrag = endImageDrag;
  this.doImageDrag = doImageDrag;
  this.redraw = redraw;	
  this.doZoom = doZoom;
  this.zoomIn = zoomIn;
  this.zoomOut = zoomOut;
  this.scrollUp = scrollUp;
  this.scrollDown = scrollDown;
  if (this.viewerImage.addEventListener) this.viewerImage.addEventListener('DOMMouseScroll', doZoom, false);	
}

//Takes in a zoom direction and calls either zoom in or zoom out on the image
//viewer if an image is loaded in the extract view.  Used when the user clicks
//on the zoom in or zoom out icon
function tryToZoom(inOrOut) {
  if(document.viewer.zoomIn != null) {
    if(inOrOut == 'in') {
      document.viewer.zoomIn();
    }
    else if(inOrOut == 'out') {
      document.viewer.zoomOut();
    }
  }
}

//Make the image in the image viewer larger
function zoomIn() {
  if(this.currentZoom < 3.81) {
    this.currentZoom = this.currentZoom * 1.25;
  }
  else {
    this.currentZoom = 4.77;
  }
  this.viewerImage.height = this.originalHeight * this.currentZoom;
  this.viewerImage.width = this.originalWidth * this.currentZoom;			
  this.redraw();	
}
	
//Make the image in the image viewer smaller
function zoomOut() {
  if(this.currentZoom > .64) {
    this.currentZoom = this.currentZoom * .8;
  }
  else {
    this.currentZoom = .4096; 
  }
  this.viewerImage.height = this.originalHeight * this.currentZoom;
  this.viewerImage.width = this.originalWidth * this.currentZoom;						
  this.redraw();	
}
	
//Called when the mouse wheel is moved in the image viewer.  Figures out which
//way the mouse wheel moved and calls the appropriate function.
function doZoom(event){		
  var delta = 0;
  if (!event) event = window.event;
  if (event.wheelDelta) {
    delta = event.wheelDelta/120; 
    if (window.opera) delta = -delta;
  } else if (event.detail) {
    delta = -event.detail/3;
  }
  if (delta)
    if (delta < 0)
      //document.viewer.zoomOut();
      document.viewer.scrollUp();
    else
      //document.viewer.zoomIn();
      document.viewer.scrollDown();
  if (event.preventDefault)
  event.preventDefault();
  event.returnValue = false;
}

function scrollUp() {
  this.topOffset -= 50;
  this.redraw();
}

function scrollDown() {
  this.topOffset += 50;
  this.redraw();
}
	
//Redraw the image in the image viewer after it has been moved
function redraw() {		
  //Make sure the viewer does not contain whitespace
  if(this.viewerImage.width < parseInt($('viewerContainer').style.width)) {
  }
  else if(this.leftOffset + this.viewerImage.width < this.width) {
    this.leftOffset = this.width - this.viewerImage.width; 		
  }
  if(this.viewerImage.width < parseInt($('viewerContainer').style.width)) {
  }
  else if(this.leftOffset > 0) {
    this.leftOffset = 0;
  }
  if(this.topOffset > 0) this.topOffset = 0;
  if(this.topOffset + this.viewerImage.height < this.height - 40) this.topOffset = this.height - this.viewerImage.height - 40;
  
  //Put the image in its new location
  this.viewer.style.left = (this.leftOffset + this.leftCorner) + 'px';
  this.viewer.style.top = (this.topOffset + this.topCorner) + 'px';
}
	
//Set the viewer to its dragging state
function startImageDrag(event) {		
  this.viewer.style.cursor="move";
  this.dragging = true;
  this.currentX = event.clientX;
  this.currentY = event.clientY;				
  if (navigator.appName != "Microsoft Internet Explorer") event.preventDefault();
  return false;
}
	
//Handles dragging the image when the mouse is moved while the viewer is in the
//dragging state 
function doImageDrag(event) {				
  if(this.dragging) {
    this.leftOffset = (this.leftOffset - (this.currentX - event.clientX));
    this.topOffset = (this.topOffset - (this.currentY - event.clientY));				
    this.currentX = event.clientX;
    this.currentY = event.clientY;
    this.redraw();
  }
}
	
//End the dragging state of the viewer
function endImageDrag(event) {		
  this.viewer.style.cursor="default";
  this.dragging = false;
}

//Sets the size of the image viewer based on how much space should be left
//empty beneath it
function setViewerSize(offset) {
  setupExtract();
  if(!offset) offset = 0;
  $('viewerContainer').style.height = (document.documentElement.clientHeight - offset) + "px";
  $('viewerContainer').style.width = (document.documentElement.clientWidth - 150) + "px";
  $('viewerContainer').style.overflow = 'hidden'; 
  $('extractBody').style.overflow = 'hidden';
  document.viewer = new imageViewer(parseInt($("viewerContainer").style.height), parseInt($("viewerContainer").style.width));
}

function showExtractOptions(control) {
  return function(e) {
    if(!e) e = window.event;
    if(e.button == 2) {
      hideOptions();
      control.style.left = (e.clientX - 8) + "px";
      control.style.top = (parseInt(e.clientY) - $('record_form').cumulativeOffset()[1] - control.getDimensions().height) + "px";
      control.toggle();
      window.optionsVisible = true;
    }
    return true;
  }
}
//Shows the translation dialog for the translation with the given id.  isLong
//is used to decide if the dialog should contain a text field or a text area
function translate(translateId, isLong, language) {
  new Ajax.Updater('translationDialog', BASE_URL + '/main_page/translationBox?id=' + translateId + '&isLong=' + isLong + '&language=' + language, 
    {
      asynchronous:true, 
      evalScripts:true, 
      onSuccess:function() {
        $('dialogMask').show();
        $('translationDialogBorder').show();
      }
    }
  );
}	

//Cancles the translation dialog without making any changes
function cancelTranslation() {
  $('translationDialogBorder').hide();
  $('dialogMask').hide();
}

//Takes a translation id and calls ajax to remove that translation from the
//database
function removeTranslation(translateId) {
  new Ajax.Request(BASE_URL + '/main_page/remove_translation?id=' + translateId + '&page=1', { asynchronous:true, evalScripts:true });
}

//Takes in the id of a translation, a language, and a new value for the
//translation, and calls ajax to update the translation to the new value
function submitTranslation(translateId, language, newValue, callback) {
  var url = BASE_URL + '/Main_Page/update_translation?id=' + translateId + '&language=' + language + '&newValue=' + newValue;
  
  new Ajax.Request(url, {
    asynchronous:true, 
    evalScripts:true, 
    onSuccess:function() {
      $('translationDialogBorder').hide();
      $('dialogMask').hide();
    }
  });		
}

//Takes in a list of select options and its selected index and calls ajax to
//display the batch with that option's value
function displayBatch(batchNumber, collectionId) {
  if(batchNumber) {
    var url = BASE_URL + '/manage/display_batch?batchId=' + batchNumber + '&collection_id=' + collectionId;
    new Ajax.Updater('batchManageContainer', url, {
      asynchronous:true, 
      evalScripts:true  
    });
  }
}

//Takes in the url of an image and an image element and displays the image in
//the element
function previewImage(e, url, image) {
  new Ajax.Updater(image, BASE_URL + '/manage/retrieve_image?filename=' + url, {method:'get', asynchronous:true});
  $('imgDiv').show();
}

//Takes in a list of select options and the selected index and calls ajax to
//add the image with the option's value as its filename to the list of images
//for the selected batch
function addImageToBatch(batchId, select) {
  urls = []
  for(k = 0; k < select.options.length; k++) {
    if(select.options[k].selected) {
      urls[urls.length] = select.options[k].value;
    }
  }
  if(urls.length > 0) {
    $('imgDiv').hide();
    new Ajax.Updater("batchManageContainer", BASE_URL + "/manage/add_image_to_batch?batchId=" + batchId + "&filenames=" + urls, {asynchronous:true, evalScripts:true}); return false;
  }
}

//Takes in a select with options that are urls of images not assigned to a
//batch.  Calls AJAX to delete the images from the server
function deleteImage(select, batch) {
  urls = []
  for(k = 0; k < select.options.length; k++) {
    if(select.options[k].selected) {
      urls[urls.length] = select.options[k].value;
    }
  }
  if(urls.length > 0) {
    $('imgDiv').hide();
    new Ajax.Updater("batchManageContainer", BASE_URL + "/manage/delete_unassigned_images?filenames=" + urls + "&batch_id=" + batch, {asynchronous:true, evalScripts:true}); return false;
  }
}

//Takes the id of a batch and a url and calls ajax to remove the image with the
//url from the batch
function removeImageFromBatch(batchId, select) {
  urls = []
  for(k = 0; k < select.options.length; k++) {
    if(select.options[k].selected) {
      urls[urls.length] = select.options[k].value;
    }
  }
  if(urls.length > 0) {
    $('imgDiv').hide();
    new Ajax.Updater('batchManageContainer', BASE_URL + "/manage/remove_image_from_batch?batchId=" + batchId + "&filenames=" + urls, {asynchronous:true, evalScripts:true}); return false;
  }
}

//Takes in a batch id and redirects the user to the extract page for the given
//batch
function extractBatch(batchId) {
  window.location= BASE_URL + '/manage/extract_batch?batchId=' + batchId;
}

//Takes in a batch id and calls ajax to delete the batch and all of its
//associated data
function deleteBatch(batchId) {
    new Ajax.Updater('batchManageContainer', BASE_URL + '/manage/delete_batch?id=' + batchId, {asynchronous:true, evalScripts:true}); return false;
}

//Takes in a collection id and calls ajax to create a new batch in the collection 
function createBatch(collectionId) {
  new Ajax.Updater('batchManageContainer', BASE_URL + '/manage/create_batch?collectionId=' + collectionId, {asynchronous:true, evalScripts:true}); return false;
}

//Takes in the url of an image and a container div and calls ajax to update the
//container and have it display the image
function viewImageToExtract(url, container) {
  $$("div.imageContainer").each(function(item) {
    item.style.border = "4px solid #e4e4ef";
    item.style.padding = "2px 2px 2px 2px";
  });
  container.style.padding = "2px 2px 2px 2px";
  container.style.border = "4px solid #330000";
  if(document.viewer) {
    setViewerSize(parseInt($('recordFormContainer').style.height) + 10);
    document.viewer.redraw();
  }
  new Ajax.Updater('viewerContainer', BASE_URL + "/extract/extractImage?url=" + url, {asynchronous:true, evalScripts:true}); return false;	
}

//Takes a batch id, a record id, and the id of the current record.  Calls ajax
//to first save the current record and then update the page to display the new
//one 
function loadRecord(batchId, recordId, currentRecordId) {
  var nextAction = function() {
    new Ajax.Updater('record_form', BASE_URL + '/extract/show_record?batch_id=' + batchId + '&record_id=' + recordId, {
      asynchronous:true,
      evalScripts:true,
      onSuccess:function() {resizeRecordForm($('recordForm'));}
    }); return false;
  }
  updateBatch(batchId, nextAction);
}

function addRecordToBatch(batchId, tableView, nextBatchGroup) {
  params = 'batch_id=' + batchId + '&table_view=' + tableView;
  options = {
    asynchronous:true,
    evalScripts:true,
    onCreate:function() {beginWait("adding...");},
    onComplete:function() {endWait();}
  }
  var nextAction = function() {
    new Ajax.Updater('record_form', BASE_URL + '/extract/create_record?' + params, options); return false;
  }
  updateBatch(batchId, nextAction);
}

function updateBatch(id, nextAction) {
  if(!nextAction) nextAction = function() {};
  new Ajax.Request(BASE_URL + "/extract/update_batch/" + id, {
    asynchronous:true, 
    evalScripts:true, 
    parameters:Form.serialize($('batch_form')),
    onSuccess:nextAction,
    onCreate:beginWait('saving...'),
    onComplete:function(){
      endWait();
    }
  }); return false;
}

//Checks to see if an authorities list is selected, and if it is it allows the
//user to check the "force" checkbox to make any attributed added a select with
//the authorities list's values as its options.  Otherwise the box is blank and
//deactivated
function enableForceCheckbox(value) {
  if(value == 0) {
    $('forceCheckbox').checked = false;
    $('forceCheckbox').disabled = true;
  }
  else {
    $('forceCheckbox').disabled = false;
  }
}

//Takes in the id of an authorities list, the name of the attriubte, the id of
//the record, if the attribute will be a checkbox, and if will be a dropdown.
//Calls ajax to create the attribute and add it to the record
function addAttributeToRecord(authoritiesListId, attribute, recordId, isCheckbox, isDropdown, batchId) { 
  if(attribute != '' && attribute != null) {
    var nextAction = function() {new Ajax.Updater('record_attributes_table', BASE_URL + '/extract/add_attribute_to_record?id=' + recordId + '&attribute=' + attribute + '&authorities_list_id=' + authoritiesListId + '&isCheckbox=' + isCheckbox + '&isDropdown=' + isDropdown, {asynchronous:true, evalScripts:true});};
    updateBatch(batchId, nextAction);
  }
}
 
//Takes in the id of an attribute record value and a record id and calls ajax
//to remove the attribute from the record
function removeAttributeFromRecord(valueId, recordId, batchId) {
  var nextAction = function() {new Ajax.Updater('record_attributes_table', BASE_URL + '/extract/remove_attribute_from_record?id=' + valueId + "&record_id=" + recordId, {asynchronous:true, evalScripts:true});};
  updateBatch(batchId, nextAction);
}

//Takes in the id of an authorities list, the name of the source attriubte, the
//id of the record, and if the source attribute will be a dropdown.  Calls ajax
//to create the source attribute and add it to the
//record
function addSourceAttributeToRecord(authoritiesListId, attribute, recordId, isDropdown, batchId) { 
  if(attribute != '' && attribute != null) {
    var nextAction = function() {new Ajax.Updater('record_source_attributes_table', BASE_URL + '/extract/add_source_attribute_to_record?id=' + recordId + '&attribute=' + attribute + '&authorities_list_id=' + authoritiesListId + "&isDropdown=" + isDropdown, {asynchronous:true, evalScripts:true});};
    updateBatch(batchId, nextAction);
  }
}

//Takes in the id of an source attribute record value and a record id and calls ajax
//to remove the source attribute from the record
function removeSourceAttributeFromRecord(valueId, recordId, batchId) {
  var nextAction = function() {new Ajax.Updater('record_source_attributes_table', BASE_URL + '/extract/remove_source_attribute_from_record?id=' + recordId + '&value_id=' + valueId, {asynchronous:true, evalScripts:true});};
  updateBatch(batchId, nextAction);
}

//Takes in a record id and calls ajax to delete the record
function deleteRecord(recordId, batchId, gridView) {
  if(confirm("Are you sure?")) {
    nextAction = function() {
      new Ajax.Updater('record_form', BASE_URL + '/extract/destroy_record/?id=' + recordId, { asynchronous:true, evalScripts:true}); return false;
    }
    updateBatch(batchId, nextAction);
  }
}

//Takes in an event name and a record id and adds the event to the record
function addEventToRecord(eventName, recordId, batchId) {
  var nextAction = function() {
    new Ajax.Updater('eventBlock', BASE_URL + '/extract/add_event_to_record?id=' + recordId + '&event_name=' + eventName,  {
      asynchronous:true, 
      evalScripts:true,
      onCreate:
        function() {
          $('eventBlock').innerHTML = '<img src="/images/wait.gif"/>';
        }
      }); return false;
  }
  updateBatch(batchId, nextAction);
}

//Takes in a record id and an event record link id.  Updates the record and and
//calls ajax to that event
function showEvent(eventRecordLinkId, recordId, batchId) {
  var nextAction = function() {
    new Ajax.Updater('eventBlock', BASE_URL + '/extract/show_event?link_id=' + eventRecordLinkId, {
      asynchronous:true, 
      evalScripts:true,
      onCreate:
        function() {
          $('eventBlock').innerHTML = '<img src="/images/wait.gif"/>';
        }
    }); return false;
  };
  updateBatch(batchId, nextAction);
}

//Takes in the id of an authorities list, the type of a place, the
//id of the record, the id of the event record link, and if the place will be
//a dropdown.  Calls ajax to create the place linke and add it to the
//event
function addPlaceToEvent(authoritiesListId, placeType, eventRecordLinkId, recordId, isDropdown, batchId) {
  if(eventRecordLinkId > 0) {
    var nextAction = function() {new Ajax.Updater('eventPlaceLinksBlock', BASE_URL + '/extract/add_place_to_event?place_type=' + placeType + '&event_record_link_id=' + eventRecordLinkId + '&authorities_list_id=' + authoritiesListId + '&isDropdown=' + isDropdown, {asynchronous:true, evalScripts:true});};
    updateBatch(batchId, nextAction);
  }
}

//Takes in an event place link id, an event record link id, and a record id and removes the event place link from the event link
function removePlaceFromEvent(linkId, eventRecordLinkId, recordId, batchId) {
  var nextAction = function() {new Ajax.Updater('eventPlaceLinksBlock', BASE_URL + '/extract/remove_place_from_event?event_place_link_id=' + linkId + '&event_record_link_id=' + eventRecordLinkId, {asynchronous:true, evalScripts:true});};
  updateBatch(batchId, nextAction);
}


//Takes in the id of an authorities list, the name of an attribute, the
//id of the record, the id of the event record link, and if the attribute will be
//a dropdown.  Calls ajax to create the attribute value and add it to the
//event
function addAttributeToEvent(authoritiesListId, attribute, eventLinkId, recordId, isDropdown, batchId) {
  if(eventLinkId > 0 && attribute != '' && attribute != null) {
    var nextAction = function() {new Ajax.Updater('attributeEventValuesBlock', BASE_URL + '/extract/add_attribute_to_event?attribute=' + attribute + '&event_record_link=' + eventLinkId + '&authorities_list_id=' + authoritiesListId + "&isDropdown=" + isDropdown, {asynchronous:true, evalScripts:true});};
    updateBatch(batchId, nextAction);
  }
}

//Takes in a record id, an attribute event value id, an event link id, and a
//record id and calls ajax to delete the attribute event value
function removeAttributeFromEvent(valueId, eventLinkId, batchId) {
  var nextAction = function() {new Ajax.Updater('attributeEventValuesBlock', BASE_URL + '/extract/remove_attribute_from_event?value_id=' + valueId + '&event_record_link=' + eventLinkId, {asynchronous:true, evalScripts:true});};
  updateBatch(batchId, nextAction);
}

//Takes in a record id and calls ajax to remove the currently selected event 
function removeEvent(eventRecordLinkId, batchId) {
  var nextAction = function() {
    new Ajax.Updater('eventBlock', BASE_URL + '/extract/remove_event/' + eventRecordLinkId, {asynchronous:true, 
      evalScripts:true,
      onCreate:
        function() {
          $('eventBlock').innerHTML = '<img src="/images/wait.gif"/>';
        }
    }); return false;
  } 
  updateBatch(batchId, nextAction);
}

//Updates whether or not the relationsihp person select is enabled depending on
//what value is stored in the relationship type select
function relationshipChanged(id) {
  var typeSelect = $('relationship_type_select_' + id);
  var personSelect = $('relationship_person_select_' + id);
  if(typeSelect.selectedIndex == 0) {
    personSelect.innerHTML = "";
    personSelect.selectedIndex = 0;
    personSelect.disabled = 'disabled';
  }
  else {
    new Ajax.Request(BASE_URL + '/extract/fill_relationship_select/' + id, {asynchronous:true, evalScripts:true, onSuccess:function() {
      personSelect.disabled = '';
    }});
  }
}

//Takes in a batch id and a status and calls ajax to update the status of the
//batch (the "extracting" column in the model) 
function setBatchStatus(batchId, state) {
  var nextAction = function() {
    new Ajax.Updater('extractMainBarItems', BASE_URL + '/extract/set_batch_status?id=' + batchId + '&batch_status=' + state, {
      asynchronous:true,
      evalScripts:true,
      onCreate:
      function() {
        $('extractMainBarItems').innerHTML = '<img src="/images/wait.gif"/>';
      }
    });
  };
  updateBatch(batchId, nextAction);
  return false;
}

//Takes in a batch id and a boolean value for verified and calls ajax to update
//the verified field of the batch
function changeBatchVerified(batchId, verified) {
  new Ajax.Updater('extract_menu', BASE_URL + '/extract/change_batch_verified?id=' + batchId + '&verified=' + verified, {
    asynchronous:true,
    evalScripts:true,
    onCreate:
      function() {
        $('extract_menu').innerHTML = '<img src="/images/wait.gif"/>';
      }
  });
  return false;
}

//Takes in the id of a batch and a boolean for if its extracted, and calls ajax
//to set the batch to if its extracted
function changeBatchExtracted(batchId, extracted) {
  new Ajax.Updater('extract_menu', BASE_URL + '/extract/change_batch_extracted?id=' + batchId + '&extracted=' + extracted, {
    asynchronous:true,
    evalScripts:true,
    onCreate:
      function() {
        $('extract_menu').innerHTML = '<img src="/images/wait.gif"/>';
      }
  });
  return false;
}

function saveFlag(id, attribute, note) {
  if(id > 0) new Ajax.Request(BASE_URL + '/extract/set_flag?id=' + id + "&attribute=" + attribute + '&note=' + note, {asynchronous:true, evalScripts:true});
  if(note != "") {
    if(attribute == "EventRecordLink") {
      $("date_prefix_" + id).style.backgroundColor = "yellow";
      $("month_select_" + id).style.backgroundColor = "yellow";
      $("day_select_" + id).style.backgroundColor = "yellow";
      $("year_select_" + id).style.backgroundColor = "yellow";
    }
    else if(attribute == "Person") {
      $("relationship_type_select_" + id).style.backgroundColor = "yellow";
      $("relationship_person_select_" + id).style.backgroundColor = "yellow";
      $("is_migrant_" + id).style.backgroundColor = "yellow";
    }
    else if(attribute == "Record") {
      $("first_name_" + id).style.backgroundColor = "yellow";
      $("last_name_" + id).style.backgroundColor = "yellow";
      $("gender_" + id).style.backgroundColor = "yellow";
    }
    else if($(convertFromCamelCase(attribute) + "_" + id).type == "checkbox") {
      $(convertFromCamelCase(attribute) + "_" + id + "_cell").style.backgroundColor = "yellow";
    }
    else {
      $(convertFromCamelCase(attribute) + "_" + id).style.backgroundColor = "yellow";
    }
  }
  hideFlag();
}

function deleteFlag(id, attribute) {
  if(id > 0) new Ajax.Request(BASE_URL + '/extract/delete_flag?id=' + id + '&attribute=' + attribute, {asynchronous:true, evalScripts:true});
  if(attribute == "EventRecordLink") {
    $("date_prefix_" + id).style.backgroundColor = "#d4d4df";
    $("month_select_" + id).style.backgroundColor = "#d4d4df";
    $("day_select_" + id).style.backgroundColor = "#d4d4df";
    $("year_select_" + id).style.backgroundColor = "#d4d4df";
  }
  else if(attribute == "Person") {
    $("relationship_type_select_" + id).style.backgroundColor = "#d4d4df";
    $("relationship_person_select_" + id).style.backgroundColor = "#d4d4df";
    $("is_migrant_" + id).style.backgroundColor = "#d4d4df";
  }
  else if(attribute == "Record") {
    $("first_name_" + id).style.backgroundColor = "#d4d4df";
    $("last_name_" + id).style.backgroundColor = "#d4d4df";
    $("gender_" + id).style.backgroundColor = "#d4d4df";
  }
  else if($(convertFromCamelCase(attribute) + "_" + id).type == "checkbox") {
    $(convertFromCamelCase(attribute) + "_" + id + "_cell").style.backgroundColor = "white";
  }
  else {
    $(convertFromCamelCase(attribute) + "_" + id).style.backgroundColor = "white";
    $(convertFromCamelCase(attribute) + "_" + id + "_cell").style.backgroundColor = "white";
  }
  hideFlag();
}

function hideFlag() {
    $('newFlagPanel').hide();
    $('dialogMask').hide();
}

//Takes in the id of a record and the name of an attribute, and uses ajax to
//Populate and show the flag panel
function showFlagPanel(attribute, id) {
  new Ajax.Updater('newFlagPanelContent', BASE_URL + '/extract/show_flag?id=' + id + "&attribute=" + attribute, {asynchronous:true, evalScripts:true});
  $("newFlagPanel").show();
  $("newFlagPanel").style.display = "block";
}

//Takes in a batch number, the id of a collection, and a user id and calls ajax
//to assign the batch to the user
function setBatchAssignment(batchNumber, collectionId, userId) {
  new Ajax.Updater('batchManageContainer', BASE_URL + '/manage/assign_batch?id=' + batchNumber + '&user_id=' + userId + '&collection_id=' + collectionId, {asynchronous:true, evalScripts:true});
  return false;
}

//Takes in the column of the translations table to use (a language) and the
//name of the key and calls ajax that updates all instances of that translation
//on the page
function showTranslationValue(column, value) {
  new Ajax.Request(BASE_URL + '/main_page/show_translation_value?column=' + column + '&value=' + value, {asynchronous:true, evalScripts:true});
}

//Takes in the name of a source attribute, its value, and the id of collection
//and calls ajax to add that source information to the collection
function addCollectionSource(attribute, value, collectionId) {
  if(attribute != '' && value != '') {
    new Ajax.Request(BASE_URL + '/manage/add_collection_source?id=' + collectionId + '&attribute=' + attribute + '&value=' + value, {asynchronous:true, evalScripts:true});
  }
}

//Takes in the id of a source attribute collection value and calls ajax to delete it
function removeCollectionSource(id) {
  new Ajax.Request(BASE_URL + '/manage/remove_collection_source?id=' + id, {asynchronous:true, evalScripts:true});
}

//Updates the options for the date in the extraction form to show the correct
//number of days in a month
function updateDateOptions(id) {
  idOption = "&event_record_link_id=" + id;
  new Ajax.Request(BASE_URL + '/extract/update_date_options?month=' + selectedValue($("month_select_" + id)) + "&day=" + $('day_select_' + id).options[$('day_select_' + id).selectedIndex].value + idOption, {asynchronous:true, evalScripts:true}); return false;
}

//Takes in a translation select and changes its id to match its translation value 
function changeTranslationSelectId(select) {
  selectedValue = select.options[select.selectedIndex].id.replace("_option", "");
  new Ajax.Request(BASE_URL + '/main_page/change_translation_select_id?id=' + select.id + '&translation_id=' + selectedValue, 
  {
    asynchronous:true, 
    evalScripts:true,
    onComplete:function() {
      select.id = new_id;
    }
  }); return false;
}

//Toggles if details in the error recovery page are visible or not 
function changeErrorContentVisible() {
  if($('errorContent').style.visibility == 'visible')
    $('errorContent').style.visibility = 'hidden';
  else 
    $('errorContent').style.visibility = 'visible';
}

//Takes in the label to show, the html element to update, the authorities list
//of the field (or 'none' if there is none) and an extra name value pair as an
//array and displays a div with a larger text area so that users can see all
//the text they are editing
function showFieldEditor(label, field, authoritiesList, valuePair) {
  alert(field);
  if(label.innerHTML) 
    $('fieldEditorHeading').innerHTML = label.innerHTML
  else
    $('fieldEditorHeading').innerHTML = label
  $('fieldEditorContent').value = field.value;
  $('fieldEditorAuthoritiesList').innerHTML = authoritiesList;
  $('fieldEditor').show();
  $('setFieldButton').onclick = function() {
    $(field.id).value = $('fieldEditorContent').value;
    $('fieldEditor').hide();
  }
}

//Takes in a form element and an authorities list id and adds an auto completer
//to the element, gettings its values from the given authorities lit
function addAutoComplete(element, authoritiesListId) {
  new Ajax.Autocompleter(element, "autoComplete", BASE_URL + "/extract/auto_complete", {
    paramName:'value',
    minChars:0,
    parameters:"authorities_list_id=" + authoritiesListId
  });
}

//Takes in the name of an authorities list and a letter and adds a new
//authorities list with the given name
function addAuthoritiesList(name, letter) {
  if(name && name != '') new Ajax.Updater('authoritiesListDiv', BASE_URL + "/manage/add_authorities_list?name=" + name + "&letter=" + letter, {asynchronous:true, evalScripts:true}); return false;
  $('new_authorities_list_field').value = "";
}

//Takes in an array of values and a letter and calls ajax to add the values to
//the currently selected authorities list
function addValuesToAuthoritiesList(values, letter) {
  new Ajax.Updater('authoritiesListDiv', BASE_URL + "/manage/add_values_to_authorities_list?values=" + values.split('\n') + "&list_id=" + $("authorities_lists").options[$("authorities_lists").selectedIndex].value + "&letter=" + letter, {asynchronous:true, evalScripts:true}); return false;

}

//Takes in the id of an authorities list and a letter and calls ajax to show
//its values
function loadAuthoritiesListValues(id, letter) {
  new Ajax.Updater('authoritiesListDiv', BASE_URL + "/manage/load_authorities_list_values/" + id + "?letter=" + letter, {asynchronous:true, evalScripts:true}); return false;
}

//Takes in a select element and a letter and calls ajax to remove the selected
//values in the select from the currently selected authorities list
function removeValuesFromAuthoritiesList(select, letter) {
  values = [];
  for(var k = 0; k < select.options.length; k++) {
    if(select.options[k].selected) values[values.length] = select.options[k].value;
  } 
  new Ajax.Updater('authoritiesListDiv', BASE_URL + "/manage/remove_values_from_authorities_list?values=" + values + "&list_id=" + $("authorities_lists").options[$("authorities_lists").selectedIndex].value + "&letter=" + letter, {asynchronous:true, evalScripts:true}); return false;
}

//Takes in the id of an authorities list and a letter and calls ajax to delete
//the list
function deleteAuthoritiesList(id, letter) {
  if(id) {
    new Ajax.Updater('authoritiesListDiv', BASE_URL + "/manage/delete_authorities_list/" + id + "?letter=" + letter, {asynchronous:true, evalScripts:true}); return false;
  }
}

//Takes in a select and returns its selected value 
function selectedValue(select) {
  if(!select) {
    return null;
  }
  if(select.selectedIndex < 0) {
    return null;
  }
  return select.options[select.selectedIndex].value;
}

//Resizes the given record form
function resizeRecordForm(form, e, offset) 
{
  if(document.documentElement.clientHeight - e.clientY < 155) return false;
  if(offset) {
    form.element.style.height = (document.documentElement.clientHeight - e.clientY - offset) + "px";
  }
  else {
    form.element.style.height = (document.documentElement.clientHeight - e.clientY) + "px";
  }
  resizeRecordFormDivs(form.element);
  if(document.viewer) {
    setViewerSize(parseInt(form.element.style.height) + 10);
    document.viewer.redraw();
  }
  $('imageListContainer').style.height = (document.documentElement.clientHeight - parseInt(form.element.style.height) - 50) + "px";
}

//Resize the contents of the record form when the user drags its handle
function resizeRecordFormDivs(form, offset)
{
  if(!offset) offset = 0;
  if(!form.style.height) return false;
  $$(".record_form").each(function (element) {element.style.height = (parseInt(form.style.height) - (50 + offset)) + "px";});
  if($('recordsDiv')) $('recordsDiv').style.height = (parseInt(form.style.height)) + "px";
}

//If the to of the record form is dragged too far down or up, put it back in a reasonable place
function relocateRecordForm(form, e, offset) 
{
  if(!form.element.style.height) return false;
  if(offset) resetHeight = 160 + offset;
  else resetHeight = 160;
  if(document.documentElement.clientHeight - e.clientY < resetHeight || e.clientY < 0) {
    
    form.element.style.height = resetHeight + "px";
    $$(".record_form").each(function (element) {element.style.height = (parseInt(form.element.style.height) - 50) + "px";});
    if($('recordsDiv')) $('recordsDiv').style.height = (parseInt(form.element.style.height)) + "px";
    form.element.style.top = "100%";
    form.element.style.marginTop = "-160px"
  }
}

//Takes in the id of a batch group and a batch id and calls ajax to delete the batch group
function deleteTreeItem(id, batchId) {
  new Ajax.Updater("batchGroupTree", BASE_URL + "/manage/delete_batch_group?id=" + id + "&batch_id=" + batchId, {asynchronous:true, evalScripts:true});
  return false;
}

//Takes in the id of a batch group and the id of a batch and adds a batch group
//to the given batch group
function addBatchGroup(id, batchId) {
  var name = $('group_name').value;
  var value = $('group_value').value
  if(name != '' && value != '') {
    new Ajax.Updater("batchGroupTree", BASE_URL + "/manage/add_batch_group/" + id + "?name=" + name + "&value=" + value + "&batch_id=" + batchId, {asynchronous:true, evalScripts:true});
  }
  return false;
}

//Takes in the id of collection and  a batch id and calls ajax to add a root
//batch group to the collection
function addRootBatchGroup(id, batchId) {
  var name = $('group_name').value;
  var value = $('group_value').value
  if(name != '' && value != '') {
    new Ajax.Updater("batchGroupTree", BASE_URL + "/manage/add_root_batch_group/" + id + "?name=" + name + "&value=" + value + "&batch_id=" + batchId, {asynchronous:true, evalScripts:true});
  }
  return false;
}

//Takes in the id of a batch group and a batch id and calls ajax to add the
//batch to the batch group
function addBatchToGroup(id, batchId) {
  new Ajax.Updater("batchGroupTree", BASE_URL + "/manage/add_batch_to_group?id=" + id + "&batch_id=" + batchId, {asynchronous:true, evalScripts:true});
  return false;
}

//Takes in a function and the element the event is for and returns an event
//handler that only calls the function if the event is not a right mouse button
//click and the target is the element itself and not one of its children.  Used
//to close context menus.
function getNotRightButtonEventHandler(func, cont) {
  return function(e) {
    if(!e) e = window.event;
    if(e.button != null) {
      if(e.button != 2) {
        /*if(window.optionsVisible) {
          if(e.srcElement) {
            if(e.srcElement.onclick) e.srcElement.onclick();
            if(e.srcElement.parentNode && e.srcElement.parentNode.onclick) e.srcElement.parentNode.onclick();
          }
          else if(e.target) {
            if(e.target.onclick) e.target.onclick();
            if(e.target.parentNode && e.target.parentNode.onclick) e.target.parentNode.onclick();
          }
        }*/
        func();
      }
    }
  }
}

//Hides the options that appear beneath fields in the extraction form
function hideOptions() {
  window.optionsVisible = false;
  $$('.recordFormOptions').each(function(item) {
    item.hide();
  });
  $$('.recordsFormOptions').each(function(item) {
    item.hide();
  });
  return true;
}

//Takes in a letter and the id of an authorities list and calls ajax to display
//the values in that list starting with the letter
function setAuthoritiesListDisplayLetter(letter, listId) {
  new Ajax.Updater("authoritiesListDiv", BASE_URL + "/manage/set_authorities_list_display_letter?letter=" + letter + "&list_id=" + listId, {asynchronous:true, evalScripts:true}); return false;
}

//This function takes in the name of a section and calls ajax to render the
//users for that section in a partial
function loadSection(section) {
  new Ajax.Updater("sectionContainer", BASE_URL + "/users/refresh_list?section_id=" + section, {asynchronous:true, evalScripts:true}); return false;
}

function convertToCamelCase(word) {
  camelCase = "";
  nextCap = false;
  for(k = 0; k < word.length; k++) {
    if(word[k] != "_" && nextCap == true) {
      camelCase += toupper(word[k]); 
      nextCap = false;
    }
    else if(word[k] != "_" && nextCap == false) {
      camelCase += word[k];
    }
    else {
      nextCap = true;
    }
  }
  return camelCase;
}

function convertFromCamelCase(word) {
  snakeCase = "";
  if(word[0]) {
    for(k = 0; k < word.length; k++) {
      if(word[k] >= "A" && word[k] <= "Z"){
        if (k > 0) snakeCase += "_" 
        snakeCase += word[k].toLowerCase();
      }
      else{
        snakeCase += word[k];
      }
    }
  }
  else {
    for(k = 0; k < word.length; k++) {
      if(word.substring(k, k + 1) >= "A" && word.substring(k, k + 1) <= "Z"){
        if (k > 0) snakeCase += "_" 
        snakeCase += word.substring(k, k + 1).toLowerCase();
      }
      else{
        snakeCase += word.substring(k, k + 1);
      }
    }
  }
  return snakeCase;
}

function setTableView(grid, batchId) {
  $('record-view-span').className == 'selected-span' ? $('record-view-span').className = 'deselected-span' : $('record-view-span').className = 'selected-span';
  $('table-view-span').className == 'selected-span' ? $('table-view-span').className = 'deselected-span' : $('table-view-span').className = 'selected-span';
  beginWait("Loading...");
  nextAction = new Ajax.Updater('record_form', BASE_URL + '/extract/set_table_view?batch=' + batchId + '&grid=' + grid, {
    asynchronous:true, 
    evalScripts:true, 
    onComplete:function(){
      endWait();
    }});
  updateBatch(batchId, nextAction);
}

function closeBatch(formContents, batchId) {
  $('close_batch').id = "true";
  new Ajax.Request(BASE_URL + "/extract/close_batch?id=" + batchId, {asynchronous:true, evalScripts:true, parameters:formContents});
}

function toggleField(field, anchor) {
  if($(field).value == '0') {
    $(field).value = '1';
    anchor.innerHTML = "<img src='" + BASE_URL + "/images/invisible.png'>";
  }
  else if($(field).value == '1') {
    $(field).value = '0';
    anchor.innerHTML = "<img src='" + BASE_URL + "/images/visible.png'>";
  }
  else if($(field).value == 'true' || $(field).value == true) {
    $(field).value = 'false';
    anchor.innerHTML = "<img src='" + BASE_URL + "/images/visible.png'>";
  }
  else if($(field).value == 'false' || $(field).value == false) {
    $(field).value = 'true';
    anchor.innerHTML = "<img src='" + BASE_URL + "/images/invisible.png'>";
  }
}

var waitCount = 0;
function beginWait(message) {
  $("loadingIcon").show();
  if(message) $("loadingIcon").innerHTML=message;
  else $("loadingIcon").innerHTML="Please wait...";
  $("dialogMask").show();
  waitCount++;
}

function endWait() {
  waitCount --;
  if(waitCount == 0) {
    $("loadingIcon").hide();
    $("dialogMask").hide();
  }
}

function copySpecialCharacter(el) {
  $('fieldEditorContent').value += el.innerHTML;
  el.className = 'clicked';
  el.onmouseout = function() {
    el.className = '';
  }
}

function addBrackets(el) {
  if($('fieldEditorContent').value[0] != '[') $('fieldEditorContent').value = '[' + $('fieldEditorContent').value + ']';
  el.className = 'clicked';
  el.onmouseout = function() {
    el.className = '';
  }
}

function toggleUpperCase(button) {
  return function() {
    $$("#specialCharacterTable td").each(function(obj) {
      obj.innerHTML = obj.innerHTML.toUpperCase();
    });
    button.innerHTML = "<img src='" + BASE_URL + "/images/down.png'>";
    button.onmousedown = toggleLowerCase(button);
  }
}

function toggleLowerCase(button) {
  return function() {
    $$("#specialCharacterTable td").each(function(obj) { 
      obj.innerHTML = obj.innerHTML.toLowerCase(); 
    });
    button.innerHTML = "<img src='" + BASE_URL + "/images/up.png'>";
    button.onmousedown = toggleUpperCase(button);
  }
}

function widenField(field) {
  temp = field.value;
  if(temp.length <= 20 && temp.length >= 5) field.size = temp.length;
  else if (temp.length > 20) field.size = 20;
  else field.size = 5;
  field.value = temp;
}
