22 April 2011

Playing with the HTML5 File API: translating a Fasta file.

In the current post, I'm using the new HTML5 File Api. This new API can read the content of a file on the client side without needing a remote server. Let me repeat this:

YOU DO NOT NEED A SERVER
YOU DO NOT NEED TO COPY AND PASTE THE CONTENT OF THE FILE IN A TEXTAREA
.
As an example, the following code reads a whole DNA fasta file stored on your computer and translate each DNA sequence to a protein. When the user selects a new file, a FileReader object is created and a callback function translating the DNA is invoked when the fasta file has been loaded.

Test (your browser must support HTML5)

:

Source code

<html>
<head>
</head>
<body>
<form>
<label for="ZmlsZXMKfiles">Select a FASTA file</label>:<input type="file" id="ZmlsZXMKfiles" multiple="true"/>
</form>
<script type="application/ecmascript">
var GENETIC_CODE="FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG";
function base2index(c)
{
switch(c)
{
case 'T':case 't': return 0;
case 'C':case 'c': return 1;
case 'A':case 'a': return 2;
case 'G':case 'g': return 3;
default: return -1;
}
}
function translate(dna)
{
var prot="";
for(var i=0;i+2 < dna.length;i+=3)
{
var base1= base2index(dna[i+0]);
var base2= base2index(dna[i+1]);
var base3= base2index(dna[i+2]);
if(base1==-1 || base2==-1 || base3==-1)
{
prot+='?';
}
else
{
prot+=GENETIC_CODE[base1*16+base2*4+base3];
}
}
return prot;
}
function readingFasta(evt)
{
if (!evt.lengthComputable) return;
var loaded = (evt.loaded / evt.total);
if (loaded > 1) return;
var pre=document.getElementById('ZmlsZXMKtext');
while(pre.hasChildNodes()) pre.removeChild( pre.firstChild );
pre.appendChild(document.createTextNode("Reading "+Math.round(loaded*100)+"%"));
}
function endReadFasta(e)
{
var pre=document.getElementById('ZmlsZXMKtext');
while(pre.hasChildNodes()) pre.removeChild( pre.firstChild );
var lines=e.target.result.split("\n");
var dna="";
var i=0;
var line;
for(;;)
{
if(i==lines.length || (line=lines[i].replace(/^\s+|\s+$/g,""))[0]=='>')
{
if(dna.length > 0)
{
var prot=translate(dna);
var j=0;
while(j < prot.length)
{
pre.appendChild(document.createTextNode(prot.substring(j,j+50)));
pre.appendChild(document.createElement("br"));
j+=50;
}
}
if(i===lines.length) break;
pre.appendChild(document.createTextNode(line));
pre.appendChild(document.createElement("br"));
dna="";
}
else
{
dna+=line;
}
++i;
}
}
function handleFileSelect(evt)
{
var files = evt.target.files; // FileList object
if(files.length!=1) return;
var reader = new FileReader();
reader.onprogress=readingFasta;
reader.onloadend=endReadFasta;
var pre=document.getElementById('ZmlsZXMKtext');
while(pre.hasChildNodes()) pre.removeChild( pre.firstChild );
pre.appendChild(document.createTextNode("Reading "+files[0].name+"..."));
reader.readAsText(files[0]);
}
document.getElementById('ZmlsZXMKfiles').addEventListener('change', handleFileSelect, false);
</script>
<pre id="ZmlsZXMKtext"></pre>
</body>
</html>
view raw translate.html hosted with ❤ by GitHub


That's it,

Pierre

1 comment:

Daniel Standage said...

Awesome! I did a lot of web programming in a former life, but I haven't kept up with the latest developments. It will be interesting to see how new web technologies impact bioinformatics!