Walking Trip …

Walking Trip

Walking Trip

Offenbach's Suite ... Warts 'n All

Offenbach's Suite ... Warts 'n All

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

Posted in Photography, Trips | Tagged , , | 34 Comments

Media Capture Ajax FormData Crontab Curl Tutorial

Media Capture Ajax FormData Crontab Curl Tutorial

Media Capture Ajax FormData Crontab Curl Tutorial

Crontab Curl techniques produce a wave of satisfaction in this programmer. That’s because batch programming is very interesting to me, and makes me feel efficient. Scheduling feels the same way for me. In broad brush terms what can “Crontab Curl” help with?

  • Crontab – scheduling technique for Linux or Unix or Mac OS X
  • Curl – web URL can be executed in a command line way

What sort of jobs can benefit from “Crontab Curl”? There are too many to mention, but applications like “watchdogs” to check for a process existence and if not there report and/or resurrect, spring to mind. With today’s “Media Capture Email” involving upload, we are going to check for “tidy up” purposes, and be able to “mop up” on issues that caused an emailing operation to fail.

This is so, because though we leave no web server (non-log) files behind with “Media Capture Email” work, on a failure some of the interim files will exist in the web server folder in which we work. What if the file naming logic was to implant within that interim file’s filename …

  • emailee to
  • emailee cc
  • emailee bcc

… to be able to allow the “curl” called mailto.php be able to re-send the email in a simpler way via …

… all of these changed to allow for these “Crontab Curl” backup thoughts to happen …

  1. Crontab … is used here via a Korn Shell script snippet …

    a=`TZ=Australia/Sydney date`
    if [ `echo $a | grep -c ':25:'` -eq 1 ]; then
    curl HTTP://www.rjmprogramming.com.au/HTMLCSS/mailto.php?postlook=y > /dev/null
    fi

    … called in crontab (on the 25th minute of each hour of every day) via …

    * * * * * /etc/init.d/cron_is_working.ksh

    … that you can change via “crontab -e”
  2. Curl mailto.php?postlook=y # changed PHP live run simulation of what “Crontab Curl” does … yes, peer to peer thinking could work too, if you prefer?! … gets help deriving emailee to, cc, bcc via the interim Korn Shell script name …

Previous relevant Media iOS Image Capture Ajax FormData Cookie Tutorial is shown below.

Media iOS Image Capture Ajax FormData Cookie Tutorial

Media iOS Image Capture Ajax FormData Cookie Tutorial

Moving on from cross-browser, with yesterday’s Canvas Image Capture Ajax FormData Ajax Email Tutorial, we move on to cross-platform issues today regarding iOS, shortcut desktop icon usage (we talked about with Web Meets Mobile via iOS Desktop Icon Tutorial) and the cache and HTTP Cookies. There are issues here.

Our research on this started where we often start, a Google search, of ios shortcut cookie issue got us to this interesting link

  • verifying, to me, there is an issue, which we (personally) see as intermittent success using iPhone and iPad shortcut desktop icons to our “Media Capture Email” web applications linking to HTTP Cookie settings that seem to work fine when doing the same thing straight from the web browser desktop application instead, and which we remembered with some code we applied to our Google Chart Pie Chart interface as per (in its case PHP) code …

    <?php
    header( "Expires: Mon, 20 Dec 1998 01:00:00 GMT" );
    header( "Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT" );
    header( 'Cache-Control: no-store, no-cache, must-revalidate' );
    header( 'Cache-Control: post-check=0, pre-check=0', false );
    header( 'Pragma: no-cache' );
    // ... rest of PHP code
    ?>
  • but applying similar code ideas appeared to work for awhile, but not reliably, so we took a pragmatic approach here …
    1. work with URL get arguments instead …
    2. intervening between touching the “Remember Me?” checkbox and the touching of the “Share icon”‘s “Add to Home Screen” link with onclick (Javascript) logic …
    3. if no files browsed for (ie. “cfile” below will be null, and documentURL is the incoming document.URL) …

      var qsprefix="?", qs="";
      if (document.getElementById('to').value.indexOf('@') != -1) {
      qs+=qsprefix + "to=" + encodeURIComponent(document.getElementById('to').value); // tn);
      qsprefix="&";
      }
      if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
      if (!cfile && qs != '' && documentURL.indexOf('to=') == -1) {

      qs+=qsprefix + "cc=" + encodeURIComponent(document.getElementById('cc').value); // tn);
      qsprefix="&";
      qs+=qsprefix + "bcc=" + encodeURIComponent(document.getElementById('bcc').value); // tn);
      qsprefix="&";
      qs+=qsprefix + "body=" + encodeURIComponent(document.getElementById('body').value); // tn);
      qsprefix="&";
      qs+=qsprefix + "swir=" + encodeURIComponent(document.getElementById('swir').value); // tn);
      qsprefix="&";
      qs+=qsprefix + "subject=" + encodeURIComponent(document.getElementById('subject').value); // tn);
      qsprefix="&";
      qs+=qsprefix + "zipname=" + encodeURIComponent(document.getElementById('zipname').value.replace(expireDate.getFullYear() + ("0" + eval(1 + expireDate.getMonth())).slice(-2) + ("0" + expireDate.getDate()).slice(-2),"yyyymmdd")); // tn);
      qsprefix="&";
      if (document.getElementById('nocamera').checked) {
      qs+=qsprefix + "nocamera=" + encodeURIComponent('true'); // tn);
      } else {
      qs+=qsprefix + "nocamera=" + encodeURIComponent('false'); // tn);
      }
      qsprefix="&";
      if (forever && 1 == 2) {
      qs+=qsprefix + "forever=" + encodeURIComponent('y'); // tn);
      qsprefix="&";
      }

      if ((document.URL.split('#')[0].split('?')[0] + qs).length < 900) {
      location.href=document.URL.split('#')[0].split('?')[0] + qs;
      }

      }
      }

Then if the iPad or iPhone user happens, by some blue moon scenario, decides to “Share icon”‘s “Add to Home Screen” it, Danno, the big long argumented URL will be saved to the iPhone or iPad shortcut desktop icon itself, and there will be less flakiness because the “connection” to HTTP Cookie settings will not be crucial.

Try any one of …

… on an iPad or iPhone, and save an emailee (to) and subject (etcetera), but do not browse for any media at this pass, then …

  1. touch “Remember Me?” checkbox
  2. touch “Share icon”‘s “Add to Home Screen” link
  3. touch that new shortcut desktop icon

… to see what we mean, here. Now you can browse (and not have to re-enter other settings) for media to your heart’s content.


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

Canvas Image Capture Ajax FormData Ajax Email Tutorial

Canvas Image Capture Ajax FormData Ajax Email Tutorial

Clearly, to build on yesterday’s Windows Web Browser F12 Development Tools Debugger Tutorial and Canvas Image Capture Ajax FormData Annotation Dropdown Tutorial we need to clear up another issue that is cross-browser by nature, that being the emailing functionality for canvas content imagery (in an email attachment). Cross-browser issues may worry you in your projects so much that you do not want to proceed without as many platforms as possible “coming along for the road” on every single coding step, but the more we program and code here, we find there are that many deprecations and changes with platforms that we prefer to leave some cross-browser issues as a thing to note, and come back to, especially if it involves an optional part of the workflow of the web application.

We want to stick with Ajax FormData methods to achieve this, this being our “line in the sand” to try to learn more about these techniques. That being the case, we were mesmerized, really awfully keen, and tickled pink, going on turquoise to learn of a Javascript function (mozGetAsFile below) that takes HTML5 canvas content and creates for you a “file” object, the type of object that prompts an uploading behaviour in the destination PHP mailto.php we are going to send to via …


function clientemail(whoto) {
var cemailhref="";
copycanvas();
cemailhref=cemailorig;
cemailhref=cemailhref.replace(':?', ':' + whoto + '?');
if (document.getElementById('cc').value.indexOf('@') != -1) {
cemailhref=cemailhref.replace('&cc=', '&cc=' + encodeURIComponent(document.getElementById('cc').value));
}
if (document.getElementById('bcc').value.indexOf('@') != -1) {
cemailhref=cemailhref.replace('&bcc=', '&bcc=' + encodeURIComponent(document.getElementById('bcc').value));
}
if (document.getElementById('body').value != '') {
cemailhref=cemailhref.replace('&body=', '&body=' + encodeURIComponent(document.getElementById('body').value));
}
if (document.getElementById('subject').value != '') {
cemailhref=cemailhref.replace('?subject=', '?subject=' + encodeURIComponent(document.getElementById('subject').value));
} else {
cemailhref=cemailhref.replace('?subject=', '?subject=' + encodeURIComponent('Canvas Image in email'));
}
document.getElementById('cemail').href=cemailhref;
document.getElementById('cemail').click();
}


function email() {
var cemailhref="";
var whoto=document.getElementById('to').value;
if (whoto.indexOf('@') == -1) {
whoto=prompt('Email To? (answer with space to open email client where in body section you can paste the canvas contents)','');
if (whoto == null) { whoto=''; }
}
if (whoto.indexOf('@') == -1) {
whoto='';
clientemail(whoto);
} else if (whoto.indexOf('@') != -1) {
var ecanvas = document.getElementById('canvaselement');
try {
canvasf = ecanvas.mozGetAsFile('canvasimage.png');
form = new FormData();
xhr = new XMLHttpRequest();
var ereader = new FileReader();
ereader.readAsDataURL(canvasf);


ereader.onloadend = function() {


form.append('to', whoto);
if (document.getElementById('cc').value.indexOf('@') != -1) {
form.append('cc', document.getElementById('cc').value);
}
if (document.getElementById('bcc').value.indexOf('@') != -1) {
form.append('bcc', document.getElementById('bcc').value);
}
if (document.getElementById('body').value != '') {
form.append('body', document.getElementById('body').value);
}
if (document.getElementById('subject').value != '') {
form.append('subject', document.getElementById('subject').value);
} else {
form.append('subject', 'Canvas Image in email');
}
form.append('filename', isipn('canvasimage.png'));
form.append('image', canvasf);
pbval+=canvasf.size;
if (pbval > pbmax) { pbmax=pbval; document.getElementById('sbig').innerHTML='' + eval(pbmax / 1048576.0) + 'mB' + pbb; document.getElementById('pb').max='' + pbmax; document.getElementById('pb').style.borderRight='5px inset red'; } else { document.getElementById('pb').style.borderRight='0px inset red'; document.getElementById('sbig').innerHTML='10mB' + pbb; }
document.getElementById('pb').value='' + pbval;
document.getElementById('pb').title='' + eval(pbval / 1048576.0) + 'mB';
if (document.getElementById('zipname').value != '') {
form.append('zipname', jsipn(document.getElementById('zipname').value));
} else {
form.append('zipname', jsipn('canvasimage.png'));
}
xhr.open('post', 'mailto.php', true);
xhr.send(form);
if (1 == 1) {
if (document.getElementById('myh3').innerHTML.indexOf('Emailed to ') != -1) {
document.getElementById('myh3').innerHTML=document.getElementById('myh3').innerHTML.split('Emailed to ')[0] + 'Emailed to ' + whoto + ' (' + document.getElementById('pb').title + ' <a style=text-decoration:underline;cursor:pointer; onclick="clientemail(' + "'" + whoto + "'" + ');" title="Use client email instead of PHP mail where canvas content can be Pasted into email body section">in a canvas image</a> media file)';
} else {
document.getElementById('myh3').innerHTML+='<br>Emailed to ' + whoto + ' (' + document.getElementById('pb').title + ' <a style=text-decoration:underline;cursor:pointer; onclick="clientemail(' + "'" + whoto + "'" + ');" title="Use client email instead of PHP mail where canvas content can be Pasted into email body section">in a canvas image</a> media file)';
}
} else {
alert('Emailed to ' + whoto + ' (' + document.getElementById('pb').title + ' in a canvas image media file)');
}
};


} catch(eee) {
var huhe=confirm('Sorry, but best we could do was copy your canvas ready for you to paste into your own email, that will open if you click OK button.');
if (huhe) {
clientemail(whoto);
}


}
}
}

… but, sadly, mozGetAsFile is a cross-browser issue itself, in that it works on Firefox (maybe only), and even then is about to be deprecated, hence the try/catch Javascript logic adding to …

  • Firefox mozGetAsFile email with canvas content attachment via PHP mail automatically … with a fallback position where we …
  • use previous canvas copy to clipboard logic then arrange an HTML “a” link “mailto:” link to the client email program where the user can Paste their canvas content data directly into the body section of the presented new email message window, which appears by a programmatical click() of that “mailto:” link

Another cross-browser issue we improved upon is the timing of the saving of the canvas contents, as a data URL, ready to perhaps store in Web Storage “localStorage”, at this juncture, rather than later on (where Firefox was okay but Chrome and Opera and Safari were not) …


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

reader.onload = function (e) {
var dataURL = e.target.result, imgl = new Image();

imgl.onload = function() {
//elem.width = imgl.width;
//elem.height = imgl.height;
this.style.height='' + this.height + 'px';
if (1 == 1) {
c = document.getElementById('canvaselement'); //querySelector('canvas'), // see Example 4
ctx = c.getContext('2d');
if (isNaN(xtop)) {
ctx.drawImage(imgl, 0, 0);
} else {
ctx.drawImage(imgl, 0, xtop);
}
} else {
cdi(imgl, 0, xtop);
}
elemtoDataURL=c.toDataURL('image/jpeg',0.5).replace(";base64,",";charset=utf-8;base64,").replace(/^daXta:image\/(png|jpg|jpeg);base64,/, "");
};

imgl.src = dataURL;
};

reader.readAsDataURL(file);
}

Lots of web inspector work again to nut out what to do on these cross-browser issues!

Yet again, you can try the changed HTML imagecapture.htm‘s live run (just images) (or, for example, live run (all three categories of “media”) for your “cross-browser issues, continued, work” for your perusal, and hope it is of some interest to you.


Previous relevant Windows Web Browser F12 Development Tools Debugger Tutorial is shown below.

Windows Web Browser F12 Development Tools Debugger Tutorial

Windows Web Browser F12 Development Tools Debugger Tutorial

As hard a lesson as it may be, when you find a cross-browser issue that only happens with a certain brand or brands of web browser, if you have the time, investigate there and then on a laptop with a web inspector of that web browser brand. So it was, today, for us with our “Media Capture Email” web application last talked about with Canvas Image Capture Ajax FormData Annotation Dropdown Tutorial, and its weaknesses with Internet Explorer and Microsoft Edge web browsers.

Maybe you have been reading this blog posting thread avidly, and the mention of those two synchs with you, as was my thought too, that these two web browsers do not support the HTML5 details/summary tags. We’d coded for this, but our first suspicion was that this rearrangement of code could be responsible for the problems. But you’ll only really know truth from whatevvvvvvvvvvvver by testing for yourself and having a web inspector like today’s (Internet Explorer) F12 Developer Tools web inspector’s …

  • console tab … and …
  • debugger tab (at least today)

… working to your advantage like with Windows Web Browser F12 Development Tools Primer Tutorial, putting you into the “shoes” of your web browser.

And that’s where the timing of the execution of external Javascript, deferred as it was, was too quick for the parent’s deferred (via setTimeout) document.body onload logic. Hence the canvas external Javascript code firing ahead of the canvas element creation … oopsy daisy! Delay, further, the parent code until past the external Javascript delay, and to sort out the problem here, we reposition the script (src=) tag (for external Javascript) to just before the </body> endtag, and we’re back in business baby!

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


Previous relevant Windows Web Browser F12 Development Tools Primer Tutorial is shown below.

Windows Web Browser F12 Development Tools Primer Tutorial

Windows Web Browser F12 Development Tools Primer Tutorial

We can’t emphasise enough how important, and useful, are the modern “breed” of web browser “web inspectors”. These useful tools are written by the web browser products to enhance the experience using that web browser, though, of course, they hope you never have to visit their accompanying “web inspectors” to nut out problems, because, of course their products are perfect … tee hee.

We find the “web inspectors” great for nutting out CSS issues first and foremost, because they will all have an “Inspect HTML Element” piece of functionality (usually their top left icon) assisting the user …

  • point at an HTML area of interest
  • that/those HTML element(s) get highlighted
  • the user picks a CSS (or Styles) tab to show what CSS “rules the roost” (ie. it is hierarchical … Cascading Style Sheet)
  • strategies, as needed, can be put in place, at the proper place, to remedy for the look the user is after, to achieve, as necessary

Today, we’re visiting the Windows browsers …

  • Internet Explorer
  • Microsoft Edge

… regarding their “web inspectors”. For both above, they are accessed via (perhaps an initial Alt-F to get the “old” menus back, as required) …


Tools -> F12 Developer Tools

… or …


Settings (icon at top right) -> F12 Developer Tools

… and then you are presented, on a non-mobile platform, with a separate window, with the menus …

  • F12
  • DOM Explorer
  • Console
  • Debugger
  • Network
  • Performance
  • Memory
  • Emulation

… and of these we spend most of our time in the “Console” tab, debugging for Javascript issues, should they arise, as that is where such error messages are shown to you, along, often with a line of code at issue, and a clickable means to get into that code, on occasions.

The “Network” menu is interesting, on instigating some PHP, in that you see the HTML and non-inline Javascript and CSS components involved in a web application, displayed to you, if you are ready with it, as you launch your web application.

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.

Posted in Ajax, eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , | Leave a comment

Media iOS Image Capture Ajax FormData Cookie Tutorial

Media iOS Image Capture Ajax FormData Cookie Tutorial

Media iOS Image Capture Ajax FormData Cookie Tutorial

Moving on from cross-browser, with yesterday’s Canvas Image Capture Ajax FormData Ajax Email Tutorial, we move on to cross-platform issues today regarding iOS, shortcut desktop icon usage (we talked about with Web Meets Mobile via iOS Desktop Icon Tutorial) and the cache and HTTP Cookies. There are issues here.

Our research on this started where we often start, a Google search, of ios shortcut cookie issue got us to this interesting link

  • verifying, to me, there is an issue, which we (personally) see as intermittent success using iPhone and iPad shortcut desktop icons to our “Media Capture Email” web applications linking to HTTP Cookie settings that seem to work fine when doing the same thing straight from the web browser desktop application instead, and which we remembered with some code we applied to our Google Chart Pie Chart interface as per (in its case PHP) code …

    <?php
    header( "Expires: Mon, 20 Dec 1998 01:00:00 GMT" );
    header( "Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT" );
    header( 'Cache-Control: no-store, no-cache, must-revalidate' );
    header( 'Cache-Control: post-check=0, pre-check=0', false );
    header( 'Pragma: no-cache' );
    // ... rest of PHP code
    ?>
  • but applying similar code ideas appeared to work for awhile, but not reliably, so we took a pragmatic approach here …
    1. work with URL get arguments instead …
    2. intervening between touching the “Remember Me?” checkbox and the touching of the “Share icon”‘s “Add to Home Screen” link with onclick (Javascript) logic …
    3. if no files browsed for (ie. “cfile” below will be null, and documentURL is the incoming document.URL) …

      var qsprefix="?", qs="";
      if (document.getElementById('to').value.indexOf('@') != -1) {
      qs+=qsprefix + "to=" + encodeURIComponent(document.getElementById('to').value); // tn);
      qsprefix="&";
      }
      if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
      if (!cfile && qs != '' && documentURL.indexOf('to=') == -1) {

      qs+=qsprefix + "cc=" + encodeURIComponent(document.getElementById('cc').value); // tn);
      qsprefix="&";
      qs+=qsprefix + "bcc=" + encodeURIComponent(document.getElementById('bcc').value); // tn);
      qsprefix="&";
      qs+=qsprefix + "body=" + encodeURIComponent(document.getElementById('body').value); // tn);
      qsprefix="&";
      qs+=qsprefix + "swir=" + encodeURIComponent(document.getElementById('swir').value); // tn);
      qsprefix="&";
      qs+=qsprefix + "subject=" + encodeURIComponent(document.getElementById('subject').value); // tn);
      qsprefix="&";
      qs+=qsprefix + "zipname=" + encodeURIComponent(document.getElementById('zipname').value.replace(expireDate.getFullYear() + ("0" + eval(1 + expireDate.getMonth())).slice(-2) + ("0" + expireDate.getDate()).slice(-2),"yyyymmdd")); // tn);
      qsprefix="&";
      if (document.getElementById('nocamera').checked) {
      qs+=qsprefix + "nocamera=" + encodeURIComponent('true'); // tn);
      } else {
      qs+=qsprefix + "nocamera=" + encodeURIComponent('false'); // tn);
      }
      qsprefix="&";
      if (forever && 1 == 2) {
      qs+=qsprefix + "forever=" + encodeURIComponent('y'); // tn);
      qsprefix="&";
      }

      if ((document.URL.split('#')[0].split('?')[0] + qs).length < 900) {
      location.href=document.URL.split('#')[0].split('?')[0] + qs;
      }

      }
      }

Then if the iPad or iPhone user happens, by some blue moon scenario, decides to “Share icon”‘s “Add to Home Screen” it, Danno, the big long argumented URL will be saved to the iPhone or iPad shortcut desktop icon itself, and there will be less flakiness because the “connection” to HTTP Cookie settings will not be crucial.

Try any one of …

… on an iPad or iPhone, and save an emailee (to) and subject (etcetera), but do not browse for any media at this pass, then …

  1. touch “Remember Me?” checkbox
  2. touch “Share icon”‘s “Add to Home Screen” link
  3. touch that new shortcut desktop icon

… to see what we mean, here. Now you can browse (and not have to re-enter other settings) for media to your heart’s content.


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

Canvas Image Capture Ajax FormData Ajax Email Tutorial

Canvas Image Capture Ajax FormData Ajax Email Tutorial

Clearly, to build on yesterday’s Windows Web Browser F12 Development Tools Debugger Tutorial and Canvas Image Capture Ajax FormData Annotation Dropdown Tutorial we need to clear up another issue that is cross-browser by nature, that being the emailing functionality for canvas content imagery (in an email attachment). Cross-browser issues may worry you in your projects so much that you do not want to proceed without as many platforms as possible “coming along for the road” on every single coding step, but the more we program and code here, we find there are that many deprecations and changes with platforms that we prefer to leave some cross-browser issues as a thing to note, and come back to, especially if it involves an optional part of the workflow of the web application.

We want to stick with Ajax FormData methods to achieve this, this being our “line in the sand” to try to learn more about these techniques. That being the case, we were mesmerized, really awfully keen, and tickled pink, going on turquoise to learn of a Javascript function (mozGetAsFile below) that takes HTML5 canvas content and creates for you a “file” object, the type of object that prompts an uploading behaviour in the destination PHP mailto.php we are going to send to via …


function clientemail(whoto) {
var cemailhref="";
copycanvas();
cemailhref=cemailorig;
cemailhref=cemailhref.replace(':?', ':' + whoto + '?');
if (document.getElementById('cc').value.indexOf('@') != -1) {
cemailhref=cemailhref.replace('&cc=', '&cc=' + encodeURIComponent(document.getElementById('cc').value));
}
if (document.getElementById('bcc').value.indexOf('@') != -1) {
cemailhref=cemailhref.replace('&bcc=', '&bcc=' + encodeURIComponent(document.getElementById('bcc').value));
}
if (document.getElementById('body').value != '') {
cemailhref=cemailhref.replace('&body=', '&body=' + encodeURIComponent(document.getElementById('body').value));
}
if (document.getElementById('subject').value != '') {
cemailhref=cemailhref.replace('?subject=', '?subject=' + encodeURIComponent(document.getElementById('subject').value));
} else {
cemailhref=cemailhref.replace('?subject=', '?subject=' + encodeURIComponent('Canvas Image in email'));
}
document.getElementById('cemail').href=cemailhref;
document.getElementById('cemail').click();
}


function email() {
var cemailhref="";
var whoto=document.getElementById('to').value;
if (whoto.indexOf('@') == -1) {
whoto=prompt('Email To? (answer with space to open email client where in body section you can paste the canvas contents)','');
if (whoto == null) { whoto=''; }
}
if (whoto.indexOf('@') == -1) {
whoto='';
clientemail(whoto);
} else if (whoto.indexOf('@') != -1) {
var ecanvas = document.getElementById('canvaselement');
try {
canvasf = ecanvas.mozGetAsFile('canvasimage.png');
form = new FormData();
xhr = new XMLHttpRequest();
var ereader = new FileReader();
ereader.readAsDataURL(canvasf);


ereader.onloadend = function() {


form.append('to', whoto);
if (document.getElementById('cc').value.indexOf('@') != -1) {
form.append('cc', document.getElementById('cc').value);
}
if (document.getElementById('bcc').value.indexOf('@') != -1) {
form.append('bcc', document.getElementById('bcc').value);
}
if (document.getElementById('body').value != '') {
form.append('body', document.getElementById('body').value);
}
if (document.getElementById('subject').value != '') {
form.append('subject', document.getElementById('subject').value);
} else {
form.append('subject', 'Canvas Image in email');
}
form.append('filename', isipn('canvasimage.png'));
form.append('image', canvasf);
pbval+=canvasf.size;
if (pbval > pbmax) { pbmax=pbval; document.getElementById('sbig').innerHTML='' + eval(pbmax / 1048576.0) + 'mB' + pbb; document.getElementById('pb').max='' + pbmax; document.getElementById('pb').style.borderRight='5px inset red'; } else { document.getElementById('pb').style.borderRight='0px inset red'; document.getElementById('sbig').innerHTML='10mB' + pbb; }
document.getElementById('pb').value='' + pbval;
document.getElementById('pb').title='' + eval(pbval / 1048576.0) + 'mB';
if (document.getElementById('zipname').value != '') {
form.append('zipname', jsipn(document.getElementById('zipname').value));
} else {
form.append('zipname', jsipn('canvasimage.png'));
}
xhr.open('post', 'mailto.php', true);
xhr.send(form);
if (1 == 1) {
if (document.getElementById('myh3').innerHTML.indexOf('Emailed to ') != -1) {
document.getElementById('myh3').innerHTML=document.getElementById('myh3').innerHTML.split('Emailed to ')[0] + 'Emailed to ' + whoto + ' (' + document.getElementById('pb').title + ' <a style=text-decoration:underline;cursor:pointer; onclick="clientemail(' + "'" + whoto + "'" + ');" title="Use client email instead of PHP mail where canvas content can be Pasted into email body section">in a canvas image</a> media file)';
} else {
document.getElementById('myh3').innerHTML+='<br>Emailed to ' + whoto + ' (' + document.getElementById('pb').title + ' <a style=text-decoration:underline;cursor:pointer; onclick="clientemail(' + "'" + whoto + "'" + ');" title="Use client email instead of PHP mail where canvas content can be Pasted into email body section">in a canvas image</a> media file)';
}
} else {
alert('Emailed to ' + whoto + ' (' + document.getElementById('pb').title + ' in a canvas image media file)');
}
};


} catch(eee) {
var huhe=confirm('Sorry, but best we could do was copy your canvas ready for you to paste into your own email, that will open if you click OK button.');
if (huhe) {
clientemail(whoto);
}


}
}
}

… but, sadly, mozGetAsFile is a cross-browser issue itself, in that it works on Firefox (maybe only), and even then is about to be deprecated, hence the try/catch Javascript logic adding to …

  • Firefox mozGetAsFile email with canvas content attachment via PHP mail automatically … with a fallback position where we …
  • use previous canvas copy to clipboard logic then arrange an HTML “a” link “mailto:” link to the client email program where the user can Paste their canvas content data directly into the body section of the presented new email message window, which appears by a programmatical click() of that “mailto:” link

Another cross-browser issue we improved upon is the timing of the saving of the canvas contents, as a data URL, ready to perhaps store in Web Storage “localStorage”, at this juncture, rather than later on (where Firefox was okay but Chrome and Opera and Safari were not) …


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

reader.onload = function (e) {
var dataURL = e.target.result, imgl = new Image();

imgl.onload = function() {
//elem.width = imgl.width;
//elem.height = imgl.height;
this.style.height='' + this.height + 'px';
if (1 == 1) {
c = document.getElementById('canvaselement'); //querySelector('canvas'), // see Example 4
ctx = c.getContext('2d');
if (isNaN(xtop)) {
ctx.drawImage(imgl, 0, 0);
} else {
ctx.drawImage(imgl, 0, xtop);
}
} else {
cdi(imgl, 0, xtop);
}
elemtoDataURL=c.toDataURL('image/jpeg',0.5).replace(";base64,",";charset=utf-8;base64,").replace(/^daXta:image\/(png|jpg|jpeg);base64,/, "");
};

imgl.src = dataURL;
};

reader.readAsDataURL(file);
}

Lots of web inspector work again to nut out what to do on these cross-browser issues!

Yet again, you can try the changed HTML imagecapture.htm‘s live run (just images) (or, for example, live run (all three categories of “media”) for your “cross-browser issues, continued, work” for your perusal, and hope it is of some interest to you.


Previous relevant Windows Web Browser F12 Development Tools Debugger Tutorial is shown below.

Windows Web Browser F12 Development Tools Debugger Tutorial

Windows Web Browser F12 Development Tools Debugger Tutorial

As hard a lesson as it may be, when you find a cross-browser issue that only happens with a certain brand or brands of web browser, if you have the time, investigate there and then on a laptop with a web inspector of that web browser brand. So it was, today, for us with our “Media Capture Email” web application last talked about with Canvas Image Capture Ajax FormData Annotation Dropdown Tutorial, and its weaknesses with Internet Explorer and Microsoft Edge web browsers.

Maybe you have been reading this blog posting thread avidly, and the mention of those two synchs with you, as was my thought too, that these two web browsers do not support the HTML5 details/summary tags. We’d coded for this, but our first suspicion was that this rearrangement of code could be responsible for the problems. But you’ll only really know truth from whatevvvvvvvvvvvver by testing for yourself and having a web inspector like today’s (Internet Explorer) F12 Developer Tools web inspector’s …

  • console tab … and …
  • debugger tab (at least today)

… working to your advantage like with Windows Web Browser F12 Development Tools Primer Tutorial, putting you into the “shoes” of your web browser.

And that’s where the timing of the execution of external Javascript, deferred as it was, was too quick for the parent’s deferred (via setTimeout) document.body onload logic. Hence the canvas external Javascript code firing ahead of the canvas element creation … oopsy daisy! Delay, further, the parent code until past the external Javascript delay, and to sort out the problem here, we reposition the script (src=) tag (for external Javascript) to just before the </body> endtag, and we’re back in business baby!

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


Previous relevant Windows Web Browser F12 Development Tools Primer Tutorial is shown below.

Windows Web Browser F12 Development Tools Primer Tutorial

Windows Web Browser F12 Development Tools Primer Tutorial

We can’t emphasise enough how important, and useful, are the modern “breed” of web browser “web inspectors”. These useful tools are written by the web browser products to enhance the experience using that web browser, though, of course, they hope you never have to visit their accompanying “web inspectors” to nut out problems, because, of course their products are perfect … tee hee.

We find the “web inspectors” great for nutting out CSS issues first and foremost, because they will all have an “Inspect HTML Element” piece of functionality (usually their top left icon) assisting the user …

  • point at an HTML area of interest
  • that/those HTML element(s) get highlighted
  • the user picks a CSS (or Styles) tab to show what CSS “rules the roost” (ie. it is hierarchical … Cascading Style Sheet)
  • strategies, as needed, can be put in place, at the proper place, to remedy for the look the user is after, to achieve, as necessary

Today, we’re visiting the Windows browsers …

  • Internet Explorer
  • Microsoft Edge

… regarding their “web inspectors”. For both above, they are accessed via (perhaps an initial Alt-F to get the “old” menus back, as required) …


Tools -> F12 Developer Tools

… or …


Settings (icon at top right) -> F12 Developer Tools

… and then you are presented, on a non-mobile platform, with a separate window, with the menus …

  • F12
  • DOM Explorer
  • Console
  • Debugger
  • Network
  • Performance
  • Memory
  • Emulation

… and of these we spend most of our time in the “Console” tab, debugging for Javascript issues, should they arise, as that is where such error messages are shown to you, along, often with a line of code at issue, and a clickable means to get into that code, on occasions.

The “Network” menu is interesting, on instigating some PHP, in that you see the HTML and non-inline Javascript and CSS components involved in a web application, displayed to you, if you are ready with it, as you launch your web application.

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.

Posted in Ajax, eLearning, Event-Driven Programming, iOS, Tutorials | Tagged , , , , , , , , , , , , , , , | Leave a comment

PHP GD Image Colour Count Primer Tutorial

PHP GD Image Colour Count Primer Tutorial

PHP GD Image Colour Count Primer Tutorial

We’ve long been interested in the idea of cataloguing the colour makeup of an image, and knew, even with *.bmp images (which are one to one pixel in their makeup) you still have to formulate a method to quickly scan the image pixel by pixel to get anywhere with an overall “Image Colour Report” concept. Even though there is, incredibly enough a …

  • PHP GD (image library) imagecolorstotal method to do just that, it doesn’t work for every type of image, so we Googled away and got to …
  • this very useful link got us onto some great and fast code to do the job, once the user enters an image URL, to get the ball rolling

Also coming into play with this work was the discovery of linear gradient CSS means by which a document.body (or other element, for that matter) background image can be given some transparency independent of the foreground (presumably more opaque) transparency, as we outlined with Rainbow Games Background Image Tutorial. Via this technique we can keep all of …

  1. user defined imagery
  2. webpage header elements
  3. number of colours reporting
  4. prompt for the user for a follow up entry

… all above the fold rather than having to scroll down past an <img></img> element to get to that last idea above. We also squeeze in an opacity in between the other opacities to a <div></div> to give a nuanced different lighting to the div background encasing the heading and report and prompt parts above. The woooooorrrrllllddd’s your oyster!

Just be ready with an image URL of interest and you can try image_colours_of.php‘s live run link to see what we mean here. We hope it is of interest for you.

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

Posted in eLearning, Tutorials | Tagged , , , , , , , , , | Leave a comment

Canvas Image Capture Ajax FormData Ajax Email Tutorial

Canvas Image Capture Ajax FormData Ajax Email Tutorial

Canvas Image Capture Ajax FormData Ajax Email Tutorial

Clearly, to build on yesterday’s Windows Web Browser F12 Development Tools Debugger Tutorial and Canvas Image Capture Ajax FormData Annotation Dropdown Tutorial we need to clear up another issue that is cross-browser by nature, that being the emailing functionality for canvas content imagery (in an email attachment). Cross-browser issues may worry you in your projects so much that you do not want to proceed without as many platforms as possible “coming along for the road” on every single coding step, but the more we program and code here, we find there are that many deprecations and changes with platforms that we prefer to leave some cross-browser issues as a thing to note, and come back to, especially if it involves an optional part of the workflow of the web application.

We want to stick with Ajax FormData methods to achieve this, this being our “line in the sand” to try to learn more about these techniques. That being the case, we were mesmerized, really awfully keen, and tickled pink, going on turquoise to learn of a Javascript function (mozGetAsFile below) that takes HTML5 canvas content and creates for you a “file” object, the type of object that prompts an uploading behaviour in the destination PHP mailto.php we are going to send to via …


function clientemail(whoto) {
var cemailhref="";
copycanvas();
cemailhref=cemailorig;
cemailhref=cemailhref.replace(':?', ':' + whoto + '?');
if (document.getElementById('cc').value.indexOf('@') != -1) {
cemailhref=cemailhref.replace('&cc=', '&cc=' + encodeURIComponent(document.getElementById('cc').value));
}
if (document.getElementById('bcc').value.indexOf('@') != -1) {
cemailhref=cemailhref.replace('&bcc=', '&bcc=' + encodeURIComponent(document.getElementById('bcc').value));
}
if (document.getElementById('body').value != '') {
cemailhref=cemailhref.replace('&body=', '&body=' + encodeURIComponent(document.getElementById('body').value));
}
if (document.getElementById('subject').value != '') {
cemailhref=cemailhref.replace('?subject=', '?subject=' + encodeURIComponent(document.getElementById('subject').value));
} else {
cemailhref=cemailhref.replace('?subject=', '?subject=' + encodeURIComponent('Canvas Image in email'));
}
document.getElementById('cemail').href=cemailhref;
document.getElementById('cemail').click();
}


function email() {
var cemailhref="";
var whoto=document.getElementById('to').value;
if (whoto.indexOf('@') == -1) {
whoto=prompt('Email To? (answer with space to open email client where in body section you can paste the canvas contents)','');
if (whoto == null) { whoto=''; }
}
if (whoto.indexOf('@') == -1) {
whoto='';
clientemail(whoto);
} else if (whoto.indexOf('@') != -1) {
var ecanvas = document.getElementById('canvaselement');
try {
canvasf = ecanvas.mozGetAsFile('canvasimage.png');
form = new FormData();
xhr = new XMLHttpRequest();
var ereader = new FileReader();
ereader.readAsDataURL(canvasf);


ereader.onloadend = function() {


form.append('to', whoto);
if (document.getElementById('cc').value.indexOf('@') != -1) {
form.append('cc', document.getElementById('cc').value);
}
if (document.getElementById('bcc').value.indexOf('@') != -1) {
form.append('bcc', document.getElementById('bcc').value);
}
if (document.getElementById('body').value != '') {
form.append('body', document.getElementById('body').value);
}
if (document.getElementById('subject').value != '') {
form.append('subject', document.getElementById('subject').value);
} else {
form.append('subject', 'Canvas Image in email');
}
form.append('filename', isipn('canvasimage.png'));
form.append('image', canvasf);
pbval+=canvasf.size;
if (pbval > pbmax) { pbmax=pbval; document.getElementById('sbig').innerHTML='' + eval(pbmax / 1048576.0) + 'mB' + pbb; document.getElementById('pb').max='' + pbmax; document.getElementById('pb').style.borderRight='5px inset red'; } else { document.getElementById('pb').style.borderRight='0px inset red'; document.getElementById('sbig').innerHTML='10mB' + pbb; }
document.getElementById('pb').value='' + pbval;
document.getElementById('pb').title='' + eval(pbval / 1048576.0) + 'mB';
if (document.getElementById('zipname').value != '') {
form.append('zipname', jsipn(document.getElementById('zipname').value));
} else {
form.append('zipname', jsipn('canvasimage.png'));
}
xhr.open('post', 'mailto.php', true);
xhr.send(form);
if (1 == 1) {
if (document.getElementById('myh3').innerHTML.indexOf('Emailed to ') != -1) {
document.getElementById('myh3').innerHTML=document.getElementById('myh3').innerHTML.split('Emailed to ')[0] + 'Emailed to ' + whoto + ' (' + document.getElementById('pb').title + ' <a style=text-decoration:underline;cursor:pointer; onclick="clientemail(' + "'" + whoto + "'" + ');" title="Use client email instead of PHP mail where canvas content can be Pasted into email body section">in a canvas image</a> media file)';
} else {
document.getElementById('myh3').innerHTML+='<br>Emailed to ' + whoto + ' (' + document.getElementById('pb').title + ' <a style=text-decoration:underline;cursor:pointer; onclick="clientemail(' + "'" + whoto + "'" + ');" title="Use client email instead of PHP mail where canvas content can be Pasted into email body section">in a canvas image</a> media file)';
}
} else {
alert('Emailed to ' + whoto + ' (' + document.getElementById('pb').title + ' in a canvas image media file)');
}
};


} catch(eee) {
var huhe=confirm('Sorry, but best we could do was copy your canvas ready for you to paste into your own email, that will open if you click OK button.');
if (huhe) {
clientemail(whoto);
}


}
}
}

… but, sadly, mozGetAsFile is a cross-browser issue itself, in that it works on Firefox (maybe only), and even then is about to be deprecated, hence the try/catch Javascript logic adding to …

  • Firefox mozGetAsFile email with canvas content attachment via PHP mail automatically … with a fallback position where we …
  • use previous canvas copy to clipboard logic then arrange an HTML “a” link “mailto:” link to the client email program where the user can Paste their canvas content data directly into the body section of the presented new email message window, which appears by a programmatical click() of that “mailto:” link

Another cross-browser issue we improved upon is the timing of the saving of the canvas contents, as a data URL, ready to perhaps store in Web Storage “localStorage”, at this juncture, rather than later on (where Firefox was okay but Chrome and Opera and Safari were not) …


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

reader.onload = function (e) {
var dataURL = e.target.result, imgl = new Image();

imgl.onload = function() {
//elem.width = imgl.width;
//elem.height = imgl.height;
this.style.height='' + this.height + 'px';
if (1 == 1) {
c = document.getElementById('canvaselement'); //querySelector('canvas'), // see Example 4
ctx = c.getContext('2d');
if (isNaN(xtop)) {
ctx.drawImage(imgl, 0, 0);
} else {
ctx.drawImage(imgl, 0, xtop);
}
} else {
cdi(imgl, 0, xtop);
}
elemtoDataURL=c.toDataURL('image/jpeg',0.5).replace(";base64,",";charset=utf-8;base64,").replace(/^daXta:image\/(png|jpg|jpeg);base64,/, "");
};

imgl.src = dataURL;
};

reader.readAsDataURL(file);
}

Lots of web inspector work again to nut out what to do on these cross-browser issues!

Yet again, you can try the changed HTML imagecapture.htm‘s live run (just images) (or, for example, live run (all three categories of “media”) for your “cross-browser issues, continued, work” for your perusal, and hope it is of some interest to you.


Previous relevant Windows Web Browser F12 Development Tools Debugger Tutorial is shown below.

Windows Web Browser F12 Development Tools Debugger Tutorial

Windows Web Browser F12 Development Tools Debugger Tutorial

As hard a lesson as it may be, when you find a cross-browser issue that only happens with a certain brand or brands of web browser, if you have the time, investigate there and then on a laptop with a web inspector of that web browser brand. So it was, today, for us with our “Media Capture Email” web application last talked about with Canvas Image Capture Ajax FormData Annotation Dropdown Tutorial, and its weaknesses with Internet Explorer and Microsoft Edge web browsers.

Maybe you have been reading this blog posting thread avidly, and the mention of those two synchs with you, as was my thought too, that these two web browsers do not support the HTML5 details/summary tags. We’d coded for this, but our first suspicion was that this rearrangement of code could be responsible for the problems. But you’ll only really know truth from whatevvvvvvvvvvvver by testing for yourself and having a web inspector like today’s (Internet Explorer) F12 Developer Tools web inspector’s …

  • console tab … and …
  • debugger tab (at least today)

… working to your advantage like with Windows Web Browser F12 Development Tools Primer Tutorial, putting you into the “shoes” of your web browser.

And that’s where the timing of the execution of external Javascript, deferred as it was, was too quick for the parent’s deferred (via setTimeout) document.body onload logic. Hence the canvas external Javascript code firing ahead of the canvas element creation … oopsy daisy! Delay, further, the parent code until past the external Javascript delay, and to sort out the problem here, we reposition the script (src=) tag (for external Javascript) to just before the </body> endtag, and we’re back in business baby!

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


Previous relevant Windows Web Browser F12 Development Tools Primer Tutorial is shown below.

Windows Web Browser F12 Development Tools Primer Tutorial

Windows Web Browser F12 Development Tools Primer Tutorial

We can’t emphasise enough how important, and useful, are the modern “breed” of web browser “web inspectors”. These useful tools are written by the web browser products to enhance the experience using that web browser, though, of course, they hope you never have to visit their accompanying “web inspectors” to nut out problems, because, of course their products are perfect … tee hee.

We find the “web inspectors” great for nutting out CSS issues first and foremost, because they will all have an “Inspect HTML Element” piece of functionality (usually their top left icon) assisting the user …

  • point at an HTML area of interest
  • that/those HTML element(s) get highlighted
  • the user picks a CSS (or Styles) tab to show what CSS “rules the roost” (ie. it is hierarchical … Cascading Style Sheet)
  • strategies, as needed, can be put in place, at the proper place, to remedy for the look the user is after, to achieve, as necessary

Today, we’re visiting the Windows browsers …

  • Internet Explorer
  • Microsoft Edge

… regarding their “web inspectors”. For both above, they are accessed via (perhaps an initial Alt-F to get the “old” menus back, as required) …


Tools -> F12 Developer Tools

… or …


Settings (icon at top right) -> F12 Developer Tools

… and then you are presented, on a non-mobile platform, with a separate window, with the menus …

  • F12
  • DOM Explorer
  • Console
  • Debugger
  • Network
  • Performance
  • Memory
  • Emulation

… and of these we spend most of our time in the “Console” tab, debugging for Javascript issues, should they arise, as that is where such error messages are shown to you, along, often with a line of code at issue, and a clickable means to get into that code, on occasions.

The “Network” menu is interesting, on instigating some PHP, in that you see the HTML and non-inline Javascript and CSS components involved in a web application, displayed to you, if you are ready with it, as you launch your web application.

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.

Posted in Ajax, eLearning, Event-Driven Programming, iOS, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , | Leave a comment

Windows Web Browser F12 Development Tools Debugger Tutorial

Windows Web Browser F12 Development Tools Debugger Tutorial

Windows Web Browser F12 Development Tools Debugger Tutorial

As hard a lesson as it may be, when you find a cross-browser issue that only happens with a certain brand or brands of web browser, if you have the time, investigate there and then on a laptop with a web inspector of that web browser brand. So it was, today, for us with our “Media Capture Email” web application last talked about with Canvas Image Capture Ajax FormData Annotation Dropdown Tutorial, and its weaknesses with Internet Explorer and Microsoft Edge web browsers.

Maybe you have been reading this blog posting thread avidly, and the mention of those two synchs with you, as was my thought too, that these two web browsers do not support the HTML5 details/summary tags. We’d coded for this, but our first suspicion was that this rearrangement of code could be responsible for the problems. But you’ll only really know truth from whatevvvvvvvvvvvver by testing for yourself and having a web inspector like today’s (Internet Explorer) F12 Developer Tools web inspector’s …

  • console tab … and …
  • debugger tab (at least today)

… working to your advantage like with Windows Web Browser F12 Development Tools Primer Tutorial, putting you into the “shoes” of your web browser.

And that’s where the timing of the execution of external Javascript, deferred as it was, was too quick for the parent’s deferred (via setTimeout) document.body onload logic. Hence the canvas external Javascript code firing ahead of the canvas element creation … oopsy daisy! Delay, further, the parent code until past the external Javascript delay, and to sort out the problem here, we reposition the script (src=) tag (for external Javascript) to just before the </body> endtag, and we’re back in business baby!

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


Previous relevant Windows Web Browser F12 Development Tools Primer Tutorial is shown below.

Windows Web Browser F12 Development Tools Primer Tutorial

Windows Web Browser F12 Development Tools Primer Tutorial

We can’t emphasise enough how important, and useful, are the modern “breed” of web browser “web inspectors”. These useful tools are written by the web browser products to enhance the experience using that web browser, though, of course, they hope you never have to visit their accompanying “web inspectors” to nut out problems, because, of course their products are perfect … tee hee.

We find the “web inspectors” great for nutting out CSS issues first and foremost, because they will all have an “Inspect HTML Element” piece of functionality (usually their top left icon) assisting the user …

  • point at an HTML area of interest
  • that/those HTML element(s) get highlighted
  • the user picks a CSS (or Styles) tab to show what CSS “rules the roost” (ie. it is hierarchical … Cascading Style Sheet)
  • strategies, as needed, can be put in place, at the proper place, to remedy for the look the user is after, to achieve, as necessary

Today, we’re visiting the Windows browsers …

  • Internet Explorer
  • Microsoft Edge

… regarding their “web inspectors”. For both above, they are accessed via (perhaps an initial Alt-F to get the “old” menus back, as required) …


Tools -> F12 Developer Tools

… or …


Settings (icon at top right) -> F12 Developer Tools

… and then you are presented, on a non-mobile platform, with a separate window, with the menus …

  • F12
  • DOM Explorer
  • Console
  • Debugger
  • Network
  • Performance
  • Memory
  • Emulation

… and of these we spend most of our time in the “Console” tab, debugging for Javascript issues, should they arise, as that is where such error messages are shown to you, along, often with a line of code at issue, and a clickable means to get into that code, on occasions.

The “Network” menu is interesting, on instigating some PHP, in that you see the HTML and non-inline Javascript and CSS components involved in a web application, displayed to you, if you are ready with it, as you launch your web application.

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


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

Posted in eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , | Leave a comment

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.

Posted in Ajax, eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Canvas Web Storage Image Capture Ajax FormData Annotation Tutorial

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.

Posted in Ajax, eLearning, Event-Driven Programming, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Mobile Canvas Image Capture Ajax FormData Annotation Tutorial

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.

Posted in Ajax, eLearning, Event-Driven Programming, iOS, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment