// snp_viewer.js Primary Snip Viz code ////////////////////////////////// // JavaScript directive: all variables have to be declared with "var", maybe other things "use strict"; //////////////////////////////////////////// // To create a SNP Viewer instance: // call SNPViewer.createSNPViewer( rootDivIdCreateRoot, requestParamsCreateRoot, configParamsCreateRoot, callbackFunctionsObjCreateRoot ) // rootDivIdCreateRoot = String with the id of the div to build the SNP viewer in // In requestParamsCreateRoot, newick or sequenceLabelsArray must be present but not both // requestParamsCreateRoot = { newick: , sequenceLabelsArray: , sequences: , requestType: , requestTypeLabel: } // newick = String containing newick representation of clustering data // sequenceLabelsArray = array with the list of labels for the provided sequences // sequences = object containing labels and sequences = { "label1": "seq1", "label2": "seq2", ... } // requestType = String containing "dna" or "protein". // These strings are available by calling SNPViewer.getRequestTypeDNA() and SNPViewer.getRequestTypeProtein(). // requestTypeLabel = String containing label for the given request type = "bases" or "residues" // configParamsCreateRoot is not currently used // callbackFunctionsObjCreateRoot = { successfullyLoadedCallback: , failToLoadCallBack: } // successfullyLoadedCallback = Method to call when the SNP viewer is completed loading and building the DOM and listeners // failToLoadCallBack = Method to call when the SNP viewer is failed loading and building the DOM and listeners // The code may throw an exception rather than call this method. //////////////////////////////////////////// // To delete a SNP Viewer Instance: // call SNPViewer.deleteSNPViewerFromRootDivId( rootDivIdCreateRoot ) // rootDivIdCreateRoot = String with the id of the div to delete the SNP viewer //////////////////////////////////////////// // Constant values that drive the code // Search for "var constants" for the object with properties that drives much of the code //////////////////////////////////////////// // Constructor function SNPViewer() { // Get the "label" used to store the SNPViewer object in the DOM object this.getDataElement = function() { return "SNPViewer"; }; // Get the "class" used to store the SNPViewer object in the DOM object of the root div var getSNPObjectStorageClassName = function() { return "SNPObjectStorageClass"; }; var snpObjectCounter = 0; // This Javascript object is for computing the score for proteins // BLOSUM80 matrix var proteinScoreStructure = { A:{A: 5, R: -2, N: -2, D: -2, C: -1, Q: -1, E: -1, G: 0, H: -2, I: -2, L: -2, K: -1, M: -1, F: -3, P: -1, S: 1, T: 0, W: -3, Y: -2, V: 0, B: -2, J: -2, Z: -1, X: -1, '*': -6, '-': -10}, R:{A: -2, R: 6, N: -1, D: -2, C: -4, Q: 1, E: -1, G: -3, H: 0, I: -3, L: -3, K: 2, M: -2, F: -4, P: -2, S: -1, T: -1, W: -4, Y: -3, V: -3, B: -1, J: -3, Z: 0, X: -1, '*': -6, '-': -10}, N:{A: -2, R: -1, N: 6, D: 1, C: -3, Q: 0, E: -1, G: -1, H: 0, I: -4, L: -4, K: 0, M: -3, F: -4, P: -3, S: 0, T: 0, W: -4, Y: -3, V: -4, B: 5, J: -4, Z: 0, X: -1, '*': -6, '-': -10}, D:{A: -2, R: -2, N: 1, D: 6, C: -4, Q: -1, E: 1, G: -2, H: -2, I: -4, L: -5, K: -1, M: -4, F: -4, P: -2, S: -1, T: -1, W: -6, Y: -4, V: -4, B: 5, J: -5, Z: 1, X: -1, '*': -6, '-': -10}, C:{A: -1, R: -4, N: -3, D: -4, C: 9, Q: -4, E: -5, G: -4, H: -4, I: -2, L: -2, K: -4, M: -2, F: -3, P: -4, S: -2, T: -1, W: -3, Y: -3, V: -1, B: -4, J: -2, Z: -4, X: -1, '*': -6, '-': -10}, Q:{A: -1, R: 1, N: 0, D: -1, C: -4, Q: 6, E: 2, G: -2, H: 1, I: -3, L: -3, K: 1, M: 0, F: -4, P: -2, S: 0, T: -1, W: -3, Y: -2, V: -3, B: 0, J: -3, Z: 4, X: -1, '*': -6, '-': -10}, E:{A: -1, R: -1, N: -1, D: 1, C: -5, Q: 2, E: 6, G: -3, H: 0, I: -4, L: -4, K: 1, M: -2, F: -4, P: -2, S: 0, T: -1, W: -4, Y: -3, V: -3, B: 1, J: -4, Z: 5, X: -1, '*': -6, '-': -10}, G:{A: 0, R: -3, N: -1, D: -2, C: -4, Q: -2, E: -3, G: 6, H: -3, I: -5, L: -4, K: -2, M: -4, F: -4, P: -3, S: -1, T: -2, W: -4, Y: -4, V: -4, B: -1, J: -5, Z: -3, X: -1, '*': -6, '-': -10}, H:{A: -2, R: 0, N: 0, D: -2, C: -4, Q: 1, E: 0, G: -3, H: 8, I: -4, L: -3, K: -1, M: -2, F: -2, P: -3, S: -1, T: -2, W: -3, Y: 2, V: -4, B: -1, J: -4, Z: 0, X: -1, '*': -6, '-': -10}, I:{A: -2, R: -3, N: -4, D: -4, C: -2, Q: -3, E: -4, G: -5, H: -4, I: 5, L: 1, K: -3, M: 1, F: -1, P: -4, S: -3, T: -1, W: -3, Y: -2, V: 3, B: -4, J: 3, Z: -4, X: -1, '*': -6, '-': -10}, L:{A: -2, R: -3, N: -4, D: -5, C: -2, Q: -3, E: -4, G: -4, H: -3, I: 1, L: 4, K: -3, M: 2, F: 0, P: -3, S: -3, T: -2, W: -2, Y: -2, V: 1, B: -4, J: 3, Z: -3, X: -1, '*': -6, '-': -10}, K:{A: -1, R: 2, N: 0, D: -1, C: -4, Q: 1, E: 1, G: -2, H: -1, I: -3, L: -3, K: 5, M: -2, F: -4, P: -1, S: -1, T: -1, W: -4, Y: -3, V: -3, B: -1, J: -3, Z: 1, X: -1, '*': -6, '-': -10}, M:{A: -1, R: -2, N: -3, D: -4, C: -2, Q: 0, E: -2, G: -4, H: -2, I: 1, L: 2, K: -2, M: 6, F: 0, P: -3, S: -2, T: -1, W: -2, Y: -2, V: 1, B: -3, J: 2, Z: -1, X: -1, '*': -6, '-': -10}, F:{A: -3, R: -4, N: -4, D: -4, C: -3, Q: -4, E: -4, G: -4, H: -2, I: -1, L: 0, K: -4, M: 0, F: 6, P: -4, S: -3, T: -2, W: 0, Y: 3, V: -1, B: -4, J: 0, Z: -4, X: -1, '*': -6, '-': -10}, P:{A: -1, R: -2, N: -3, D: -2, C: -4, Q: -2, E: -2, G: -3, H: -3, I: -4, L: -3, K: -1, M: -3, F: -4, P: 8, S: -1, T: -2, W: -5, Y: -4, V: -3, B: -2, J: -4, Z: -2, X: -1, '*': -6, '-': -10}, S:{A: 1, R: -1, N: 0, D: -1, C: -2, Q: 0, E: 0, G: -1, H: -1, I: -3, L: -3, K: -1, M: -2, F: -3, P: -1, S: 5, T: 1, W: -4, Y: -2, V: -2, B: 0, J: -3, Z: 0, X: -1, '*': -6, '-': -10}, T:{A: 0, R: -1, N: 0, D: -1, C: -1, Q: -1, E: -1, G: -2, H: -2, I: -1, L: -2, K: -1, M: -1, F: -2, P: -2, S: 1, T: 5, W: -4, Y: -2, V: 0, B: -1, J: -1, Z: -1, X: -1, '*': -6, '-': -10}, W:{A: -3, R: -4, N: -4, D: -6, C: -3, Q: -3, E: -4, G: -4, H: -3, I: -3, L: -2, K: -4, M: -2, F: 0, P: -5, S: -4, T: -4, W: 11, Y: 2, V: -3, B: -5, J: -3, Z: -3, X: -1, '*': -6, '-': -10}, Y:{A: -2, R: -3, N: -3, D: -4, C: -3, Q: -2, E: -3, G: -4, H: 2, I: -2, L: -2, K: -3, M: -2, F: 3, P: -4, S: -2, T: -2, W: 2, Y: 7, V: -2, B: -3, J: -2, Z: -3, X: -1, '*': -6, '-': -10}, V:{A: 0, R: -3, N: -4, D: -4, C: -1, Q: -3, E: -3, G: -4, H: -4, I: 3, L: 1, K: -3, M: 1, F: -1, P: -3, S: -2, T: 0, W: -3, Y: -2, V: 4, B: -4, J: 2, Z: -3, X: -1, '*': -6, '-': -10}, B:{A: -2, R: -1, N: 5, D: 5, C: -4, Q: 0, E: 1, G: -1, H: -1, I: -4, L: -4, K: -1, M: -3, F: -4, P: -2, S: 0, T: -1, W: -5, Y: -3, V: -4, B: 5, J: -4, Z: 0, X: -1, '*': -6, '-': -10}, J:{A: -2, R: -3, N: -4, D: -5, C: -2, Q: -3, E: -4, G: -5, H: -4, I: 3, L: 3, K: -3, M: 2, F: 0, P: -4, S: -3, T: -1, W: -3, Y: -2, V: 2, B: -4, J: 3, Z: -3, X: -1, '*': -6, '-': -10}, Z:{A: -1, R: 0, N: 0, D: 1, C: -4, Q: 4, E: 5, G: -3, H: 0, I: -4, L: -3, K: 1, M: -1, F: -4, P: -2, S: 0, T: -1, W: -3, Y: -3, V: -3, B: 0, J: -3, Z: 5, X: -1, '*': -6, '-': -10}, X:{A: -1, R: -1, N: -1, D: -1, C: -1, Q: -1, E: -1, G: -1, H: -1, I: -1, L: -1, K: -1, M: -1, F: -1, P: -1, S: -1, T: -1, W: -1, Y: -1, V: -1, B: -1, J: -1, Z: -1, X: -1, '*': -6, '-': -10}, '*':{A: -6, R: -6, N: -6, D: -6, C: -6, Q: -6, E: -6, G: -6, H: -6, I: -6, L: -6, K: -6, M: -6, F: -6, P: -6, S: -6, T: -6, W: -6, Y: -6, V: -6, B: -6, J: -6, Z: -6, X: -6, '*': 1, '-': -10}, '-':{A: -10, R: -10, N: -10, D: -10, C: -10, Q: -10, E: -10, G: -10, H: -10, I: -10, L: -10, K: -10, M: -10, F: -10, P: -10, S: -10, T: -10, W: -10, Y: -10, V: -10, B: -10, J: -10, Z: -10, X: -10, '*': -10, '-': 1} }; // This Javascript object is for DNA for determining which differences are "silent" // DNA codonds by the Amino Acid they generate var dnaCodonsByGenAminoAcidInitialArray = [ [ 'ATT', 'ATC', 'ATA' ], [ 'CTT', 'CTC', 'CTA', 'CTG', 'TTA', 'TTG' ], [ 'GTT', 'GTC', 'GTA', 'GTG' ], [ 'TTT', 'TTC' ], [ 'ATG' ], [ 'TGT', 'TGC' ], [ 'GCT', 'GCC', 'GCA', 'GCG' ], [ 'GGT', 'GGC', 'GGA', 'GGG' ], [ 'CCT', 'CCC', 'CCA', 'CCG' ], [ 'ACT', 'ACC', 'ACA', 'ACG' ], [ 'TCT', 'TCC', 'TCA', 'TCG', 'AGT', 'AGC' ], [ 'TAT', 'TAC' ], [ 'TGG' ], [ 'CAA', 'CAG' ], [ 'AAT', 'AAC' ], [ 'CAT', 'CAC' ], [ 'GAA', 'GAG' ], [ 'GAT', 'GAC' ], [ 'AAA', 'AAG' ], [ 'CGT', 'CGC', 'CGA', 'CGG', 'AGA', 'AGG' ], [ 'TAA', 'TAG', 'TGA' ] ]; // function to load the array into an object of objects for easier lookup var dnaCodonsByGenAminoAcidSetup = function( ) { var dnaCodonsByGenAminoAcid = {}; for ( var outerCount = 0; outerCount < dnaCodonsByGenAminoAcidInitialArray.length; outerCount++ ) { var dnaCodonOriginalAssocArray = dnaCodonsByGenAminoAcidInitialArray[ outerCount ]; for ( var dnaCodonAssocArrayCount = 0; dnaCodonAssocArrayCount < dnaCodonOriginalAssocArray.length; dnaCodonAssocArrayCount++ ) { var dnaCodonInArray = dnaCodonOriginalAssocArray[ dnaCodonAssocArrayCount ]; var dnaCodonNewSubAssocObject = {}; for ( var copyCount = 0; copyCount < dnaCodonOriginalAssocArray.length; copyCount++ ) { if ( copyCount !== dnaCodonAssocArrayCount ) { dnaCodonNewSubAssocObject[ dnaCodonOriginalAssocArray[ copyCount ] ] = true; } } dnaCodonsByGenAminoAcid[ dnaCodonInArray ] = dnaCodonNewSubAssocObject; } } return dnaCodonsByGenAminoAcid; } // dnaCodonsByGenAminoAcid = { 'codon1': { 'assocCodon1a': true, 'assocCodon1b': true }, 'codon2': { 'assocCodon2a': true, 'assocCodon2b': true }, ... } var dnaCodonsByGenAminoAcid = dnaCodonsByGenAminoAcidSetup( ); //////////////////////// // getProteinScoreForTwoLetters // compute the score between 2 protein letters, based on the above matrix var getProteinScoreForTwoLetters = function ( letter1, letter2 ) { var proteinScoreGroup = proteinScoreStructure[ letter1 ]; if ( proteinScoreGroup === undefined ) { throw "getProteinScoreForTwoLetters( letter1, letter2 ): letter1 is not found in proteinScoreStructure, letter1 = |" + letter1 + "|"; } var proteinScore = proteinScoreGroup[ letter2 ]; if ( proteinScore === undefined ) { throw "getProteinScoreForTwoLetters( letter1, letter2 ): letter2 is not found in proteinScoreGroup, letter1 = |" + letter1 + "|, letter2 = |" + letter2 + "|"; } return proteinScore; }; //////////////////////// // getDNACodonAssocCodons // get the object of associated DNA Codons that generate the same Amino Acid var getDNACodonAssocCodons = function ( dnaCodon ) { var DNACodonAssocCodons = dnaCodonsByGenAminoAcid[ dnaCodon ]; if ( ! DNACodonAssocCodons ) { DNACodonAssocCodons = null; } return DNACodonAssocCodons; }; //////////////////////////////////////////////// // static function to delete a SNP viewer // This uses jQuery to removing everything inside the enclosing div, removing all listeners to those HTML elements in the process // The overall SNPViewerInternal object is attached to an object that is a child div so when that div is removed, // the overall SNPViewerInternal object is free to be garbage collected unless other code on the page is holding a reference. // this.deleteSNPViewerFromRootDivId this.deleteSNPViewerFromRootDivId = function ( rootDivIdCreateRoot ) { var $rootDivIdCreateRoot = $("#" + rootDivIdCreateRoot ); // getting the actual SNPViewer object is optional since it will go away when it is no longer referenced. // var SNPObjectStorageNodeSelector = "#" + rootDivIdCreateRoot + " ." + getSNPObjectStorageClassName(); // // var $SNPObjectStorageNode = $( SNPObjectStorageNodeSelector ); // // var internalVariableSNPViewer = $SNPObjectStorageNode.data( SNPViewer.getDataElement() ); $rootDivIdCreateRoot.empty(); }; // static function to create a new object this.createSNPViewer = function ( rootDivIdCreateRoot, requestParamsCreateRoot, configParamsCreateRoot, callbackFunctionsObjCreateRoot ) { // internal "class" constructor to create actual stored object var SNPViewerInternal = function ( rootDivId, requestParams, configParams, callbackFunctionsObj ) { snpObjectCounter++; var SNPIDCounterAppend = "-" + snpObjectCounter; // callbackFunctionsObj // { successfullyLoadedCallback: successfullyLoadedCallback, failToLoadCallBack: failToLoadCallBack } var isLoggingToConsole = function( ) { return false; if ( console ) { return true; } }; var logToConsole = function( itemToLog ) { if ( console ) { // console.log( itemToLog ); } }; var $rootDivId = $("#" + rootDivId ); if ( $rootDivId.size() === 0 ) { throw "Unable to find root div id passed in, rootDivID = " + rootDivId; } // Hide the root div so the user doesn't see it being developed $( $rootDivId ).css("visibility", "hidden"); var newickString = requestParams.newick; var sequenceLabelsArray = requestParams.sequenceLabelsArray; var sequencesObject = requestParams.sequences; var requestType = requestParams.requestType; var requestTypeLabel = requestParams.requestTypeLabel; // put on the page after "Showing " if ( newickString !== undefined && sequenceLabelsArray !== undefined ) { throw "requestParams.newick and requestParams.sequenceLabelsArray cannot both be set to a value"; } if ( ( newickString === undefined || newickString === "" ) && ( sequenceLabelsArray === undefined || sequenceLabelsArray.length === 0 ) ) { throw "requestParams.newick or requestParams.sequenceLabelsArray must be set to a value, but not both"; } if ( sequencesObject === undefined || sequencesObject === null ) { throw "requestParams.sequences must be set to a value"; } if ( requestType === undefined || requestType === "" ) { throw "requestParams.requestType must be set to a value"; } if ( requestTypeLabel === undefined || requestTypeLabel === "" ) { throw "requestParams.requestTypeLabel must be set to a value"; } if ( SNPViewer.getRequestTypeDNA() !== requestType && SNPViewer.getRequestTypeProtein() !== requestType ) { throw "requestParams.requestType must be '" + SNPViewer.getRequestTypeDNA() + "' or '" + SNPViewer.getRequestTypeProtein() + "'."; } if ( callbackFunctionsObj.successfullyLoadedCallback === undefined || callbackFunctionsObj.successfullyLoadedCallback === null ) { throw "callbackFunctionsObj.successfullyLoadedCallback must be set to a value"; } if ( callbackFunctionsObj.failToLoadCallBack === undefined || callbackFunctionsObj.failToLoadCallBack === null ) { throw "callbackFunctionsObj.failToLoadCallBack must be set to a value"; } // callbackFunctionsObj // { successfullyLoadedCallback: successfullyLoadedCallback, failToLoadCallBack: failToLoadCallBack } ////////////////// /// Constants var constants = { standardDNACodonLength: 3, // number of characters in one DNA codon minimumDraggableBoxInnerWidth: 8, // optional widths of a single bar where the selector box is, ( For 1 bar = one letter ) optionalWidthsOfAboveSingleLineOneToOne: [ 4, 3, 2 ], // [ 5, 4, 3 ], // optional widths of a single bar where the selector box is optionalWidthsOfAboveSingleLine: [ 2 ], // [ 5, 4, 3 ], // minimum height of a single bar where the selector box is minHeightOfAboveSingleLine: 4, // opacity value for DNA silent mutations on a scale of zero to one. dnaSilentMutationOpacity: 0.5, // minimum opacity value on a scale of zero to one. minOpacity: 0.4, // For Sequence block, the number of columns displayed will be a multiple of this seqBlockColumnMultiple: 5, // For Sequence block, remove this from available width to help ensure it doesn't wrap onto the next line seqBlockPaddingRight: 5, // in pixels // Dendrogram constants // width in pixels widthDendrogramOneLevel: 10, dendrogramLineColor: "#ff0000", // red // ID constants sequenceIdPrefix: "sequence", barIdPrefix: "barPos", strainIdPrefix: "strain", // attribute in the strain that identifies it's position arrayIndexAttrLabel: "arrayIndex", // attribute in the sequenceLetter that identifies it's position sequencePositionAttrLabel: "seqPos", strainPermHighlightingAttrYes: "YES", strainPermHighlightingAttrNo: "NO", strainHoverHighlightingAttrYes: "YES", strainHoverHighlightingAttrNo: "NO", upperBarChartEntryIdPrefix: "upperBarChartEntry-", // a single pixel PNG with a transparent clear background transparentPixelPNG: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAAXNSR0IArs4c6QAAAAtJREFUCNdjYGAAAAADAAEg1ZTHAAAAAElFTkSuQmCC" }; /////////////////////// // Classes ///////////// // this is for processing the block that displays the sequences var SequenceDisplayBlock = function ( ) { this.parentToUpdateOnChange = undefined; // set later this.currentLeftSequencePosition = 0; /////////////////////////////////////////////////// // setParentToUpdateOnChange // Set the parent to update this.setParentToUpdateOnChange = function ( parentToUpdateOnChangeNewValue ) { this.parentToUpdateOnChange = parentToUpdateOnChangeNewValue; } /////////////////////////////////////////////////// // populateSequenceBlock // put the chunk of the sequences that will fit into the block this.populateSequenceBlock = function ( ) { if ( this.parentToUpdateOnChange === undefined || this.parentToUpdateOnChange === null ) { throw "SequenceDisplayBlock object state error: this.parentToUpdateOnChange must be set before calling this.populateSequenceBlock()"; } this.populateBarChartDivsOfSeqBlock(); this.populateMainSequenceBlock(); }; /////////////////////////////////////////////////// // updateSequenceBlockForStrainChange // update the sequence block for a strain being clicked on ( selected or deselected ) this.updateSequenceBlockForStrainChange = function ( ) { if ( this.parentToUpdateOnChange === undefined || this.parentToUpdateOnChange === null ) { throw "SequenceDisplayBlock object state error: this.parentToUpdateOnChange must be set before calling this.updateSequenceBlockForStrainChange()"; } this.populateBarChartDivsOfSeqBlock(); this.populateMainSequenceBlock(); }; /////////////////////////////////////////////////// // private // populateBarChartDivsOfSeqBlock // populate the Bar Chart Divs Of the Sequence Block this.populateBarChartDivsOfSeqBlock = function ( ) { var count; var barChartRoot = $("#barChart" + SNPIDCounterAppend); // remove existing data in the block barChartRoot.empty(); // Place space characters (" ") in the barChart area var barChartDivsToAdd = ""; for ( count = 0; count < globalVariables.numberOfSeqCharsDisplayed; count++ ) { var seqPosition = count + this.currentLeftSequencePosition; var score = globalVariables.sequenceVarianceScoresArray[ seqPosition ]; if ( score > 0 ) { var scoreIE8 = score * 100; // 0 - 100; barChartDivsToAdd += "
 
"; } else { barChartDivsToAdd += "
 
"; } if ( SNPViewer.getRequestTypeDNA() === requestType && count < ( globalVariables.numberOfSeqCharsDisplayed - 1 ) && seqPosition % constants.standardDNACodonLength === ( constants.standardDNACodonLength - 1 ) ) { barChartDivsToAdd += "
 
"; } } barChartRoot.append( barChartDivsToAdd ); }; /////////////////////////////////////////////////// // populateMainSequenceBlock // populate the Main Sequence Block this.populateMainSequenceBlock = function ( ) { var seqNum; var seqArr = globalVariables.sequencesInStrainOrder.sequences; var sequencesRoot = $("#SequencesRoot" + SNPIDCounterAppend); // remove existing data in the block sequencesRoot.empty(); var lastSequenceNum = seqArr.length - 1; var lastPosition = globalVariables.numberOfSeqCharsDisplayed - 1; // loop through sequences for( seqNum = 0; seqNum < seqArr.length; seqNum++ ){ var strainHighlighted = false; var classAddForStrainHighlighted = ""; var strainItem = globalVariables.strainList[ seqNum ]; if ( ( strainItem.strainPermHighlighting === constants.strainPermHighlightingAttrYes ) || ( strainItem.strainHoverHighlighting === constants.strainHoverHighlightingAttrYes ) ) { strainHighlighted = true; } var sequence = seqArr[ seqNum ].sequence; sequencesRoot.append( "
" ); var sequenceDiv = $("#" + constants.sequenceIdPrefix + seqNum + SNPIDCounterAppend ); var letterDivs = ""; // loop through positions for( var pos = 0; pos < globalVariables.numberOfSeqCharsDisplayed; pos++ ){ var seqSingle = sequence.charAt( pos + this.currentLeftSequencePosition ); var seqPos = pos + this.currentLeftSequencePosition; var seqId = createSequenceId( seqNum, seqPos ); var score = globalVariables.sequenceVarianceScoresArray[ seqPos ]; letterDivs += "
" + seqSingle + "
"; if ( SNPViewer.getRequestTypeDNA() === requestType && pos < ( globalVariables.numberOfSeqCharsDisplayed - 1 ) && seqPos % constants.standardDNACodonLength === ( constants.standardDNACodonLength - 1 ) ) { letterDivs += "
 
"; } } sequenceDiv.append( letterDivs ); // var strainItem = globalVariables.strainList[ seqNum ]; // // if ( ( strainItem.strainPermHighlighting === constants.strainPermHighlightingAttrYes ) || // ( strainItem.strainHoverHighlighting === constants.strainHoverHighlightingAttrYes ) ) { // // highlightSequenceLetters( seqNum ); // } } // enable/disable the left and right arrows by showing the appropriate arrows if ( this.currentLeftSequencePosition <= 0 ) { // page left disabled $( "#left-scroll-arrow" + SNPIDCounterAppend ).hide(); $( "#left-scroll-arrow-disabled" + SNPIDCounterAppend ).show(); } else { // page left enabled $( "#left-scroll-arrow-disabled" + SNPIDCounterAppend ).hide(); $( "#left-scroll-arrow" + SNPIDCounterAppend ).show(); } if ( this.currentLeftSequencePosition >= ( globalVariables.primaryBarChartData.maxSequenceLength - globalVariables.numberOfSeqCharsDisplayed ) ) { // page right disabled $( "#right-scroll-arrow" + SNPIDCounterAppend ).hide(); $( "#right-scroll-arrow-disabled" + SNPIDCounterAppend ).show(); } else { // page right enabled $( "#right-scroll-arrow-disabled" + SNPIDCounterAppend ).hide(); $( "#right-scroll-arrow" + SNPIDCounterAppend ).show(); } // var dnaStartIdent = "
"; // // // loop through positions // for( var pos = 0; pos < globalVariables.numberOfSeqCharsDisplayed; pos++ ){ // // var seqPos = pos + this.currentLeftSequencePosition; // // if ( ( seqPos % 3 ) === 0 ) { // // dnaStartIdent += "
@
"; // } else { // // dnaStartIdent += "
 
"; // } // // // if ( SNPViewer.getRequestTypeDNA() === requestType && seqPos % constants.standardDNACodonLength === ( constants.standardDNACodonLength - 1 ) ) { // // dnaStartIdent += "
 
"; // } // } // // dnaStartIdent += "
"; // // sequencesRoot.append( dnaStartIdent ); }; /////////////////////////////////////////////////// // addNavArrowsBelowSequenceBlock - called once on SNP viewer creation to set up the navigation arrows this.addNavArrowsBelowSequenceBlock = function() { // Add nav arrows below the sequence block. // Assume that the sequence block is initially created at the start of the sequences ( start position zero ). var htmlAdditionForArrow = "