File API File and Reader Objects Aesthetics Tutorial

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.

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 *