//some constants
var proxyURL = window.location.protocol + "//"+ window.location.hostname + window.location.pathname;
//experiment options are fetched from dbregulation.dict_exp_technique_types
//added N/A option 
var experiment_options = [{"name":"N/A","id":0},{"name":"2-D electrophoresis","id":103},{"name":"5`-RACE","id":910},{"name":"Array analysis","id":84},{"name":"Atomic force microscopy","id":864},{"name":"Challenge phage assay","id":142},{"name":"Chemical cross-linking","id":85},{"name":"Chromatin immunoprecipitation","id":676},{"name":"Circular permutation","id":129},{"name":"Colony hybridization","id":86},{"name":"Colorimetric assay","id":143},{"name":"Competitive binding","id":136},{"name":"Complementation","id":87},{"name":"Conclusion","id":104},{"name":"Cycle Selection","id":128},{"name":"Deletion analysis","id":871},{"name":"Depurination assay","id":130},{"name":"Diffusion test","id":88},{"name":"Disc diffusion method","id":144},{"name":"DNA immunoprecipitation assay","id":89},{"name":"Dot/slot blot","id":90},{"name":"Electron microscopy","id":105},{"name":"Enzyme activity assay","id":91},{"name":"Filter binding assay","id":92},{"name":"Fluorescence anisotropy","id":852},{"name":"Footprinting","id":93},{"name":"Fusion construction","id":94},{"name":"Gel filtration","id":123},{"name":"Gel retardation","id":95},{"name":"Global transcription analysis","id":131},{"name":"Immunochemical analisys","id":106},{"name":"Immunogold labelling","id":134},{"name":"Ligation/RT-PCR  assay","id":132},{"name":"Methylation assay","id":107},{"name":"Methylation interference footprinting","id":112},{"name":"Microarray assay","id":108},{"name":"mRNA quantity assay","id":127},{"name":"Mutagenesis","id":109},{"name":"Mutant analysis","id":110},{"name":"Northern blot","id":97},{"name":"Nuclease mapping","id":135},{"name":"Nuclease protection assay","id":98},{"name":"Nuclease treatment","id":145},{"name":"PAG electrophoresis","id":138},{"name":"PCR","id":936},{"name":"Plasmid profile","id":111},{"name":"Premethylation assay","id":113},{"name":"Primer extension","id":99},{"name":"Probing","id":100},{"name":"Protein function analysis","id":859},{"name":"Protein quantity assay","id":124},{"name":"Pulse labelling","id":146},{"name":"RACE","id":114},{"name":"Radioimmune assay","id":137},{"name":"Real-time PCR","id":125},{"name":"Regulator overexpression","id":935},{"name":"Regulator transfection","id":888},{"name":"Restriction enzyme protection assay","id":126},{"name":"Reverse transcription","id":101},{"name":"RNA hybrid dublex assay","id":115},{"name":"RNase protection","id":102},{"name":"RT-PCR","id":116},{"name":"SDS-electrophoresis","id":139},{"name":"Sequence analysis","id":117},{"name":"Southern blot","id":29},{"name":"Southwestern blot","id":118},{"name":"Titration assay","id":119},{"name":"Transcription in vitro","id":120},{"name":"Transporter activity assay","id":121},{"name":"UV cross-linking","id":122},{"name":"UV influence assay","id":141},{"name":"Western blotting","id":96},{"name":"X-ray analysis","id":140},{"name":"Yeast two-hybrid system","id":133}];
var find_sequence_action = 'find_sequence';
var add_spacer_action = 'add_spacer';
var add_sequence_action = 'add_sequence';
var max_sequence_width = 14;//for printing formatted sequence
var SET_LOCATION=true;
var CAN_MODIFY_LOCATIONS = true;
var CANNOT_MODIFY_LOCATIONS = false;
var DISABLE_GROUP = true;
var ENABLE_GROUP = false;
var UPLOAD_SEQUENCE = 0;
var COMPLETE_CALL_BACK = 1;
var undefined; // = void 0;
// A utility function that returns true if a string contains only 
// whitespace characters.
function isblank(s)
{
    for(var i = 0; i < s.length; i++) {
        var c = s.charAt(i);
        if ((c != ' ') && (c != '\n') && (c != '\t')) return false;
    }
    return true;
}
// This is the function that performs form verification. It will be invoked
// from the onSubmit() event handler. The handler should return whatever
// value this function returns.
function verify(f)
{
    var msg;
    var empty_fields = "";
    var errors = "";

    // Loop through the elements of the form, looking for all 
    // text and textarea elements that don't have an "optional" property
    // defined. Then, check for fields that are empty and make a list of them.
    // Also, if any of these elements have a "min" or a "max" property defined,
    // then verify that they are numbers and that they are in the right range.
    // Put together error messages for fields that are wrong.
    for(var i = 0; i < f.length; i++) {
        var e = f.elements[i];
        var result = check_field(e);
        empty_fields += result[0];
        errors += result[1];
    }

    // Now, if there were any errors, display the messages, and
    // return false to prevent the form from being submitted. 
    // Otherwise return true.
    if (!empty_fields && !errors) return true;

    msg  = "______________________________________________________\n\n"
    msg += "The form was not submitted because of the following error(s).\n";
    msg += "Please correct these error(s) and re-submit.\n";
    msg += "______________________________________________________\n\n"

    if (empty_fields) {
        msg += "- The following required field(s) are empty:" 
                + empty_fields + "\n";
        if (errors) msg += "\n";
    }
    msg += errors;
    alert(msg);
    return false;
}


//similar to verify, takes list of elements instead of a form
function verify_fields(f)
{
    var msg;
    var empty_fields = "";
    var errors = "";

    for(var i = 0; i < f.length; i++) {
        var e = f[i];
        var result = check_field(e);
        empty_fields += result[0];
        errors += result[1];
    }

    // Now, if there were any errors, display the messages, and
    // return false to prevent the form from being submitted. 
    // Otherwise return true.
    if (!empty_fields && !errors) return true;

    msg  = "";

    if (empty_fields) {
        msg += "- The following required field(s) are empty:" 
                + empty_fields + "\n";
        if (errors) msg += "\n";
    }
    msg += errors;
    alert(msg);
    return false;
}

function check_field(e)
{
	var empty_fields = "";
    var errors = "";
	if ((
				(e.type == "text")
			|| (e.type == "textarea") 
        	|| (e.type == "select-one")
        	|| (e.type == "select-multiple")
        	|| (e.type == "file")
        ) && !e.optional && !e.disabled ) {
            // first check if the field is empty
            if ((e.value == null) || (e.value == "") || isblank(e.value)) {
                empty_fields += "\n          " + e.name;
            } else 

            // Now check for fields that are supposed to be numeric.
            if (e.numeric!= null &&  ((e.min != null) || (e.max != null) )) { 
                var v = parseFloat(e.value);
                if (isNaN(v) || 
                    ((e.min != null) && (v < e.min)) || 
                    ((e.max != null) && (v > e.max))) {
                    errors += "- The field " + e.name + " must be a number";
                    if (e.min != null) 
                        errors += " that is greater than " + e.min;
                    if (e.max != null && e.min != null) 
                        errors += " and less than " + e.max;
                    else if (e.max != null)
                        errors += " that is less than " + e.max;
                    errors += ".\n";
                }
            }
        }
    return [empty_fields, errors];
}



/*
function _assequence_pubmed_id() {
        var e = this;
        e.numeric = true;
        e.min = 1;
        var msg="- PubMed Id";
        
        //common part
        var ret = '';
        eval(complete_check_field);
        return ret;
}

function _assequence_gene_name() {
        var e = this;
        msg="- Gene";
        //common part
        var ret = '';
        eval(complete_check_field);
        return ret;
}
*/


function find_child_by_name(parent_node, tag_name, name) {
	var children = parent_node.getElementsByTagName(tag_name);
	var child_node;
	for (var i=0; i<children.length;++i){
		if(children[i].getAttribute('name')==name){
			child_node = children[i];
			break;
		}
	}
	return child_node;
}


function add_alignment_sequences()
{
	var fld_matrix_info = document.getElementById('matrix_info');
	if ( fld_matrix_info.value == "" ) {
		alert('Please upload sequences first.');
		return false;
	}
	var info =  fld_matrix_info.value.parseJSON();
	
	var spacer = document.getElementById('use_spacer_check');
	if ( spacer.checked ) {//make sure all sequences are added
		var last_row_info = info[info.length-1];
		var seq_length = last_row_info.sequences.length;
		if ( seq_length==1 ){
			alert('Please upload another sequence when using spacer.');
			return false;
		}  
	}
	
	//verify fields
	var group = document.getElementById("alignment_sequences");
	var inputs = group.getElementsByTagName("INPUT");
	var selects = group.getElementsByTagName("SELECT");
	var fields = new Array(inputs.length+selects.length);
	for (var i=0; i<inputs.length;++i) {
		fields[i] = inputs[i];
	}
	
	for (i=0; i<selects.length;++i) {
		fields[inputs.length+i] = selects[i];
	}
	
	if ( !verify_fields(fields)){
		return false;
	}
	
	for (var j=0; j< info.length; j++ ) {
		if ( info[j].seqfeature_id != "" ){
			continue;
		}
		
		//find a row
		var tbl = document.getElementById('alignment_sequences');
 		var row = tbl.tBodies[0].rows[j+1];//skipping header row
		//find gene_node
		var gene_node = find_child_by_name(row, 'INPUT', 'sequence_gene_name');
		var tf_name = gene_node.value;
		var params = '&page=find_seqfeature&headertype=text/html&tf_name='+tf_name+
		'&taxon_id='+info[j].taxon_id +	'&tf_idx='+j;
		sendRequest(params, function (response, status) 
		{
			var obj =  response.parseJSON();
			var idx = obj.tf_idx;
			if (obj.error) {
				alert(obj.error +' for '+ info[idx].species);
				return;
			} else {
				var row_info = info[idx];
				row_info.seqfeature_id = obj.seqfeature_id;
				var row = tbl.tBodies[0].rows[idx+1];//skip header row
				var gene_node = find_child_by_name(row, 'INPUT', 'sequence_gene_name');
				var gene_value = gene_node.value;
				var parent_node = gene_node.parentNode;
				parent_node.removeChild(gene_node);
				parent_node.innerHTML += gene_value;
				row_info.seqname = gene_value;//use gene_name as seqname
				var seqname = find_child_by_name(row, 'td', 'seqname');
				seqname.innerHTML = gene_value;
				var experiment = find_child_by_name(row, 'SELECT', 'experiment');
				var exp_parent_node = experiment.parentNode;
				var k=0;
				var exp_value = '';
				for (var j=0; j< experiment.length; ++j){
					if (experiment.options[j].selected) {
						var cur_value = experiment.options[j].value;
						exp_value += experiment.options[j].innerHTML + '<br>';
						row_info.experiments[k++] = cur_value;
					}
				}
				//replace experiment with text
				exp_parent_node.removeChild(experiment);
				exp_parent_node.innerHTML += exp_value;
				
				var pubmed_id = find_child_by_name(row, 'INPUT', 'sequence_pubmed_id');
				//hide sequence_pubmed_id
				parent_node = pubmed_id.parentNode;
				var pm_value = pubmed_id.value;
				//cannot change type dinamically in IE. Need to replace the element
				parent_node.removeChild(pubmed_id);
				parent_node.innerHTML += pm_value;
				row_info.pubmed_id = pm_value;
				//save new matrix_info
				fld_matrix_info = document.getElementById('matrix_info');
				fld_matrix_info.value = info.toJSONString();
			}
		});
	}
}



function upload_sequence()
{
	//verify fields
	var group = document.getElementById("upload_sequence");
	var inputs = group.getElementsByTagName("INPUT");
	var fields = new Array(inputs.length);
	var start, stop;
	for (var i=0; i<inputs.length;++i) {
		var input = inputs[i];
		fields[i] = input;
   		if (input.type == "text"){
   			if ( input.id == "spacer_min" ) {
	   			parser.readValue(input);
			   	if (input.underlyingValue == undefined)
	           		return false;
   				start = parseInt(input.value);
   			} else if ( input.id == "spacer_max" ) {
   				parser.readValue(input);
			   	if (input.underlyingValue == undefined)
	           		return false;
   				stop = parseInt(input.value);
   			}
       	}
    	if (start > stop) {
    		alert('format error: spacer min is greater than spacer max.')
    		return false;
    	}
	}
	/*
	for (i=0; i<selects.length;++i) {
		fields[inputs.length+i] = selects[i];
	}
	*/
	for (var i=0; i<fields.length;++i)
		fields[i].optional = false; //these will be re-set by InfoSubmit
	var fields_valid = verify_fields(fields);
	if ( !fields_valid ){
		return false;
	}
	var up_seq_info = document.getElementById('up_seq_info');
	var accession_number = document.getElementById('accession_number').value;
	var sequence = document.getElementById('sequence').value;
	if ( up_seq_info.value != "" ){//second call to force select location  
		var obj = up_seq_info.value.parseJSON();
		var info = obj[0];
		//make sure we still have the same sequence
		var last_sequence = info.sequences[info.sequences.length-1];
		var last_accession_number = info.accession_number;
		if ( sequence!=last_sequence || accession_number!=last_accession_number ) {
			up_seq_info.value = "";
			//delete the table, do AJAX again
			delete_all_rows(document.getElementById('uploaded_sequence_location'));
			upload_sequence();
			return;
		}
		
		var selects = group.getElementsByTagName("SELECT");
		var fields_valid = verify_fields(selects);
		if ( !fields_valid ){
			return false;
		}
		var locations = info.locations;
		var el_location = document.getElementById('sequence_location');
		if ( el_location != null ) {//force select
			var defloc_idx = el_location.selectedIndex;
			locations[0] = locations[defloc_idx];
			locations.length = 1;//truncate locations
		}
		completeCallback(obj.toJSONString());
	} else {//first call, do AJAX
		create_up_seq_table();
		var params = '&page=parse_fasta_file&headertype=text/html&action=' + find_sequence_action + 
		'&accession_number='+accession_number+
			'&sequence='+sequence;
		sendRequest(params, function (response, status) 
		{
			up_seq_info.value = response; 
			completeCallback(response);
		});
	}
}

function add_tf(select_genome)
{
	var taxon_id;
	var taxon_name;
	
	//verify input
	var tf_names = document.getElementById('tf_names');
	var el_pubmed_id = document.getElementById('pubmed_ids');
	var fields = [tf_names, select_genome, el_pubmed_id]
	
	if ( !verify_fields(fields)){
		return false;
	}
	
	var tf_entered = document.getElementById('tf_names').value;
	tf_entered = tf_entered.replace(/\s+/,"");
	var tf_names = tf_entered.split(/\s*,\s*/);
	
	var prefix = /^\s*-+.+:/;
	//var prefix = /species/g;
	var sel_option = select_genome.options[select_genome.selectedIndex];
	taxon_id = sel_option.value;
	taxon_name = sel_option.innerHTML;
	var match = prefix.test(taxon_name);
	var index = taxon_name.search(prefix);
	taxon_name = taxon_name.replace(prefix,"");
	
	for (var j=0; j< tf_names.length; j++ ) {
		//use AJAX
		var tf_name = tf_names[j].replace(/\s+/,"");
		if (tf_name == "") continue;
		var params = '&page=find_seqfeature&headertype=text/html&tf_name='+tf_name+'&taxon_id='+taxon_id;
		sendRequest(params, function (response, status) 
		{
			var obj =  response.parseJSON();
			if (obj.error) {
				alert(obj.error +' for '+ taxon_name);
				return;
			} else {
				addRowToTFTable(obj.tf_name, taxon_name, obj.seqfeature_id, el_pubmed_id.value);
			}
		});
	}
}

function format_sequence(seq, max_width) {
	if (max_width >= seq.length)
		return seq;
	var fseq = '';
	var i=0, j=0;
	while ( i<seq.length ) {
		var ch = j<max_width ? seq.charAt(++i) : '<br>';
		if (j==max_width)
			j=-1;
		fseq += ch;
		++j;
	}

	return fseq;
}

function addRowToAlignmentTable(info)
{
	var TABLE_NAME = 'alignment_sequences';
	var tbl = document.getElementById(TABLE_NAME);
	
	var nextRow = tbl.tBodies[0].rows.length;
	var num = nextRow;
	// add the row
	var row = tbl.tBodies[0].insertRow(num);
	
	var cur_cell=0;
	var cell = row.insertCell(cur_cell++);
	cell.setAttribute('align','center');
	cell.innerHTML = info.seqname;
	cell.setAttribute('id', 'seqname');
	cell.setAttribute('name', 'seqname');
	
	cell = row.insertCell(cur_cell++);
	cell.innerHTML = info.species;
	
	cell = row.insertCell(cur_cell++);
	cell.setAttribute('align', 'left');
	cell.setAttribute('id', 'al_sequence');
	cell.setAttribute('name', 'al_sequence');
	cell.innerHTML = format_sequence(info.sequences[0], max_sequence_width);
	
	cell = row.insertCell(cur_cell++);
	cell.setAttribute('align','center');
	cell.setAttribute('id', 'al_locations');
	cell.setAttribute('name', 'al_locations');
	var locations = info.locations;
	var loc = locations[0];
	cell.innerHTML = loc.start + '-' + loc.end;
	
	cell = row.insertCell(cur_cell++);
	cell.setAttribute('align','center');
	cell.setAttribute('id', 'strand');
	cell.setAttribute('name', 'strand');
	cell.innerHTML = loc.strand==1 ? '+' : '-';
	cell = row.insertCell(cur_cell++);
	cell.setAttribute('align','center');
	txtInp = document.createElement('input');
	txtInp.setAttribute('name', 'sequence_gene_name');
	txtInp.setAttribute('id', 'sequence_gene_name');
	//txtInp.parse = _assequence_gene_name;
	cell.appendChild(txtInp);
	
	var fld_seqfeature_id = document.createElement('input');
	fld_seqfeature_id.setAttribute('type', 'hidden');
	fld_seqfeature_id.setAttribute('id', 'gene_id');
	fld_seqfeature_id.setAttribute('name', 'gene_id');
	fld_seqfeature_id.setAttribute('value',"");
	cell.appendChild(fld_seqfeature_id);
	
	cell = row.insertCell(cur_cell++);
	cell.setAttribute('align','left');

	var experiments = document.createElement('select');
	experiments.setAttribute('name', 'experiment');
	experiments.setAttribute('id', 'experiment');
	experiments.setAttribute('multiple', true);
	experiments.setAttribute('size',4);
	for (var i=0; i<experiment_options.length; ++i){
		var option = document.createElement('option');
		option.setAttribute('value', experiment_options[i].id);	
		option.innerHTML = experiment_options[i].name;
		experiments.appendChild(option);
	}
	
	cell.appendChild(experiments);
	var hidden_field = document.createElement('input');
	hidden_field.setAttribute('type', 'hidden');
	hidden_field.setAttribute('id', 'experiment_id');
	hidden_field.setAttribute('name', 'experiment_id');
	hidden_field.setAttribute('value',"");
	cell.appendChild(hidden_field);
	
	cell = row.insertCell(cur_cell++);
	txtInp = document.createElement('input');
	txtInp.setAttribute('name', 'sequence_pubmed_id');
	txtInp.setAttribute('id', 'sequence_pubmed_id');
	cell.appendChild(txtInp);
}

function addRowToTFTable(tf_name, taxon_name, seqfeature_id, pubmed_id)
{
	var TABLE_NAME = 'selected_profiles';
	var tbl = document.getElementById(TABLE_NAME);
	var nextRow = tbl.tBodies[0].rows.length;
	var num = nextRow;
	
	// add the row
	var row = tbl.tBodies[0].insertRow(num);
	var cur_cell=0;

	var cell = row.insertCell(cur_cell++);
	cell.innerHTML = tf_name;
	var txtInp = document.createElement('input');
	txtInp.setAttribute('type', 'hidden');
	txtInp.setAttribute('id', 'tf_name');
	txtInp.setAttribute('name', 'tf_name');
	txtInp.setAttribute('value', tf_name);
	cell.appendChild(txtInp);
	
	cell = row.insertCell(cur_cell++);
	cell.innerHTML = taxon_name;
	txtInp = document.createElement('input');
	txtInp.setAttribute('type', 'hidden');
	txtInp.setAttribute('name', 'taxon_name');
	//txtInp1.setAttribute('width', '40px');
	txtInp.setAttribute('value', taxon_name);
	cell.appendChild(txtInp);

	var fld_seqfeature_id = document.createElement('input');
	fld_seqfeature_id.setAttribute('type', 'hidden');
	fld_seqfeature_id.setAttribute('name', 'seqfeature_id');
	fld_seqfeature_id.setAttribute('value', seqfeature_id);
	cell.appendChild(fld_seqfeature_id);
	
	cell = row.insertCell(cur_cell++);
	cell.innerHTML = pubmed_id;
	txtInp = document.createElement('input');
	txtInp.setAttribute('type', 'hidden');
	txtInp.setAttribute('name', 'pubmed_id');
	txtInp.setAttribute('value', pubmed_id);
	cell.appendChild(txtInp);
	
	
	cell = row.insertCell(cur_cell++);
	var btnEl = document.createElement('input');
	btnEl.setAttribute('type', 'button');
	btnEl.setAttribute('value', 'Delete');
	btnEl.onclick = function () {deleteCurrentRow(this)};
	cell.appendChild(btnEl);
}

// If there isn't an element with an onclick event in your row, then this function can't be used.
function deleteCurrentRow(obj)
{
	//if (hasLoaded) {
		var delRow = obj.parentNode.parentNode;
		var tbl = delRow.parentNode.parentNode;
		var rIndex = delRow.sectionRowIndex;
		delRow.parentNode.deleteRow(rIndex);
		//deleteRows(rowArray);
		//reorderRows(tbl, rIndex);
	//}
}

function add_recommended_options (theSelFrom)
{
	var taxon_ids = new Array();
	var taxon_names = new Array();
	var prefix = /^\s*-+.+:/;
	var cur_index = 0;
	for(var i=0; i < theSelFrom.length; i++) {
		if(theSelFrom.options[i].selected) {
		   	var taxon_id = theSelFrom.options[i].value;
			taxon_ids[cur_index] = taxon_id;
		  	var taxon_name = theSelFrom.options[i].innerHTML;
		  	var index = taxon_name.search(prefix);
		  	taxon_name = taxon_name.replace(prefix,"");
		  	taxon_names[cur_index] = taxon_name;
		  	cur_index++;
		}
	}
	
	if ( taxon_ids.length == 0 ) {
		alert('Please select species.');
		return;
	}
	
	var taxon = document.getElementById("taxon_include_check");
	var inclusion, threshold, distance;
	if ( ! taxon.checked ) {//include
		inclusion = 1;
		//figure threshold
		var precalc_threshold = document.getElementById("precalc_threshold");
		if ( precalc_threshold.checked ) {
			threshold = 'pre-calculate';
		} else {
			var input = document.getElementById("taxon_threshold");
			parser.readValue(input);
		   	if (input.underlyingValue == undefined)
		    	return;
	    	threshold = input.value;
		}
		
		//process distance
		var group = document.getElementById("distance_group");
		var inputs = group.getElementsByTagName("input");
		var start, stop, origin;
		for (var j=0; j< inputs.length; j++) {
			var input = inputs[j];
	   		if (input.type == "text"){
	   			if ( input.id == "distance_from_gene_start" ) {
		   			parser.readValue(input);
				   	if (input.underlyingValue == undefined)
		           		return;
	   				start = parseInt(input.value);
	   			} else if ( input.id == "distance_from_gene_stop" ) {
	   				parser.readValue(input);
				   	if (input.underlyingValue == undefined)
		           		return;
	   				stop = parseInt(input.value);
	   			}
	       	}
	    	if (start > stop) {
	    		alert('format error: start is greater than stop.')
	    		return;
	    	}
	    }
	    var selectFrom = group.getElementsByTagName("select")[0];
	    for(var i=0; i < selectFrom.length; i++) {
			if(selectFrom.options[i].selected) {
			   	origin = selectFrom.options[i].value;
			   	break;
			}
		}
		
		distance = start+":"+stop+":"+origin;
	} else {
		inclusion = 0;
	}
	
	for (var j=0; j< taxon_ids.length; j++ ) {
		addRowToOptionsTable(inclusion, threshold, distance, taxon_names[j], taxon_ids[j]);
	}

}

function addRowToOptionsTable(inclusion, threshold, distance, taxon_name, taxon_id)
{
	var TABLE_NAME = 'recommended_options';
	var tbl = document.getElementById(TABLE_NAME);
	var nextRow = tbl.tBodies[0].rows.length;
	var num = nextRow;
	var curr_cell = 0;
	
	// add the row
	var row = tbl.tBodies[0].insertRow(num);

	var cell = row.insertCell(curr_cell++);
	cell.innerHTML = taxon_name;
	txtInp = document.createElement('input');
	txtInp.setAttribute('type', 'hidden');
	txtInp.setAttribute('id', 'ro_taxon_name');
	txtInp.setAttribute('name', 'ro_taxon_name');
	txtInp.setAttribute('value', taxon_name);
	cell.appendChild(txtInp);
	
	//create hidden input field for storing taxon_id
	var fld_taxon_id = document.createElement('input');
	fld_taxon_id.setAttribute('type', 'hidden');
	fld_taxon_id.setAttribute('id', 'ro_taxon_id');
	fld_taxon_id.setAttribute('name', 'ro_taxon_id');
	fld_taxon_id.setAttribute('value', taxon_id);
	cell.appendChild(fld_taxon_id);
	
	cell = row.insertCell(curr_cell++);
	cell.innerHTML = ( inclusion == 1 ) ? 'include' : 'exclude';
	var txtInp = document.createElement('input');
	txtInp.setAttribute('type', 'hidden');
	txtInp.setAttribute('name', 'inclusion');
	txtInp.setAttribute('value', inclusion);
	cell.appendChild(txtInp);
	
	cell = row.insertCell(curr_cell++);
	var threshold_show = (threshold != null) ? threshold : '';
	cell.innerHTML = threshold_show;
	txtInp = document.createElement('input');
	txtInp.setAttribute('type', 'hidden');
	txtInp.setAttribute('name', 'threshold');
	txtInp.setAttribute('value', threshold);
	cell.appendChild(txtInp);
	
	cell = row.insertCell(curr_cell++);
	var distance_show = '';
	if ( distance!= null ) {
		var region = distance.split(":");
		distance_show = region[0] + ".." + region[1] + " bps " + " from " + region[2];
	}
	cell.innerHTML = distance_show;
	var txtInp = document.createElement('input');
	txtInp.setAttribute('type', 'hidden');
	txtInp.setAttribute('name', 'distance');
	txtInp.setAttribute('value', distance);
	cell.appendChild(txtInp);
	
	cell = row.insertCell(curr_cell++);
	var btnEl = document.createElement('input');
	btnEl.setAttribute('type', 'button');
	btnEl.setAttribute('value', 'Delete');
	btnEl.onclick = function () {deleteCurrentRow(this)};
	cell.appendChild(btnEl);
}


function resetOptions(){
	var option_groups = document.getElementsByName("option_group");
	var taxon = document.getElementById("taxon_include_check");
	for (var i=0; i< option_groups.length; i++) {
		disableGroup(option_groups[i], taxon.checked);
	}
	resetThreshold();
 }
 
 function resetThreshold(){
	var taxon = document.getElementById("taxon_include_check");
	if (taxon==null)
		return;
	if (taxon.checked)
		return;
	var precalc_threshold = document.getElementById("precalc_threshold");
	var taxon_threshold = document.getElementById("taxon_threshold");
	taxon_threshold.disabled = precalc_threshold.checked;

 }
 
 function resetSpacer(){
 	var group = document.getElementById('spacer_group');
	disableGroup(group,ENABLE_GROUP);
		
 	var spacer = document.getElementById('use_spacer_check');
	var group = document.getElementById('spacer_fields');
	disableGroup(group,!spacer.checked);
	
	//spacer use disables file upload
	group = document.getElementById('file_upload_group');
	disableGroup(group, spacer.checked);
 }
    
 function disableGroup(group, flag){
	var disabled_color = "";
   	if ( flag  ){
    			disabled_color = "gray";
       	}
    
    var labels = group.getElementsByTagName("label"); 
	for (var j=0; j< labels.length; j++) {
		var label = labels[j];
     		label.style.color=disabled_color;
    	}
    	
    labels = group.getElementsByTagName("legend"); 
	for (var j=0; j< labels.length; j++) {
		var label = labels[j];
     		label.style.color=disabled_color;
    	}
    
    var inputs = group.getElementsByTagName("input");
	for (var j=0; j< inputs.length; j++) {
		var input = inputs[j];
   		if (input.type != "radio"){
    		input.disabled=flag;
       	}
    }
    var selects = group.getElementsByTagName("select");
	for (var j=0; j< selects.length; j++) {
		var input = selects[j];
      		input.disabled=flag;
    	}
}
	
function onSubmit(oFrm) {
	var pageEl = document.getElementById("page");
	if(document.pressed == 'Upload Fasta File') {
	 	pageEl.value="parse_fasta_file";
	 	var el_file_upload = document.getElementById("file_upload");
	 	el_file_upload.optional = false;
	 	var fields = [el_file_upload];
		var fields_valid = verify_fields(fields);
		if ( !fields_valid)
			return false;
		create_up_seq_table();
	 	AIM.submit(oFrm, {'onStart' : startCallback, 'onComplete' : completeCallback});
	 } else if(document.pressed == 'Submit') {
	 	pageEl.value="process_alignment_entry";
	 	oFrm.setAttribute('target', '_self');
	 	return InfoSubmit(oFrm);
	 }
	return true;
}

function InfoSubmit(oFrm){
	oFrm.organism_name.optional=true;
	oFrm.select_genome.optional=true;
	oFrm.transcription_factor_names.optional=true;
	oFrm.pubmed_ids.optional=true;
	oFrm.organism_name1.optional=true;
	oFrm.select_genome_1.optional=true;
	oFrm.file_upload.optional=true;
	oFrm.accession_number.optional=true;
	oFrm.sequence.optional=true;
	
	var form_valid = false;
	form_valid = verify(oFrm);
	if ( !form_valid ){
		return false;
	}
	
	var errors = "";
	//check if there any rows in selected_profiles table
	var e=document.getElementById('tf_name');
	if ( e == null ) {
		errors += "transcription factors";
		errors += "\n";
	}; 
	
	
	var fld_matrix_info = document.getElementById('matrix_info');
	if ( fld_matrix_info.value == "" ) {
		errors += "alignment sequences";
		errors += "\n";
	} 
	
	
	e=document.getElementById('ro_taxon_id');
	if ( e == null  ) {
		errors += "recommended optons";
		errors += "\n";
	};
	
	if ( errors || (errors && errors != "" ) ) {
		alert('please add: \n'+ errors);
		return false;
	}
	
	 //check if we save the sequences
	e=document.getElementsByName("sequence_gene_name");
	if ( e!=null && e.length > 0 ) {
		alert('Please add alignment sequences');
		return false;
	} 
	
	/*
	var seq_feature_ids = document.getElementsByName('gene_id');
	
	for (var j=0; j< seq_feature_ids.length; j++ ) {
		alert ( seq_feature_ids[j].value  );
	}
	*/
};

var complete_check_field = "\
        var empty_field = '';\n\
	    var error = '';\n\
        var result = check_field(e);\n\
        empty_field += result[0];\n\
        error += result[1];\n\
        var bSuccess = !empty_field && !error;\n\
        if (empty_field) {\n\
    	    msg += '- The required field is empty.' \n\
	    };\n\
	    msg += error;\n\
        this.parse.errorMessage = msg;\n\
        if (!bSuccess) \n\
        	ret = undefined\n\
        else \n\
        	ret = e.value;";
        	        	
function _asspacer_min() {
        var e = this;
        e.numeric = true;
        e.min = 0;
        msg="- spacer: min";
        
        //common part
        var ret = '';
        eval(complete_check_field);
        return ret;
}

function _asspacer_max() {
        var e = this;
        e.numeric = true;
        e.min = 0;
        msg="- spacer: max";
        
        //common part
        var ret = '';
        eval(complete_check_field);
        return ret;
}

function _asdistance_from_gene_start() {
        var e = this;
        e.numeric = true;
        e.min = -500;
        e.max = 100;
        msg="- distance from gene: start";
        
        //common part
        var ret = '';
        eval(complete_check_field);
        return ret;
}

function _asdistance_from_gene_stop() {
        var e = this;
        e.numeric = true;
        e.min = -500;
        e.max = +100;
        msg="- distance from gene: stop";

        //common part
        var ret = '';
        eval(complete_check_field);
        return ret;

}

function _astaxon_threshold() {
        var e = this;
        e.numeric = true;
        e.min = 0;
        e.max = 1.0e-03;
        msg="- threshold";
        //common part
        var ret = '';
        eval(complete_check_field);
        return ret;
}

var parser = new Object;
parser.readValue = function(oField) {
        if (typeof oField.parse == 'function') {
            oField.underlyingValue = oField.parse();
        } else {
            oField.underlyingValue = new String(oField.value);
        }
        if (oField.underlyingValue == undefined){
           	alert(oField.value + oField.parse.errorMessage);
        }
        parser.showFormatted(oField);
}
parser.showUnderlying = function(oField) {
        // don't use alert statements in this function
        if (oField.underlyingValue != undefined) {
                oField.underlyingValue.format = oField.underlyingValue._baseFormat;
                oField.value = oField.underlyingValue.toString();
        }
}
parser.showFormatted = function(oField) {
        if (oField.underlyingValue != undefined) {
                if (typeof oField.format == 'string')
                        oField.underlyingValue.format = oField.format;
                oField.value = oField.underlyingValue.toString();
        }
}


function getHTTPRequest() {
var req = null;
    try
    {
		if( window.XMLHttpRequest ) {
			req = new XMLHttpRequest;
		} else if (window.ActiveXObject) {
			req = new ActiveXObject("Microsoft.XMLHTTP");
		}
    } 
	catch(a){}
	return req;
}

function empty_function()
{
}

function sendRequest(parameters, callback) {
	var request=getHTTPRequest();
	if (!request)  {
		alert('You browser does not allow asynchronous calls. Please use the latest version of the browser.');
		return false;
	}

	if (callback) {
		 request.onreadystatechange=function() {
		 	 if (request.readyState==4) {
				 if (request.status == 200) {
					callback( request.responseText, request.status);
					request.onreadystatechange=empty_function;
				 } else {
					alert ( "Not able to get response from server." );
				 }
			 }
		 }
	}
  request.open("POST",proxyURL,true);
  request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  request.setRequestHeader("Content-length", parameters.length);
  request.setRequestHeader("Connection", "close");
  request.send(parameters);
  //return true;
}

function startCallback() 
{
	// make something useful before submit (onStart)
	return true;
}

function delete_all_rows(tbl) {
	var last_row = tbl.tBodies[0].rows.length-1;
	while (last_row > 0) {
		tbl.tBodies[0].deleteRow(last_row);
		last_row--;
	}
}

//clear alignment_sequences data
function undo_upload_sequences(){
//
	var tbl = document.getElementById('alignment_sequences');
	delete_all_rows(tbl);
	//clear matix_info hash
	var fld_matrix_info = document.getElementById('matrix_info');
	fld_matrix_info.setAttribute('value', "");
	
	var up_seq_info = document.getElementById('up_seq_info');
	up_seq_info.value = "";
	
	tbl = document.getElementById('uploaded_sequence_location');
	delete_all_rows(tbl);
	resetSpacer();
}

function process_select(evt) {
	
	var target = evt.target;
	if (typeof target == 'undefined' )//may happen in IE
		target = document.getElementById('sequence_location');//evt.target;
	var up_seq_info = document.getElementById('up_seq_info');
	var obj = up_seq_info.value.parseJSON();
	var info = obj[0];
	var location = info.locations[target.selectedIndex];
	var up_seq_strand = document.getElementById('up_seq_strand');
	up_seq_strand.innerHTML = location.strand == 1 ? '+' :  '-';
	set_spacer(info, location, CANNOT_MODIFY_LOCATIONS);
}

function create_locations(locations){
	var elloc = document.createElement('select');
	elloc.setAttribute('id', 'sequence_location');
	elloc.setAttribute('name', 'sequence_location');
	var sel_size = locations.length < 4 ? locations.length : 4;
	elloc.setAttribute('size',sel_size);
	for (var i=0; i<locations.length; ++i){
		var option = document.createElement('option');
		option.setAttribute('value', i);
		var loc = locations[i];	
		option.innerHTML = loc.start + '-' + loc.end;
		elloc.appendChild(option);
	}
	if (elloc.addEventListener){
 		elloc.addEventListener('change', process_select, false); 
	} else if (elloc.attachEvent){//IE
  		elloc.attachEvent('onchange', process_select);
	}
	//elloc.onchange = "JavaScript:alert(this.options[this.selectedIndex].value)";
	return elloc;
}

function set_spacer(info, location, can_modify_locations) {
	//check if we can set spacer
	var can_use_spacer = false;
	var spacer_status = COMPLETE_CALL_BACK;
	var fld_matrix_info = document.getElementById('matrix_info');
	var prev_resp = fld_matrix_info.value;
	var spacer = document.getElementById('use_spacer_check');
	var msg="";
	if ( !spacer.checked || prev_resp == "" ){
		info.action = add_sequence_action;
		return [spacer_status, msg];
	}
	//get last sequence
	var prev_obj = prev_resp.parseJSON();
	var last_row_info = prev_obj[prev_obj.length-1];
	var last_locations = last_row_info.locations;
	var last_loc_idx = last_locations.length-1;
	if ( last_loc_idx>0 ){//start new sequences
		info.action = add_sequence_action;
		return [spacer_status, msg];
	}
	
	if ( last_row_info.taxon_id != info.taxon_id ){
		msg="Cannot use spacer for different genomes.";
		spacer_status = UPLOAD_SEQUENCE;
		return [spacer_status, msg];
	}
	 
	var last_location = last_locations[last_loc_idx];
	
	/* set spacer length */
	var spacer_length;
	if (location.strand==last_location.strand){//the same strands
		if (location.strand==1) 
			spacer_length = location.start-last_location.end;
		else 
			spacer_length = last_location.start-location.end;
	} else {//opposite strands
		if (location.strand==1) 
			spacer_length = location.start-last_location.start;
		else 
			spacer_length = location.end-last_location.end;
	}
	
	var spacer_min = document.getElementById("spacer_min").value; 
	var spacer_max = document.getElementById("spacer_max").value;
	can_use_spacer = spacer_min <= spacer_length && spacer_length <= spacer_max;
	
	var cell_spacer = document.getElementById("up_seq_spacer");
	cell_spacer.className = can_use_spacer ? "" : "RED";					
	cell_spacer.innerHTML = spacer_length;
	
	var locations = info.locations;
	if ( !can_use_spacer ){
		msg="Spacer length is outside the range.";
		spacer_status = UPLOAD_SEQUENCE;
		return [spacer_status, msg];
	}
	
	if ( locations.length==1 ) {
		var TABLE_NAME = 'uploaded_sequence_location';
		var tbl = document.getElementById(TABLE_NAME);
		var last_row_idx = tbl.tBodies[0].rows.length-1;
		var row = tbl.tBodies[0].rows[last_row_idx];
		var cell_loc = find_child_by_name(row, 'td', 'up_seq_locations');
		var cell_strand = find_child_by_name(row, 'td', 'up_seq_strand');
		var location = locations[0];
		cell_loc.innerHTML = location.start + '-' + location.end;
		cell_strand.innerHTML = location.strand == 1 ? '+' : '-';
	}
	
	if ( can_modify_locations ) {
		last_row_info.spacer_length = spacer_length;
		last_row_info.spacer_min = document.getElementById("spacer_min").value; 
		last_row_info.spacer_max = document.getElementById("spacer_max").value;
		//add location to the last row
		last_locations[++last_loc_idx] = location;
		// add another sequence. Can re-use last_loc_idx
		var last_sequences = last_row_info.sequences;
		last_sequences[last_loc_idx] = info.sequences[0];
		//save modified matrix.info
		fld_matrix_info.value = prev_obj.toJSONString();
		info.action = add_spacer_action;
	} 
	
	return [spacer_status, msg];;
}

function create_up_seq_table(){
	var TABLE_NAME = 'uploaded_sequence_location';
	var tbl = document.getElementById(TABLE_NAME);
	delete_all_rows(tbl);
	var nextRow = tbl.tBodies[0].rows.length;
	// add the row
	var row = tbl.tBodies[0].insertRow(nextRow);
	var cur_cell=0;
	var cell_loc = row.insertCell(cur_cell++);
	cell_loc.setAttribute('align','center');
	cell_loc.setAttribute('id', 'up_seq_locations');
	cell_loc.setAttribute('name', 'up_seq_locations');
	
	var cell_strand = row.insertCell(cur_cell++);
	cell_strand.setAttribute('align','center');
	cell_strand.setAttribute('id', 'up_seq_strand');
	cell_strand.setAttribute('name', 'up_seq_strand');
	
	var cell_spacer = row.insertCell(cur_cell++);
	cell_spacer.setAttribute('align','center');
	cell_spacer.setAttribute('id', 'up_seq_spacer');
	cell_spacer.setAttribute('name', 'up_seq_spacer');
}

function replace_up_seq_table(info){
	var TABLE_NAME = 'uploaded_sequence_location';
	var tbl = document.getElementById(TABLE_NAME);
	var last_row_idx = tbl.tBodies[0].rows.length-1;
	var row = tbl.tBodies[0].rows[last_row_idx];
	var cell_loc = find_child_by_name(row, 'td', 'up_seq_locations');
	var cell_strand = find_child_by_name(row, 'td', 'up_seq_strand');
	var locations = info.locations;
	if ( locations.length==1 ) {
		var location = locations[0];
		cell_loc.innerHTML = location.start + '-' + location.end;
		cell_strand.innerHTML = location.strand == 1 ? '+' : '-';
	} else
		cell_loc.appendChild(create_locations(locations));
}
function completeCallback(response) {
	var obj =  response.parseJSON();
	if (typeof obj.error != 'undefined') {
		alert(obj.error);
		return;
	}
	
	var fld_matrix_info = document.getElementById('matrix_info');
	var prev_resp = fld_matrix_info.value;
	var info = obj[0];
	var up_seq_info = document.getElementById('up_seq_info');
	if ( info.action==find_sequence_action ){//update uploaded_sequence_location table
		var locations = info.locations;
		if ( locations.length==1 ) {
			var location = locations[0];
			var ret_status = set_spacer(info, location, CAN_MODIFY_LOCATIONS);
			var spacer_status = ret_status[0]; 
			var msg = ret_status[1];
			if ( spacer_status==UPLOAD_SEQUENCE ){
				var up_seq_info = document.getElementById('up_seq_info');
				//up_seq_info.value="";
				if (msg!="")
					alert(msg);
			} else {
				completeCallback(obj.toJSONString());
			}
		} else {//multiple locations
			//cell_loc.appendChild(create_locations(info.locations));
			replace_up_seq_table(info);
			upload_sequence();//have a user select a location
		}
	} else if ( info.action==add_spacer_action ) {
		replace_up_seq_table(info);
		var prev_obj = prev_resp.parseJSON();
		var last_row_index = prev_obj.length-1;
		var last_row_info = prev_obj[last_row_index];
		var last_locations = last_row_info.locations;
		var last_loc_idx = last_locations.length-1; 
		var last_location = last_locations[last_loc_idx];
		var last_sequence = last_row_info.sequences[last_loc_idx];
	  	var TABLE_NAME = 'alignment_sequences';
		var tbl = document.getElementById(TABLE_NAME);
		var lastRowIndex = tbl.tBodies[0].rows.length-1;
		var lastRow = tbl.tBodies[0].rows[lastRowIndex];
		
		//merge sells with new sequence data
		
		var seq_cell = find_child_by_name(lastRow, 'td', 'al_sequence');
		seq_cell.innerHTML += '<br><br>' + format_sequence(last_sequence, max_sequence_width);
		
		var loc_cell = find_child_by_name(lastRow, 'td', 'al_locations');
		loc_cell.innerHTML += '<br><br>'+last_location.start + '-' + last_location.end;
		
		var strand_cell = find_child_by_name(lastRow, 'td', 'strand');
		var sign = last_location.strand==1 ? '+' : '-';
		strand_cell.innerHTML += '<br><br>'+ sign;
		up_seq_info.value = "";
		
	} else {//other actions
		replace_up_seq_table(info);
		up_seq_info.value = "";
		//lock spacer
		var group = document.getElementById('spacer_group');
		disableGroup(group,DISABLE_GROUP);
		
		//add some place holders to info
		for (var j=0; j< obj.length; j++ ) {
			var row_info = obj[j];
			row_info.seqfeature_id = "";
			row_info.experiments = new Array();
			row_info.pubmed_id = "";
		}
		response = obj.toJSONString();
		
		//merge with new response
		var resp = prev_resp == "" ? response : prev_resp.substring(0,prev_resp.length-1) + ',' + 
			response.substring(1,response.length);
		fld_matrix_info.value = resp;
		for (j=0; j< obj.length; ++j)
			addRowToAlignmentTable(obj[j]);
	}
}


/**
*
*  AJAX IFRAME METHOD (AIM)
*  http://www.webtoolkit.info/
*
**/

AIM = {

	frame : function(c) {

		//var n = 'f' + Math.floor(Math.random() * 99999);
		var n = 'fmatrix_info'
		var fid = document.getElementById(n);
		if (fid==null) {
			var d = document.createElement('DIV');
			d.innerHTML = '<iframe style="display:none" src="about:blank" id="'+n+'" name="'+n+'" onload="AIM.loaded(\''+n+'\')"></iframe>';
			document.body.appendChild(d);
		}

		var i = document.getElementById(n);
		if (c && typeof(c.onComplete) == 'function') {
			i.onComplete = c.onComplete;
		}

		return n;
	},

	form : function(f, name) {
		f.setAttribute('target', name);
	},

	submit : function(f, c) {
		AIM.form(f, AIM.frame(c));
		if (c && typeof(c.onStart) == 'function') {
			return c.onStart();
		} else {
			return true;
		}
	},

	loaded : function(id) {
		var i = document.getElementById(id);
		if (i.contentDocument) {
			var d = i.contentDocument;
		} else if (i.contentWindow) {
			var d = i.contentWindow.document;
		} else {
			var d = window.frames[id].document;
		}
		if (d.location.href == "about:blank") {
			return;
		}

		if (typeof(i.onComplete) == 'function') {
			i.onComplete(d.body.innerHTML);
		}
	}

}


// Run code when the page loads.  From
// http://simon.incutio.com/archive/2004/05/26/addLoadEvent
function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}

function init() {
	
	var spacer = document.getElementById('use_spacer_check');
	if (spacer == null)
		return;
	var group = document.getElementById('spacer_group');
	spacer.checked = false;
	resetSpacer();
	var up_seq_info = document.getElementById('up_seq_info');
	up_seq_info.value = "";
	resetOptions();
	resetThreshold();
	//reset matrix_info
	var fld_matrix_info = document.getElementById('matrix_info');
	var matrixAlignment = document.getElementById("matrixAlignment");
	matrixAlignment.taxon_threshold.parse = _astaxon_threshold;
	matrixAlignment.distance_from_gene_start.parse = _asdistance_from_gene_start;
	matrixAlignment.distance_from_gene_stop.parse = _asdistance_from_gene_stop;
	matrixAlignment.spacer_min.parse = _asspacer_min;
	matrixAlignment.spacer_max.parse = _asspacer_max;
	matrixAlignment.name.focus();
}

addLoadEvent( init );

