Canvas Image Capture Ajax FormData Annotation Dropdown Tutorial

Canvas Image Capture Ajax FormData Annotation Dropdown Tutorial

Canvas Image Capture Ajax FormData Annotation Dropdown Tutorial

It is probably not surprising we involve HTML select element (“dropdowns”) related to our progress on canvas based Web Storage standing order type scenarios with our “Media Capture Email” web application we got the Web Storage working with yesterday’s Canvas Web Storage Image Capture Ajax FormData Annotation Tutorial. We’ve said it before, but we’ll say it again, why we like HTML select (“dropdown”) elements so much …

  • they can take up very little room but have lots of choices in single selection mode … one of our featured dropdowns is like this … in addition to …
  • they can allow for multiple selections, as the other of our dropdowns features today … and in this scenario you usually need a button to say “when” … but …
  • a single selection dropdown can act like a button (as we do today) … in addition to the fact that …
  • there are a ton of data parts to an HTML select (dropdown) element, the first three of which we actively use today …
    1. value
    2. text (derived from its child option element innerHTML)
    3. child option element title
    4. parent select element title
    5. data attributes
  • event-wise the onchange event is reliable and easy to use
  • the (dropdown) onclick event is available, perhaps, as a means to handle event propagation you want to do something about, as we do regarding details/summary nesting of our dropdowns, today

In our “day of the dropdown” we decided on the following (single selection) select element onchange logic as (where it references the (multiple selection id=lsset) select element choices made by the user (as a list of (we hope) non-scribble annotations saved by the user into the canvas, and recalled via the Web Storage on web application re-entry …


function dells(tv) {
var jik=0, huhis='', imgl=null;
if (tv == 'reshow') {
imgl = new Image();


imgl.onload = function() {
var iik=0, jjk=0, cmds=[];
elem.width = this.width;
elem.height = this.height;
context.drawImage(imgl, 0, 0);
for (iik=0; iik<ls_datauri_cmds.length; iik++) {
cmds=ls_datauri_cmds[iik].split(';');
for (jjk=0; jjk<cmds.length; jjk++) {
eval(cmds[jjk]);
}
}
};


imgl.src = ls_datauri;


} else if (tv == 'edit') {
imgl = new Image();


imgl.onload = function() {
var iik=0, jjk=0, cmds=[], huhis='';
elem.width = this.width;
elem.height = this.height;
context.clearRect(0,0,elem.width,elem.height);
context.drawImage(imgl, 0, 0);
for (iik=0; iik<ls_datauri_cmds.length; iik++) {
huhis=prompt('Optionally change away for ' + document.getElementById('optsel' + eval(1 + iik)).title, ls_datauri_cmds[iik]);
if (huhis != null) {
cmds=huhis.split(';');
} else {
cmds=ls_datauri_cmds[iik].split(';');
}
for (jjk=0; jjk<cmds.length; jjk++) {
eval(cmds[jjk]);
}
}
};


imgl.src = ls_datauri;


} else if (tv == 'editthese') {
imgl = new Image();

imgl.onload = function() {
var ois=document.getElementById('lssel');
var i=0, iik=0, jjk=0, cmds=[], huhis='';
elem.width = this.width;
elem.height = this.height;
context.clearRect(0,0,elem.width,elem.height);
context.drawImage(imgl, 0, 0);
for (iik=0; iik<ls_datauri_cmds.length; iik++) {
if (ois.options[eval(1 + iik)].selected) {
huhis=prompt('Optionally change away for ' + document.getElementById('optsel' + eval(1 + iik)).title, ls_datauri_cmds[iik]);
} else {
huhis=ls_datauri_cmds[iik];
}
if (huhis != null) {
cmds=huhis.split(';');
} else {
cmds=ls_datauri_cmds[iik].split(';');
}
for (jjk=0; jjk<cmds.length; jjk++) {
eval(cmds[jjk]);
}
}
};


imgl.src = ls_datauri;


} else if (tv == 'editothers') {
imgl = new Image();


imgl.onload = function() {
var ois=document.getElementById('lssel');
var i=0, iik=0, jjk=0, cmds=[], huhis='';
elem.width = this.width;
elem.height = this.height;
context.clearRect(0,0,elem.width,elem.height);
context.drawImage(imgl, 0, 0);
for (iik=0; iik<ls_datauri_cmds.length; iik++) {
if (ois.options[eval(1 + iik)].selected) {
huhis=ls_datauri_cmds[iik];
} else {
huhis=prompt('Optionally change away for ' + document.getElementById('optsel' + eval(1 + iik)).title, ls_datauri_cmds[iik]);
}
if (huhis != null) {
cmds=huhis.split(';');
} else {
cmds=ls_datauri_cmds[iik].split(';');
}
for (jjk=0; jjk<cmds.length; jjk++) {
eval(cmds[jjk]);
}
}
};


imgl.src = ls_datauri;


} else if (tv == 'onlyshowthese') { // value=editthese value=editothers value=onlyshowthese value=onlyshowothers
imgl = new Image();


imgl.onload = function() {
var ois=document.getElementById('lssel');
var i=0, iik=0, jjk=0, cmds=[], huhis=' ';
elem.width = this.width;
elem.height = this.height;
context.clearRect(0,0,elem.width,elem.height);
context.drawImage(imgl, 0, 0);
for (iik=0; iik<ls_datauri_cmds.length; iik++) {
if (ois.options[eval(1 + iik)].selected) {
huhis=ls_datauri_cmds[iik];
} else {
huhis='';
}
if (huhis != null) {
cmds=huhis.split(';');
} else {
cmds=ls_datauri_cmds[iik].split(';');
}
if (huhis != '') {
for (jjk=0; jjk<cmds.length; jjk++) {
eval(cmds[jjk]);
}
}
}
};


imgl.src = ls_datauri;


} else if (tv == 'onlyshowothers') {
imgl = new Image();


imgl.onload = function() {
var ois=document.getElementById('lssel');
var i=0, iik=0, jjk=0, cmds=[], huhis=' ';
elem.width = this.width;
elem.height = this.height;
context.clearRect(0,0,elem.width,elem.height);
context.drawImage(imgl, 0, 0);
for (iik=0; iik<ls_datauri_cmds.length; iik++) {
if (ois.options[eval(1 + iik)].selected) {
huhis='';
} else {
huhis=ls_datauri_cmds[iik];
}
if (huhis != null) {
cmds=huhis.split(';');
} else {
cmds=ls_datauri_cmds[iik].split(';');
}
if (huhis != '') {
for (jjk=0; jjk<cmds.length; jjk++) {
eval(cmds[jjk]);
}
}
}
};


imgl.src = ls_datauri;


} else {
localStorage.removeItem("imagecapture");
localStorage.removeItem("imagecapture_name");
localStorage.removeItem("imagecapture_cmds");
}
}

You can try today’s changed HTML imagecapture.htm‘s live run (just images) (or, for example, live run (all three categories of “media”) for your scrutiny and perusal, and we hope it is of some interest to you.


Previous relevant Canvas Web Storage Image Capture Ajax FormData Annotation Tutorial is shown below.

Canvas Web Storage Image Capture Ajax FormData Annotation Tutorial

Canvas Web Storage Image Capture Ajax FormData Annotation Tutorial

It’s time for “Intersessional Thoughts Part II” today, continuing on with our “Media Capture Email” web application from yesterday’s Mobile Canvas Image Capture Ajax FormData Annotation Tutorial. Previously, for some intersessional thoughts that did not involve a lot of data, we used …

  • HTTP Cookies … whose length limitation is like the web address URL length limitation … but today, we want to be able to recall HTML5 canvas base image and added annotation between sessions … a lot of data … so we start to (additionally) involve …
  • Web Storage localStorage

… the latter of which can handle 5mB type scenarios.


var ls_datauri='';
var ls_datauri_name='';
var ls_datauri_cmds=[];

var ls_datauri_select='';


function dells(tv) {
if (tv == 'reshow') {
var imgl = new Image();

imgl.onload = function() {
elem.width = this.width;
elem.height = this.height;
context.drawImage(imgl, 0, 0);
for (var iik=0; iik<ls_datauri_cmds.length; iik++) {
eval(ls_datauri_cmds[iik]);
}
};

imgl.src = ls_datauri;
} else {
localStorage.removeItem("imagecapture");
localStorage.removeItem("imagecapture_name");
localStorage.removeItem("imagecapture_cmds");
}
}


function lsset() {
localStorage.setItem("imagecapture", elemtoDataURL); //elem.toDataURL());
localStorage.setItem("imagecapture_name", cfile[0].name);
var ccc="";
for (var icc=0; icc<canvascommands.length; icc++) {
ccc+=canvascommands[icc] + String.fromCharCode(10);
}
localStorage.setItem("imagecapture_cmds", encodeURIComponent(ccc));
}


function cookieVal(cName) {
if (localStorage) {
if (localStorage.getItem("imagecapture")) {
ls_datauri_name=localStorage.getItem("imagecapture_name");
ls_datauri_select="<select size=1 id=lssel multiple><option value=>" + ls_datauri_name + "</option></select>"
var c_ls_datauri_cmds=decodeURIComponent(localStorage.getItem("imagecapture_cmds"));
var c_ls=1;
for (var ik=0; ik<c_ls_datauri_cmds.split(';').length; ik++) {
if ((c_ls_datauri_cmds.split(';')[ik] + ';').length > 5) {
ls_datauri_cmds.push(c_ls_datauri_cmds.split(';')[ik] + ';');
ls_datauri_select=ls_datauri_select.replace("</select>", "<option value='" + c_ls_datauri_cmds.split(';')[ik] + ';' + "'>" + c_ls_datauri_cmds.split(';')[ik] + ';' + "</option></select>");
ls_datauri_select=ls_datauri_select.replace(' size=' + c_ls, ' size=' + eval(eval('' + 1) + eval('' + c_ls)));
c_ls++;
}
}
ls_datauri=localStorage.getItem("imagecapture");
var imgl = new Image();

imgl.onload = function() {
elem.width = this.width;
elem.height = this.height;
context.drawImage(imgl, 0, 0);
if (document.getElementById('detcanvas')) {
document.getElementById('detcanvas').setAttribute('open', 'true');
}
document.getElementById('sumcanvas').innerHTML=document.getElementById('sumcanvas').innerHTML.replace(' below ...', ' ... last saved ' + ls_datauri_select + ' <select onchange=dells(this.value);><option value=>below</option><option value=deleted>deleted</option><option value=reshow>reshow</option></select> ...');
for (var iik=0; iik<ls_datauri_cmds.length; iik++) {
eval(ls_datauri_cmds[iik]);
canvascommands.push((ls_datauri_cmds[iik] + ';').replace(';;',';'));
}
};

imgl.src = ls_datauri;
}
}

var tCookie=document.cookie.split("; ");


for (var j=0; j<tCookie.length; j++) {
if (cName == tCookie[j].split("=")[0]) {
return decodeURIComponent(tCookie[j].split("=")[1]);
}
}
return '';
}

… which is heading towards the “standing order” HTML5 canvas annotating ideas we are thinking of, in terms of concepts like timesheet filling in. We are getting there, but not there yet, with today’s changed HTML imagecapture.htm‘s live run (just images) (or, for example, live run (all three categories of “media”) for your scrutiny and perusal. Today’s tutorial picture explains some of the practicalities for users to achieve this recallable canvas base image with annotations data.


Previous relevant Mobile Canvas Image Capture Ajax FormData Annotation Tutorial is shown below.

Mobile Canvas Image Capture Ajax FormData Annotation Tutorial

Mobile Canvas Image Capture Ajax FormData Annotation Tutorial

Yesterday’s Canvas Image Capture Ajax FormData Annotation Tutorial‘s new Canvas Annotation functionality was not great for mobile devices. Today, we improve via …

  • “floating” better the position of our “overlayed” Canvas Annotation menu so that it sidles up near canvas click/touch places rather than sitting, statically, in that first details/summary element forever … but in order to do that we lost the “native” canvas web browser Copy Image functionalities of yesterday … so …
  • we add onto that Canvas Annotation menu a home-grown (thanks to this useful link) Javascript code …

    function copycanvas() {
    var wimg = document.createElement('img');
    wimg.src = elem.toDataURL()

    var wdiv = document.createElement('div');
    wdiv.contentEditable = true;
    wdiv.appendChild(wimg);
    document.body.appendChild(wdiv);

    // do copy
    SelectText(wdiv);
    document.execCommand('Copy');
    document.body.removeChild(wdiv);
    }

    function SelectText(element) { // thanks to https://stackoverflow.com/a/40547470/1118626
    var doc = document;
    if (doc.body.createTextRange) {
    var range = document.body.createTextRange();
    range.moveToElementText(element);
    range.select();
    } else if (window.getSelection) {
    var selection = window.getSelection();
    var range = document.createRange();
    range.selectNodeContents(element);
    selection.removeAllRanges();
    selection.addRange(range);
    }
    }

    … that on an iPad you touch that new button then touch the scissors on the keyboard menu, and that gets you to the point that if you are in the body section of an email the Paste link will add the canvas contents as an email attachment where you have your cursor placed in that email body section

… and you can see how we changed things for mobile device (more practical) use, with today’s changed HTML imagecapture.htm‘s live run (just images) (or, for example, live run (all three categories of “media”) for your scrutiny and perusal.


Previous relevant Canvas Image Capture Ajax FormData Annotation Tutorial is shown below.

Canvas Image Capture Ajax FormData Annotation Tutorial

Canvas Image Capture Ajax FormData Annotation Tutorial

A precursor to today’s continuation of “Image Capture Email” web application HTML5 canvas functionality was the previous Image Capture Ajax FormData Upload Canvas Tutorial as that proof of concept that the canvas …

  • onclick event could be trapped and coded for (especially regarding non-scribble “discrete click/touch” event logic) … but you’ll know yourself if you’ve coded for some canvas annotation work you need to cater, also for the events …
  • touchmove … especially regarding mobile device “scribbling” annotation
  • mousemove … especially regarding non-mobile device “scribbling” annotation
  • touchend
  • mouseup
  • touchstart
  • mousedown
  • mouseover

… that we would have last talked about with Signature Signature Emoji Placeholder Lookup Tutorial‘s world.js external Javascript.

And so, onto the recent Media Capture Asynchronous Ajax FormData Upload Progress Tutorial you can now see an additional “Canvas Annotation” form to offer …

  • text (optionally rotated and colour controlled (like others below)) via 1 discrete click (done first)
  • line via 2 discrete clicks/touches (done first)
  • rectangle via 2 discrete clicks/touches (done first)
  • circle via 2 discrete clicks/touches (done first)
  • scribble (after 2 second delay)
  • end of scribble
  • image via 1 discrete click (done first)

… which now features this changed HTML imagecapture.htm‘s live run (just images) (or, for example, live run (all three categories of “media”) for your scrutiny and perusal. The new “Canvas Annotation” sits within the newly worded “More Email and Canvas Annotation Ideas” (first) details/summary (“revealer”) HTML element (except for Internet Explorer nor Microsoft Edge web browsers, that is). So far, we leave you with native web browser functionality “smarts” regarding canvas elements, the “not to be sneezed at” (Google Chrome example options) …

  • Copy image
  • Save Image As

… that could be your means to construct your own email attachment via a paste operation into an (client) email (application) message body.


Previous relevant Media Capture Asynchronous Ajax FormData Upload Progress Tutorial is shown below.

Media Capture Asynchronous Ajax FormData Upload Progress Tutorial

Media Capture Asynchronous Ajax FormData Upload Progress Tutorial

Onto the recent Image Capture Asynchronous Ajax FormData Upload Tutorial “Media Capture” web application (but a “spoiler alert” soon (maybe tomorrow) is that we will argue that this can become a mobile application for you mobile users too), today we …

  • add megabytes involved in email attachments and numbers of media files involved as emailed to the messaging of the web application … as well as cumulative usage for …
  • add an HTML5 progress element

… that we embellish so that you see …

  • cumulative megabytes of email attachment data you are creating, encouraging you via the 10mB initial maximum, to Curb Your Enthusiasm
  • number of media files attached and/or within a single zip file attachment

… to keep the user better informed of … progress.

Also, we haven’t finished yet, but we think we’re closer to allowing for mixed media selections within any one of …

… for you to try yourself, we certainly do hope.


Previous relevant Image Capture Asynchronous Ajax FormData Upload Tutorial is shown below.

Image Capture Asynchronous Ajax FormData Upload Tutorial

Image Capture Asynchronous Ajax FormData Upload Tutorial

Out of the recent Image Capture Ajax FormData Upload Canvas Tutorial HTML’s Javascript Ajax open statement asynchronous (third) argument


var xhr = new XMLHttpRequest();
xhr.open('post', 'mailto.php', true);
xhr.send(form);

… being true (ie. asynchronous) not able to be changed to false (ie. synchronous) in client Javascript (ie. it has no (serverside) PHP sleep type of function), as it is now deprecated and is dangerous anyway, resulted in 34560 seconds of work per “letter of deprecation” (ie. 2 days) as we pondered, with large images with multiple uploads on an iPhone camera image captured there and then, two choices …

  1. you can use false (ie. synchronous) Ajax open calls when involving Web Workers, at the clientside, but we decided to …
  2. make the (serverside) PHP mailto.php do the synchronous “simulation” of what is required to get the job done

Okay, so lots of Ajax transfers are hitting the PHP at once? Is this the go?

Not exactly, as we introduce small delays between xhr.open() calls using the Javascript timer setTimeout() function.

What stops the PHP getting confused?

A few things here. On multiple large transfer scenarios, we force the PHP to use zipfile (email attachment) PHP functionality. That PHP zipfile gets a client IP address component to its name. As each Ajax transfer arrives and is uploaded ready to zip the data up, we flag that zipping has started ahead of us starting zipping. This flagging is recognized when the next Ajax transfer arrives soon after (but delayed that little bit that we introduced at the clientside), and the PHP sleep can be used to simulate a truly synchronous Ajax scenario with a “delays until ready” paradigm.

We didn’t have the best programming day in the world yesterday, and a PHP solution may take you a lot less time, but nonetheless the Web Worker synchronous Ajax solution may be more to your liking.

Like last time, below are …

You can also see this play out at WordPress 4.1.1’s Image Capture Asynchronous Ajax FormData Upload Tutorial.


Previous relevant Image Capture Ajax FormData Upload Canvas Tutorial is shown below.

Image Capture Ajax FormData Upload Canvas Tutorial

Image Capture Ajax FormData Upload Canvas Tutorial

In amongst the media …

  • images
  • audio
  • video

… “talents” of our latest “Media Capture Email” web application, there is another important distinction, for us. It is so much easier to annotate “images” via the HTML(5) canvas element, which you’d have noticed we catered for from the word go, when we started this project, only considering “images”. Talk of the canvas element’s talents are all about …

  • annotation
  • images … especially in terms of …
  • positioning (above)
  • transforming (above)

And so, onto yesterday’s Media Capture Ajax FormData Upload Details Tutorial, we’re starting out on our embellishments to functionality via that canvas element sitting there for image display.

Primarily, the area where we need to start here, is with defining onclick and/or onmousedown and/or ontouchdown event logic definition.

The other matter attended to today, and still ongoing, is for multiple image photo captured there and then (on an iPhone for example) issues.

Below are …


Previous relevant Media Capture Ajax FormData Upload Details Tutorial is shown below.

Media Capture Ajax FormData Upload Details Tutorial

Media Capture Ajax FormData Upload Details Tutorial

We’re trying to improve functionality and usability of the “Media Capture Email” web application we last talked about with Media Multiple Capture Ajax FormData Upload Tutorial yesterday.

Today’s work …

  • for web browsers that are not Internet Explorer nor Microsoft Edge we add even more “reveal” logic that makes use of the HTML details/summary elements to unclutter what is cluttered, or, what could get cluttered (via concertinaing up ( ie. [detailsObject].removeAttribute(‘open’) ) what is not the latest media displayed down the bottom of the webpage, that helps keep new images above the fold
  • we’ve added our first CSS styling ideas …

    <style>
    * { font-family: Verdana; }
    summary { width:100%; background-color:#f0f0f0; }
    #topdmenu { background-color:#e0e0e0; }
    hr { height:2px; background-color:orange; }
    details { background-color:#d0d0d0; }
    #topmostmenu { background-color:#c0c0c0; }
    input { background-color:#f0b0d0; }
    textarea { background-color:#f7f7f7; }
    select { background-color:silver; }
    </style>

    … to add some colour, and colour coding of logic parts to the webpage, as well as a change of font, to Verdana
  • adds CC and BCC and Body email functionalities

It’s time to talk about our growing usage of …


<script type='text/javascript'>
document.write([someHtml]);
</script>

… that “plonks” some HTML where it is used in the webpage at the context this Javascript is positioned at. Sound a bit like PHP? Well, a bit, but don’t think you can suddenly do all the operating system and file and database manipulations PHP is capable of just because you use document.write([someHTML]). The use of document.write([someHTML]) has a big advantage, to onload logics for example, though. It can have if/else logic derived from address bar URL arguments and/or Cookie and/or WebStorage and/or navigation object web browser characteristic determinations to change the HTML written on the fly, even before document.body onload event logics.

Below are …

… for you to try yourself, we hope.

You can also see this play out at WordPress 4.1.1’s Media Capture Ajax FormData Upload Details Tutorial.


Previous relevant Media Multiple Capture Ajax FormData Upload Tutorial is shown below.

Media Multiple Capture Ajax FormData Upload Tutorial

Media Multiple Capture Ajax FormData Upload Tutorial

We’re “opening our horizons” or “genericizing our purposes” (but you need a licence for this one … it’s all in the wording) to improve on the recent Image Multiple Capture Ajax FormData Upload Tutorial‘s functionality today. That’ll be why we’ve replaced in the blog posting title (of equal length … snaps to that blogger!) the word “Image” for the more generic term “Media”. “Media”, to us, encompasses …

  • images
  • audio
  • video

… media. Being as all three are concepts that can be attached in emails, and displayed in a webpage, they have more in common than they are different by nature, though it must be said …

  • we baulked at displaying non-image “media” in (an HTML5) canvas element
  • mimetypes are really only of relevance to non-image “media” elements
  • “controls” and “play” functionality is only relevant to non-image “media” elements

Otherwise, though we wrote HTML code components for all three “media” categories, a lot of the code concepts are shared as you can see for yourself with …

… means by which, small “media” files of various “categories” above can be combined into email attachments (with all that same “standing order” thoughts of last time), zipped up or not, as the case may be. Typically, email size restrictions are to around or under 10mB of data (ie. less than a minute of video/audio is best).


Previous relevant Image Multiple Capture Ajax FormData Upload Tutorial is shown below.

Image Multiple Capture Ajax FormData Upload Tutorial

Image Multiple Capture Ajax FormData Upload Tutorial

Please feel free to demand a refund for today’s blog posting whose title is just rearranged title words of yesterday’s Image Capture Ajax FormData Multiple Upload Tutorial but there is a real development here, and it concerns what happens when you execute this web application on a mobile platform.

On a mobile platform, the “capture” attribute of the input element “kicks in”, if you will. So, you may sagely ask, “how does this fit with the ‘multiple’ attribute?”. Excellent question! It doesn’t really, the way we worked it as of yesterday, but today we make amends.

Add one more concept, and we think we can have a pretty good “standing order” type of web application. That “concept” is to add in HTTP Cookie functionality for “intersessional memory” (should the user click the “Remember Me?” checkbox) covering …

  • email “to” address
  • a “no camera” checkbox to force mobile platforms to represent the menu where images can be either …
    1. browsed for … or …
    2. taken there and then … ie. making full use of the “capture” attribute of the HTML input element
  • zipfile name
  • send when [number] or above ie. if ([number] is) 2 then only upload after the “capture” or “browse picking” of at least 2 images … this is the setting that allows “capture” to live with “multiple” (with or without “zipping”)
  • email “subject”

Perhaps you take 2 photos of a particular view each day and send them to a particular email friend with your iPad. Fill out the above once, click the “Remember Me?” to just, from then on, execute the web application, and press the button twice to take two photos twice, and there you are with a behind the scenes emailing of those photos to your friend. That is the sort of functionality we think of as a “standing order”.

Why not try today’s changed HTML imagecapture.htm‘s live run link?


Previous relevant Image Capture Ajax FormData Multiple Upload Tutorial is shown below.

Image Capture Ajax FormData Multiple Upload Tutorial

Image Capture Ajax FormData Multiple Upload Tutorial

Regular readers at this blog would appreciate the idea that lately we have had a big emphasis on groups of images. There were (the recent) …

… we get to our first revisit of Image Capture ideas in yesterday’s Image Capture Ajax FormData Upload Primer Tutorial featuring Ajax FormData functionality, allowing for a …

  • one image file at a time …
    1. image display
    2. canvas [context].drawImage() display
    3. upload as email attachment “upload”

    … and now, in “onions of the 4th dimension” feel, today, our extensions of functionality allow for “groups of images” (in a new context view) …

  • one or more image file(s) at a time …
    1. image display(s)
    2. canvas [context].drawImage() display(s)
    3. upload as email attachment(s) “upload(s)”

… all possible because of the multiple attribute as per …


<input type="file" name="image" accept="image/*" multiple capture>

… that truly manifests itself, in practice, for the user of today’s changed HTML imagecapture.htm‘s live run when they browse for image files, where they can pick more than one image in any one browsing session. In broad brush terms that change in Javascript “client” land means what was (once) a File Object now should be handled in terms of it now being a File Array of Objects. In bold we show how that changed the code of yesterday …


var cfile=[], tops=[], awidth=0, atop=0, c=null, ctx=null, kk=0;
function bp() {
var input = document.querySelector('input[type=file]'); // see Example 4

input.onchange = function () {
var file = input.files[0];
cfile = file;

for (var ii=0; ii<file.length; ii++) {
if (ii == 0) { drawOnCanvas(file); } // see Example 6
if (ii == 0) { upload(file); }
if (eval(1 + eval('' + ii)) == file.length) { whenokdrawOnCanvas(); } // displayAsImage(file); // see Example 7
}
};

var cdate = new Date();
cdatestr=cdate.getFullYear() + ("0" + eval(1 + cdate.getMonth())).slice(-2) + ("0" + cdate.getDate()).slice(-2);
document.getElementById('zipname').placeholder+=' ... imagezip_' + cdatestr + '.zip';

}


function whenokdrawOnCanvas() {
if (kk == cfile.length) {
c = document.querySelector('canvas'), // see Example 4
ctx = c.getContext('2d'),
c.width = awidth;
c.height = Math.abs(atop);
if (atop < 0) { atop = -atop; } for (var jk=0; jk<kk; jk++) { drawOnCanvas(cfile[jk], tops[jk]); } } else { setTimeout(whenokdrawOnCanvas); } }


function drawOnCanvas(file, xtop) {
var reader = new FileReader();

reader.onload = function (e) {
var dataURL = e.target.result, img = new Image();
// c = document.querySelector('canvas'), // see Example 4
// ctx = c.getContext('2d'),


img.onload = function() {
//c.width = img.width;
//c.height = img.height;
ctx.drawImage(img, 0, xtop); // 0
};


img.src = dataURL;
};


reader.readAsDataURL(file);
}

… and …


function upload(file) {
var form = new FormData(),
xhr = new XMLHttpRequest();

if (document.getElementById('to').value.indexOf('@') != -1) {
form.append('to', document.getElementById('to').value);
if (document.getElementById('subject').value != '') {
form.append('subject', document.getElementById('subject').value);
} else {
form.append('subject', 'Image in email');
}
form.append('filename', file[0].name);
}
form.append('image', file[0]);
if (document.getElementById('zipname').value != '') { // new zipfile email attachment input element
form.append('zipname', document.getElementById('zipname').value);
}
if (file.length > 1) {
for (var iii=1; iii<file.length; iii++) {
if (document.getElementById('to').value.indexOf('@') != -1) {
form.append('filename' + iii, file[iii].name);
}
form.append('image' + iii, file[iii]);
}
}

xhr.open('post', 'mailto.php', true);
xhr.send(form);
}

… combines with new (static) HTML/Javascript …


 <input onblur="if (this.value.indexOf('@') != -1 && this.value != '@') { document.getElementById('zipname').style.display='inline-block'; } " id="to" name="to" type="text" style="inline-block;" placeholder="Optionally email to" value=""> <input id="subject" name="subject" type="text" style="inline-block;" placeholder="Optional email subject" value=""> <input onclick="if (this.value == '' && this.placeholder.indexOf(' ... ') != -1) { this.value=this.placeholder.split(' ... ')[1]; } " style="display:none;width:30%;" id="zipname" name="zipname" type="text" placeholder="Optional zipfile email attachment name" value="">

… so that where the changes manifest themselves for the supervised and changed PHP mailto.php are that we now have to allow for …

  • zipping up (possibly) multiple image(s) into the one zipfile email attachment … or …
  • allow for multiple image file email attachments

Below, you can compare new multiple mode (left) to old single choice mode (right) …

New live run Old live run

Previous relevant Image Capture Ajax FormData Upload Primer Tutorial is shown below.

Image Capture Ajax FormData Upload Primer Tutorial

Image Capture Ajax FormData Upload Primer Tutorial

Were you around and interested in the media capture and upload concepts presented when we discussed this topic with HTML5 Camera API Audio Video Tutorial? Back then, central to the workings of this blog posting’s web application is a perfectly readable, and “obvious” piece of HTML we can show you below …


<form style='display:none;' id='myform' method='POST' enctype='application/x-www-urlencoded' action='//www.rjmprogramming.com.au/HTMLCSS/camera_api.php' target='myiframetwo'>
<input id='mydurl' name='mydurl' type='hidden' value=''></input>
<input id='mymobile' name='mymobile' type='hidden' value=''></input>
<input id='mode' name='mode' value='y'></input>
<input id='fclick' type='submit' value='Email'></input>
</form>
<iframe style='display:none;' id='myiframetwo' name='myiframetwo' src='//www.rjmprogramming.com.au/HTMLCSS/camera_api.php'></iframe>

… and then later some HTML input element to enable image capture was dynamically added …


<input onclick="document.getElementById('aemail').style.display='inline';" type="file" id="take_photograph" accept="image/*">

… the file contents ending up in that mydurl input type=hidden field and back to this same PHP code for “upload” (where there are lots of steps to the “upload” process before it ends up as a web server file, and lots of other uses can be made for that media data ahead of that “total” “upload” … as you see with today’s work as well).

All fairly conventional HTML navigational fare here, and useful, and good.

But … and didn’t you just know there’d be a “but” … today we start down the line of Image Media Capture Uploading that only needs the “hard” (first draft simple) HTML (of today’s new imagecapture.html‘s live run) …


<input type="file" name="image" accept="image/*" capture>

… and then, thanks to the inspiration from https://www.w3.org/TR/html-media-capture/ our code involves …

  • document.body onload (<body onload=’bp();’ style=’background-color:lightblue;’>) logic …

    function bp() {
    var input = document.querySelector('input[type=file]'); // see Example 4

    input.onchange = function () {
    var file = input.files[0];

    upload(file);
    drawOnCanvas(file); // see Example 6
    displayAsImage(file); // see Example 7
    };
    }
  • to link to the Javascript Ajax upload(file) function, featuring the FormData object code …

    function upload(file) {
    var form = new FormData(),
    xhr = new XMLHttpRequest();

    if (document.getElementById('to').value.indexOf('@') != -1) {
    form.append('to', document.getElementById('to').value);
    if (document.getElementById('subject').value != '') {
    form.append('subject', document.getElementById('subject').value);
    } else {
    form.append('subject', 'Image in email');
    }
    form.append('filename', file.name);
    }
    form.append('image', file);
    xhr.open('post', 'mailto.php', true);
    xhr.send(form);
    }
  • as the link to the serverside (new) PHP uploader functionality of mailto.php

You may want to say “so what”. It’s true that this approach is still based on an HTML form, just that it is dynamically created. Yes, that’s true, but it is also true that the onset of mobile applications spurred that increasing use of Ajax techniques of “navigational messaging”, so to start using these techniques means more that you are “going with the flow”, and be able to adapt to these more modern approaches to these media uploading ideas.


Previous relevant HTML5 Camera API Audio Video Tutorial is shown below.

HTML5 Camera API Audio Video Tutorial

HTML5 Camera API Audio Video Tutorial

Yesterday we started down the line of examining the Camera API in HTML5 with HTML5 Camera API Primer Tutorial as shown below.

There we thought of the “Camera” being a camera of “Images”, but most modern smart phones or tablets have a Camera app that can capture …

  • Video
  • Audio
  • Image

… media sources.

These two new media sources “Audio” and “Video” above need the intervention of a PHP server side emailer functionality in order to send out HTML emails with data URI “src=” HTML elements for these two types of media data.

How do we work this for the user using this web application? We allow the “media sources” above be part of an HTML “select” dropdown and separate the choices in the predominantly Javascript DOM “client feeling” code via the use of “document.URL” logic control (of Javascript DOM document.write() method) as per this …


<script type='text/javascript'>
if (document.URL.toLowerCase().indexOf('video') != -1) {
// Video specific logic ... eg. ...
document.write('<input onclick="document.getElementById(' + "'" + 'aemail' + "'" + ').style.display=' + "'" + 'inline' + "'" + ';" type="file" id="take_photograph" accept="video/*">');
} else if (document.URL.toLowerCase().indexOf('audio') != -1) {
// Audio specific logic ... eg. ...
document.write('<input onclick="document.getElementById(' + "'" + 'aemail' + "'" + ').style.display=' + "'" + 'inline' + "'" + ';" type="file" id="take_photograph" accept="audio/*">');
} else {
// Image specific logic ... eg. ...
document.write('<input onclick="document.getElementById(' + "'" + 'aemail' + "'" + ').style.display=' + "'" + 'inline' + "'" + ';" type="file" id="take_photograph" accept="image/*">');
}
</script>

… skeletal HTML code design approach. This approach is only an easy thing to implement when it is driven in its logic by something that exists intact before the document.body onload event, that being document.URL that equates to the web browser address bar URL.

So this led us to the HTML parent web application you could call camera_api.htm that you can try with this live run link, and that changed in this way to be able to process those newly introduced Audio and Video media sources that get emailed via our new PHP server side emailer camera_api.php but bear in mind that long running Audio and/or Video media captures are not welcome. Otherwise, please feel free to try out this web application working with your Camera app.


Previous relevant HTML5 Camera API Primer Tutorial is shown below.

HTML5 Camera API Primer Tutorial

HTML5 Camera API Primer Tutorial

Okay, so more HTML5 awaits, and we start down the track today with some research and development regarding the Camera API, and point you towards a few unbelievably great resources that have been put before us …

… and this led us to this proof of concept web application you could call camera_api.html that you can try with this live run link. The fly in the ointment, however, is browser and platform compatibility here. The web application …

  • asks the user for permission to use the camera to take photographs with the device’s camera … and/or
  • asks the user to point to a local (photograph) file … and then we …
  • interface either of these photographic data source and funnel it through email (client) functionality, optionally

Browser and platform wise, that first bit of functionality above is only supported, notionally, on Firefox and Google Chrome web browsers on Android, though we also found it worked on an (iOS) iPad. Most browsers and platforms work with the latter two features above.

So what are the Javascript syntax highlights of making the first two of the list above … ie. the Camera API (in HTML5) … to work. You need …

  • capturing the data via the device camera, via

    <input onclick="document.getElementById('aemail').style.display='inline';" type="file" id="take_photograph" accept="image/*">
  • use of as createObjectURL method as per

    var imgURL = window.URL.createObjectURL(file);
  • or alternatively, the use of the FileReader object as per

    var fileReader = new FileReader();

Try it out yourself to get this web application into context.

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.


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.


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.


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.


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 Ajax, eLearning, Event-Driven Programming, Tutorials and tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>