File API File and Reader Objects Client Server Tutorial

File API File and Reader Objects Client Server Tutorial

File API File and Reader Objects Client Server Tutorial

When you are “surfing the net” entering URLs in web browser address bars or clicking hyperlinks you are a “client” but once you “go” you visit a “server” of one sort or another, and today, moving forward with our “media browser” web application we start down the road adding to …

  • the “client” browsing we’ve started … with …
  • “server” feeling interfacings …

… in the sense that we add a chance for the user to enter a URL for some “server based media data input” as well as a “pallette” on which to display the user work, which we use an HTML5 canvas element for. Now the canvas is a client element collecting user graphical data, it also serves as a “conduit” type of element to the “server” world, what we tend to classify as …

  • a sharing mechanism, given the web support to sharing canvas data as image data that can be attached in an email for instance … as well as an …
  • accountability tool … as a way to save your work for later in the session, and perhaps as we go along but not today, between sessions

… that latter condition a “mulling point” as we are going to try to go as far as we can without involving a “serverside” language like PHP. All this work is the HTML and Javascript and CSS available to everybody who can access a web browser and a text editor, at its simplest.

Please feel free to see what we mean trying out that “halfway house” between “client” and “server”, the great “canvas” graphical tool that came in with HTML with server_client.html‘s live run link, a lot of which will be familiar to you from yesterday’s File API File and Reader Objects Aesthetics Tutorial “client” forerunner work.


Previous relevant File API File and Reader Objects Aesthetics Tutorial is shown below.

File API File and Reader Objects Aesthetics Tutorial

File API File and Reader Objects Aesthetics Tutorial

Yesterday’s File API File and Reader Objects Primer Tutorial left us with a web application that presented input type=file “multiple” collected local (ie.client) file data into …

  • new (webpage popup) window … the default, or …
  • iframe

… that latter option lacking “aesthetic” qualities, we reckon. In thinking about how to improve the “iframe” functionality aesthetics we first thought …

  • horizontally separating … the 4 categories of file data (image, audio, video, other) … into an HTML table, one “tr” row, with 4 “td” columns … but rejected this because any one data type (other than “audio”) could hog 100% of device width on its own … so instead we changed our thinking to code for …
  • vertically separating via …
    1. (our favourite “reveal” strategy pairing of) details/summary tags (or div/div nested for Microsoft Internet Explorer and Edge browsers) … combined with …
    2. horizontal rule (hr) elements

… combined with event logic with that “vertical separating” whereby a first time new category of data usage’s chances of presenting the new data “above the fold” is improved (an easier and/or more natural proposition with “vertical separating” than with “horizontal separating”, we think).

The “details/summary” logic is much simpler here, just involving Javascript codelines such as …


document.getElementById('dtlo').open=false; // closes a details dataset
document.getElementById('dtlv').open=true; // opens a details dataset

The ▶ “div/div” nested iframe logic 🔻 is quite complex, involving Javascript codelines (exemplified for the image data type code) such as …


// global Javascript (up the top) below
var isIE = (navigator.appName == 'Microsoft Internet Explorer' || (navigator.appName == "Netscape" && navigator.appVersion.indexOf('Edge') > -1));
var dsplus="Image";
var dsprefix="<details open><summary>"; // + dsplus
var dsmid="</summary>";
var dssuffix="<hr></details>";

if (isIE) {
dsprefix="<div style=vertical-align:top; id=divsummarytotalsimage style='display:inline-block;vertical-align:top;' onclick=\"document.getElementById('xx').style.display=document.getElementById(tdownright('xx')).style.display.replace('inline-block','no~ne').replace('none','inline-bl~ock').replace('~','');\"><span style='display:iNlInE-bLoCk;' id=rightimage>&#9654;</span><span style='display:NoNe;' id=downimage>&#128315;</span> <DIV id=divshtimage style='display:inline-block;vertical-align:top;'><span id=summarytotalsimage>"; // + dsplus
dsmid="</span>";
dssuffix="</DIV><hr></div>";
}

// snippet within readBlob() function below
if (dsprefix.indexOf('image') != -1) {
dp='<hr>' + dsprefix.replace(/xx/g,'vb').replace(/image/g,'video') + 'Video' + dsmid + dssuffix;
dp+=dsprefix.replace(/xx/g,'ab').replace(/image/g,'audio') + 'Audio' + dsmid + dssuffix;
dp+=dsprefix.replace(/xx/g,'ib').replace(/image/g,'other') + 'Other' + dsmid + dssuffix;
dp+=dsprefix.replace('iNlInE-bLoCk','none').replace('NoNe','inline-block').replace(/xx/g,'gb') + 'Image' + dsmid;
}
else {
dp=dsprefix.replace('><',' id=dtlv><') + 'Video  ' + dsmid + dssuffix;
dp+=dsprefix.replace('><',' id=dtla><') + 'Audio  ' + dsmid + dssuffix;
dp+=dsprefix.replace('><',' id=dtlo><') + 'Other  ' + dsmid + dssuffix;
dp+=dsprefix.replace('><',' id=dtli><') + 'Image  ' + dsmid;
}
document.getElementById('icontent').innerHTML+=dp + ipre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + isuf + ds;

} else if (document.getElementById('dtli') || document.getElementById('divshtimage')) {
if (dsprefix.indexOf('image') != -1) {
if (document.getElementById('ab')) { document.getElementById(downright('ab')).style.display='none'; }
if (document.getElementById('vb')) { document.getElementById(downright('vb')).style.display='none'; }
if (document.getElementById('ib')) { document.getElementById(downright('ib')).style.display='none'; }
document.getElementById('divshtimage').innerHTML+=ipre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + isuf;
tdownright('gb');
}
else {
document.getElementById('dtla').open=false;
document.getElementById('dtlv').open=false;
document.getElementById('dtlo').open=false;
document.getElementById('dtli').open=true;
document.getElementById('dtli').innerHTML+=ipre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + isuf;
}
} else {
document.getElementById('icontent').innerHTML+=ipre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + isuf;
}
} else {
wo=window.open(wp1,wp2);
wo.document.write(ipre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + isuf);
wo.document.title = mfile.name.replace(/\\/g,'/').split('/')[eval(-1 + mfile.name.replace(/\\/g,'/').split('/').length)];
}
} // else if ... audio/video/other

// end of readBlob snippet above

function tdownright(inid) {
if (inid.substring(0,1) == 'g') {
document.getElementById('rightimage').style.display=document.getElementById('rightimage').style.display.toLowerCase().replace('inline-block','no~ne').replace('none','inline-bl~ock').replace('~',''); //'inline-block';
document.getElementById('downimage').style.display=document.getElementById('downimage').style.display.toLowerCase().replace('inline-block','no~ne').replace('none','inline-bl~ock').replace('~','');
} else if (inid.substring(0,1) == 'a') {
document.getElementById('rightaudio').style.display=document.getElementById('rightaudio').style.display.toLowerCase().replace('inline-block','no~ne').replace('none','inline-bl~ock').replace('~','');
document.getElementById('downaudio').style.display=document.getElementById('downaudio').style.display.toLowerCase().replace('inline-block','no~ne').replace('none','inline-bl~ock').replace('~','');
} else if (inid.substring(0,1) == 'v') {
document.getElementById('rightvideo').style.display=document.getElementById('rightvideo').style.display.toLowerCase().replace('inline-block','no~ne').replace('none','inline-bl~ock').replace('~','');
document.getElementById('downvideo').style.display=document.getElementById('downvideo').style.display.toLowerCase().replace('inline-block','no~ne').replace('none','inline-bl~ock').replace('~','');
} else if (inid.substring(0,1) == 'i') {
document.getElementById('rightother').style.display=document.getElementById('rightother').style.display.toLowerCase().replace('inline-block','no~ne').replace('none','inline-bl~ock').replace('~','');
document.getElementById('downother').style.display=document.getElementById('downother').style.display.toLowerCase().replace('inline-block','no~ne').replace('none','inline-bl~ock').replace('~','');
}
return inid;
}



function downright(inid) {
if (inid.substring(0,1) == 'g') {
document.getElementById('rightimage').style.display='inline-block';
document.getElementById('downimage').style.display='none';
} else if (inid.substring(0,1) == 'a') {
document.getElementById('rightaudio').style.display='inline-block';
document.getElementById('downaudio').style.display='none';
} else if (inid.substring(0,1) == 'v') {
document.getElementById('rightvideo').style.display='inline-block';
document.getElementById('downvideo').style.display='none';
} else if (inid.substring(0,1) == 'i') {
document.getElementById('rightother').style.display='inline-block';
document.getElementById('downother').style.display='none';
}
return inid;
}

Why not see what we mean at the changed client_browsing.htm‘s live run link? Huh?


Previous relevant File API File and Reader Objects Primer Tutorial is shown below.

File API File and Reader Objects Primer Tutorial

File API File and Reader Objects Primer Tutorial

Thanks to this great link we discovered a better way to combine the wonders of …

… in the scenario of a web application (remaining correct and asynchronous in its) use of an input type=file “multiple” browser element accessing the wonderful File API, such as …


<head>
<script type='text/javascript'>
function onl() {
document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);
}
</script>
</head>
<body style="background-color:#f0f0f0;" onload="onl();">
<input onclick="this.value=null;" onchange="document.getElementById('ibut').click();" style='width:50%;background-color:orange;' type="file" id="files" name="file" accept="image/*,video/*,audio/*,application/*,text/*" multiple />
<span class="readBytesButtons">
<button style='display:none;' data-startbyte="0" data-endbyte="4">1-5</button>
<button style='display:none;' data-startbyte="5" data-endbyte="14">6-15</button>
<button style='display:none;' data-startbyte="6" data-endbyte="7">7-8</button>
<button id=ibut style='background-color:pink;display:none;'>Send to Server Top Half</button>
</span>

You can see us applying new ideas to our usual readBlob (that we get to output data URIs today) …


function readBlob(opt_startByte, opt_stopByte) {
files = document.getElementById('files').files;
xx=[];
yy=[];
ten=500;
ixy=0;
awis=[];
ahis=[];
awx=[];
awy=[];
awid=[];
reader=[];
blob=[];
var ij=0;
kij=0;
kkij=0;
lastiw=0;
lastih=0;
if (!files.length) {
alert('Please select a file!');
return;
}
for (ij=0; ij<files.length; ij++) {
file = files[ij];
filen = file.name;
lasttype = file.type;
fs.push(file.name.replace(/\\/g,'/').split('/')[eval(-1 + file.name.replace(/\\/g,'/').split('/').length)]);
start = parseInt(opt_startByte) || 0;
stop = parseInt(opt_stopByte) || file.size - 1;


reader.push(new FileReader());

// If we use onloadend, we need to check the readyState.
// Thanks to https://stackoverflow.com/questions/12546775/get-filename-after-filereader-asynchronously-loaded-a-file
reader[ij].onloadend = (function(mfile) {
return
function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
if (mfile.type.indexOf('image/') == 0) {
if (document.getElementById('ibchkbox').checked) {
if (document.getElementById('gb')) {
document.getElementById('gb').src=evt.target.result.replace('data:;', 'data:' + mfile.type + ';');
} else {
document.getElementById('icontent').innerHTML+=ipre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + isuf;
}
} else {
wo=window.open(wp1,wp2);
wo.document.write(ipre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + isuf);
wo.document.title = mfile.name.replace(/\\/g,'/').split('/')[eval(-1 + mfile.name.replace(/\\/g,'/').split('/').length)];
}
} else if (mfile.type.indexOf('audio/') == 0) {
if (document.getElementById('ibchkbox').checked) {
if (document.getElementById('ab')) {
document.getElementById('ab').src=evt.target.result.replace('data:;', 'data:' + mfile.type + ';');
} else {
document.getElementById('icontent').innerHTML+=apre + mfile.type + amid + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + asuf.replace('><', ' id=v' + mfile.name + '><');
}
} else {
wo=window.open(wp1,wp2);
wo.document.write(apre + mfile.type + amid + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + asuf.replace('><', ' id=a' + mfile.name + '><'));
wo.document.title = mfile.name.replace(/\\/g,'/').split('/')[eval(-1 + mfile.name.replace(/\\/g,'/').split('/').length)];
}
} else if (mfile.type.indexOf('video/') == 0) {
if (document.getElementById('ibchkbox').checked) {
if (document.getElementById('vb')) {
document.getElementById('vb').src=evt.target.result.replace('data:;', 'data:' + mfile.type + ';');
} else {
document.getElementById('icontent').innerHTML+=vpre + mfile.type + vmid + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + vsuf.replace('><', ' id=v' + mfile.name + '><');
}
} else {
wo=window.open(wp1,wp2);
wo.document.write(vpre + mfile.type + vmid + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + vsuf.replace('><', ' id=v' + mfile.name + '><'));
wo.document.title = mfile.name.replace(/\\/g,'/').split('/')[eval(-1 + mfile.name.replace(/\\/g,'/').split('/').length)];
}
} else {
if (document.getElementById('ibchkbox').checked) {
if (document.getElementById('ib')) {
document.getElementById('ib').src=evt.target.result.replace('data:;', 'data:' + mfile.type + ';');
} else {
document.getElementById('icontent').innerHTML+=opre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + osuf;
}
} else {
wo=window.open(wp1,wp2);
wo.document.write(opre + evt.target.result.replace('data:;', 'data:' + mfile.type + ';') + osuf);
wo.document.title = mfile.name.replace(/\\/g,'/').split('/')[eval(-1 + mfile.name.replace(/\\/g,'/').split('/').length)];
}
}
} };
})(files[ij]);

blob.push(file.slice(start, stop + 1));
reader[ij].readAsDataURL(blob[ij]);
kij++;
}
}

… featuring in our proof of concept File API “Client Browsing” client_browsing.html web application’s live run link. Notice how the File object’s “mfile.type” is used within the FileReader object’s “onloadend” event logic … a powerful combination of objects in an asynchronous scenario, that asynchronicity ensured by involving a return scenario … cute,huh?!

You can also see this play out at WordPress 4.1.1’s File API File and Reader Objects Primer Tutorial.

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

This entry was posted in eLearning, Event-Driven Programming, Tutorials and tagged , , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *