/***********************************************************************

Purpose: presents a survey that unfolds questions gradually concerning
documents that the user has read and how the user accessed
them. Launched from the accompanying index.html page.

Conventions:

jQuery requires that a callback to an element be added after the
element is added. (That is, old callbacks are not automatically
applied to newly added elements, even if the elements match the
conditions for the callback.)

The program uses DOM as little as possible. Instead of navigating up
and down the DOM stack, the program assigns unique identifiers to the
elements it has to manipulate. These identifiers are names, classes,
id's, or some combination.

Inputs are uniquely identified by id's or classes where possible;
names just have unique numbers. But extra strings are added to make
unique names if the input fields have to be passed to the server
program, or if the class field must be used for some other purpose (as
in <div> elements that use class names for layout).

The program uses a number of global variables, defined near the end,
to store state information used by multiple functions. Most are arrays
that grow dynamically as new elements are added.

***********************************************************************/

/***********************************************************************

Convenience functions.

***********************************************************************/

/* Change a decimal number from 0 to 15 to the corresponding
   hexadecimal digit. */

function hex_char(n) {
  if ( n>= 0 && n <= 9 )
  {
    return(parseInt(n,"10"));
  }
  if (n == 10) { return('A'); }
  if (n == 11) { return('B'); }
  if (n == 12) { return('C'); }
  if (n == 13) { return('D'); }
  if (n == 14) { return('E'); }
  if (n == 15) { return('F'); }
  return(parseInt(0,"10"));
}

/* Change a decimal number from 0 to 255 to the corresponding
   two-character hexadecimal number. */

function hex_word(n) {
     return( hex_char(parseInt(n / 16,"10")) +
	     hex_char(parseInt(n % 16,"10")));
}

/* Sets color for a document block. Call this whenever a block changes. */

function set_background(block, doc_num) {

  block.css("background", "#" +
			   hex_word(doc_background[doc_num][0]) +
			   hex_word(doc_background[doc_num][1]) +
			   hex_word(doc_background[doc_num][2]));
}

/* Sets color for the small block for next document. Call this whenever a block changes. */

function set_next_background(block) {

  block.css("background", "#" +
			   hex_word(doc_background_red) +
			   hex_word(doc_background_green) +
			   hex_word(doc_background_blue));
}

/* Finish initialization for each document block, setting global
   variables. Call this when creating new doc bock.*/

function update_doc_block_info(doc_num) {

  /* Save this background color. */

  doc_background[doc_num] = [];
  doc_background[doc_num][0] = doc_background_red;
  doc_background[doc_num][1] = doc_background_green;
  doc_background[doc_num][2] = doc_background_blue;

  /* Make next document's background darker, but not so dark that the
     black text can't be read. */

  if ( doc_background_red >= maximum_darkness &&
       doc_background_green >= maximum_darkness &&
       doc_background_blue >= maximum_darkness )
    {
      doc_background_red -= color_difference;
      doc_background_green -= color_difference;
      doc_background_blue -= color_difference;
    }

  /* Initialize flags for this document. */

  print_clicked[doc_num] = false;
  online_clicked[doc_num] = false;

}

/* Save colors for this search string and update them for next search string.*/

function update_searchstring_info(num) {

  /* Save this searchstring color. */

  searchstring_color[num] = [];
  searchstring_color[num][0] = searchstring_color_red;
  searchstring_color[num][1] = searchstring_color_green;
  searchstring_color[num][2] = searchstring_color_blue;

  /* Set up next color. */
  if ( searchstring_color_red >= maximum_darkness &&
       searchstring_color_green >= maximum_darkness &&
       searchstring_color_blue >= maximum_darkness )
  {
    searchstring_color_red -= color_difference;
    searchstring_color_green -= color_difference;
    searchstring_color_blue -= color_difference;
  }
}

/* Creates doc block. */

function build_block_information (doc_num, doc_name) {

    doc_next=parseInt(doc_num,"10")+1;
    block_information = $(block_information_1 + doc_num +
		block_information_2 + doc_num +
		block_information_3 + doc_name +
		block_information_4 + doc_num +
		block_information_5 + doc_num +
		block_information_6 + doc_background[doc_num][0] +
		block_information_7 + doc_num +
		block_information_8 + doc_background[doc_num][1] +
		block_information_9 + doc_num +
		block_information_10 + doc_background[doc_num][2] +
		block_information_11 + doc_num +
		block_information_12 + doc_num +
		block_information_13 + doc_num +
		block_information_14 + doc_num +
		block_information_15 + display_name[doc_num] +
		block_information_16 + doc_num +
		block_information_17 + doc_num +
		block_information_18 + doc_num +
		block_information_19 + doc_num +
		block_information_20 + doc_num +
		block_information_21 + doc_num +
		block_information_22 + doc_num +
		block_information_23 + doc_num +
		block_information_24 + doc_num +
		block_information_25 + doc_num +
		block_information_26 + doc_num +
		block_information_27 + doc_num +
		block_information_28 + doc_num +
		block_information_29 + doc_num +
		block_information_30 + doc_num +
		block_information_31 + doc_num + underline + ref_num +
		block_information_32 + doc_num + underline + ref_num +
		block_information_33);

  return(block_information);
}

/***********************************************************************

JavaScript event traps.

***********************************************************************/

/* Runs at every key press; allows the Enter key to be used only in textareas. */

function catch_enter_key(event) {

/* Assembled with help from
   http://www.bloggingdeveloper.com/post/Disable-Form-Submit-on-Enter-Key-Press.aspx
  and http://www.quirksmode.org/js/events_properties.html. */

    if (window.event) { //IE
	 key = window.event.keyCode;
	 target = window.event.srcElement;
    }
    else { //Firefox
	 key = event.which;
	 target = event.target;
    }
    if (target.nodeType == 3) { // work around Safari bug
		target = target.parentNode;
    }
    if (target.type == "textarea") {
	/* Allow all keypresses in textareas, including Enter key. */
	return;
    }
    else {
	/* Allow any keypresses except Enter key, outside textareas. */
	return (key != 13);
    }
}

/***********************************************************************

Callbacks.

***********************************************************************/

/* Restores a doc block that was removed by remove_doc_block; a
   callback set up by remove_doc_block. */

function restore_doc_block(arg) {
  doc_num = arg.data.doc_num;
  $('div#block_' + doc_num).show();
  $('input[@class="remove"]').attr("checked","");
  $('div#restore_' + doc_num).remove();

  /* Create and install the hidden input that indicates the block
     should not be removed by the server program. */
  restore_input = restore_input_1 + doc_num  +
      restore_input_2;
  $('input[@name="remove_' + doc_num + '"]').replaceWith(restore_input);

}

/* Runs when the user removes a doc block.
   Doesn't remove it now; but hides it and marks it so the script can
   remove it later. This allows the user to reverse the operation. */

function remove_doc_block() {

  doc_num = this.name;

  /* Create and install the hidden input that indicates the block
     should be removed by the server program. */
  remove_input = remove_input_1 + doc_num  +
      remove_input_2;
  $('input[@name="remove_' + doc_num + '"]').replaceWith(remove_input);

  /* Create and install the block displayed to the user. */
  replacement_block = $('	<div class="doc_block" id="restore_' + doc_num + '"> \
 <div id="restore_input_'  + doc_num + '" class="right-mark"> \
	<input type="checkbox" name="' + doc_num + '" class="restore" /> \
	  Restore this document entry. \
	</div> \
	<div class="left-mark" id="replacement_' + doc_num + '">'
	 + display_name[doc_num] + '</div></div>');

  /* First install replacement block, then hide the current doc block. */
  replacement_block.insertAfter($('div#block_' + doc_num));
  replacement_block.css("background",
			  "#" + hex_word(doc_background[doc_num][0]) +
			   hex_word(doc_background[doc_num][1]) +
			   hex_word(doc_background[doc_num][2]));

  $('div#block_' + doc_num).hide();

  /* Set up the restoration of the block. */
  $('input[@class="restore"][@name="' + doc_num + '"]').bind("click", { doc_num: doc_num }, restore_doc_block);
}

/* Restores a doc block that was hidden by hide_doc_block; a
   callback set up by hide_doc_block. */

function show_doc_block(arg) {
  doc_num = arg.data.doc_num;
  $('div#block_' + doc_num).show();
  $('input[@class="hide"]').attr("checked","");
  $('div#show_' + doc_num).remove();
}

/* Runs when the user hides a doc block. */

function hide_doc_block() {

  doc_num = this.name;

  /* Create and install the block displayed to the user. */
  replacement_block = $('	<div class="doc_block" id="show_' + doc_num + '"> \
 <div id="show_input_'	+ doc_num + '" class="right-mark"> \
	<input type="checkbox" name="' + doc_num + '" class="show" /> \
	  Show this document entry. \
	</div> \
	<div class="left-mark" id="replacement_' + doc_num + '">' +
	 display_name[doc_num] + '</div></div>');

  /* First install replacement block, then hide the current doc block. */
  replacement_block.insertAfter($('div#block_' + doc_num));
  replacement_block.css("background",
			  "#" + hex_word(doc_background[doc_num][0]) +
			   hex_word(doc_background[doc_num][1]) +
			   hex_word(doc_background[doc_num][2]));

  $('div#block_' + doc_num).hide();

  /* Set up the reshowing of the block. */
  $('input[@class="show"][@name="' + doc_num + '"]').bind("click", { doc_num: doc_num }, show_doc_block);

}

/* Runs when user clicks in the box to add an index entry. */

function add_index_next() {
     match = this.name.match(/^term_(\d+)_(\d+)$/);
     if (match)
     {
	doc_num=match[1];
	num=match[2];

	if ( term_clicked[num] == false )
	{

	  /* First-time flag: don't run this function again on the
	     same input field. */
	  term_clicked[num] = true;

	  /* Create a new block so the user can enter information on
	     the index term. */
	  index_contained = $(index_contained_1 + doc_num + underline + num +
		  index_contained_2);

	  /* Place at the end of the current index term block. */
	  $('div#term_' + doc_num + underline + num).append(index_contained);

	  /* Create a new block so the user can enter the next index term. */
	  index_additional = $(index_additional_1 +
		  doc_num + underline + term_num +
		  index_additional_2 + doc_num + underline + term_num +
		  index_additional_3);

	  /* Place at the end of the block holding all index terms. */
	  $('div#index_' + doc_num).append(index_additional);

	  /* Add callbacks
	     When user enters an index term.
	     When user clicks on the box indicating the term was found in the index. */
	  $('input[@name="term_' + doc_num +
	    underline + term_num + '"]').bind("click", add_index_next);

	  $('input[@name="entries_' + doc_num +
	    underline + num + '"]').bind("click", { doc_num: doc_num, num: num },
		 function(arg) {
		    /* Make sure the user entered a term before clicking. */
		    doc_num=arg.data.doc_num;
		    num=arg.data.num;
		    current_term = $('input[@name="term_' + doc_num + underline + num + '"]').val();
		    if ( current_term === null || current_term.match(/^\s*$/) )
		    {
		      alert("Please enter an index term first");
		      $('input[@name="entries_' + doc_num +
		      underline + num + '"]').attr("checked","");
		      return;
		    }
		 });

	  /* Prepare for next index term. */
	  term_clicked[term_num] = false;
	  term_num++;
	}
     }
}

/* Runs when the user clicks the Print box. */

function add_index_block() {

  match = this.name.match(/^type_(\d+)$/);
  if (match)
  {
    doc_num=match[1];

    /* Toggle between print and online. Only one block (an index
    block for a print document, or a searchstring block for an online
    document) can appear at at time. */
    if ( online_clicked[doc_num] == true )
    {
      online_clicked[doc_num] = false;
      $('div#searchblock_' + doc_num).remove();
    }

    if ( print_clicked[doc_num] == false )

    {
     /* First-time flag: don't run this function again on the same input field. */
      print_clicked[doc_num] = true;

      /* Create and install the block accepting information on an index. */
      index_first = $(index_first_1 + doc_num +
	  index_first_2 + doc_num + underline + term_num +
	  index_first_3 + doc_num + underline + term_num +
	  index_first_4);

      /* Place near end of doc block before final questions. */
      index_first.insertBefore($('div#doc_final_' + doc_num));
      term_clicked[term_num] = false;

      /* Add callback: when user enters an index term. */
      $('input[@name="term_' + doc_num + underline + term_num + '"]').bind("click", add_index_next);

      /* Keep track of clicks soa new block is added only once by each
	 input field. */
       term_clicked[term_num] = false;

       /* Prepare for next index term. */
       term_num++;
    }
  }
}

/* Runs when user checks the "Add information" box for a document. */

function add_to_doc() {

  doc_num = this.name;

  doc_name = $('input#doc_name_' + doc_num).val();

  if ( doc_name === null || doc_name.match(/^\s*$/) )
  {
    alert("Please enter a name or URL first");
    $('input[@class="add_to_doc"][@name="' + doc_num + '"]').attr("checked","");
    return;
  }

  /* Prepare for next doc block to be created. */
  doc_block_num++;

  /* To set up a name block for the following document. */
  doc_next = doc_block_num;

  update_doc_block_info(doc_next);

  /* Create the name to display at the top of the block. */
  if ( doc_name.length > max_display_length )
  {
    display_name[doc_num] = doc_name.substring(0,truncated_display_length) + "...";
  }
  else
  {
    display_name[doc_num] = doc_name;
  }

  /* A new block for the next document will be added at the end of the
     doc blocks. */
  $('div#nextdoc').remove();

  block_information = build_block_information(doc_num, doc_name);

  block_information.insertBefore($('div#observations'));

  /* Assign the color to the current block. */

  set_background($('div#block_' + doc_num), doc_num);

  /* Create and append small block for next document. */
  new_doc = new_doc_1 + doc_next +
	    new_doc_2 + doc_next +
	    new_doc_3;

  /* Place at the end of the current doc block. */
  $('div#doc_final_' + doc_num).append(new_doc);
  set_next_background($('div#nextdoc'));

  /* Add callbacks. */
  doc_block_setup(doc_num);

}

/* Runs when a user clicks on input box to add information about a
   search string. */

function add_searchstring_doc_block() {

  match = this.name.match(/^entries_(\d+)_(\d+)$/);
  if (match)
  {
    doc_num=match[1];
    num=match[2];
    current_searchstring = $('input[@name="searchstring_' + doc_num + underline + num + '"]').val();

    if ( current_searchstring === null || current_searchstring.match(/^\s*$/) )
    {
      alert("Please enter a search string first");
      $('input[@name="entries_' + doc_num +
	       underline + num + '"]').attr("checked","");
      return;
    }

    /* Create a block to replace the one that the user clicked, the
       user can enter information on the new document. */
    searchdoc_first = searchdoc_first_1 + doc_num + underline + num + underline + searchdoc_num +
	 searchdoc_first_2 + doc_num + underline + num + underline + searchdoc_num +
	 searchdoc_first_3;

    /* Place at the end of the current search block, getting rid of click box. */
    ($('div#searchstring_found_' + doc_num + underline + num)).append(searchdoc_first);

    /* Add callback: when user enters a document found through a search. */
    $('input#searchdoc_name_' + doc_num + underline + num + underline + searchdoc_num).bind("click", add_searchdoc_next);

    /* Set color to the color used for this search string. */
    $('input#searchdoc_name_' + doc_num + underline + num + underline + searchdoc_num).css("background", "#" +
			   hex_word(searchstring_color[num][0]) +
			   hex_word(searchstring_color[num][1]) +
			   hex_word(searchstring_color[num][2]));

    /* Prepare for next document. */
    searchdoc_clicked[searchdoc_num] = false;
    searchdoc_num++;
  }
}

/* Runs when user clicks in the box to add a search string. */

function add_searchstring_next() {

  match = this.name.match(/^searchstring_(\d+)_(\d+)$/);
  if (match)
  {
    doc_num=match[1];
    num=match[2];

    if ( searchstring_clicked[num] == false )
    {

      /* First-time flag: don't run this function again on the same
	 input field. */
      searchstring_clicked[num] = true;

      update_searchstring_info(searchstring_num);

      /* Create a new block so the user can enter information on
	 the search string. */
      searchstring_contained = $(searchstring_contained_1 + doc_num + underline + num +
	searchstring_contained_2 + doc_num + underline + num +
	searchstring_contained_3 + doc_num + underline + num +
	searchstring_contained_4);

      /* Place at the end of the current search string block. */
      $('div#searchstring_' + doc_num + underline + num).append(searchstring_contained);

      /* Create a new block so the user can enter the next search string. */
      searchstring_additional = $(searchstring_additional_1 + doc_num + underline + searchstring_num +
	    searchstring_additional_2 + searchstring_color[searchstring_num][0] +
	    searchstring_additional_3 + doc_num + underline + searchstring_num +
	    searchstring_additional_4 + searchstring_color[searchstring_num][1] +
	    searchstring_additional_5 + doc_num + underline + searchstring_num +
	    searchstring_additional_6 + searchstring_color[searchstring_num][2] +
	    searchstring_additional_7 + doc_num + underline + searchstring_num +
	    searchstring_additional_8 + doc_num + underline + searchstring_num +
	    searchstring_additional_9);

      /* Place at the end of the block holding all search strings. */
      $('div#searchblock_' + doc_num).append(searchstring_additional);

      /* Set color. */
      $('input[@name="searchstring_' + doc_num + underline + searchstring_num + '"]').css("background",
	    "#" + hex_word(searchstring_color[searchstring_num][0]) +
		  hex_word(searchstring_color[searchstring_num][1]) +
		  hex_word(searchstring_color[searchstring_num][2]));

      /* Add callbacks:
	 When user enters a search string.
	 When user clicks to indicate that a search turned up entries.
      */
      $('input[@name="searchstring_' + doc_num +
	       underline + searchstring_num + '"]').bind("click", add_searchstring_next);
      $('input[@name="entries_' + doc_num +
	       underline + num + '"]').bind("click", add_searchstring_doc_block);

      /* Prepare for next search string. */
      searchstring_clicked[searchstring_num] = false;
      searchstring_num++;
    }
  }
}

/* Runs when the user clicks the Online box. */

function add_searchstring_block() {

  match = this.name.match(/^type_(\d+)$/);
  if (match)
  {

    doc_num=match[1];

    /* Toggle between print and online. Only one block (an index
    block for a print document, or a searchstring block for an online
    document) can appear at at time. */
    if ( print_clicked[doc_num] == true )
    {
      print_clicked[doc_num] = false;
      $('div#index_' + doc_num).remove();
    }

    if ( online_clicked[doc_num] == false )
    {
     /* First-time flag: don't run this function again on the same input field. */
      online_clicked[doc_num] = true;

      update_searchstring_info(searchstring_num);

      /* Create and install the block accepting information on a
	search string. */
      searchstring_first = $(searchstring_first_1 + doc_num +
	  searchstring_first_2 + doc_num + underline + searchstring_num +
	  searchstring_first_3 + searchstring_color[searchstring_num][0] +
	  searchstring_first_4 + doc_num + underline + searchstring_num +
	  searchstring_first_5 + searchstring_color[searchstring_num][1] +
	  searchstring_first_6 + doc_num + underline + searchstring_num +
	  searchstring_first_7 + searchstring_color[searchstring_num][2] +
	  searchstring_first_8 + doc_num + underline + searchstring_num +
	  searchstring_first_9 + doc_num + underline + searchstring_num +
	  searchstring_first_10);

      /* Place near end of doc block before final questions. */
      searchstring_first.insertBefore($('div#doc_final_' + doc_num));
      searchstring_clicked[searchstring_num] = false;

      $('input[@name="searchstring_' + doc_num +
	  underline + searchstring_num + '"]').css("background",
	  "#" + hex_word(searchstring_color[searchstring_num][0]) +
	  hex_word(searchstring_color[searchstring_num][1]) +
	  hex_word(searchstring_color[searchstring_num][2]));

      /* Add callback: when user clicks to enter a search string. */
      $('input[@name="searchstring_' + doc_num +
	  underline + searchstring_num + '"]').bind("click",
	  add_searchstring_next);

      /* Keep track of clicks soa new block is added only once by each
	 input field. */
       searchstring_clicked[searchstring_num] = false;

       /* Prepare for next search string. */
       searchstring_num++;
    }
  }
}

/* Runs when a user clicks on input box to add information about a
   document to which the current document referred. */

function add_doc_through_referral() {
  match = this.name.match(/^(\d+)_(\d+)$/);

  if (match)
  {
    old_doc_num=match[1];
    num=match[2];
    referring_doc_name = $('input[@name="doc_name_' + old_doc_num + '"]').val();

    /* Try to get name to fit on a single line. */
    if ( referring_doc_name.length > max_referrer_length )
    {
      referring_doc_name = referring_doc_name.substring(0,truncated_referrer_length) + "...";
    }

    new_doc_name = $('input[@name="referred_doc_' + old_doc_num + underline + num + '"]').val();

    if ( new_doc_name === null || new_doc_name.match(/^\s*$/) )
    {
      alert("Please enter a name or URL first");
      $('input[@class="add_referred_doc"][@name="' + doc_num + underline + num + '"]').attr("checked","");
      return;
   }

  /* To set up a name block for the following document. */
  target_num = doc_block_num;

  /* For next doc block to be created. */
  doc_block_num++;

  /* To set up a name block for the following document. */
  doc_next = doc_block_num;

  /* Create the name to display at the top of the block. */
  if ( new_doc_name.length > max_display_length )
  {
    display_name[target_num] = new_doc_name.substring(0,truncated_display_length) + "...";
  }
  else
  {
    display_name[target_num] = new_doc_name;
  }

  update_doc_block_info(doc_next);

  /* A new block for the next document will be added at the end of the
     doc blocks. */
  $('div#nextdoc').remove();

  block_information = build_block_information(target_num, new_doc_name);

  block_information.insertBefore($('div#observations'));

  /* Assign the color to the current block. */
  set_background($('div#block_' + target_num), target_num);

  /* Add callbacks. */
  doc_block_setup(target_num);

  /* Links back and forth between referrer document and new document. */
  referrer = referrer_1 + old_doc_num + underline + num +
      referrer_2 + old_doc_num + underline + + num + underline + target_num +
      referrer_3 + target_num +
      referrer_4 + new_doc_name +
      referrer_5;

  target_id = target_id_1 + target_num +
    target_id_2;

  target = target_1 + target_num +
      target_2;

  return_div = return_div_1 + old_doc_num + underline + num +
      return_div_2 + old_doc_num + underline + num +
      return_div_3 + referring_doc_name +
      return_div_4;

  /* Add a hidden input with new document number so old document knows where it is. */
  $('div#ref_click_' + old_doc_num + underline + num).prepend(target_id);

  /* Add a link to the old document so the user can find the new one. */
  $('div#ref_click_' + old_doc_num + underline + num).replaceWith(referrer);

  /* Add an <a name...> link to the target. */
  $('div#block_' + target_num).prepend(target);

  /* Add two links to the new document so the user can find the old one. */
  $(return_div).insertAfter($('div[@name="top_line_' + target_num + '"]'));
  $('div#doc_final_' + target_num).append(return_div);

  $('div#referrer_' + old_doc_num + underline + num).children('a').css("background", "#" +
			   hex_word(doc_background[target_num][0]) +
			   hex_word(doc_background[target_num][1]) +
			   hex_word(doc_background[target_num][2]));

  /* Create and append small block for next document. */
  new_doc = new_doc_1 + doc_next +
	   new_doc_2 + doc_next +
	   new_doc_3;

  /* Place at the end of the target doc block (which is the current
     last doc block). */
  $('div#doc_final_' + target_num).append(new_doc);
  set_next_background($('div#nextdoc'));

    /* Add callback: when the user clicks on the box to add
       information about the next document. */
  $('input[@class="add_to_doc"][@name="' + next + '"]').bind("click", add_to_doc);


  /* Take user right to new document. */
  window.location = "#target_" + target_num;
  }

}

/* Runs when user clicks in a box to indicate that a document referred to another. */

function add_reference_block() {

  match = this.name.match(/^(\d+)_(\d+)$/);
  if (match)
  {
    doc_num=match[1];
    num=match[2];  // Number of reference, incrementing as new references are added.

    /* Create a block to replace the one that the user clicked, so
       user can enter information on the referenced document. */
    referred_contained = referred_contained_1 + doc_num + underline + num +
      referred_contained_2 + doc_num + underline + num +
      referred_contained_3 + doc_num + underline + num +
      referred_contained_4 + doc_num + underline + num +
      referred_contained_5 + doc_num + underline + num +
      referred_contained_6;

    $('div#referred_' + doc_num + underline + num).replaceWith(referred_contained);

    /* Prepare for next reference. */
    ref_num++;

    /* Create a block so the user can enter another reference; add
       after the referred_contained block just created. */
    referred_additional = referred_additional_1 + doc_num + underline + ref_num +
      referred_additional_2 + doc_num + underline + ref_num +
      referred_additional_3;
    $(referred_additional).insertAfter($('div#referrer_' + doc_num + underline + num));

      /* Add callbacks:
	 When user clicks to indicate looking at another document.
	 When user clicks to add information about a document.
      */

    $('input[@class="reference"][@name="' + doc_num + underline + ref_num + '"]').bind("click", add_reference_block);
    $('input[@class="add_referred_doc"][@name="' + doc_num + underline + num + '"]').bind("click", add_doc_through_referral);

  }

}

/* Adds callbacks for a newly created document block. */

function doc_block_setup(num) {

    next = parseInt(num,"10")+1;

  /* When user clicks to remove a doc block. */
  $('input[@class="remove"][@name="' + num + '"]').bind("click", remove_doc_block);

  /* When user clicks to hide a doc block. */
  $('input[@class="hide"][@name="' + num + '"]').bind("click", hide_doc_block);

  /* When user clicks on the print box. */
  $('input[@class="print"][@name="type_' + num + '"]').bind("click", add_index_block);

  /* When user clicks on the online box. */
  $('input[@class="online"][@name="type_' + num + '"]').bind("click", add_searchstring_block);

  /* When user clicks on the box to indicate looking at another document. */
  $('input[@class="reference"][@name="' + num + underline + ref_num + '"]').bind("click", add_reference_block);

  /* When user clicks on the box to add information about the next document. */
  $('input[@class="add_to_doc"][@name="' + next + '"]').bind("click", add_to_doc);

}

/* Runs when a user clicks on input box to add information about a
   document which was found through a search. */

function add_doc_through_searchstring() {

  match = this.name.match(/^(\d+)_(\d+)_(\d+)$/);

  if (match)
  {
    old_doc_num=match[1];
    string_num=match[2];
    num=match[3];

    referring_doc_name = $('input[@name="doc_name_' + old_doc_num + '"]').val();
    referring_searchstring = $('input[@name="searchstring_' + old_doc_num + underline + string_num + '"]').val();

    new_doc_name = $('input#searchdoc_name_' + old_doc_num + underline + string_num + underline + num).val();

    /* I don't try to get name and search string to fit on a single
       line, unlike the add_doc_through_referral function, because
       there's too much text to achieve that goal. */

    if ( new_doc_name === null || new_doc_name.match(/^\s*$/) )
    {
      alert("Please enter a name or URL first");
      $('input[@class="add_to_searchstring_doc"][@name="' + doc_num + underline + string_num + underline + num + '"]').attr("checked","");
      return;
    }

    /* To set up a name block for the following document. */
    target_num = doc_block_num;

    /* For next doc block to be created. */
    doc_block_num++;

    /* To set up a name block for the following document. */
    doc_next = doc_block_num;

    /* Create the name to display at the top of the block. */
    if ( new_doc_name.length > max_display_length )
    {
      display_name[target_num] = new_doc_name.substring(0,truncated_display_length) + "...";
    }
    else
    {
      display_name[target_num] = new_doc_name;
    }

    update_doc_block_info(doc_next);

    /* A new block for the next document will be added at the end of the
       doc blocks. */
    $('div#nextdoc').remove();

    block_information = build_block_information(target_num, new_doc_name);

    block_information.insertBefore($('div#observations'));

    /* Assign the color to the current block. */
    set_background($('div#block_' + target_num), target_num);

    /* Create and append small block for next document. */
    new_doc = new_doc_1 + doc_next +
	   new_doc_2 + doc_next +
	   new_doc_3;

  /* Place at the end of the target doc block (which is the current
     last doc block). */
    $('div#doc_final_' + target_num).append(new_doc);
    set_next_background($('div#nextdoc'));

    /* Add callbacks. */
    doc_block_setup(target_num);

    /* Links back and forth between searchstring and new document. */
    search_referrer = search_referrer_1 + old_doc_num + underline + num +
	 search_referrer_2 + old_doc_num + underline + string_num + underline +
	   + num + underline + target_num +
	 search_referrer_3 + target_num +
	 search_referrer_4 + new_doc_name +
	 search_referrer_5;

    target_id = target_id_1 + target_num +
       target_id_2;

    target = target_1 + target_num +
	 target_2;

    search_return_div = search_return_div_1 + old_doc_num + underline + num +
	 search_return_div_2 + old_doc_num + underline + string_num + underline + num +
	 search_return_div_3 + referring_doc_name +
	 search_return_div_4 + referring_searchstring +
	 search_return_div_5;

    /* Add an <a name...> link to the target. */
    $('div#block_' + target_num).prepend(target);

    /* Add a link from the old document to the target. */
    $('div#searchstring_click_' + old_doc_num + underline + string_num + underline + num).replaceWith(search_referrer);

    /* Add a link to the new document so the user can find the old one. */
     $(search_return_div).insertAfter($('div[@name="top_line_' + target_num + '"]'));

  /* Add a hidden input with new document number so old document knows where it is. */
    $('div#searchstring_click_' + old_doc_num + underline + string_num + underline + num).prepend(target_id);

    /* Because of a jQuery bug, the following CSS change applies only to
       the first occurrence. */

    $('div#link_back_' + old_doc_num + underline + num).children('a').css("background", "#" +
	  hex_word(searchstring_color[string_num][0]) +
	  hex_word(searchstring_color[string_num][1]) +
	  hex_word(searchstring_color[string_num][2]));

    /* Add another link to the new document so the user can find the old one. */
    $('div#referred_' + target_num + underline + num).append(search_return_div);

    /* Currently has no effect, but leaving it in anyway. */
    $('div#search_referrer_' + old_doc_num + underline + num).children('a').css("background", "#" +
	  hex_word(searchstring_color[string_num][0]) +
	  hex_word(searchstring_color[string_num][1]) +
	  hex_word(searchstring_color[string_num][2]));

    /* Take user right to new document. */
    window.location = "#target_" + target_num;
  }

}

/* Runs when user clicks in the box to add a document found through a searchstring. */

function add_searchdoc_next() {

   match = this.id.match(/^searchdoc_name_(\d+)_(\d+)_(\d+)$/);
   if (match)
   {
     doc_num=match[1];
     string_num=match[2];
     num=match[3];

     if ( searchdoc_clicked[num] == false )
     {
       /* First-time flag: don't run this function again on the
	  same input field. */
       searchdoc_clicked[num] = true;

       /* Create a new block so the user can enter information on
	  the new document. */
       searchdoc_contained = $(searchdoc_contained_1 + doc_num + underline + string_num + underline + num +
	searchdoc_contained_2 + doc_num + underline + string_num + underline + num +
	searchdoc_contained_3 + doc_num + underline + string_num + underline + num +
	searchdoc_contained_4);

       /* Place at the end of the current search block. */
       $('div#search_followed_' + doc_num + underline + string_num + underline + num).append(searchdoc_contained);

       /* Add callback: when user clicks a box to add information
	  about a document. */
       $('input[@class="add_to_searchstring_doc"][@name="' + doc_num + underline + string_num + underline + num + '"]').bind("click", add_doc_through_searchstring);

       /* Create a new block so the user can enter the next document found. */
       searchdoc_additional = $(searchdoc_additional_1 + doc_num + underline + string_num + underline + searchdoc_num +
	 searchdoc_additional_2 + doc_num + underline + string_num + underline + searchdoc_num +
	 searchdoc_additional_3);

       /* Place after the current document found on this search. */
       searchdoc_additional.insertAfter($('div#search_followed_' + doc_num + underline + string_num + underline + num));

       /* Set color to the color used for this search string. */
       $('input#searchdoc_name_' + doc_num + underline + string_num + underline + searchdoc_num).css("background", "#" +
		     hex_word(searchstring_color[string_num][0]) +
		     hex_word(searchstring_color[string_num][1]) +
		     hex_word(searchstring_color[string_num][2]));

       /* Add callback: when user enters a document found through a search. */
       $('input#searchdoc_name_' + doc_num + underline + string_num + underline + searchdoc_num).bind("click", add_searchdoc_next);

       /* Prepare for next document. */
       searchdoc_clicked[searchdoc_num] = false;
       searchdoc_num++;
     }
   }
}

/***********************************************************************

Blocks of HTML.

***********************************************************************/

/* Block displayed on initial index.html form. */
first_doc_name='\
<div class="doc_block" id="nextdoc"> <! -- Start consulted block --> \
  Enter the name or URL for the first document or site you used: \
  <div class="no_set_off"> \
    <input class="start" id="doc_name_0" size="65" /> \
  </div> \
  <div class="no_set_off"> \
    <input type="checkbox" class="add_to_doc" name="0" /> \
	  Add information about this document. \
  </div>';

/* Block for information on each document. */
block_information_1='\
  <div class="no_set_off" class="doc_block" id="block_';

block_information_2='"> <!-- Start doc block --> \
    <input type="hidden" name="doc_name_';

block_information_3='" value="';

block_information_4='" /> \
    <input type="hidden" name="remove_';

block_information_5='" value="0" /> \
    <input type="hidden" name="doc_red_';

block_information_6='" value="';

block_information_7='" /> \
    <input type="hidden" name="doc_green_';

block_information_8='" value="';

block_information_9='" /> \
    <input type="hidden" name="doc_blue_';

block_information_10='" value="';

block_information_11='" /> \
    <div class="no_set_off" name="top_line_';

block_information_12='"> <!-- Start top line --> \
      <div class="right-mark"> <!-- Start control buttons--> \
	<div class="no_set_off"> \
	<input class="remove" type="checkbox" name="';

block_information_13='" class="remove" /> \
	  Remove this document entry. \
	</div> \
	<div class="no_set_off"> \
	<input class="hide" type="checkbox" name="';

block_information_14='" class="hide" /> \
	  Temporarily hide this document entry. \
	</div> \
      </div> <!-- End control buttons--> \
      <div id="doc_name_';

block_information_15='" class="left-mark">';

block_information_16='\
      </div> \
    </div> <!-- End top line --> \
    <div class="set_off"> <!-- Start print/online block --> \
      How did you access the document? (Choose one) \
      <div class="indent"> \
	<div class="no_set_off"> \
	  <input type="radio" class="online" name="type_';

block_information_17='" value="online" /> \
	  Online (a search engine, blog, online book, article, etc.) \
	</div> \
	<div class="no_set_off"> \
	  <input type="radio" class="print" name="type_';

block_information_18='" value="print" /> \
	  Print or other analog media (a book, magazine article, conference proceedings, video, microfiche, etc.) \
	</div> \
      </div> \
    </div> <!-- End print/online block --> \
    <div class="set_off"> \
      Why did you choose this document? \
    </div> \
    <div class="center"> \
    <textarea name="why_chosen_';

block_information_19='" cols="70" rows="5"></textarea> \
    </div> \
    <div class="center"> \
      <input type="checkbox" name="read_';

block_information_20='" value="';

block_information_21='" /> \
    Click here if you read all or parts of the document. \
    </div> \
    <div class="center"> <!-- Start usefulness rating --> \
      <div class="set_off"> \
	How useful was the information you found? (Rate from 1 to 6) \
      </div> \
      <table align="center" summary="Rating usefulness of document"> \
	<tr> <td> (Not useful at all) </td> <td> 1 </td> <td> 2 </td> <td> 3 </td> <td> 4 </td> <td> 5 </td> <td> 6 </td> <td> (Most useful) </td> </tr> \
	<tr> \
	   <td> </td> \
	   <td> \
	     <input type="radio" name="usefulness_';

block_information_22='" value="1" /> </td> \
	   <td> \
	    <input type="radio" name="usefulness_';

block_information_23='" value="2" /> \
	  </td> \
	  <td> \
	    <input type="radio" name="usefulness_';

block_information_24='" value="3" /> \
	  </td> \
	  <td> \
	    <input type="radio" name="usefulness_';

block_information_25='" value="4" /> \
	  </td> \
	  <td> \
	    <input type="radio" name="usefulness_';

block_information_26='" value="5" /> \
	  </td> \
	  <td> \
	    <input type="radio" name="usefulness_';

block_information_27='" value="6" /> \
	  </td> \
	  <td> \
	  </td> \
	</tr> \
      </table> \
      <div class="set_off"> \
	<input type="checkbox" name="resolve_';

block_information_28='" /> \
	Click here if the information resolved your original problem. \
      </div> \
    </div> <!-- End usefulness rating --> \
    <hr class="subsidiary" /> \
    <div class="set_off" id="div_observations_';

block_information_29='"> \
    <i>Optional</i>: Enter any observations you have about the \
    document and your use of the information in it. \
    </div> \
    <div class="center"> \
    <textarea name="observations_doc_';

block_information_30='" cols="70" rows="5"></textarea> \
    </div> \
    <div id="doc_final_';

block_information_31='"> <!-- Start final doc block --> \
  <hr class="subsidiary" /> \
      <div class="end_block" id="referred_';

block_information_32='"> \
	<input type="checkbox" class="reference" name="';

block_information_33='" /> \
      Click here if you looked at another document that this one referred to. \
      </div> \
    </div> <!-- End final doc block --> \
  </div> <!-- End doc block --> \
';

/* Input for removing a block, set to remove it. */
remove_input_1='\
    <input type="hidden" name="remove_';

remove_input_2='" value="1" />';

/* Input for removing a block, set to keep it. */
restore_input_1='\
    <input type="hidden" name="remove_';

restore_input_2='" value="0" />';

/* Small block to display after all doc blocks, to accept new document. */
new_doc_1='								\
    <div class="doc_block" id="nextdoc"> <! -- Start consulted block --> \
      If you consulted more documents or sites, enter the name or URL of \
      the next one here: \
      <div class="no_set_off"> \
	<input class="next" id="doc_name_';

new_doc_2='" size="65" /> \
      </div> \
      <div class="no_set_off"> \
	  <input type="checkbox" class="add_to_doc" name="';

new_doc_3='" /> \
	  Add information about this document. \
      </div> \
    </div> <! -- End consulted block -->';

/ * First index term for each document. */
index_first_1='\
  <div id="index_';

index_first_2='" class="set_off"> <!-- Start index inquiry --> \
  <hr class="subsidiary" /> \
    <div id="term_';

index_first_3='" class="no_set_off"> \
      If you used an index, enter the first term you looked up. \
      <input type="text" name="term_';

index_first_4='" size="40" /> \
    </div> \
  </div> <!-- End index inquiry -->';

/ * Information about each index term. */
index_contained_1='\
      <div class="indent"> \
	<input type="checkbox" name="entries_';

index_contained_2='" /> \
	Click here if the index contained any entries for the term. \
      </div> \
     <hr class="subsidiary" />';

/ * Form to accept new index term. */
index_additional_1='\
      <div id="term_';

index_additional_2='" class="set_off"> \
    Enter the next term you looked up. \
    <input type="text" name="term_';

index_additional_3='" size="40" /> \
  </div>';

/ * First search string for each document. */
searchstring_first_1='\
  <div id="searchblock_';

searchstring_first_2='" class="set_off"> <!-- Start searchstring inquiry --> \
  <hr class="subsidiary" /> \
    <input type="hidden" name="search_red_';

searchstring_first_3='" value="';

searchstring_first_4='" /> \
    <input type="hidden" name="search_green_';

searchstring_first_5='" value="';

searchstring_first_6='" /> \
    <input type="hidden" name="search_blue_';

searchstring_first_7='" value="';

searchstring_first_8='" /> \
    <div id="searchstring_';

searchstring_first_9='" class="no_set_off"> \
      If you performed any searches on this page, enter the first \
      search string you tried. \
      <input type="text" name="searchstring_';

searchstring_first_10='" size="40" /> \
    </div> \
  </div> <!-- End searchstring inquiry -->';

/ * Information about each search string. */
searchstring_contained_1='\
      <div id="searchstring_found_';

searchstring_contained_2='"> \
	<div id="searchstring_input_';

searchstring_contained_3='"> \
	  <input type="checkbox" name="entries_';

searchstring_contained_4='" /> \
	  Click here if the search turned up any entries. \
	</div> \
      </div>';

/ * Form to accept new search string. */
searchstring_additional_1='\
    <hr class="subsidiary" /> \
    <input type="hidden" name="search_red_';

searchstring_additional_2='" value="';

searchstring_additional_3='" /> \
    <input type="hidden" name="search_green_';

searchstring_additional_4='" value="';

searchstring_additional_5='" /> \
    <input type="hidden" name="search_blue_';

searchstring_additional_6='" value="';

searchstring_additional_7='" /> \
      <div id="searchstring_';

searchstring_additional_8='" class="set_off"> \
    Enter the next search string you tried. \
    <input type="text" name="searchstring_';

searchstring_additional_9='" size="40" /> \
  </div>';

/ * Information about each document found through a reference. */
referred_contained_1='\
      <div id="referrer_';

referred_contained_2='"> \
	Enter the name or URL for the document or site: \
	<input type="text" name="referred_doc_';

referred_contained_3='" size="40" /> \
	<div class="indent" id="ref_click_';

referred_contained_4='"> \
	  <input type="checkbox" class="add_referred_doc" name="';

referred_contained_5='" /> \
	    Click here to add information about the document or site. \
	</div> \
	<hr class="subsidiary" /> \
	<a name="referrer_';

referred_contained_6='"></a> \
      </div>';

/ * Form to accept new document through a reference. */
referred_additional_1='\
      <div class="end_block" id="referred_';

referred_additional_2='"> \
	<input type="checkbox" class="reference" name="';

referred_additional_3='" /> \
      Click here if you looked at yet another document that this one referred to. \
	<hr class="subsidiary" /> \
      </div>';

/ * Block added to old document to link to new one found through a reference. */
referrer_1='\
      <div class="indent" id="referrer_';

referrer_2='"> \
	<input type="hidden" name="reference_';

referrer_3='"> \
	<a href="#target_';

referrer_4='"> \
	Click here to return to top of <span class="strong">';

referrer_5='</span></a> \
      </div>';

/ * Target of link from old document to new one. */
target_1='\
<a name="target_';

target_2='"></a>';

/* Hidden input so old document can find the new one. */
target_id_1='\
<input class="hidden" name="';

target_id_2='" />';

/* Link from old document back to old one that referred to it. */
return_div_1='\
<div id="link_back_';

return_div_2='" class="indent"> \
  <a href="#referrer_';

return_div_3='"> \
  Click here to return to referring document, <span class="strong">';

return_div_4='</span></a> \
      </div>';

/ * First document found for each search string. */
searchdoc_first_1='\
<div id="search_followed_';

searchdoc_first_2='"> \
  If you followed one or more links, enter the name or URL of the first site here: \
  <div class="no_set_off"> \
    <input id="searchdoc_name_';

searchdoc_first_3='" size="65" /> \
  </div> \
</div>';

/ * Information about each document found through a search. */
searchdoc_contained_1='\
  <div class="no_set_off" id="searchstring_click_';

searchdoc_contained_2='"> \
    <input type="checkbox" name="';

searchdoc_contained_3='" class="add_to_searchstring_doc" /> \
      Click here to add information about this document. \
  </div> \
  <a name="search_referrer_';

searchdoc_contained_4='"></a>';

/ * Form to accept new document found through a search. */
searchdoc_additional_1='\
<div id="search_followed_';

searchdoc_additional_2='"> \
  If you followed another link from this same search, enter the name or URL of the next site here: \
  <div class="no_set_off"> \
    <input id="searchdoc_name_';

searchdoc_additional_3='" size="65" /> \
  </div> \
</div>';

/ * Block added to old document to link to new one found through a search. */
search_referrer_1='\
      <div class="indent" id="search_referrer_';

search_referrer_2='"> \
	<input type="hidden" name="search_reference_';

search_referrer_3='"> \
	<a href="#target_';

search_referrer_4='"> \
	Click here to return to top of <span class="strong">';

search_referrer_5='</span></a> \
      </div>';

/* Link from old document back to old one that pointed to it through a search. */
search_return_div_1='\
<div id="link_back_';

search_return_div_2='" class="indent"> \
  <a href="#search_referrer_';

search_return_div_3='"> \
  Click here to return to referring document, <span class="strong">';

search_return_div_4='</span>, search string <span class="strong">';

search_return_div_5='</span</a> \
      </div>';


/***********************************************************************

Global variables.

***********************************************************************/


underline='_';

/* The following colors mark successive doc blocks. */
doc_background_red = 230;
doc_background_green = 240;
doc_background_blue = 240;

/* Values to plug in to make colors of doc block. */
doc_background = [];

/* The following colors mark successive index terms because the terms
   can get pretty far from the original box where the user clicks. */
searchstring_color_red = 255;
searchstring_color_green = 240;
searchstring_color_blue = 252;

/* Values to plug in to make colors of index term. */
searchstring_color = [];

color_difference = 16;
maximum_darkness = 180;

max_display_length = 35;
truncated_display_length = max_display_length - 4;

max_referrer_length = 20;
truncated_referrer_length = max_referrer_length - 4;

/* Names to show at the top of each doc block. */
display_name = [];

/* Lists of things that can be clicked. These are used first-time
   flags, so functions don't run again on the same input field. */
print_clicked = [];
online_clicked = [];
term_clicked = [];
searchstring_clicked = [];
searchdoc_clicked = [];

/* Document block numbers, term numbers, searchstring numbers, and
   document reference numbers simply increment so that they're unique.
   These global variables create the names of fields passed to the
   server, and lSome also are used as indexes into arrays of
   colors. */

doc_block_num = 0;
term_num = 0;
searchstring_num = 0;
searchdoc_num = 0;
ref_num = 0;

/***********************************************************************

  Function in jQuery object.

***********************************************************************/

$(document).ready(function() {

  $(first_doc_name).insertBefore($('div#observations'));
  update_doc_block_info(0);

  /* Assign the color to current block. */
  set_background($('div#nextdoc'), 0);

  /*
    Callback when user clicks in the input box to enter a document name.
  */
  $('input[@class="add_to_doc"][@name="0"]').bind("click", add_to_doc);

});
