  var gSectionCurrentlyEditing;
  function loadProfileSection( userId, type )
  {
    var params = 'type=' + type + '&userId=' + userId;
    ajaxUpdate( getDivName( type ),
                '/viewProfileSection.dobbb',
                params );
  }
  function editProfileSection( type )
  {
    if( gSectionCurrentlyEditing )
    {
      alert( 'You already have another section of your profile open for edit.  Please close that section before editing this one' );
    }
    else
    {
      gSectionCurrentlyEditing = type;
      var params = 'type=' + type;
      ajaxUpdate( getDivName( type ),
                  '/editProfileSection.dobbb',
                  params,
                  onEditFormLoadSuccess,
                  failureToLoadEditDiv,
                  'get',
                  onEditFormLoadCompletion );
    }
  }
  function onEditFormLoadSuccess()
  {
    var editingDiv = $( getDivName( gSectionCurrentlyEditing ) );
    editingDiv.className = 'activeEdit infoContainer ' + getPositionClass( gSectionCurrentlyEditing ) + ' clearfix';
  }
  function onEditFormLoadCompletion()
  {
    if( gSectionCurrentlyEditing == 'p' )
    {
      //set the initial disabled-ness of the "state" picker
      changeCountry( 'profile.personalInformation.hometown' );
      changeCountry( 'profile.personalInformation.current' );
      var dayValue = $( 'hiddenDayValueField' ).value;
      populateDatePicker( 'profile.personalInformation.birthdate', 'yearPicker', 'monthPicker', 'dayPicker', dayValue );
      initializeLightbox(); //for lightbox
    }
    else if( gSectionCurrentlyEditing == 'e' )
    {
      var numProfileInstitutions = $( 'profileInstIndex' ).value;
      //alert('checking country data for ' + numProfileInstitutions + ' institutions ' );
      for( var c = 0; c < numProfileInstitutions; c++ )
      {
        changeCountry( 'profile.educationInformation.profileInstitutions[' + c + '].inst' );
      }
    }
  }
  function failureToLoadEditDiv( request )
  {
    //switch the div back to inactive
    deActivateDiv( gSectionCurrentlyEditing );
    //show the inline receipt for the 500 we got.
    defaultOnFailure( request );
  }
  function getPositionClass( type )
  {
    if( type == 'p' )
    {
      return 'leader';
    }
    return 'secondi';
  }
  function getDivName( type )
  {
    return type + 'ProfileDiv';
  }
  function getFormName( type )
  {
    return type + 'ProfileSectionForm';
  }
  //used for when we change the country in any locationPicker.tag
  function changeCountry( prefix )
  {
    var countryPicker = $( prefix + 'Country' );
    var countryPickerVal = countryPicker.value;
    var statePicker = $( prefix + 'State' );
    if( valIsUSOrCanada( countryPickerVal ) )
    {
      statePicker.disabled = false;
    }
    else
    {
      statePicker.disabled = true;
      statePicker.selectedIndex = 0;
    }
    return statePicker;
  }
  function valIsUSOrCanada( countryPickerVal )
  {
    return countryPickerVal == 'United States' || countryPickerVal == 'Canada' || countryPickerVal == '';
  }
  function validateInterestsInfo( type )
  {
    return true;
  }
  function validateContactInfo( type )
  {
    return true;
  }
  function validatePersonalInfo( type )
  {
    return true;
  }
  function validateWorkInfo( type )
  {
    return true;
  }
  function validateEducationInfo( type )
  {
    return true;
  }
  function validateNetworkPrivacy( type )
  {
    return true;
  }
  function saveSection( type, validationFunction )
  {
    //ensure that the validation function succeeded
    if( validationFunction( type ) )
    {
      var theForm = $( getFormName( type ) );
      var params = marshallParams( theForm );
      ajaxUpdate( getDivName( type ),
                  '/editProfileSection.dobbb',
                  params,
                  onSaveSuccess,
                  onSaveFailure,
                  'post' );
    }
  }
  function onSaveSuccess()
  {
    reportAjaxSuccessInline( "Profile section successfully saved" );
    deActivateDiv( gSectionCurrentlyEditing );
  }
  function onSaveFailure( request )
  {
    defaultOnFailure( request, 'edit_profile_receipt_' + gSectionCurrentlyEditing );
  }
  function cancelSection( type )
  {
    deActivateDiv( type );
    loadProfileSection( '', type );
  }
  function deActivateDiv( type )
  {
    var editingDiv = $( getDivName( type ) );
    editingDiv.className = 'infoContainer ' + getPositionClass( type ) + ' clearfix';
    gSectionCurrentlyEditing = '';
  }
  function sendUploadImage( form )
  {
    var input = $( 'photoUploadElement' );
    if( !input.value )
    {
      alert( 'You must select an image to upload first.' );
      return false;
    }
    return AIM.submit( form, { 'onStart' : startUploadImage, 'onComplete' : doneUploadingImage } )
  }
  function startUploadImage()
  {
    //nothing to do here yet
  }
  function doneUploadingImage( returnedHtml )
  {
    //alert( 'results:' + returnedHtml );
    var results = parseReceiptJSON( returnedHtml );
    if( !results )
    {
      reportLightboxError( 'Unexpected error when uploading image.  Image might not have successfully uploaded.' );
      return;
    }
    var status = results['inlineReceiptStatus'];
    var message = results['inlineReceiptMessage'];
    var lightboxErr = $( 'lightboxError' );
    if( status == 'SUCCESS' )
    {
      hideLightbox();
      reportAjaxSuccessInline( message );
      var image = $( 'photoInEditForm' );
      var userId = $( 'profileUserId').value;
      image.src = '/profileImage.dobbb?userId=' + userId + '&pictureViewMode=Preview&' + makeRandomString();
      //tell the form that we have a new image to upload
      $( 'photoStatus' ).value = 'ADD';
      //show the "remove photo button"
      $( 'removePhotoButtonLink' ).style.display = 'block';
    }
    else
    {
      reportLightboxError( message );
    }
  }
  function reportLightboxError( message )
  {
    alert( message );
  }
  function removeImage()
  {
    //point the image at the "no picture" image
    $( 'photoInEditForm' ).src = '/images/user_no_picture_Profile.png';
    //tell the form that we have to remove whatever image was previously uploaded
    $( 'photoStatus' ).value = 'REMOVE';
    $( 'removePhotoButtonLink' ).style.display = 'none';
  }
  //these three alias functions are here in case we need to customize how they remove stuff in the future
  function removeEmailAddress( rowId )
  {
    removeMultiAdderRow( rowId );
  }
  function removeIM( rowId )
  {
    removeMultiAdderRow( rowId );
  }
  function removeExternalLink( rowId )
  {
    removeMultiAdderRow( rowId );
  }
  function removeInst( rowId )
  {
    removeEntireDivFromMultiAdder( rowId )
  }
  function removeWork( rowId )
  {
    removeEntireDivFromMultiAdder( rowId )
  }
  //this removal method is different in that it hides the entire div as well as disabling the fields
  function removeEntireDivFromMultiAdder( rowId )
  {
    var rowElem = $( rowId );
    rowElem.style.display = 'none';
    //disable the hidden input that passes along this row's value(s)
    disableAllChildInputs( rowElem );
  }
  //generic row remover that
  //1) disables all input fields
  //2) hides all of the images (remove buttons)
  //3) strikes through the span fields
  function removeMultiAdderRow( rowId )
  {
    var rowElem = $( rowId );
    var buttons = rowElem.getElementsByTagName( "IMG" );
    for( var c = 0; c < buttons.length; c++ )
    {
      buttons[c].style.display = 'none';
    }
    var displaySpans = rowElem.getElementsByTagName( "SPAN" );
    for( var c = 0; c < displaySpans.length; c++ )
    {
      displaySpans[c].style.textDecoration = 'line-through';
    }
    //disable the hidden input that passes along this row's value(s)
    disableAllChildInputs( rowElem );
  }
  function afterUniversityChosen( inputElement, selectedItemElement )
  {
    //0) trim the value in the input box (our trickery with hidden fields means extra spaces after the institution name
    inputElement.value = trim( inputElement.value );
    //1) get the values from the selected item.  city/state/country are in hidden inputs inside the li element
    var elementId = selectedItemElement.id;
    var cityValue = $( 'uCity' + elementId ).value;
    var stateValue = $( 'uState' + elementId ).value;
    var countryValue = $( 'uCountry' + elementId ).value;
    //2) figure out what row number we're looking at by parsing out the number value from the input element's id
    var targetId = inputElement.id;
    var regex = /(\d+)/;
    var result = targetId.match( regex );
    var rownum = result[0];
    //3) now go get the city/state/country elements for this row, and set the new values on them
    var base = 'profile.educationInformation.profileInstitutions[' + rownum + '].university.university';
    var cityElem = $( base + 'City' );
    cityElem.value = cityValue;
    var countryPickerElem = $( base + 'Country' );
    setSelectedValue( countryPickerElem, countryValue );
    var statePickerElem = changeCountry( base );
    if( !statePickerElem.disabled )
    {
      setSelectedValue( statePickerElem, stateValue );
    }
  }
  function setSelectedValue( selectBox, newValue )
  {
    var found = false;
    for( var c = 0; !found && c < selectBox.options.length; c++ )
    {
      var thisOption = selectBox.options[c];
      if( thisOption.value == newValue )
      {
        selectBox.selectedIndex = c;
        found = true;
      }
    }
  }
  function attachOnChangeToCountry( prefix )
  {
    var countryField = $( prefix + 'Country' );
    countryField.onchange = function(){ changeCountry(prefix) };
  }
  function addNewInstRow()
  {
    var newBlockNum = addNewRowFromTemplate( 'instRow[#]', 'institutionContainerDiv', 'lastInstRow', 'profileInstIndex' )
    evalRunThisBlocks( newBlockNum ); //enable the autocomplete on inst name
    //cloneNode apparently doesn't activate onchange events in IE, so we do it manually after the cloning
    attachOnChangeToCountry( 'profile.educationInformation.profileInstitutions[' + newBlockNum + '].university.university' );
  }
  function addNewWorkplaceRow()
  {
    var newBlockNum = addNewRowFromTemplate( 'workplaceRow[#]', 'workplaceContainerDiv', 'lastWorkplaceRow', 'workplaceIndex' )
    //cloneNode apparently doesn't activate onchange events in IE, so we do it manually after the cloning
    attachOnChangeToCountry( 'profile.workInformation.workplaces[' + newBlockNum + '].work' );
  }
  function addNewEmailRow()
  {
    addNewRowFromTemplate( 'emailRow[#]', 'emailTable', 'lastEmailRow', 'emailIndex' )
  }
  function addNewIMRow()
  {
    addNewRowFromTemplate( 'imRow[#]', 'imTable', 'lastIMRow', 'imIndex' )
  }
  function addNewExtLinkRow()
  {
    addNewRowFromTemplate( 'extLinkRow[#]', 'extLinkTable', 'lastExtLinkRow', 'extLinkIndex' )
  }
  function addNewRowFromTemplate( templateId, tableId, lastRowId, indexId )
  {
    var template = $( templateId );
    var copyToInsert = template.cloneNode( true );
    var parent = $( tableId );
    var lastRow = $( lastRowId );
    var indexElement = $( indexId );
    var newNumber = indexElement.value;
    //if it's a table, go insert under the tbody.
    if( parent.tagName == 'TABLE' )
    {
      for( var c = 0; c < parent.childNodes.length; c++ )
      {
        var childNode = parent.childNodes[c];
        //have to iterate because IE/ff handle tbody differently.
        //find the tbody element and insert our new row.
        if( childNode.tagName == 'TBODY' )
        {
          insertAndIncrement( copyToInsert, newNumber, indexElement, childNode, lastRow );
        }
      }
    }
    //otherwise it's a div, insert normally
    else
    {
      insertAndIncrement( copyToInsert, newNumber, indexElement, parent, lastRow );
    }
    return newNumber;
  }
  function insertAndIncrement( copyToInsert, newNumber, indexElement, newParent, lastRow )
  {
    copyToInsert.style.display = '';
    enableAllChildInputs( copyToInsert );
    replacePlaceholders( copyToInsert, newNumber );
    newNumber++;
    indexElement.value = newNumber;
    newParent.insertBefore( copyToInsert, lastRow );
  }
  function disableAllChildInputs( node )
  {
    toggleAllChildInputsEnabledStatus( node, true );
  }
  function enableAllChildInputs( node )
  {
    toggleAllChildInputsEnabledStatus( node, false );
  }
  function toggleAllChildInputsEnabledStatus( node, newstatus )
  {
    for( var c = 0; c < node.childNodes.length; c++ )
    {
      var currChild = node.childNodes[c];
      if( currChild.tagName == 'INPUT' || currChild.tagName == 'SELECT' )
      {
        currChild.disabled = newstatus;
      }
      else
      {
        toggleAllChildInputsEnabledStatus( currChild, newstatus );
      }
    }
  }
  function doReportProfile( userName )
  {
    ajaxUpdate('report_profile_form', '/reportProfile.dobbb?user_name=' + userName, '', onReportProfileLoadSuccess, onReportProfileLoadFailure, 'get');
  }
  function onReportProfileLoadSuccess()
  {
    showBox('report_profile_form', 'repProBut', 'true');
  }
  function onReportProfileLoadFailure( request )
  {
    setErrorInlineReceipt(getStatusText(request))
  }
  reportProfile = function()
  {
    var params = marshallParams( $( 'reportProfileForm' ) );
    toggleReportProfileActionButton( true );
    ajaxRequest( '/reportProfile.dobbb',
                 params,
                 onReportProfileSuccess,
                 onReportProfileFailure );
    return true;
  }
  toggleReportProfileActionButton = function( newDisabled )
  {
    var button = $( 'reportProfileSubmit' )
    if( button )
    {
      button.disabled = newDisabled;
    }
  }
  onReportProfileFailure = function( request )
  {
    alert( getStatusText( request ) );
    toggleReportProfileActionButton( false );
  }
  onReportProfileSuccess = function( request )
  {
    toggleReportProfileActionButton( false );
    var result;
    try
    {
      result = eval( request.responseText );
      reportAjaxSuccessInline( result.message );
      $( 'reportProfileForm' ).reset();
    }
    catch( e )
    {
      setSessionTimeoutReceipt();
    }
    hideContextMenu();
  }