My List Token Subject Positioning Tutorial

My List Token Subject Positioning Tutorial

My List Token Subject Positioning Tutorial

With our “My List” (last talked about with List Web Application PHP Tutorial) web application “subject token” work on top of yesterday’s Vertex Pointing Game Token Subject Positioning Tutorial we …

  • allow for [name] as being mapped to email address or the “John Smith” of an email address such as “John Smith [jsmith@anemailprovider.com]” …
  • positioning of an Inline HTML Email body sectioning for incoming relatively positioned HTML data where the $_POST[‘doboth’] is allowed to contain a suitable top offset to the appended HTML code

This means the changed emailhtml.php helps out the changed mylist.htm that you can try out at this live run link to see what we mean here.

Those emailhtml.php main code parts now sit as …

<?php

$fflist="";
$ffname="";
$subjarr=["", "", "", ""];

function zmail($zris, $zxsis, $ztis, $zhis) {
global $subjarr, $fflist, $ffname;
if (strpos($zxsis, "[") === false && strpos($zxsis, "<") === false && $zxsis != "") {
$zxsis.=" at [date] for [files]";
analtoken($zxsis, "");
}
subjtokenization($fflist, "files");
subjtokenization($ffname, "name");
if ($ffname == "") { $zhis=str_replace("<files>", $fflist, str_replace("[files]", $fflist, $zhis)); }
$zhis=str_replace("<files>", $fflist, str_replace("[files]", $fflist, str_replace("<name>", $ffname, str_replace("[name]", $ffname, $zhis))));
return mail($zris, subjtokenization($zxsis,"subject"), $ztis, $zhis);
}

function analtoken($inofinterest, $ifnotblankbody) {
global $subjarr, $fflist, $ffname;
$inofinterest=trim($inofinterest);
if ($ifnotblankbody == "" && $inofinterest != "") { // subject
if (strpos($inofinterest, "[") === false && strpos($inofinterest, "<") === false && $inofinterest != "") {
$inofinterest.=" [lf] at [date] [lf] for [files]";
}
if (strpos(($inofinterest . "~"), "]~") !== false && strpos(($inofinterest . "~"), "[") !== false) {
$subjarr[3]="html";
$inofinterest=str_replace("[date]", date('l jS \of F Y h:i:s A'), $inofinterest);
if (isset($_SERVER['HTTP_REFERER'])) {
$inofinterest=str_replace("[httpreferer]", $_SERVER['HTTP_REFERER'], $inofinterest);
$inofinterest=str_replace("[serveraddr]", $_SERVER['SERVER_ADDR'], $inofinterest);
$inofinterest=str_replace("[requesttime]", $_SERVER['REQUEST_TIME'], $inofinterest);
$inofinterest=str_replace("[httpacceptlanguage]", $_SERVER['HTTP_ACCEPT_LANGUAGE'], $inofinterest);
$inofinterest=str_replace("[httpuseragent]", $_SERVER['HTTP_USER_AGENT'], $inofinterest);
$inofinterest=str_replace("[remoteaddr]", $_SERVER['REMOTE_ADDR'], $inofinterest);
$inofinterest=str_replace("[requesturi]", $_SERVER['REQUEST_URI'], $inofinterest);
if (isset($_SERVER['PATH_INFO'])) {
$inofinterest=str_replace("[pathinfo]", $_SERVER['PATH_INFO'], $inofinterest);
}
}
if ($ffname != "") { $inofinterest=str_replace("[name]", $ffname, $inofinterest); }
$inofinterest=str_replace("[lf]", "\n", $inofinterest);
$inofinterest=str_replace("[crlf]", "\r\n", $inofinterest);
$inofinterest=str_replace(" ", " + ", $inofinterest);
$huharr=explode("[", $inofinterest);
if (strpos(($inofinterest . "~"), "]") !== false && strpos(($inofinterest . "~"), "[") !== false) {
for ($ih=1; $ih<sizeof($huharr); $ih++) {
$thisone=explode("]", $huharr[$ih])[0];
if (strpos($thisone, " ") === false) {
if (isset($_POST[$thisone])) {
$inofinterest=str_replace("[" . $thisone . "]", str_replace("+", " ", urldecode($_POST[$thisone])), $inofinterest);
} else if (isset($_GET[$thisone])) {
$inofinterest=str_replace("[" . $thisone . "]", str_replace("+", " ", urldecode($_GET[$thisone])), $inofinterest);
}
}
}
}
if (strpos(($inofinterest . "~"), "]") !== false && strpos(($inofinterest . "~"), "[") !== false) {
$huharr=explode("[", $inofinterest);
$proposedih=$huharr[0];
for ($ih=1; $ih<sizeof($huharr); $ih++) {
$thisone=explode("]", $huharr[$ih])[0];
if ($huharr[$ih] != ($thisone . "]")) {
$proposedih.=explode(($thisone . "]"), $huharr[$ih])[1];
}
}
$subjarr[0]=str_replace("\n", " ", str_replace("\r\n", " ", $proposedih));
if (substr($inofinterest, 0, 1) == "[") {
$subjarr[1]=str_replace(" ", " + ",str_replace("\n", "<br>", str_replace("[", "<", str_replace("]", ">", $inofinterest))));
} else {
if (strpos($inofinterest, "\n") !== false) {
$huharr=explode("\n", $inofinterest);
$subjarr[1]="<html><body><textarea style='width:90%;font-size:28px;font-weight:bold;border:1px solid transparent;background-color:#f0f0f0;' rows=" . (1 + sizeof($huharr)) . ">" . str_replace(" ", " + ",$inofinterest) . "</textarea></body></html>";
} else {
$subjarr[1]="<html><body><h1>" . str_replace(" ", " + ",$inofinterest) . "</h1></body></html>";
}
}
} else {
$subjarr[0]=str_replace("\n", " ", str_replace("\r\n", " ", $inofinterest));
if (strpos($inofinterest, "\n") !== false) {
$huharr=explode("\n", $inofinterest);
$subjarr[1]="<html><body><textarea style='width:90%;font-size:28px;font-weight:bold;border:1px solid transparent;background-color:#f0f0f0;' rows=" . (1 + sizeof($huharr)) . ">" . str_replace(" ", " + ",$inofinterest) . "</textarea></body></html>";
} else {
$subjarr[1]="<html><body><h1>" . str_replace(" ", " + ",$inofinterest) . "</h1></body></html>";
}
}
}
} else if ($inofinterest != "") { // body
if (strpos($inofinterest, "@") !== false) {
if (strpos($inofinterest, "[") !== false && strpos($inofinterest, "]") !== false) {
$ffname=trim(explode("[", explode(",", $inofinterest)[0])[0]);
} else {
$ffname=explode(",", $inofinterest)[0];
}
} else {
$ifnotblankbody=trim($ifnotblankbody);
}
}
return $inofinterest;
}


function subjtokenization($inthing, $inmode) {
global $subjarr, $fflist, $ffname;
if ($inmode == "subject") {
if ($subjarr[0] != "") {
if ($fflist == "" && $ffname == "") { return $subjarr[0]; }
if ($fflist == "") { return str_replace("<name>", $ffname, str_replace("[name]", $ffname, $subjarr[0])); }
return str_replace("<name>", $ffname, str_replace("[name]", $ffname, str_replace("<files>", $fflist, str_replace("[files]", $fflist, str_replace("<file>", $fflist, str_replace("[file]", $fflist, $subjarr[0]))))));
} else if (strpos($inthing, "[") !== false) {
if ($fflist == "" && $ffname == "") { return str_replace("[date]", date('l jS \of F Y h:i:s A'), $inthing); }
if ($fflist == "") { return str_replace("<name>", $ffname, str_replace("[name]", $ffname, str_replace("[date]", date('l jS \of F Y h:i:s A'), $inthing))); }
return str_replace("<name>", $ffname, str_replace("[name]", $ffname, str_replace("<files>", $fflist, str_replace("[files]", $fflist, str_replace("<file>", $fflist, str_replace("[file]", $fflist, str_replace("[date]", date('l jS \of F Y h:i:s A'), $inthing)))))));
}
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, $inthing));
} else if (substr($inmode,0,11) == "bodysubject") {
if ($subjarr[1] != "") {
$bsprefix="";


if (strlen($inmode) > 11) {

$bsprefix=str_replace("<body>","",str_replace("</body>","",str_replace("<html>","",str_replace("</html>","",substr($inmode,11)))));
$tbdiv="</body>";
$tbz=0;
if (isset($_POST['doboth'])) {
if (substr(($_POST['doboth'] . ' '),0,1) >= "0" && substr(($_POST['doboth'] . ' '),0,1) <= "9") {
$tbz='' . $_POST['doboth'];
}
} else if (isset($_GET['doboth'])) {
if (substr(($_GET['doboth'] . ' '),0,1) >= "0" && substr(($_GET['doboth'] . ' '),0,1) <= "9") {
$tbz='' . $_GET['doboth'];
}
}
$tbits=explode("top:", $bsprefix);
for ($it=1; $it<sizeof($tbits); $it++) {
$tbdiv="</div></body>";
if ($tbz < trim(explode("px", $tbits[$it])[0])) {
$tbz=(0 + trim(explode("px", $tbits[$it])[0]));
}
}
if ($tbdiv == "</div></body>") {
$tbz+=20;
$bsprefix.="<div style='position:absolute;left:0px;top:" . $tbz . "px;'>";
}
$subjarr[1]=str_replace("</body>", $tbdiv, str_replace("<body>", "<body>" . str_replace(" ", " + ",$bsprefix), $subjarr[1]));
}
if (substr($subjarr[1], 0, 1) == "<" && strpos($subjarr[1], "</h1>") !== false) {
$subjarr[1]=str_replace("</h1>", "</h1><h3>" . str_replace("\n", "<br>", $inthing) . "</h3>", $subjarr[1]);
} else if (substr($subjarr[1], 0, 1) == "<" && strpos($subjarr[1], "</body>") !== false) {
$subjarr[1]=str_replace("</body>", "<h3>" . str_replace("\n", "<br>", $inthing) . "</h3></body>", $subjarr[1]);
}
if ($fflist == "" || 1 == 1) { return $subjarr[1]; }
return str_replace(" ", " + ",str_replace("<files>", $fflist, str_replace("[files]", $fflist, $subjarr[1])));
}
} else if ($inmode == "body") {
if ($subjarr[2] != "") {
return $subjarr[2];
}
} else if ($inmode == "contenttype") {
if ($subjarr[3] != "") {
return $subjarr[3];
}
} else if ($inmode == "file") {
$subjarr[1]=str_replace("<file>", $inthing, str_replace("[file]", $inthing, $subjarr[1]));
} else if ($inmode == "name" && $inthing != "") {
$subjarr[0]=str_replace("<name>", $inthing, str_replace("[name]", $inthing, $subjarr[0]));
$subjarr[1]=str_replace("<name>", $inthing, str_replace("[name]", $inthing, $subjarr[1]));
if ($subjarr[0] != "" && $subjarr[1] != "") {
if (strpos(preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[1]))), preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[0])))) !== false) {
$subjarr[0].=explode("<", explode(preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[0]))), preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[1]))))[1])[0];
}
}
} else if ($inmode == "files" && $inthing != "") {
$subjarr[0]=str_replace("<files>", $inthing, str_replace("[files]", $inthing, $subjarr[0]));
$subjarr[1]=str_replace("<files>", $inthing, str_replace("[files]", $inthing, $subjarr[1]));
if ($subjarr[0] != "" && $subjarr[1] != "") {
if (strpos(preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[1]))), preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[0])))) !== false) {
$subjarr[0].=explode("<", explode(preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[0]))), preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[1]))))[1])[0];
}
}
}
return $inthing;
}

?>

… mainly to cater for that name [name] type of subject token.

See also in today’s tutorial picture how Safari (web browser) Develop menu’s Web Inspector’s Network tab can help with PHP child (in iframe) Warning message troubleshooting.


Previous relevant Vertex Pointing Game Token Subject Positioning Tutorial is shown below.

Vertex Pointing Game Token Subject Positioning Tutorial

Vertex Pointing Game Token Subject Positioning Tutorial

You may have noticed in yesterday’s Vertex Pointing Game Token Subject Tutorial

some email clients allow the attachment but do not show position:absolute very well (eg Gmail webmail) while Apple macOS Mail shows position:absolute well but (at least for us) the attachments are not being downloaded, for our HTML content today

… which is a tad frustrating, but we do not think is an excuse to throw up the hands and give up, to settle for the lowest common denominator solution to the idea of creating the clearest emails you can code for. In other words, you cannot avoid the email client differences, but in a case like this, we think you should cater for the most lenient email client as far as text/html content goes. For us, that is Apple macOS Mail email client where that “position:absolute;” HTML is honoured. Luckily, thinking about solutions to separating the text/html body content parts away from the attachment parts …

  • our first more complex though to use global attributes regarding CSS top co-ordinate (and mapping otherwise, before email creation) … we had enough time …

  • to reject on behalf of encasing the “non-graph” parts of that text/html within a new encasing HTML div element to which we can apply …
    1. position: absolute
    2. top: (20 + maximum calculated “top” of rest)px

    … was a far better and simpler solution
    <?php

    if (strlen($inmode) > 11) {

    $bsprefix=str_replace("<body>","",str_replace("</body>","",str_replace("<html>","",str_replace("</html>","",substr($inmode,11)))));
    $tbdiv="</body>";
    $tbz=0;
    $tbits=explode("top:", $bsprefix);
    for ($it=1; $it<sizeof($tbits); $it++) {
    $tbdiv="</div></body>";
    if ($tbz < trim(explode("px", $tbits[$it])[0])) {
    $tbz=(0 + trim(explode("px", $tbits[$it])[0]));
    }
    }
    if ($tbdiv == "</div></body>") {
    $tbz+=20;
    $bsprefix.="<div style='position:absolute;left:0px;top:" . $tbz . "px;'>";
    }
    $subjarr[1]=str_replace("</body>", $tbdiv, str_replace("<body>", "<body>" . str_replace(" ", " + ",$bsprefix), $subjarr[1]));

    }

    ?>

And so the changed emailhtml.php helps out the changed square_hr_tracing.htm that you can try out at this live run link to see what we mean, by entering an email address into that “Plot Axes” textbox after defining your Linear or Parabola equation.


Previous relevant Vertex Pointing Game Token Subject Tutorial is shown below.

Vertex Pointing Game Token Subject Tutorial

Vertex Pointing Game Token Subject Tutorial

Adding onto yesterday’s Flowchart and Venn Diagram and Mind Map Token Subject Emoji Tutorial email “subject tokens” progress, today we change our most generic email helper, the changed emailhtml.php to conjoin …

  • Vertex Pointing Game for Linear and Parabola equation drawing purposes on a grid) …
  • combined with, for the first time an email requirement for an email HTML attachment whose contents will also be included within the body top section text/html explanations above the attachment … why? …
  • some email clients allow the attachment but do not show position:absolute very well (eg Gmail webmail) while Apple macOS Mail shows position:absolute well but (at least for us) the attachments are not being downloaded, for our HTML content today

Let’s update you with emailhtml.php’s new “subject token” functions …

<?php

$fflist="";
$subjarr=["","","",""];

function zmail($zris, $zxsis, $ztis, $zhis) {
global $subjarr, $fflist;
if (strpos($zxsis, "[") === false && strpos($zxsis, "<") === false && $zxsis != "") {
$zxsis.=" at [date] for [files]";
analtoken($zxsis, "");
}
subjtokenization($fflist, "files");
$zhis=str_replace("<files>", $fflist, str_replace("[files]", $fflist, $zhis));
return mail($zris, subjtokenization($zxsis,"subject"), $ztis, $zhis);
}

function analtoken($inofinterest, $ifnotblankbody) {
global $subjarr, $fflist;
$inofinterest=trim($inofinterest);
if ($ifnotblankbody == "" && $inofinterest != "") { // subject
if (strpos($inofinterest, "[") === false && strpos($inofinterest, "<") === false && $inofinterest != "") {
$inofinterest.=" [lf] at [date] [lf] for [files]";
}
if (strpos(($inofinterest . "~"), "]~") !== false && strpos(($inofinterest . "~"), "[") !== false) {
$subjarr[3]="html";
$inofinterest=str_replace("[date]", date('l jS \of F Y h:i:s A'), $inofinterest);
if (isset($_SERVER['HTTP_REFERER'])) {
$inofinterest=str_replace("[httpreferer]", $_SERVER['HTTP_REFERER'], $inofinterest);
$inofinterest=str_replace("[serveraddr]", $_SERVER['SERVER_ADDR'], $inofinterest);
$inofinterest=str_replace("[requesttime]", $_SERVER['REQUEST_TIME'], $inofinterest);
$inofinterest=str_replace("[httpacceptlanguage]", $_SERVER['HTTP_ACCEPT_LANGUAGE'], $inofinterest);
$inofinterest=str_replace("[httpuseragent]", $_SERVER['HTTP_USER_AGENT'], $inofinterest);
$inofinterest=str_replace("[remoteaddr]", $_SERVER['REMOTE_ADDR'], $inofinterest);
$inofinterest=str_replace("[requesturi]", $_SERVER['REQUEST_URI'], $inofinterest);
if (isset($_SERVER['PATH_INFO'])) {
$inofinterest=str_replace("[pathinfo]", $_SERVER['PATH_INFO'], $inofinterest);
}
}
$inofinterest=str_replace("[lf]", "\n", $inofinterest);
$inofinterest=str_replace("[crlf]", "\r\n", $inofinterest);
$inofinterest=str_replace(" ", " + ", $inofinterest);
$huharr=explode("[", $inofinterest);
if (strpos(($inofinterest . "~"), "]") !== false && strpos(($inofinterest . "~"), "[") !== false) {
for ($ih=1; $ih<sizeof($huharr); $ih++) {
$thisone=explode("]", $huharr[$ih])[0];
if (strpos($thisone, " ") === false) {
if (isset($_POST[$thisone])) {
$inofinterest=str_replace("[" . $thisone . "]", str_replace("+", " ", urldecode($_POST[$thisone])), $inofinterest);
} else if (isset($_GET[$thisone])) {
$inofinterest=str_replace("[" . $thisone . "]", str_replace("+", " ", urldecode($_GET[$thisone])), $inofinterest);
}
}
}
}
if (strpos(($inofinterest . "~"), "]") !== false && strpos(($inofinterest . "~"), "[") !== false) {
$huharr=explode("[", $inofinterest);
$proposedih=$huharr[0];
for ($ih=1; $ih<sizeof($huharr); $ih++) {
$thisone=explode("]", $huharr[$ih])[0];
if ($huharr[$ih] != ($thisone . "]")) {
$proposedih.=explode(($thisone . "]"), $huharr[$ih])[1];
}
}
$subjarr[0]=str_replace("\n", " ", str_replace("\r\n", " ", $proposedih));
if (substr($inofinterest, 0, 1) == "[") {
$subjarr[1]=str_replace(" ", " + ",str_replace("\n", "<br>", str_replace("[", "<", str_replace("]", ">", $inofinterest))));
} else {
if (strpos($inofinterest, "\n") !== false) {
$huharr=explode("\n", $inofinterest);
$subjarr[1]="<html><body><textarea style='width:90%;font-size:28px;font-weight:bold;border:1px solid transparent;background-color:#f0f0f0;' rows=" . (1 + sizeof($huharr)) . ">" . str_replace(" ", " + ",$inofinterest) . "</textarea></body></html>";
} else {
$subjarr[1]="<html><body><h1>" . str_replace(" ", " + ",$inofinterest) . "</h1></body></html>";
}
}
} else {
$subjarr[0]=str_replace("\n", " ", str_replace("\r\n", " ", $inofinterest));
if (strpos($inofinterest, "\n") !== false) {
$huharr=explode("\n", $inofinterest);
$subjarr[1]="<html><body><textarea style='width:90%;font-size:28px;font-weight:bold;border:1px solid transparent;background-color:#f0f0f0;' rows=" . (1 + sizeof($huharr)) . ">" . str_replace(" ", " + ",$inofinterest) . "</textarea></body></html>";
} else {
$subjarr[1]="<html><body><h1>" . str_replace(" ", " + ",$inofinterest) . "</h1></body></html>";
}
}
}
} else if ($inofinterest != "") { // body
$ifnotblankbody=trim($ifnotblankbody);
}
return $inofinterest;
}


function subjtokenization($inthing, $inmode) {
global $subjarr, $fflist;
if ($inmode == "subject") {
if ($subjarr[0] != "") {
if ($fflist == "") { return $subjarr[0]; }
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, str_replace("<file>", $fflist, str_replace("[file]", $fflist, $subjarr[0]))));
} else if (strpos($inthing, "[") !== false) {
if ($fflist == "") { return str_replace("[date]", date('l jS \of F Y h:i:s A'), $inthing); }
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, str_replace("<file>", $fflist, str_replace("[file]", $fflist, str_replace("[date]", date('l jS \of F Y h:i:s A'), $inthing)))));
}
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, $inthing));
} else if (substr($inmode,0,11) == "bodysubject") {
if ($subjarr[1] != "") {
$bsprefix="";
if (strlen($inmode) > 11) {

$bsprefix=str_replace("<body>","",str_replace("</body>","",str_replace("<html>","",str_replace("</html>","",substr($inmode,11)))));
$subjarr[1]=str_replace("<body>", "<body>" . $bsprefix, $subjarr[1]);
}
if (substr($subjarr[1], 0, 1) == "<" && strpos($subjarr[1], "</h1>") !== false) {
$subjarr[1]=str_replace("</h1>", "</h1><h3>" . str_replace("\n", "<br>", $inthing) . "</h3>", $subjarr[1]);
} else if (substr($subjarr[1], 0, 1) == "<" && strpos($subjarr[1], "</body>") !== false) {
$subjarr[1]=str_replace("</body>", "<h3>" . str_replace("\n", "<br>", $inthing) . "</h3></body>", $subjarr[1]);
}
if ($fflist == "" || 1 == 1) { return $subjarr[1]; }
return str_replace(" ", " + ",str_replace("<files>", $fflist, str_replace("[files]", $fflist, $subjarr[1])));
}
} else if ($inmode == "body") {
if ($subjarr[2] != "") {
return $subjarr[2];
}
} else if ($inmode == "contenttype") {
if ($subjarr[3] != "") {
return $subjarr[3];
}
} else if ($inmode == "file") {
$subjarr[1]=str_replace("<file>", $inthing, str_replace("[file]", $inthing, $subjarr[1]));
} else if ($inmode == "files" && $inthing != "") {
$subjarr[0]=str_replace("<files>", $inthing, str_replace("[files]", $inthing, $subjarr[0]));
$subjarr[1]=str_replace("<files>", $inthing, str_replace("[files]", $inthing, $subjarr[1]));
if ($subjarr[0] != "" && $subjarr[1] != "") {
if (strpos(preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[1]))), preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[0])))) !== false) {
$subjarr[0].=explode("<", explode(preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[0]))), preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[1]))))[1])[0];
}
}
}
return $inthing;
}

?>

We hope you try the changed square_hr_tracing.htm that you can try out at this live run link to see what we mean.


Previous relevant Gimp Guillotine Token Subject Tutorial is shown below.

Gimp Guillotine Token Subject Tutorial

Gimp Guillotine Token Subject Tutorial

On top of yesterday’s Feedback Annotation Canvas Image Tokens Tutorial “first cab off the rank” for “subject token” email functionality is today’s Gimp Guillotine Follow Up web application (last discussed with Gimp Guillotine Absolute to Relative Image Url Tutorial) “next cab off the rank” software integration for “subject tokens”.

Yesterday’s Stop Press gave you a heads up that yesterday’s promise …

[lf] line feed and [crlf] carriage return/line feed

… required PHP tweaking, unsurprisingly. And some $_SERVER[] array assumptions we made were not the greatest things to assume, and so we started using that ever useful PHP isset function to help out here.

Below are the new PHP code changes as a result of this “second cab” …

<?php

$fflist="";
$subjarr=["", "", "", ""];

function zmail($zris, $zxsis, $ztis, $zhis) {
global $subjarr, $fflist;
if (strpos($zxsis, "[") === false && strpos($zxsis, "<") === false && $zxsis != "") {
$zxsis.=" at [date] for [files]";
analtoken($zxsis, "");
}
subjtokenization($fflist, "files");
$zhis=str_replace("<files>", $fflist, str_replace("[files]", $fflist, $zhis));
return mail($zris, subjtokenization($zxsis,"subject"), $ztis, $zhis);
}


function analtoken($inofinterest, $ifnotblankbody) {
global $subjarr, $fflist;
$inofinterest=trim($inofinterest);
if ($ifnotblankbody == "" && $inofinterest != "") { // subject
if (strpos(($inofinterest . "~"), "]~") !== false && strpos(($inofinterest . "~"), "[") !== false) {
$subjarr[3]="html";
$inofinterest=str_replace("[date]", date('l jS \of F Y h:i:s A'), $inofinterest);
if (isset($_SERVER['HTTP_REFERER'])) {
$inofinterest=str_replace("[httpreferer]", $_SERVER['HTTP_REFERER'], $inofinterest);
$inofinterest=str_replace("[serveraddr]", $_SERVER['SERVER_ADDR'], $inofinterest);
$inofinterest=str_replace("[requesttime]", $_SERVER['REQUEST_TIME'], $inofinterest);
$inofinterest=str_replace("[httpacceptlanguage]", $_SERVER['HTTP_ACCEPT_LANGUAGE'], $inofinterest);
$inofinterest=str_replace("[httpuseragent]", $_SERVER['HTTP_USER_AGENT'], $inofinterest);
$inofinterest=str_replace("[remoteaddr]", $_SERVER['REMOTE_ADDR'], $inofinterest);
$inofinterest=str_replace("[requesturi]", $_SERVER['REQUEST_URI'], $inofinterest);
if (isset($_SERVER['PATH_INFO'])) {
$inofinterest=str_replace("[pathinfo]", $_SERVER['PATH_INFO'], $inofinterest);
}
}

$inofinterest=str_replace("[lf]", "\n", $inofinterest);
$inofinterest=str_replace("[crlf]", "\r\n", $inofinterest);
$huharr=explode("[", $inofinterest);
if (strpos(($inofinterest . "~"), "]") !== false && strpos(($inofinterest . "~"), "[") !== false) {
for ($ih=1; $ih<sizeof($huharr); $ih++) {
$thisone=explode("]", $huharr[$ih])[0];
if (strpos($thisone, " ") === false) {
if (isset($_POST[$thisone])) {
$inofinterest=str_replace("[" . $thisone . "]", str_replace("+", " ", urldecode($_POST[$thisone])), $inofinterest);
} else if (isset($_GET[$thisone])) {
$inofinterest=str_replace("[" . $thisone . "]", str_replace("+", " ", urldecode($_GET[$thisone])), $inofinterest);
}
}
}
}
if (strpos(($inofinterest . "~"), "]") !== false && strpos(($inofinterest . "~"), "[") !== false) {
$huharr=explode("[", $inofinterest);
$proposedih=$huharr[0];
for ($ih=1; $ih<sizeof($huharr); $ih++) {
$thisone=explode("]", $huharr[$ih])[0];
if ($huharr[$ih] != ($thisone . "]")) {
$proposedih.=explode(($thisone . "]"), $huharr[$ih])[1];
}
}
$subjarr[0]=str_replace("\n", " ", str_replace("\r\n", " ", $proposedih));
if (substr($inofinterest, 0, 1) == "[") {
$subjarr[1]=str_replace("\n", "<br>", str_replace("[", "<", str_replace("]", ">", $inofinterest)));
} else {
if (strpos($inofinterest, "\n") !== false) {
$huharr=explode("\n", $inofinterest);
$subjarr[1]="<html><body><textarea style='width:90%;font-size:28px;font-weight:bold;border:1px solid transparent;background-color:#f0f0f0;' rows=" . (1 + sizeof($huharr)) . ">" . $inofinterest . "</textarea></body></html>";
} else {
$subjarr[1]="<html><body><h1>" . $inofinterest . "</h1></body></html>";
}
}
} else {
$subjarr[0]=str_replace("\n", " ", str_replace("\r\n", " ", $inofinterest));
if (strpos($inofinterest, "\n") !== false) {
$huharr=explode("\n", $inofinterest);
$subjarr[1]="<html><body><textarea style='width:90%;font-size:28px;font-weight:bold;border:1px solid transparent;background-color:#f0f0f0;' rows=" . (1 + sizeof($huharr)) . ">" . $inofinterest . "</textarea></body></html>";
} else {
$subjarr[1]="<html><body><h1>" . $inofinterest . "</h1></body></html>";
}
}
}
} else if ($inofinterest != "") { // body
$ifnotblankbody=trim($ifnotblankbody);
}
return $inofinterest;
}


function subjtokenization($inthing, $inmode) {
global $subjarr, $fflist;
if ($inmode == "subject") {
if ($subjarr[0] != "") {
if ($fflist == "") { return $subjarr[0]; }
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, str_replace("<file>", $fflist, str_replace("[file]", $fflist, $subjarr[0]))));
} else if (strpos($inthing, "[") !== false) {
if ($fflist == "") { return str_replace("[date]", date('l jS \of F Y h:i:s A'), $inthing); }
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, str_replace("<file>", $fflist, str_replace("[file]", $fflist, str_replace("[date]", date('l jS \of F Y h:i:s A'), $inthing)))));
}
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, $inthing));
} else if ($inmode == "bodysubject") {
if ($subjarr[1] != "") {
if (substr($subjarr[1], 0, 1) == "<" && strpos($subjarr[1], "</h1>") !== false) {
$subjarr[1]=str_replace("</h1>", "</h1><h3>" . str_replace("\n", "<br>", $inthing) . "</h3>", $subjarr[1]);
} else if (substr($subjarr[1], 0, 1) == "<" && strpos($subjarr[1], "</body>") !== false) {
$subjarr[1]=str_replace("</body>", "<h3>" . str_replace("\n", "<br>", $inthing) . "</h3></body>", $subjarr[1]);
}
if ($fflist == "" || 1 == 1) { return $subjarr[1]; }
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, $subjarr[1]));
}
} else if ($inmode == "body") {
if ($subjarr[2] != "") {
return $subjarr[2];
}
} else if ($inmode == "contenttype") {
if ($subjarr[3] != "") {
return $subjarr[3];
}
} else if ($inmode == "file") {
$subjarr[1]=str_replace("<file>", $inthing, str_replace("[file]", $inthing, $subjarr[1]));
} else if ($inmode == "files" && $inthing != "") {
$subjarr[0]=str_replace("<files>", $inthing, str_replace("[files]", $inthing, $subjarr[0]));
$subjarr[1]=str_replace("<files>", $inthing, str_replace("[files]", $inthing, $subjarr[1]));
if ($subjarr[0] != "" && $subjarr[1] != "") {
if (strpos(preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[1]))), preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[0])))) !== false) {
$subjarr[0].=explode("<", explode(preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[0]))), preg_replace('/\s+/', ' ', str_replace("<br>","",str_replace("\n","",$subjarr[1]))))[1])[0];
}

}
}
return $inthing;
}

?>

And so that got us better using an HTML textarea element for body wording over multiple line purposes, as email text on top of any attachments placed with the web application’s emails sent out.

To see these improved email Gimp Guillotine web application integrations the changed gimp_guillotine_followup.php that you can try out at this live run link is worth a try.


Previous relevant Feedback Annotation Canvas Image Tokens Tutorial is shown below.

Feedback Annotation Canvas Image Tokens Tutorial

Feedback Annotation Canvas Image Tokens Tutorial

The discovery in yesterday’s Linux sendmail Remote Attachment Tutorial that …

in the “body” section part of the email above the attachment we’ve written functionality for Content-Type: text/plain …

so why not today write functionality to cater for Content-Type: text/html here (if allowed … spoiler alert … yes, it is … we tried some, and it worked, and we do this when a user defines their own tailored email subject, as talked about below)

… has far reaching implications for lots of inhouse web applications, improving the email look we can develop and improve upon. And so, today, we start out on that software integration journey, picking on the Feedback web application of the recent Feedback Annotation Canvas Image Filter Tutorial as the first guinea pig one to try.

We decided to approach it with a concept we like almost as much as we like “delimiter solutions”, that being a “token solution”. Not a forlorn solution, but a solution using …

Tokens
A token is basically a variable that you can store data in or retrieve data from at runtime in your guiDesigner projects. A token has a name and a value.

Token Naming
Suggested Syntax: [name]

A token can be named anything you like, but we suggest you follow the syntax above, including the square brackets in your token names. By doing this, it makes it easier to see where your token is actually being used within command values, etc.

… a square bracket [name] system “slapped over” by PHP mail preparation execution “value” substitution.

The first two such generic [name]s we try in this first round of work are used in the Feedback web application’s email Subject field for …

  • [date]
  • [files]

… but as the days go on we are going to allow and test …

  • some PHP $_SERVER[] variables
  • $_POST[] or $_GET[] arguments
  • [lf] line feed and [crlf] carriage return/line feed
  • [file] for first file only

As you will have surmised, this is a serverside PHP job, it being an email creation component change. The totally new PHP bits are …

<?php

$fflist="";
$subjarr=["", "", "", ""];

function zmail($zris, $zxsis, $ztis, $zhis) {
global $subjarr, $fflist;
if (strpos($zxsis, "[") === false && strpos($zxsis, "<") === false && $zxsis != "") {
$zxsis.=" at [date] for [files]";
analtoken($zxsis, "");
}
subjtokenization($fflist, "files");
$zhis=str_replace("<files>", $fflist, str_replace("[files]", $fflist, $zhis));
return mail($zris, subjtokenization($zxsis,"subject"), $ztis, $zhis);
}


function analtoken($inofinterest, $ifnotblankbody) {
global $subjarr, $fflist;
$inofinterest=trim($inofinterest);
if ($ifnotblankbody == "" && $inofinterest != "") { // subject
if (strpos(($inofinterest . "~"), "]~") !== false && strpos(($inofinterest . "~"), "[") !== false) {
$subjarr[3]="html";
$inofinterest=str_replace("[date]", date('l jS \of F Y h:i:s A'), $inofinterest);
$inofinterest=str_replace("[httpreferer]", $_SERVER['HTTP_REFERER'], $inofinterest);
$inofinterest=str_replace("[serveraddr]", $_SERVER['SERVER_ADDR'], $inofinterest);
$inofinterest=str_replace("[requesttime]", $_SERVER['REQUEST_TIME'], $inofinterest);
$inofinterest=str_replace("[httpacceptlanguage]", $_SERVER['HTTP_ACCEPT_LANGUAGE'], $inofinterest);
$inofinterest=str_replace("[httpuseragent]", $_SERVER['HTTP_USER_AGENT'], $inofinterest);
$inofinterest=str_replace("[remoteaddr]", $_SERVER['REMOTE_ADDR'], $inofinterest);
$inofinterest=str_replace("[requesturi]", $_SERVER['REQUEST_URI'], $inofinterest);
$inofinterest=str_replace("[pathinfo]", $_SERVER['PATH_INFO'], $inofinterest);
$inofinterest=str_replace("[lf]", "\n", $inofinterest);
$inofinterest=str_replace("[crlf]", "\r\n", $inofinterest);
$huharr=explode("[", $inofinterest);
if (strpos(($inofinterest . "~"), "]") !== false && strpos(($inofinterest . "~"), "[") !== false) {
for ($ih=1; $ih<sizeof($huharr); $ih++) {
$thisone=explode("]", $huharr[$ih])[0];
if (strpos($thisone, " ") === false) {
if (isset($_POST[$thisone])) {
$inofinterest=str_replace("[" . $thisone . "]", str_replace("+", " ", urldecode($_POST[$thisone])), $inofinterest);
} else if (isset($_GET[$thisone])) {
$inofinterest=str_replace("[" . $thisone . "]", str_replace("+", " ", urldecode($_GET[$thisone])), $inofinterest);
}
}
}
}
if (strpos(($inofinterest . "~"), "]") !== false && strpos(($inofinterest . "~"), "[") !== false) {
$huharr=explode("[", $inofinterest);
$proposedih=$huharr[0];
for ($ih=1; $ih<sizeof($huharr); $ih++) {
$thisone=explode("]", $huharr[$ih])[0];
if ($huharr[$ih] != ($thisone . "]")) {
$proposedih.=explode(($thisone . "]"), $huharr[$ih])[1];
}
}
$subjarr[0]=str_replace("\n", " ", str_replace("\r\n", " ", $proposedih));
if (substr($inofinterest, 0, 1) == "[") {
$subjarr[1]=str_replace("\n", "<br>", str_replace("[", "<", str_replace("]", ">", $inofinterest)));
} else {
if (strpos($inofinterest, "\n") !== false) {
$huharr=explode("\n", $inofinterest);
$subjarr[1]="<html><body><textarea style='width:100%;' rows=" . sizeof($huharr) . ">" . str_replace("\n", "<br>", str_replace("\r\n", "<br>", $inofinterest)) . "</textarea></body></html>";
} else {
$subjarr[1]="<html><body><h1>" . $inofinterest . "</h1></body></html>";
}
}
} else {
$subjarr[0]=str_replace("\n", " ", str_replace("\r\n", " ", $inofinterest));
if (strpos($inofinterest, "\n") !== false) {
$huharr=explode("\n", $inofinterest);
$subjarr[1]="<html><body><textarea style='width:100%;' rows=" . sizeof($huharr) . ">" . str_replace("\n", "<br>", str_replace("\r\n", "<br>", $inofinterest)) . "</textarea></body></html>";
} else {
$subjarr[1]="<html><body><h1>" . $inofinterest . "</h1></body></html>";
}
}
}
} else if ($inofinterest != "") { // body
$ifnotblankbody=trim($ifnotblankbody);
}
return $inofinterest;
}


function subjtokenization($inthing, $inmode) {
global $subjarr, $fflist;
if ($inmode == "subject") {
if ($subjarr[0] != "") {
if ($fflist == "") { return $subjarr[0]; }
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, str_replace("<file>", $fflist, str_replace("[file]", $fflist, $subjarr[0]))));
} else if (strpos($inthing, "[") !== false) {
if ($fflist == "") { return str_replace("[date]", date('l jS \of F Y h:i:s A'), $inthing); }
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, str_replace("<file>", $fflist, str_replace("[file]", $fflist, str_replace("[date]", date('l jS \of F Y h:i:s A'), $inthing)))));
}
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, $inthing));
} else if ($inmode == "bodysubject") {
if ($subjarr[1] != "") {
if (substr($subjarr[1], 0, 1) == "<" && strpos($subjarr[1], "</h1>") !== false) {
$subjarr[1]=str_replace("</h1>", "</h1><h3>" . str_replace("\n", "<br>", $inthing) . "</h3>", $subjarr[1]);
} else if (substr($subjarr[1], 0, 1) == "<" && strpos($subjarr[1], "</body>") !== false) {
$subjarr[1]=str_replace("</body>", "<h3>" . str_replace("\n", "<br>", $inthing) . "</h3></body>", $subjarr[1]);
}
if ($fflist == "" || 1 == 1) { return $subjarr[1]; }
return str_replace("<files>", $fflist, str_replace("[files]", $fflist, $subjarr[1]));
}
} else if ($inmode == "body") {
if ($subjarr[2] != "") {
return $subjarr[2];
}
} else if ($inmode == "contenttype") {
if ($subjarr[3] != "") {
return $subjarr[3];
}
} else if ($inmode == "file") {
$subjarr[1]=str_replace("<file>", $inthing, str_replace("[file]", $inthing, $subjarr[1]));
} else if ($inmode == "files" && $inthing != "") {
$subjarr[0]=str_replace("<files>", $inthing, str_replace("[files]", $inthing, $subjarr[0]));
$subjarr[1]=str_replace("<files>", $inthing, str_replace("[files]", $inthing, $subjarr[1]));
if ($subjarr[0] != "" && $subjarr[1] != "") {
if (strpos($subjarr[1], $subjarr[0]) !== false) {
$subjarr[0].=explode("<", explode($subjarr[0], $subjarr[1])[1])[0];
}
}
}
return $inthing;
}

?>

… related to (examples of) how it gets used in the rest of the code …

<?php

// Early on, as a subject input data item is identified ...
$psubject = analtoken(explode("~", str_replace("+"," ",urldecode($_GET['tdsubj'])))[0],"");
// Content-Type (for body section part above any attachments) ...
$headers .= "Content-Type: text/" . subjtokenization("plain", "contenttype") . "; charset=\"iso-8859-1\"" . $eol;
// Attachment file name established ...
if ($fflist == "") {
$fflist=$filename;
} else {
$fflist.="," . $filename;
}

$headers .= "Content-Disposition: attachment;filename=\"" . subjtokenization($filename,"file") . "\"" . $eol;
// New call to create the email, via a new call ...
zmail($ris, $xsis, $tis, $his);

?>

The changed PHP world.php represents about 98% of the changes, the changed feedback.htm representing the “informing the user of the token possibilities” only, that you can try out at this live run link.

Stop Press

A follow up (“Guinea Pig Two”) tutorial (called Gimp Guillotine Token Subject Tutorial as of 20th May 2020) has taught us some lessons for a subject like …


Feedback [lf] at [date] [crlf] ... [files]

… along with some $_SERVER[] array (PHP) isset checking, and some textarea styling (for multiple line subjects in the body section), caused a further changed PHP world.php to be set into play for your retesting purposes.


Previous relevant Feedback Annotation Canvas Image Filter Tutorial is shown below.

Feedback Annotation Canvas Image Filter Tutorial

Feedback Annotation Canvas Image Filter Tutorial

There are other image filters we can apply on top of yesterday’s Feedback Annotation Canvas Pixels Tutorial canvas pixel and transformational ones, they being ones that make use of the PHP GD image library. But there is a way to integrate this new functionality into our Feedback web application, rather than reinventing any wheels.

We’re going to integrate to the PHP web application featured in Gimp Guillotine Absolute to Relative Image URL Tutorial to make this happen and introduce in a new HTML select (dropdown) element, as per …


<select id=phpsel onchange=phpselit(this.value);><option value=''>Image Filter ...</option><option value='emboss'>Emboss</option><option value='edge'>Edge</option><option value='negedge'>Negedge</option><option value='sharpen'>Sharpen</option><option value='boxblur'>Boxblur</option><option value='negate'>Negate</option><option value='colourizered'>Colourizered</option><option value='colourizegreen'>Colourizegreen</option><option value='colourizeblue'>Colourizeblue</option><option value='colourize'>Colourize</option><option value='pixellate'>Pixellate</option><option value='smooth'>Smooth</option><option value='contrast'>Contrast</option><option value='brightness'>Brightness</option><option value='sketchy'>Sketchy</option></select>

… teamed with new navigational img and form and iframe related invisible elements as per …


<img onload=myiminteresting(this); style=display:none; id=myimx src=''></img><form target=myiframenine method=POST style=display:none; action='../PHP/gimp_guillotine_followup.php'><div id=phpaction style=display:none;></div><textarea name=duis id=duis style=display:none;></textarea><input id=bduis type=submit style=display:none; value=Act></input></form><iframe style='display:none;' name='myiframenine' id='myiframenine' src='../PHP/gimp_guillotine_followup.php'></iframe>

… that teams with new Javascript as per …


function myiminteresting(iois) {
if (iois != null) {
if (iois.src.replace(document.URL,'').trim() != '') {
if (document.getElementById('myimx').src.replace(document.URL,'') != '') {
if (parent.document.getElementById('canvaselement')) {
parent.document.getElementById('canvaselement').getContext('2d').drawImage(document.getElementById('myimx'), 0, 0, document.getElementById('myimx').width, document.getElementById('myimx').height);
parent.document.getElementById('phpsel').value='';
} else {
context.drawImage(document.getElementById('myimx'), 0, 0, document.getElementById('myimx').width, document.getElementById('myimx').height);
document.getElementById('phpsel').value='';
}
canvascommands.push("context.drawImage(document.getElementById('myimx'), 0, 0);");
}
}
}
}

function postphpselit() {
document.getElementById('duis').innerHTML=elem.toDataURL("image/png",0);
document.getElementById('myimx').src=document.URL;
document.getElementById('bduis').click();
}

function phpselit(tv) {
if (tv.trim() != '') {
if (document.getElementById('myimx').src.replace(document.URL,'') != '') {
postphpselit();
} else {
document.getElementById('bduis').name=tv.trim();
icontain=true;
icover=false;
document.getElementById('pcbut').click();
setTimeout(postphpselit, 3000);
}
}
}

… and a changed PHP receiving …

<?php

if (isset($_POST['duis'])) {
new_content(urldecode($_POST['duis']));
exit;
}

?>

… and a new local rewritten function code snippet as per

<?php

function ourfile_get_contents($ourfilename) {
global $zipfile, $ziparrc, $ziparr, $ext;
if (trim($zipfile) == "") {
if (substr(($ourfilename . " "),0,5) == "data:") {
$ext="." .
explode("/", explode(";base64,", str_replace(" ","+",$ourfilename))[0])[-1 + sizeof(explode("/", explode(";base64,", str_replace(" ","+",$ourfilename))[0]))]; // /jpeg;
return base64_decode(explode(";base64,", str_replace(" ","+",$ourfilename))[1]);
}

return file_get_contents($ourfilename);
} // lots more code follows
}

?>

… and a new code snippet in each if block of function new_content as per …

<?php

function new_content($zfilename) {
global $div_img, $ext;
if (isset($_GET['emboss']) || isset($_POST['emboss'])) {
$im_php = imagecreatefromstring(ourfile_get_contents($zfilename));
$emboss = array([-2, -1, 0], [-1, 1, 1], [0, 1, 2]);
imagefilter($im_php, IMG_FILTER_EMBOSS);
$new_name = 'anewimage0.jpg';
$nj=0;
while (file_exists('anewimage' . $nj . '.jpg')) {
$nj++;
$new_name = 'anewimage' . $nj . '.jpg';
}
imagejpeg($im_php, $new_name);
$qpzm='data:image/jpeg;base64,' . base64_encode(ourfile_get_contents($new_name));
imagedestroy($im_php);
unlink($new_name);
if (strpos($_SERVER['HTTP_REFERER'], "/feedback") !== false && strpos($_SERVER['HTTP_REFERER'], "rjmprogramming.com.au") !== false) {
echo "<!doctype html><html><body onload=\" if (parent.document.getElementById('myimx')) { parent.document.getElementById('myimx').src='" . $qpzm . "'; } \"></body></html>";
exit;
}

return $qpzm;
} // lots more code if blocks follows
}

?>

… yet again, in the changed feedback.htm (and its changed external Javascript world.js and calling changed PHP GD logic helper gimp_guillotine_followup.php) live run, for you to try, we hope.


Previous relevant Feedback Annotation Canvas Pixels Tutorial is shown below.

Feedback Annotation Canvas Pixels Tutorial

Feedback Annotation Canvas Pixels Tutorial

So far with our revisit work on the Feedback web application of yesterday’s Feedback Annotation Image Cover Contain Tutorial we haven’t talked much about the middle person conduit of data, the HTML(5) canvas element, it being a useful “middle person conduit candidate” because …

  • after data is captured to a canvas element it can easily be exported onto its next use via [canvasElement].toDataURL() method …
  • a variety of HTML(5) canvas data “populator” functions like [canvasContext].drawImage() method allow data to come into canvas …

… but the canvas element also has “rearrange of data” functions too.

Two at a pixel level are [canvasContext].getImageData() and [canvasContext].putImageData() used to add some new Annotation image functionality for …

  • Grayscale
  • Inverse

… and regarding “transformational” ways to “rearrange data” we offer …

  • Flip
  • Flop

… presented in terms of a user interface as HTML input type=checkbox as per (and Stop Press) …


&nbsp;&nbsp;Grayscale:&nbsp;<input id=chkgrayscale title=Grayscale type=checkbox onchange=oureval('dograyscale=',this.checked);></input>&nbsp;&nbsp;Inverse:&nbsp;<input id=chkinverse title=Inverse type=checkbox onchange=oureval('doinverse=',this.checked);></input>&nbsp;&nbsp;Flip:&nbsp;<input id=chkflip title=Flip type=checkbox onchange=oureval('doflip=',this.checked);></input>&nbsp;&nbsp;Flop:&nbsp;<input id=chkflop title=Flop type=checkbox onchange=oureval('doflop=',this.checked);></input>

… and supported by the new Javascript …


var dograyscale=false;
var doinverse=false;
var doflop=false;
var doflip=false;

function oureval(incmd, twot) {
eval(incmd + twot);
twot='!' + incmd.split("=")[0] + "; document.getElementById('" + incmd.split("=")[0].replace('do','chk') + "').checked=" + incmd.split("=")[0] + ";";
canvascommands.push(incmd + twot);
}

function ourDrawImage(ioo, ione, itwo, ithree, ifour, ifive, isix, iseven, ieight) { // thanks to https://stackoverflow.com/questions/3129099/how-to-flip-images-horizontally-with-html5
if (doflip) {
context.setTransform(-1,0,0,1,elem.width,0); // thanks to https://stackoverflow.com/questions/42844470/how-to-rotate-and-mirror-canvas-element
} else if (doflop) {
context.setTransform(1,0,0,-1,0,elem.height); // thanks to https://stackoverflow.com/questions/42844470/how-to-rotate-and-mirror-canvas-element
}
if (typeof ieight !== 'undefined') {
context.drawImage(ioo, ione, itwo, ithree, ifour, ifive, isix, iseven, ieight);
if (dograyscale) { grayscale(ioo, ione, itwo, ithree, ifour, ifive, isix, iseven, ieight); }
if (doinverse) { inverse(ioo, ione, itwo, ithree, ifour, ifive, isix, iseven, ieight); }
} else if (typeof isix !== 'undefined') {
context.drawImage(ioo, ione, itwo, ithree, ifour, ifive, isix);
if (dograyscale) { grayscale(ioo, ione, itwo, ithree, ifour, ifive, isix); }
if (doinverse) { inverse(ioo, ione, itwo, ithree, ifour, ifive, isix); }
} else {
context.drawImage(ioo, ione, itwo, ithree, ifour);
if (dograyscale) { grayscale(ioo, ione, itwo, ithree, ifour); }
if (doinverse) { inverse(ioo, ione, itwo, ithree, ifour); }
}
}

function inverse(ioo, ione, itwo, ithree, ifour, ifive, isix, iseven, ieight) { // thanks to https://www.w3schools.com/tags/canvas_getimagedata.asp
var i;
var imgData;
if (typeof ieight !== 'undefined') {
imgData=context.getImageData(ione, itwo, ithree, ifour);
} else if (typeof isix !== 'undefined') {
imgData=context.getImageData(ione, itwo, ithree, ifour);
} else {
imgData=context.getImageData(ione, itwo, ithree, ifour);
}
var data = imgData.data;
for (i=0;i<data.length;i+=4) {
data[i]=eval(255 - data[i]);
data[i+1]=eval(255 - data[i+1]);
data[i+2]=eval(255 - data[i+2]);
//data[i+3]=eval(15); //255); // - data[i+3]);
}
context.putImageData(imgData,ione, itwo);
}

function grayscale(ioo, ione, itwo, ithree, ifour, ifive, isix, iseven, ieight) { // thanks to https://www.w3schools.com/tags/canvas_getimagedata.asp
var i;
var imgData;
if (typeof ieight !== 'undefined') {
imgData=context.getImageData(ione, itwo, ithree, ifour);
} else if (typeof isix !== 'undefined') {
imgData=context.getImageData(ione, itwo, ithree, ifour);
} else {
imgData=context.getImageData(ione, itwo, ithree, ifour);
}
var data = imgData.data;
for (i = 0; i < data.length; i += 4) {
var bright = 0.34 * data[i] + 0.5 * data[i + 1] + 0.16 * data[i + 2];
data[i] = bright;
data[i + 1] = bright;
data[i + 2] = bright;
}
context.putImageData(imgData,ione, itwo);
}

… again, in the changed feedback.htm (and its changed external Javascript world.js) live run, for you to try, we hope.

Stop Press

We needed to consider integration with the Undo and Redo functionality.


Previous relevant Feedback Annotation Image Cover Contain Tutorial is shown below.

Feedback Annotation Image Cover Contain Tutorial

Feedback Annotation Image Cover Contain Tutorial

Do you remember a discussion here about the CSS property background-size we discussed with CSS3 Background Size Contain and Cover Primer Tutorial? It’s become one of our favourite properties ever since our bid for the Opera House failed?!

Well, today, we’re channeling that excellent concept to add some image to canvas placement additions to functionality, and scaling thoughts, regarding the Annotation section of our Feedback web application (last talked about with the recent Mobile Feedback Annotation Image Camera Capture Tutorial) which we have been revisiting lately.

Think of the two this way …

  • Contain (within canvas) retains an image’s aspect ratio but may scale it as to best fit within the bounds of the canvas given the dimensions of the image
  • Cover (within canvas) is unlikely to retain the aspect ratio as it scales the image to fit the dimensions of the canvas

These two options have the advantage that no user clicks on the canvas need happen ahead of image placement. As this is the case, we feel we can avail the user of this new functionality in two ways, those being …

  • Four new buttons …

    <button id=pcbut onclick='zeroone=1.0; readBlob(0,0);'>Place Click</button><button id=ocbut onclick='zeroone=1.0; readOBlob(0,0);'>Overlay Click</button><button onclick="icover=true; icontain=false; document.getElementById('pcbut').click();">Cover Place</button><button onclick="icontain=true; icover=false; document.getElementById('pcbut').click();">Contain Place</button><button onclick="icover=true; icontain=false; document.getElementById('ocbut').click();">Cover Overlay</button><button onclick="icontain=true; icover=false; document.getElementById('ocbut').click();">Contain Overlay</button>
  • Four new dropdown options on that scaling dropdown …

    <select id='imageclickmode' onchange=' if (eval(this.value) == 4) { icover=true; icontain=false; document.getElementById("pcbut").click(); } else if (eval(this.value) == 6) { icover=true; icontain=false; document.getElementById("ocbut").click(); } else if (eval(this.value) == 5) { icover=false; icontain=true; document.getElementById("pcbut").click(); } else if (eval(this.value) == 7) { icover=false; icontain=true; document.getElementById("ocbut").click(); } else { imageclickmode=dmyformit(eval(this.value)); } '><option value=0>Scaling as shown above</option><option value=1>Scaling to fit last two click/touch rectangle</option><option value=2>Scaling to suit last two click/touch rectangle width</option><option value=3>Scaling to suit last two click/touch rectangle height</option><option value=4>Cover Place</option><option value=5>Contain Place</option><option value=6>Cover Overlay</option><option value=7>Contain Overlay</option></select>

    … (we now remind the user about for all image browse completions (either taking a photo or successfully browsing for one))

Though by the end it doesn’t look much like an Android Toast temporary HTML div element (dialog box) showing this advice, a lot of its workings are based on how we applied Toast to the marmalade of our previous web application sautésortie (as per Daylight Saving Time Google Geo Chart Tooltips Tutorial).

Today, the changed feedback.htm‘s changed external Javascript world.js is called by our Feedback web application for your perusal and trial.


Previous relevant Mobile Feedback Annotation Image Camera Capture Tutorial is shown below.

Mobile Feedback Annotation Image Camera Capture Tutorial

Mobile Feedback Annotation Image Camera Capture Tutorial

Mobile devices, those “smart ones”, gave us a very useful advantage on top of a lot of the laptops that preceded them (regarding personal computing) … the inbuilt camera. HTML came along before the modern smart phone or tablet, so the HTML mechanism to support the webpage creation and storing of images via access to the device’s inbuilt camera had to be agreed upon. So, onto the progress of yesterday’s Feedback Emoji Mixed Content Tutorial we came up with (in the changed world.js external Javascript called by our Feedback web application) …


<img onload='thisim=this;' style='width:30px;height:32px;font-size:30px;' src='//www.rjmprogramming.com.au/MarkItUp/image.png' onclick=" bmode=' an image '; document.getElementById('file').click(); document.getElementById('file').style.display='inline-block'; document.getElementById('dpf').style.display='block'; " alt='Image' title='Image' id=imagefile></img><span id=spanimo></span><input onchange=' audiomaybe(); ' style='display:none;' id='file' type='file' name='file' data-ucapture='user' accept='image/*' data-capture='camera'>

… the apt snippet being (merely) accept=’image/*’ to allow for all of …

  • Take Photo
  • Photo Library
  • Browse…

… on those “smart mobile devices”. Nothing else “web application workflow wise” is needed. Everything becomes possible to use your “smart mobile device camera” to take a photo after the button press and capture and store it on the canvas element, perhaps on its way to a Feedback Email through to an emailee of the user’s choosing.

But how to flag to that “smart mobile device” user that this new functionality is available? We decided on a “ternary slide animation button” (ie. 3 slides) to replace a single “image button” to flag this, and hooked into the HTML above with the accompanying Javascript event logic as per …


var thisim=null, thisimo=null;

setTimeout(changeifile, 2000);

function changeifile() {
var irect, thisimsrc='none', donext=true, randnis=Math.floor(Math.random() * 19876452);
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
if (thisim) {
if (thisimo) { thisimo=document.getElementById('spanimo'); thisimsrc='' + thisimo.style.display; if (thisimsrc.trim() == '') { thisimsrc='none'; thisimo=null; } }
if (thisimsrc.toLowerCase() == 'none') { //thisim.src.indexOf('image.png') != -1) {
if (thisimo) {
if (eval(randnis % 2) == 1) {
document.getElementById('spanimo').style.fontSize='30px';
document.getElementById('spanimo').style.zIndex='777';
document.getElementById('spanimo').style.opacity='1.0';
document.getElementById('spanimo').style.border='1px dotted red';
document.getElementById('spanimo').style.display='inline-block';
document.getElementById('spanimo').style.marginLeft='-34px';
document.getElementById('spanimo').style.marginTop='-14px';
document.getElementById('spanimo').innerHTML='&#128247;';
thisimo.style.display='inline-block';
thisim.style.opacity='0.0';
} else {
thisim.style.opacity='1.0';
}
thisim.style.borderRadius='35px';
thisim.style.border='5px solid black';
} else {
irect=thisim.getBoundingClientRect();
if (eval('' + irect.left) != 0) {
thisimo=document.getElementById('spanimo');
if (eval(randnis % 2) == 1) {
document.getElementById('spanimo').style.fontSize='30px';
document.getElementById('spanimo').style.zIndex='777';
document.getElementById('spanimo').style.opacity='1.0';
document.getElementById('spanimo').style.border='1px dotted red';
document.getElementById('spanimo').style.display='inline-block';
document.getElementById('spanimo').style.marginLeft='-34px';
document.getElementById('spanimo').style.marginTop='-14px';
document.getElementById('spanimo').innerHTML='&#128247;';
thisim.style.opacity='0.0';
} else {
thisim.style.opacity='1.0';
}
thisim.style.borderRadius='35px';
thisim.style.border='5px solid black';
} else {
setTimeout(changeifile, 8000);
donext=false;
}
}
} else {
if (thisimo) {
thisimo.style.display='none';
thisim.style.opacity='1.0';
thisim.style.borderRadius='';
thisim.style.border='';
}
}
}
if (donext) { setTimeout(changeifile, 2000); }
}
}

… making use of …

  • combination of border-radius:35px; and border:5px solid black; for one of the new slide ideas … versus …
  • combination of span (📷) and display:inline-block; and font-size:30px; and margin-left:-34px; for the other one of the new slide ideas

… in the changed feedback.htm live run, for you to try, we hope.


Previous relevant Feedback Emoji Mixed Content Tutorial is shown below.

Feedback Emoji Mixed Content Tutorial

Feedback Emoji Mixed Content Tutorial

The issue of Mixed Content (ie. the mixing of http: and https: protocol) web content is an issue to look out for should you be a web application developer with a penchant for the HTML iframe element. We approached the fixing of Mixed Content issues for two issues in two different ways today. As a result …

  • for an emoji web application not asking for any personalized user entries we just decided to perform a one off check of https: protocol usage and redirected to http: as per the added Javascript …

    if (document.URL.toLowerCase().indexOf('https:') == 0) {
    location.href='http' + document.URL.substring(5);
    }


    </script>
    </head>
    <body>

    … in the changed fairy_story_assistant.html live run supervisor of the changed fairy_story_assistant.php Fairy Story creator web application … “easy peasy” but not so good for a more sensitive …
  • feedback (involving emoji HTML iframe) web application (which you can read about at the recent Feedback Inline HTML Form Email Collaboration Animation Tutorial below) that has email sharing functionality we decided to nut out how to make the “Mixed Content” weak emoji HTML iframe child work for the https: protocol (and remain working for the http: protocol, as it always had) … via, in broad brush terms …
    1. when using https: protocol separate navigation to navigate to some middle person PHP … as per in the changed feedback.htm live run‘s …

      <script type='text/javascript'>
      if (document.URL.toLowerCase().indexOf('http:') != -1) {
      document.write("
      <td id='emojis' style='vertical-align:top;border:4px solid red; float:left; height:180px; -webkit-overflow-scrolling:touch;overflow:hidden; align: top;'><iframe style='height:240px;' name='emojis' id='emojis' src='//www.rjmprogramming.com.au/PHP/emoticon_keyboard_shortcuts.php#myh3'></iframe></td>");
      } else {
      document.write("<td id='emojis' style='vertical-align:top;border:4px solid red; float:left; height:180px; -webkit-overflow-scrolling:touch;overflow:hidden; align: top;'><iframe style='height:240px;' name='emojis' id='emojis' src='//www.rjmprogramming.com.au/PHP/emoticonkeyboardshortcuts.php#myh3'></iframe></td>");
      }
      </script>

    2. and within the middle person PHP we start to use (for us) text/html data-URIs (associated with an HTML iframe’s “src” attribute) as per PHP (help via file_get_contents()) …
      <?php

      $pineapple=file_get_contents("HTTP://emojiterra.com/pineapple");
      $pineto='data:text/html,' . urlencode($pineapple);

      $pineapp=file_get_contents("HTTP://afeld.github.io/emoji-css/");
      $pinetwo='data:text/html,' . urlencode($pineapp);

      echo str_replace(' src="HTTP://afeld.github.io/emoji-css/"', ' src="' . $pinetwo . '"', str_replace(' src="HTTP://emojiterra.com/pineapple/"', ' src="' . $pineto . '"', str_replace(' src="//afeld.github.io/emoji-css/"', ' src="' . $pinetwo . '"', str_replace(' src="//emojiterra.com/pineapple/"', ' src="' . $pineto . '"', file_get_contents("../PHP/emoticon_keyboard_shortcuts.htm")))));

      ?>
      … as a means whereby you can substitute any “protocol syntax” for “data-URI syntax” (as that transportable way to define data, at the expense of verbosity) … an advantage here being the lack of any need to involve any “srcdoc” attribute, at all
    3. as well as “the first port of call” checks for needless use of “http:” and “https:” hard codings, where absolute URLs starting with // are “all the go”

Food for thought, we hope.


Previous relevant Feedback Inline HTML Form Email Collaboration Animation Tutorial is shown below.

Feedback Inline HTML Form Email Collaboration Animation Tutorial

Feedback Inline HTML Form Email Collaboration Animation Tutorial

In order to add “animation” thoughts into the mix of the thinking regarding the “Feedback” web application of Feedback Inline HTML Form Email Collaboration Recall Tutorial we had to …

  1. establish you can define an animated GIF that is not just the first slide, static, in an HTML img element using a data URI for the src attribute … check
  2. see if the animated GIF could be the background to an Inline HTML Email textarea element, animated … uncheck, alas, as well as to do with the usual size of such animated GIFs (to avoid the dreaded Gmail Clipping perhaps) … so …
  3. team up the attached image email with the Inline HTML Form Email one we now …
    • ditch the textarea background attempts when a .gif image involved
    • guarantee email subjects match (for both types of email)
    • place the same GMT date string in both emails to be a search of emails criteria for the collaborators (even offering a webmail link for the second collaborator having a Gmail email address)

How does the user of …

… even involve Animated GIFs? Well …

  • down in the green “Annotations” section …
  • there is an “image” icon/button you can click …
  • to browse for image files to upload, and they can be Animated GIFs (or they could come from the “Image URL” textbox as well) … and then …
  • clicking the “Place into Canvas” button … will …
  • add into the top left white section (with pink border) a new Animated GIF thumbnail button … that if pressed …
  • causes a check to be made if there is enough information to email those two email types to the Email To email address

… that’s how! And if a picture tells a thousand words, watch out for the “verbosity overload” with your Animated GIFs!


Previous relevant Feedback Inline HTML Form Email Collaboration Recall Tutorial is shown below.

Feedback Inline HTML Form Email Collaboration Recall Tutorial

Feedback Inline HTML Form Email Collaboration Recall Tutorial

Just because yesterday’s Feedback Inline HTML Form Email Collaboration Accountability Tutorial‘s Inline HTML Email Form got dumbed down from method=POST to method=GET (and so the data URI data of the image subject matter could not be “chained along” in the email thread of our Feedback and Collaboration subset of functionality from our Feedback web application) doesn’t mean we have to …

  • give up on recall via serverside language (PHP) methodologies (though we do have some ideas for a “gap year” project one day) … because there is still …
  • client-side recall via what many people know as (Javascript DOM) HTTP Cookies, though today we’re using localStorage web browser local storage, usually only for the original author of the image subject matter

Why “localStorage” and not “HTTP Cookies”? Have you ever seen the error message …


HTTP 414 "Request URI too long"

… surfing the net? Many of us, for sure. It happens when the URL at the address bar exceeds length limits for the web server it is destined to liaise with. HTTP Cookies work to this same limit, more or less. We tend to think 800 to 900 characters for RJM Programming regarding this HTTP 414 error. That’s why we’re always raving about “method=POST” and PHP’s $_POST array (rather than method=GET and $_GET array), because that 800 to 900 is not going to handle the data URI length for that image. HTTP Cookies came first, but then localStorage got invented. Yayyyyyyyyyyyy!!!!!!!

How do we work localStorage into the changed feedback.htm‘s Feedback live run underlying web application, bearing in mind, it is only useful for the original “author” of the image data (on the web browser they were using at the time of Inline HTML Form Email relay to their fellow collaborator)?

Checking for a previous storing of an Inline HTML Form Email image in localStorage at document.body onload event Javascript function “onloading”

var imgd=null;
var dval='';
function onloading() {
//other logic here
if (window.localStorage) {
for (var iq in window.localStorage) {
var val = localStorage.getItem(iq);
if (val) {
if (iq == 'lf_img') {
dval=decodeURIComponent(val);
if (document.getElementById('dilhe').innerHTML.indexOf('"checkbox"') == -1) {
document.getElementById('dilhe').innerHTML+=' <span id=rcbx title="Recall last Inline HTML Email image into canvas just below">Recall Last? <input type="checkbox" onchange="loadimgd();"></input></span>';
}
}
}
}
}
//other logic here
}
… adding that new checkbox, as found, that, if checked will cause the Javascript function “loadimgd” to be executed, as per …

function loadimgd() {
var ditems=dval.split(' ');
if (ditems.length >= 5) {
imgd = new Image();

imgd.onload = function() {
context.drawImage(imgd, 0, 0);
};

imgd.src = ditems[4];
document.getElementById('myto').value = ditems[0];
if (ditems[1].replace("@","").trim() != "") { document.getElementById('mycc').value = ditems[1]; }
if (ditems[2].replace("@","").trim() != "") { document.getElementById('mybcc').value = ditems[2]; }
if (ditems[3].replace(/\~/g," ").trim() != "") { document.getElementById('feedback').value = ditems[3].replace(/\~/g,' '); }
if (document.getElementById('rcbx')) {
document.getElementById('rcbx').innerHTML="";
}
}
}
… filling in emailee and subject textboxes, as well as initializing the canvas with the image subject data found … and kicking off all this localStorage storing of images happens when the user clicks the “Send Feedback as Inline HTML Email” button, as per Javascript function “lssave”

function lssave() {
if (window.localStorage) {
if (document.getElementById('myto').value.indexOf('@') != -1) {
var ccis=document.getElementById('mycc').value;
var bccis=document.getElementById('mybcc').value;
var fbis=document.getElementById('feedback').value.replace(/\ /g, '~');
if (ccis == '') { ccis='@'; }
if (bccis == '') { bccis='@'; }
if (fbis == '') { fbis='~'; }
localStorage.setItem('lf_img', encodeURIComponent(document.getElementById('tdto').value + ' ' + ccis + ' ' + bccis + ' ' + fbis + ' ' + elem.toDataURL("image/png",0)));
if (document.getElementById('dilhe').innerHTML.indexOf('"checkbox"') == -1) {
document.getElementById('dilhe').innerHTML+=' <span id=rcbx>Recall Last? <input type="checkbox" onchange="loadimgd();"></input></span>';
}
}
}
}

As you might surmise, best used to pick up where you left off developing an idea or concept.


Previous relevant Feedback Inline HTML Form Email Collaboration Accountability Tutorial is shown below.

Feedback Inline HTML Form Email Collaboration Accountability Tutorial

Feedback Inline HTML Form Email Collaboration Accountability Tutorial

Yesterday’s Feedback Inline HTML Form Email Collaboration Reply Tutorial left off with an …

  • initial image creation phase … and from there we talked about the new …
  • Inline HTML Form Email (textarea background image) approach … to collaborating with a second collaborator via …
  • HTML form method=POST means

… and that method=POST had two implications, those being …

  1. you need to involve a serverside language such as PHP to work with method=POST … its large data handling capabilities meaning …
  2. we could send the image (of feedback and collaboration focus) as a data URL along with the email
  3. … but, alas, looking more into the practicalities of involving both email clients we’ve tried here …

    • Gmail via a web browser URL (webmail email client) shows the Inline HTML Email Form without the textarea background data URL showing, yet the old email attachment sending of that same image data works to be able to download this Feedback image
    • the macOS Mail desktop application email client shows the Inline HTML Email Form with the textarea background data URL showing, yet the old email attachment sending of that same image data does not work (to be able to download this Feedback image)

    … that macOS Mail desktop application choice above, we found, only transfered our collaboration data if we used method=GET on our Inline HTML Form Email forms. Out the door goes chaining the image data URL data along with the email any more! Boo hoo! How else, now, can we be “accountable” (to us, to do with whether you can recreate a scenario, or value add)? Well, we have that first email involving both Email To and Email From to work with, where both parties will have access to a downloading method to get to the image data, unless they have deleted the original email(s), that is. What is a way to go back to an email? We chose to “chain along” a GMT date time (to second accuracy) within the email thread, to apply here. Accountability back to the original image data subject matter we hope, and keeping the web application project idea of not having to store all these images on the RJM Programming web server. Rather, the mail servers involved are the repository of these image data discussion points.

    Have another look, anyway, at …


    Previous relevant Feedback Inline HTML Form Email Collaboration Reply Tutorial is shown below.

    Feedback Inline HTML Form Email Collaboration Reply Tutorial

    Feedback Inline HTML Form Email Collaboration Reply Tutorial

    Yesterday’s Feedback Inline HTML Form Email Collaboration Tutorial start has been continued, and we were surprised how hard it was replying to that first Inline HTML Email to another Inline HTML Email and swapping the emailee To with the emailee From, but there you go. Sometimes it is hard to tell what will be difficult and what not.

    And even with this “reply to first collaboration call email” now set up to chain the emailing collaboration text between the two collaborators, we find some mysteries we’ll keep you posted on. The most intriguing is the Inline HTML Email form behaviour for textarea elements only accepting space characters when you paste them in, but not typing them in. Go figure! It’s probably something on our end, but have never seen this before. Work for tomorrow.

    Have a look, anyway, at …

    Let’s face it. It’s a work in progress!


    Previous relevant Feedback Inline HTML Form Email Collaboration Tutorial is shown below.

    Feedback Inline HTML Form Email Collaboration Tutorial

    Feedback Inline HTML Form Email Collaboration Tutorial

    We want to embark on a more collaborative phase to our Feedback web application last tweaked with the recent Feedback SMS via Highlighting Mark Tag Tutorial.

    What’s changed here (at RJM Programming recently) to make this something we have mulled over in our mind, and imagined, is our PHP mail techniques to send Inline HTML Form Emails. So this means, now …

    • our changed feedback.htm‘s live run has a new “Send Feedback as Inline HTML Email” button … that sends a new …
    • HTML …

      document.getElementById('tdhuhta').innerHTML='<body><h1>Feedback and Collaboration to ' + vstvs + '</h1><br><h3>RJM Programming<h3><br><br><form method=POST action="' + document.URL.split('HTMLCSS/feedback.htm')[0] + 'PHP/emoticon_keyboard_shortcut.php">' + 'Feedback: <br><textarea rows=15 cols=300 name=already title="Multi-line feedback" style=' + "'" + 'width:' + ('' + document.getElementById('canvaselement').width).replace('px','') + 'px;height:' + ('' + document.getElementById('canvaselement').height).replace('px','') + 'px;background:URL("' + canvascont + '");' + "'" + '></textarea><input type=hidden name=dataurlis value="' + canvascont + '"></input><br><br>One line feedback: <input type=text placeholder="Enter any one line feedback here" value="" name="oneliner"></input><input type=hidden value="' + document.getElementById('tdto').value + '" name="emailtois"></input><br><br>' + ('<input type=hidden value="' + document.getElementById('tdcc').value + '" name="emailfromis"></input>').replace('<input type=hidden value=""','Email from: <input type=text value=""') + '<br><br><input type=submit style="background-color:yellow;" value="Feedback back to RJM Programming"></input></form></body>';

      … which, as you can see, passes on to (a supervised) the changed emoticon_keyboard_shortcuts.php (but not changed yet for the next phase of “Analyzing the Response to the Initial Feedback with Your Collaborator” … tomorrow’s work) the data items …

      1. Email To (relative to first Feedback web application initiator)
      2. Email From (relative to first Feedback web application initiator)
      3. Feedback Image Data URL (which also helps create a background image to the textarea element of the Inline HTML Form Email)
      4. Feedback Response Collaboration multi-line text
      5. Feedback Response Collaboration single-line text

    We found our two types of email client for our Gmail behaved differently for this new email component …

    • Gmail via a web browser URL (webmail email client) shows the Inline HTML Email Form without the textarea background data URL showing, yet the old email attachment sending of that same image data works to be able to download this Feedback image
    • the macOS Mail desktop application email client shows the Inline HTML Email Form with the textarea background data URL showing, yet the old email attachment sending of that same image data does not work (to be able to download this Feedback image)

    As a result, we continue to send both email approaches.

    Our dream with this project is that our mail server can be that “honest broker” between two (or more) collaborators tweaking image based discussion points, and tomorrow’s “Analyzing the Response to the Initial Feedback with Your Collaborator” represents another step towards this aim. We hope you join us on this project!

    You can also see this play out at WordPress 4.1.1’s Feedback Inline HTML Form Email Collaboration Tutorial.


    Previous relevant Feedback SMS via Highlighting Mark Tag Tutorial is shown below.

    Feedback SMS via Highlighting Mark Tag Tutorial

    Feedback SMS via Highlighting Mark Tag Tutorial

    It’s come around to that time of the year. Yes, it’s the day after yesterday, and the previous Email Subject Line Emojis Primer Tutorial last reference to our Feedback web application (around here) deserves a revisit. Why? The recent talking points …

    • mark tag
    • SMS communication via the SMS client (eg. Messages app) and via a sms: “a” link
    • highlighted text Javascript logic

    … spring to mind … and HTML div contenteditable=true is really useful here too. We often want to filter data, and highlighting text is a new area of interest to us with our web applications recently.

    See if this interests you with the changed feedback.htm‘s live run link.


    Previous relevant Email Subject Line Emojis Primer Tutorial is shown below.

    Signature Signature Emoji Placeholder Lookup Tutorial

    Email Subject Line Emojis Primer Tutorial

    There are two themes to today’s Email Subject Line Emojis Primer Tutorial blog posting, those being …

    • if you have a programming job, and it sounds daunting on paper, it is good to mull (ie. think) for a while on it, and let it (ie. your mind) stew through possibilities, so that the topic of “Emojis on Email Subject Lines”, which you seem to see everywhere these days (or is Christmas arriving soon?!), didn’t seem so daunting when we categorized the hardest bit of the job (some would be saying dohhhhhh!) being the display of emojis to choose, when it mulledoccurred to us that we spent quite some hours with the web application featured in Signature Signature Emoji Placeholder Lookup Tutorial displaying emojis for the purpose of (Feedback and/or Contact Us) communications, and so the integration with this (and very easy and small it was) was the way to go, as a means whereby we can share with you (ie. you) a feel for what we mean here … however, and didn’t you just know that a “but” would be around the next carriage return …
    • but we would suggest that because you gain knowledge of a programming technique you think of “association” and “judiciousness” as well, because these emojis in subject lines appear to be associated with “marketing” a lot, and perhaps the use in business communication should be avoided … pretty obviously those decisions are up to users, and the context, and seriousness of the communications involved

    The other thing is that your normal native emailing methods via webmail URLs or client email programs will have native functionality that you can add an emoji to email subject lines yourself. We just turn what used to be a hardcoded webpage piece of text into an HTML input type=button button to facilitate the changed feedback.htm‘s live run


    document.write("<input type=button value=Subject onclick=\"document.getElementById('feedback').value+=document.getElementById('myfeedback').value;\" title='Optionally (and judiciously) add emojis to right onto subject line'></input>: <input style='width:160px; align:right;' type='text' id='feedback' onblur=\" document.getElementById('mysubject').value=this.value; document.getElementById('myisubject').value=this.value; fixmyemail(this.value + ' ',1); \" value='Feedback'></input><br><input type='button' id='feedbutton' onclick=\" xcapture(document.getElementById('mydurl'),document.getElementById('bsubmit'),document.getElementById('myemail')); \" value='Send Feedback' style='background-color:yellow; '></input>");

    … so, as you can see, not much to do here, so jobs “can sometimes integrate themselves off others” (quite simply) is our message today.


    Previous relevant Signature Signature Emoji Placeholder Lookup Tutorial is shown below.

    Signature Signature Emoji Placeholder Lookup Tutorial

    Signature Signature Emoji Placeholder Lookup Tutorial

    If you are interested in Emojis, perhaps we should direct you to read, back in time, Emoji Name Search Primer Tutorial, because it was there we tweaked onto the great Emoji Terra website’s permalink arrangements for Emoji lookups, that can be used to glean the CodePoint information needed to construct simple or compound Emojis via the String.fromCodePoint() Javascript function.

    You’d be surprised to hear, perhaps, that to make this happen involved changes to three pieces of code where yesterday’s Signature Signature Emoji Placeholder Tutorial changes only involved one.

    So, within the onblur event keyboard activity of our new HTML input type=text element, what ways are available to enter an Emoji now …

    • enter dot delimited CodePoint numbers … eg. … 128675.127996
    • enter HTML dec format … eg. &#128675;&#127996;
    • enter Mac OS X Command-Control-Space or Windows+; to get to an Emoji menu method of entry
    • continuously changing case piece of text that will be looked up at Emoji Terra … eg. … aPpLe

    … as well as the onclick Emojis in the placeholder method. Other approaches make whatever text you enter go through to the awaiting HTML textarea element and onto the awaiting HTML canvas element, and perhaps onto the awaiting emailee recipient.

    Happy 😁 Emoji entry making!


    Previous relevant Signature Signature Emoji Placeholder Tutorial is shown below.

    Signature Signature Emoji Placeholder Tutorial

    Signature Signature Emoji Placeholder Tutorial

    Akin to the Contact Us Feedback Emoji Placeholder Tutorial ideas for “Emoji Placeholders” the other thought we had in this line of thinking was for interfacing this new idea as another revisit to the web application of User of Signature Signature Revisit Primer Tutorial, as emoji creation is a useful adjunct to any communication tool.

    Again, very similar code is involved, that being to external Javascript sitting in an HTML iframe, so parent.document becomes the go this time …


    function ipf() {
    var chac=-1; //Math.floor(Math.random() * 79) + 128512;
    var chactwo=[]; //Math.floor(Math.random() * 4) + 127995;


    if (parent.document) {
    if (parent.document.getElementById('iplaceholder')) {

    var elist=['128512.128591',
    '128640.128767',
    '9728.9983',
    '&#127939;&#127998;&#8205;&#9792;&#65039;',
    '&#127939;&#8205;&#9794;&#65039;',
    '&#127939;&#127998;&#8205;&#9792;&#65039;','&#127939;&#8205;&#9794;&#65039;','&#127939;&#127995;&#8205;&#9792;&#65039;','&#127939;&#127999;','&#127939;&#127997;','&#127939;&#127999;','&#127939;&#127998;&#8205;&#9792;&#65039;','&#127939;&#127995;&#8205;&#9792;&#65039;',
    '&#127939;&#127998;&#8205;&#9792;&#65039;','&#127939;&#8205;&#9794;&#65039;','&#127939;&#127995;&#8205;&#9792;&#65039;','&#127939;&#127999;','&#127939;&#127997;','&#127939;&#127999;','&#127939;&#127998;&#8205;&#9792;&#65039;','&#127939;&#127995;&#8205;&#9792;&#65039;',
    '&#128675;&#8205;&#9792;&#65039;','&#128675;','&#128675;','&#128675;&#127996;','&#128675;&#127997;','&#128675;&#127998;','&#128675;&#127995;&#8205;&#9792;&#65039;','&#128675;&#127997;&#8205;&#9792;&#65039;','&#128675;&#127998;&#8205;&#9792;&#65039;','&#128675;&#127996;&#8205;&#9792;&#65039;','&#128675;&#127995;','&#128675;&#127999;&#8205;&#9792;&#65039;','&#128675;&#127999;',
    '&#128675;&#8205;&#9792;&#65039;','&#128675;','&#128675;','&#128675;&#127996;','&#128675;&#127997;','&#128675;&#127998;','&#128675;&#127995;&#8205;&#9792;&#65039;','&#128675;&#127997;&#8205;&#9792;&#65039;','&#128675;&#127998;&#8205;&#9792;&#65039;','&#128675;&#127996;&#8205;&#9792;&#65039;','&#128675;&#127995;','&#128675;&#127999;&#8205;&#9792;&#65039;','&#128675;&#127999;',
    '9984.10175',
    '127744.128511',
    '129280.129535',
    '128512.128591'];


    var ehac=Math.floor(Math.random() * elist.length), mul='', ichac=0;


    if (elist[ehac].indexOf('.') != -1) {
    chac=Math.floor(Math.random() * eval(eval(elist[ehac].split('.')[1]) - eval(elist[ehac].split('.')[0]))) + eval(elist[ehac].split('.')[0]);
    } else {
    chactwo=(elist[ehac] + ';').replace(';;','').replace('&#','').split(';&#');
    for (ichac=0; ichac<chactwo.length; ichac++) {
    mul+=String.fromCodePoint(eval('' + chactwo[ichac]));
    }
    }


    if (parent.document.getElementById('iplaceholder').placeholder.length >= 39) {
    if (chac >= 0) {
    parent.document.getElementById('iplaceholder').placeholder=String.fromCodePoint(chac);
    } else {
    parent.document.getElementById('iplaceholder').placeholder=mul;
    }
    } else {
    if (chac >= 0) {
    parent.document.getElementById('iplaceholder').placeholder+=String.fromCodePoint(chac);
    } else {
    parent.document.getElementById('iplaceholder').placeholder+=mul;
    }
    }
    setTimeout(ipf, 2500);
    }
    }

    }


    setTimeout(ipf, 2500);

    … this time entering the Javascript DOM pieced together HTML …


    var emoji_placeholder="<br><input onblur=\"if (this.value.length > 0) { document.getElementById('myta').value+=this.value; this.value=''; } else if (this.placeholder.length > 0) { document.getElementById('myta').value+=this.placeholder; this.placeholder=''; }\" onclick=\"if (this.placeholder.length > 0) { document.getElementById('myta').value+=this.placeholder; this.placeholder=''; }\" type=text style='width:30%;border:1px dotted yellow;' value='' title='Click when you like an emoji to place below' id='iplaceholder' placeholder=''></input>";
    parent.document.getElementById('toptd').innerHTML+=pdfbookdata + "<div id='domymd5' style='text-decoration:underline;cursor:pointer;' onclick=\" document.getElementById('" + topielem.id + "').contentWindow.setdomymd5(); this.innerHTML=''; \"></div> <div id='dmycbox'><input id=mycbox style='border:4px outset green;background-color:lightgray;-webkit-appearance: none;-moz-appearance:none;appearance:none;height:35px;text-decoration:line-through;' onclick=\"if (this.value.indexOf('Show ') == 0) { document.getElementById('topiframe').style.display='block'; this.value=this.value.replace('Show ','Hide '); this.style.textDecoration='line-through'; } else { document.getElementById('topiframe').style.display='none'; this.value=this.value.replace('Hide ','Show '); this.style.textDecoration='none'; }\" type=button value='Hide Signature Panel 💳'></input> <input id='jsdownload' style='border:4px outset green;background-color:lightgray;-webkit-appearance: none;-moz-appearance:none;appearance:none;height:35px;' type='button' value='Download 💾' onclick=\" document.getElementById('" + topielem.id + "').contentWindow.download(); \"></input> <input id='jsnewwindow' style='border:4px outset green;background-color:lightgray;-webkit-appearance: none;-moz-appearance:none;appearance:none;height:35px;' type='button' value='New Windows 📑' onclick=\" document.getElementById('" + topielem.id + "').contentWindow.wop(); \"></input> <input style='display:none;border:4px outset green;background-color:lightgray;-webkit-appearance: none;-moz-appearance:none;appearance:none;height:35px;' id='jsundo' type='button' value='Undo ❌' onclick=\" document.getElementById('" + topielem.id + "').contentWindow.undosnapshotcanvas(); \"></input> <input style='display:none;border:4px outset green;background-color:lightgray;-webkit-appearance: none;-moz-appearance:none;appearance:none;height:35px;' id='jsredo' type='button' value='Redo ✔' onclick=\" document.getElementById('" + topielem.id + "').contentWindow.redosnapshotcanvas(); \"></input>" + emoji_placeholder + "<br><br><input style=' width: 18px; height: 18px; position: relative; margin: 2px auto; background: #fcfff4; background: linear-gradient(top, #fcfff4 0%, #dfe5d7 40%, #b3bead 100%); border-radius: 25px; box-shadow: inset 0px 1px 1px white, 0px 1px 3px rgba(0,0,0,0.5);' onchange=\" if (this.checked) { document.getElementById('" + topielem.id + "').contentWindow.evalit('transcontent=true'); } else { document.getElementById('" + topielem.id + "').contentWindow.evalit('transcontent=false'); } transcontent=this.checked;\" type='checkbox' id='transcontent' title='Transform left 👈 canvas 🎨 content versus look (of it only)' checked></input> Content Flip ↔: <input onchange=\" if (this.checked) { document.getElementById('" + topielem.id + "').contentWindow.evalit('always_horizontally_flip=true'); } else { document.getElementById('" + topielem.id + "').contentWindow.evalit('always_horizontally_flip=false'); } always_horizontally_flip=this.checked;\" style=' width: 18px; height: 18px; position: relative; margin: 2px auto; background: #fcfff4; background: linear-gradient(top, #fcfff4 0%, #dfe5d7 40%, #b3bead 100%); border-radius: 25px; box-shadow: inset 0px 1px 1px white, 0px 1px 3px rgba(0,0,0,0.5);' type='checkbox' id='autoflip' title='Horizontally Flip left 👈 canvas 🎨'></input> Flop 🙃: <input title='Vertically Flop left 👈 canvas 🎨' onchange=\" if (this.checked) { document.getElementById('" + topielem.id + "').contentWindow.evalit('always_vertically_flop=true'); } else { document.getElementById('" + topielem.id + "').contentWindow.evalit('always_vertically_flop=false'); } always_vertically_flop=this.checked;\" style=' width: 18px; height: 18px; position: relative; margin: 2px auto; background: #fcfff4; background: linear-gradient(top, #fcfff4 0%, #dfe5d7 40%, #b3bead 100%); border-radius: 25px; box-shadow: inset 0px 1px 1px white, 0px 1px 3px rgba(0,0,0,0.5);' type='checkbox' id='autoflop'></input> Rotation 🎡: <input title='Rotate (in degrees) left 👈 canvas 🎨' id='autorotation' style='width:35px;' type=number onblur=\" document.getElementById('" + topielem.id + "').contentWindow.evalit('rotis=' + this.value); " + intocb + "\" onchange=\" document.getElementById('" + topielem.id + "').contentWindow.evalit('rotis=' + this.value); " + intocb + "\" min='-360' max='360' value='0' step='1'></input>°<br><br>Email 📧 To: <input title='Separate email 📧 to from optional email cc by (,) and from optional email bcc by (;) and suffixed, optionally by (:) followed by an email Subject' id='jsemail' type='text' onblur=' jsemail=this.value;' value='" + jsemail + "'></input> <input id='jsemailb' style='display:none;border:4px outset green;background-color:lightgray;-webkit-appearance: none;-moz-appearance:none;appearance:none;height:35px;' type='button' onclick=\"document.getElementById('jsemail').value=document.getElementById('jsemail').value.trim() + ' ';\" value='Email 📧'></input>  <input id='jsemailpdf' style='display:none;border:4px outset green;background-color:lightgray;-webkit-appearance: none;-moz-appearance:none;appearance:none;height:35px;' type='button' onclick=\"document.getElementById('jsemail').value=document.getElementById('jsemail').value.trim() + ' ';\" value='Email PDF 📄'></input>  <input id='jsemailp' style='display:none;border:4px outset green;background-color:lightgray;-webkit-appearance: none;-moz-appearance:none;appearance:none;height:35px;' type='button' onclick=\"document.getElementById('jsemail').value=document.getElementById('jsemail').value.trim() + ' ';\" value='Postcard ✉'></input><br><div id='danimation'>" + insidedanimation + "</div><br>" + sobutton + "<br><select onchange=\" document.getElementById('" + topielem.id + "').contentWindow.rezero(); \" style='width:92%; -webkit-border-radius: 20px; -moz-border-radius: 20px; border-radius: 20px;border: 5px solid #ccc;background-color:lightgreen;' id='dcm' title='Discrete click/touch mode'><option id='odef' value=>Discrete Canvas 🎨 Click/Touch 🖱 Mode [Rectangle (outline) 🔲 (via two clicks 🖱🖱)]</option><option value='lo'>Line 📏 (via two clicks 🖱🖱)</option><option value='im'>Image 🖼 URL ⚓ (sized via two clicks 🖱🖱)</option><option value='ib'>Image 🖼 Browse 📂 (sized via two clicks 🖱🖱)</option>" + pdfideas + "<option value='Im'>Background 🌦 Canvas Image 🖼 URL ⚓ (Image dimension changes) (can do Standing Orders 📆, as below)</option><option value='Ib'>Background 🌦 Canvas Image 🖼 Browse 📂 (Image dimension changes)</option><option value='IM'>Background 🌦 Image 🖼 Canvas URL ⚓ (Canvas dimension changes) (can do Standing Orders 📆, as below)</option><option value='IB'>Background 🌦 Image 🖼 Canvas Browse 📂 (Canvas dimension changes)</option><option value='iM'>Background 🌦 Canvas Image 🖼 Camera 📷 (Image dimension changes) (as applicable)</option><option value='iB'>Background 🌦 Image 🖼 Canvas Camera 📷 (Canvas dimension changes) (as applicable)</option><option value='ro'>Rectangle (outline) 🔲 (via two clicks 🖱🖱)</option><option value='rx'>Rectangle (clear) ⬜ (via two clicks 🖱🖱)</option><option value='rf'>Rectangle (filled) ⬛ (via two clicks 🖱🖱)</option><option value='co'>Circle (outline via centre then point on circle) ⭕ (via two clicks 🖱🖱)</option><option value='cf'>Circle (filled via centre then point on circle) 🔵 (via two clicks 🖱🖱)</option><option value='Text'>Text ⌨ (of textarea) Top Left 🖱</option><option value='text'>Text ⌨ (of textarea) Top Left and Top Right 🖱🖱</option><option value='textseq'>Sequential Text 📆 Centre Left 1 and Centre Left 2 🖱🖱</option><option value=' '>Discrete Canvas 🎨 Click/Touch 🖱 Mode (no action) ✍</option></select><div id='divbrowse' style='display:none;'>" + cbrowse_nocapture + "</div><br><br>👈 Canvas🎨 Font⬇<input style='width:70px;' id='jscf' type='text' onblur='jscf=this.value;' value='" + jscf + "'></input> <input id='colcf' type='text' style='color:blue;width:120px;' onblur=\"colcf=this.value; this.style.color=this.value.split(' ')[eval(-1 + this.value.split(' ').length)];\" value='" + colcf + "'></input> <input title='Text rotation 🎡 (in degrees) for left 👈 canvas 🎨' id='trotation' style='width:35px;' type=number onblur=\" document.getElementById('" + topielem.id + "').contentWindow.evalit('trotis=' + this.value); trotis=this.value;\" onchange=\" document.getElementById('" + topielem.id + "').contentWindow.evalit('trotis=' + this.value); trotis=this.value;\" min='-360' max='360' value='0' step='1'></input>°<br><br><textarea title='What is typed here goes over to left 👈 canvas 🎨' style='border:8px dashed yellow;' id='myta' rows=" + eighty + " cols=60 value=''></textarea>" + tenimages + "</div>";

    Here is the signature_signature.js external Javascript with its changes for you to examine, or you could try this live run link.

    And then we had a look at the logic of the “New Windows” button. We learnt from this great link, thanks, that it can be best to involve an HTML iframe when using window.open in Chrome (and then we learnt, Safari) for a PDF data url, as well as Chrome being pretty against a straight data uri window.open first parameter generally. That being the case, signature_signature.js external Javascript changed this way and signature_signature.php PHP changed this way.


    Previous relevant Contact Us Feedback Emoji Placeholder Tutorial is shown below.

    Contact Us Feedback Emoji Placeholder Tutorial

    Contact Us Feedback Emoji Placeholder Tutorial

    Continuing on …

    … we’re pretty keen, around here, with the concept of “Emoji Placeholder”, where an HTML input type=text element’s placeholder attribute is …

    • populated with Emoji data (that can join into the Contact Us or Feedback message data) suggested by the web application … as a contrast to the previous arrangements where, for the most part …
    • the user could “go fishing” for their own Emojis (at their instigation)

    Why do this? Well, for us …

    • sometimes we’re happy to be offered a suggestion, when it comes to Emojis … and …
    • letting the web application be involved we can offer some “compound Emojis” (those involving multiple argument calls to String.fromCodePoint() complementing some of the ideas from last week in Compound Emoji via Codepoint Primer Tutorial) … and, as mentioned before …
    • for optional functionalities, we like the semi-transparent look of an HTML input type=text element presentation of its “placeholder” attribute data … and, event logic wise …
    • an HTML input type=text element involving this can separate (and be functional for both of) onclick event logic dealing with the “placeholder” attribute Emojis and onblur event logic dealing with any “value” attribute data they may add themselves in between Emojis to explain their Contact Us or Feedback message data

    Today’s one new Javascript function changes to feedback.htm combines ideas from other blog postings mentioned above (as well as Rainbow Games Background Image Mobile Tutorial), to be a standalone setTimeout controlled additional piece of Javascript …


    function ipf() {
    var chac=-1; //Math.floor(Math.random() * 79) + 128512;
    var chactwo=[]; //Math.floor(Math.random() * 4) + 127995;


    var elist=['128512.128591',
    '128640.128767',
    '9728.9983',
    '&#127939;&#127998;&#8205;&#9792;&#65039;',
    '&#127939;&#8205;&#9794;&#65039;',
    '&#127939;&#127998;&#8205;&#9792;&#65039;','&#127939;&#8205;&#9794;&#65039;','&#127939;&#127995;&#8205;&#9792;&#65039;','&#127939;&#127999;','&#127939;&#127997;','&#127939;&#127999;','&#127939;&#127998;&#8205;&#9792;&#65039;','&#127939;&#127995;&#8205;&#9792;&#65039;',
    '&#127939;&#127998;&#8205;&#9792;&#65039;','&#127939;&#8205;&#9794;&#65039;','&#127939;&#127995;&#8205;&#9792;&#65039;','&#127939;&#127999;','&#127939;&#127997;','&#127939;&#127999;','&#127939;&#127998;&#8205;&#9792;&#65039;','&#127939;&#127995;&#8205;&#9792;&#65039;',
    '&#128675;&#8205;&#9792;&#65039;','&#128675;','&#128675;','&#128675;&#127996;','&#128675;&#127997;','&#128675;&#127998;','&#128675;&#127995;&#8205;&#9792;&#65039;','&#128675;&#127997;&#8205;&#9792;&#65039;','&#128675;&#127998;&#8205;&#9792;&#65039;','&#128675;&#127996;&#8205;&#9792;&#65039;','&#128675;&#127995;','&#128675;&#127999;&#8205;&#9792;&#65039;','&#128675;&#127999;',
    '&#128675;&#8205;&#9792;&#65039;','&#128675;','&#128675;','&#128675;&#127996;','&#128675;&#127997;','&#128675;&#127998;','&#128675;&#127995;&#8205;&#9792;&#65039;','&#128675;&#127997;&#8205;&#9792;&#65039;','&#128675;&#127998;&#8205;&#9792;&#65039;','&#128675;&#127996;&#8205;&#9792;&#65039;','&#128675;&#127995;','&#128675;&#127999;&#8205;&#9792;&#65039;','&#128675;&#127999;',
    '9984.10175',
    '127744.128511',
    '129280.129535',
    '128512.128591'];


    var ehac=Math.floor(Math.random() * elist.length), mul='', ichac=0;


    if (elist[ehac].indexOf('.') != -1) {
    chac=Math.floor(Math.random() * eval(eval(elist[ehac].split('.')[1]) - eval(elist[ehac].split('.')[0]))) + eval(elist[ehac].split('.')[0]);
    } else {
    chactwo=(elist[ehac] + ';').replace(';;','').replace('&#','').split(';&#');
    for (ichac=0; ichac<chactwo.length; ichac++) {
    mul+=String.fromCodePoint(eval('' + chactwo[ichac]));
    }
    }


    if (document.getElementById('iplaceholder').placeholder.length >= 59) {
    if (chac >= 0) {
    document.getElementById('iplaceholder').placeholder=String.fromCodePoint(chac);
    } else {
    document.getElementById('iplaceholder').placeholder=mul;
    }
    } else {
    if (chac >= 0) {
    document.getElementById('iplaceholder').placeholder+=String.fromCodePoint(chac);
    } else {
    document.getElementById('iplaceholder').placeholder+=mul;
    }
    }
    setTimeout(ipf, 2500);
    }


    setTimeout(ipf, 2500);

    … working off the new HTML (and inline CSS and inline (event logic) Javascript) …


    <br><input onblur="if (this.value.length > 0) { document.getElementById('myfeedback').value+=this.value; this.value=''; } else if (this.placeholder.length > 0) { document.getElementById('myfeedback').value+=this.placeholder; this.placeholder=''; }" onclick="if (this.placeholder.length > 0) { document.getElementById('myfeedback').value+=this.placeholder; this.placeholder=''; }" type=text style='width:100%;border:1px dotted yellow;' value='' title='Click when you like an emoji to place above' id='iplaceholder' placeholder=''></input>

    … to become that subtly more functional web application that you can try for yourself at this live run link.


    Previous relevant Contact Us Feedback Animated GIF Tutorial is shown below.

    Contact Us Feedback Animated GIF Tutorial

    Contact Us Feedback Animated GIF Tutorial

    We can’t imagine how much longer it would have taken us to suss out the solution to our desire of having our Animated GIF email attachments for the “Feedback” web application not have a black background without great advice from Stackoverflow‘s great link. Yesterday’s Contact Us Feedback Smoothly Filtering Tutorial told of the virtues of “empirical” thinking. Today we come back to the advice of the knowledgeable. Both approaches have their worth.

    You may have wondered about why this is an issue. Well, the PHP imagegif method has had a bit of a chequered history in the PHP GD image library, perhaps regarding its flakiness retaining opacity, something the PNG image format is best at. The Animated GIF, via data URI, creation code needs all the bold bits specially regarding GIF work below …


    $eachonestring="

    \$text='';

    // Open the first source image and add the text.
    \$underimage = imagecreatefromjpeg('source01.jpg');
    \$old_width = imagesx(\$underimage);
    \$old_height = imagesy(\$underimage);
    \$image = imagecreatetruecolor(\$old_width, \$old_height);
    \$black = imagecolorallocatealpha(\$image, 254, 254, 254, 0);
    imagefill(\$image, 0, 0, \$black);
    imagecopyresampled(\$image, \$underimage, 0, 0, 0, 0, \$old_width, \$old_height, \$old_width, \$old_height);
    imagecolortransparent(\$image, \$black);

    \$text_color = imagecolorallocate(\$image, 200, 200, 200);
    imagestring(\$image, 5, 5, 5, \$text, \$text_color);

    // Generate GIF from the $image
    // We want to put the binary GIF data into an array to be used later,
    // so we use the output buffer.
    ob_start();
    imagegif(\$image);
    \$frames[]=ob_get_contents();
    \$framed[]=40; // Delay in the animation.
    ob_end_clean();

    // And again..
    ";

    Perhaps the crucial code line, here, is imagecolortransparent(\$image, \$black); using your selected “masking” colour (and background colour) as the basis for manipulating the image on “all but that colour”, which we chose as that wee bit different to white, but looks like white as your new Animated GIF background colour.

    We don’t mind a black background, but it is a bit awkward for a couple of reasons …

    • any pure black text (and we often choose black for text) will disappear into a black background
    • the result of the HTML5 canvas [canvasElement].toDataURI(‘image/png’,0); has a white background, so there is quite a degree of inconsistency if we make no attempts at today’s changes

    … as you can see with the finished Animated GIF we created that inspired the tutorial picture above, below …

    As you might surmise …

    We hope you try some email attachment “Feedback” animations, yourself.


    Previous relevant Contact Us Feedback Smoothly Filtering Tutorial is shown below.

    Contact Us Feedback Smoothly Filtering Tutorial

    Contact Us Feedback Smoothly Filtering Tutorial

    Around here we think it’s fairer on you readers to be quite empirical about the study of web applications. That’s not to say we don’t have the utmost respect for all that the great Stackoverflow website offers regarding great analysis of issues and ideas in this area, thanks. Nevertheless … and didn’t you know there wouldn’t be a but, exactly?! … to be empirical means we can at least say that we try web applications we talk about under some platforms and web browsers, ourselves, and so can say at the time of writing such and such display such and such a behaviour. Ideally, we’d mention versions of things much more, but for us, that is too far over the top for the technicality we wish to impart, with this blog.

    Yesterday’s Contact Us Feedback Filtering WordPress Tutorial gave us some “filtering” capabilities, but the way it flashed the “whole shebang” temporarily at the start wore away at our “programming conscience”, and we determined that us knowing in our minds “that the web application display doesn’t stay that way” is just not good enough, nor fair, in the sense that there are a lot of users out there, in this day and age of interruption, that might interpret this “flashing” of disappearing functionality as “suss”, so we set out on a web application client approach to refining this behaviour to not have this “flashing” look. Before we go further, it should be noted that if we were prepared to use PHP serverside thoughts here you could research the incredibly useful ob_end_clean(); and ob_start(); and ob_get_contents(); approaches, these being so useful they are intrinsic to speed improvements that effectively zip up the blog contents you are reading right now (and which you can read more about at EasyApache in cPanel Primer Tutorial) to solve this dilemma.

    For us to solve it we empirically determined that …

    • document.body onload=onloading(); event trapping … will not cover …
    • after <body onload=onloading();> the <script type=’text/javascript’> document.write([HTMLgoesHere]); </script>

    … the (empirical) lesson being that, even though it is more awkward and disparate to do this, you must address the “if” statements required with that “after <body onload=onloading();> the <script type=’text/javascript’> document.write([HTMLgoesHere]); </script>” as described above, otherwise you remain with the flashing as we can show you (or refresh for you) below …

    … <iframe id=’notsmooth’ src=’//www.rjmprogramming.com.au/HTMLCSS/feedback.htm?justideas=maybe‘ title=’Word Search’></iframe> that is a “smoother” display (or refresh if you want to see in action, for yourself) via the improved … <iframe id=smooth src=’//www.rjmprogramming.com.au/HTMLCSS/feedback.htm?justideas=y‘ title=’Word Search’></iframe> …

    A variation that justified our optimistic self delusion “that the web application display doesn’t stay that way” is good enough, is that …

    • you quickly click that first refresh link above …
    • quickly click inside the “To:” textbox …
    • if you are quick enough the “full shebang” shows else if you didn’t click in this field or were too slow, the “reduced shebang” shows Deluded self: “A feature rather than a confusion.” … and what causes this to happen ..
      1. we make “justideas=y” the value of a global variable … var basis=”justideas=y”; (and make it so that this basis global variable is used everywhere in the code except in the first two “if”s just after “<body onload=onloading();> the <script type=’text/javascript’> “) …

        var exs='';
        if (document.URL.indexOf('justideas=') != -1) exs='display:none;'; // start with nothing
        if (document.URL.indexOf('justideas=maybe') != -1) exs='';
      2. change the workings of the “To” textbox as per

        document.write("To: <input onclick=\"basis=basis.replace('justideas','nowayjose');\" style='width:200px; align:right;' type='email' id='myto' onblur=\" fixto(this.value); \" value=''></input><br>");

    The improved feedback.htm HTML and Javascript feedback “reduction” functionality that changed from that last time in order for the content to be smoothly “reduced” (aka ?justideas=y) in this way and which you can test for yourself at this reduced live run link (the independent way, or the WordPress way) or full functionality live run link.


    Previous relevant Contact Us Feedback Filtering WordPress Tutorial is shown below.

    Contact Us Feedback Filtering WordPress Tutorial

    Contact Us Feedback Filtering WordPress Tutorial

    Yesterday’s Emoji Contact Us Feedback Filtering Tutorial‘s new filtering functionality related to a “section” of the “Feedback” web application it was applied to. And this exemplifies, for us, that the term “modularisation” can take on various “levels” of modularisation such as …

    • high level modularisation as per MVC types of coding styles that modularise the underlying code, and in all likelihood, the “look” of the resultant web pages … all the way through to …
    • … OOP code classes line up with web application “item look” … to …
    • a web application “looks modular”, with elements organized into “container” elements, but to look at the Javascript, and maybe the HTML of the web application, it is hard to see any of this “modularisation” in terms of its code

    If it is your job to “reduce” a web application into a “contained” section of the web page display of that web application, even that (most rudimentary) last level of “modularisation” above is fine to …

    • work out what differentiates normal “busy” display from the pared down “reduced” look … today, for us, it’s ?justideas=y added to our URL to become today’s reduced live run link (as distinct to a full live run link)
    • work out codewise how to manifest that difference above, and that is, for us …

      if (document.URL.indexOf('justideas=') == -1) {
      // pared down "reduced" look code goes here
      } else {
      // normal "busy" display code goes here
      }
    • think about when and where to intervene in the code, so that you can come up with a code line like today’s …

      if (document.URL.indexOf('justideas=') != -1) {

      document.body.innerHTML='<div id=ideas>' + ideasprefix + amongthis + ideassuffix + '</div>';

      } else if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {

      document.getElementById('ideas').innerHTML=ideasprefix + amongthis + '<br><iframe id=ideasiframe style="display:none;-webkit-overflow-scrolling:touch;overflow:scroll;" src=""></iframe>' + ideassuffix;

      } else {

      document.getElementById('ideas').innerHTML=ideasprefix + amongthis + ideassuffix;

      }


      … where ideas is an element “ID” (of a “container” element) both before (when it is a table cell (td) element) and after (when it is a div element, on its own within the document.body’s content (ie. its innerHTML))

    • … for us, that being the successful HTML iframe onload event (Client Pre-emptive Iframe logic) code, after which the HTML dropdown containing blog posting unique word “option” tags are complete
    • use a web inspector to see where else in the whole Javascript logic you’ll need to refine with “if (document.URL.indexOf(‘justideas=’) != -1) { } else { }” interventions, via those web inspector Console tab errors, that are bound to occur instigating the steps above

    So this leaves us with “why?”. Well, what is a “section” of the “Feedback” web application could happily sit as a WordPress Blog menu item, because we can imagine you, the reader, could benefit as a researcher, or “driller innerer oferer more detail and more specificity” might like to hone in on a particular blog posting topic of interest using this technique.

    What of the WordPress end of this interfacing of functionality? Further down the “well” (tee hee), this is as easy as falling off a log …

    • Pick a menu item name, ours being “Word Search”
    • as admin of your WordPress Blog use the Add Page icon to type “Word Search” into the title field … and then in the “body textarea” …

    • <iframe src='//www.rjmprogramming.com.au/HTMLCSS/feedback.htm?justideas=y' title='Word Search'></iframe>
    • Add or Update into the WordPress Blog menu

    Sew if you like, while you see the feedback.htm HTML and Javascript feedback functionality that changed from that last time to be able to be “reduced” (aka ?justideas=y) in this way and which you can test for yourself at this reduced live run link (the independent way, or the WordPress way) or full functionality live run link.


    Previous relevant Emoji Contact Us Feedback Filtering Tutorial is shown below.

    Emoji Contact Us Feedback Filtering Tutorial

    Emoji Contact Us Feedback Filtering Tutorial

    Do not know if you have been trying the functionality in the third table cell up near the top of the Feedback web application last talked about at yesterday’s Emoji Contact Us Feedback Email Animation Tutorial but if you have (or haven’t (welcome aboard)) that dropdown in that third cell contains all the blog postings on this blog, as a prompter for a topic of an email you could send to us as an email piecing together your feedback.

    Today’s improvements concern two areas …

    • redelving into our favourite HTML “reveal” tool, the details/summary partnership and the idea that the summary part of this could contain an HTML select (dropdown) element … and you might call today’s work the “guinea pig project” here, as we expect to improve, and also …
    • finding a way, that we think has great potential, for people using this blog for research and development and/or as a learning tool, a “filtering” mechanism to hone in on topics of interest (which now can open a popup or iframe (for mobile)) to any chosen blog posting of interest

    How do we determine topics of interest? Scan every word we’ve ever used in a blog posting title, and if that word satisfies a few criteria, and hasn’t been mentioned before, gets added to an array of different such words, sorted at the end and added (ie. appended to the HTML select element’s innerHTML property) to the pre-existing options of that details/summary dropdown, that being …

    … or as HTML (with innerHTML being emboldened … I’d just give up and take it to the beach …

    … if I were you
    ) …


    <select id='bigselect'><option value=''>Ideas:</option><option value='Cut to the Chase'>Cut to the Chase</option><option value='Feedback'>Feedback ... all versus ...</option></select>

    … whereby if the user selects one of these “filterers”, they being given lowercase values, we filter that dropdown’s initial “big content” filtering it down into “little content” via that tried and true Siri dropdown, go and filterre-establishment of a smaller innerHTML property for that details/summary dropdown, the understanding being we can at any time go back to the “big content” by re-establishing the innerHTML to this (Javascript) global variable value should the user repick one of those non-lowercase options.

    What’s “Cut to the Chase”? It’s our trying to help busy blog readers just wanting to jump to executing the “action item” of a blog posting straight away.

    So, see the feedback.htm HTML and Javascript feedback functionality that changed from that last time in this way and which you can test for yourself at this live run link.


    Previous relevant Emoji Contact Us Feedback Email Animation Tutorial is shown below.

    Emoji Contact Us Feedback Email Animation Tutorial

    Emoji Contact Us Feedback Email Animation Tutorial

    Adding to yesterday’s Emoji Contact Us Feedback Animation Tutorial‘s Feedback animation beginnings, after today’s work, we can email animated GIF animations via an email attachment.

    To avoid too many files being involved we sharpen up the data URI usage aspects to the …

    … animated GIF email attachment functionality as you can see below …

    As you might imagine, using data URIs can avoid some file creation but asks a lot of data transfer techniques, hence the need below (in an example of 4 slides to an animated GIF where you can imagine the huge data URI strings within the src=””s below) with the HTML form navigation used between the supervisor and the animated GIF creator PHP …


    <form target='gifa' style='display:none;' action='//www.rjmprogramming.com.au/PHP/animegif/tutorial_to_animated_gif.php' method='POST'>
    <input type=hidden id=slideshow name=slideshow value=' src="[dataURIslide1]" src="[dataURIslide2]" src="[dataURIslide3]" src="[dataURIslide4]" '></input>
    <input type=hidden id=delay name=delay value='4000'></input>
    <input type=hidden id=stitle name=stitle value='Animated Feedback'></input>
    <input type=hidden id=outfile name=outfilex value='animated_gif_slideshow'></input>
    <input id=olbit type=submit value=Submit></input>
    </form>

    … needs that method=”POST” to work these animated GIF creations.

    We must say here, that to use an animated GIF is just one slideshow (or animation) approach, and we mention many other ideas regarding slideshow usage. Another we thought about would have involved HTML attachments that use no Javascript, just CSS, to create animations via document.body background images. We may try this technique further down the track.


    Previous relevant Emoji Contact Us Feedback Animation Tutorial is shown below.

    Emoji Contact Us Feedback Animation Tutorial

    Emoji Contact Us Feedback Animation Tutorial

    As we said early on in the recent blog postings on this thread of postings last talked about with yesterday’s Emoji Contact Us Feedback Copy and Paste Tutorial

    … but we envisage, optimistically, to involve animation and more refined positioning possibilities

    Well, the news is, we’re getting closer, by allowing for the “internal use only” creation (and playing) of an animation slideshow from changing canvas image representations, if that is what you want to do, that is. It uses a self-destructing HTML div element presentation we’re not sure whether we’ve ever used before. As you may know, an HTML div element, being the “container” (innerHTML) element that it is, can self-destruct via a myriad of methods, the last of which below being our method for today’s work …

    • Javascript DOM [divElementObject].style.display=’none';
    • Javascript DOM [divElementObject].style.visibility=’hidden'; // this one may leave whitespace depending
    • Javascript DOM [divElementObject].style.width=’0px'; (or [divElementObject].style.height=’0px'; … you get the gist?)
    • Javascript DOM [divElementObject].style.top=’-700px'; (or [divElementObject].style.left=’-500px'; … you get the gist?)
    • Javascript DOM [divElementObject].style.opacity=’0′;
    • Javascript DOM [divElementObject].style.fontColor=’transparent'; // if data is textual and this one may leave whitespace depending
    • Javascript DOM [divElementObject].className='[classThatMakesDivElementInvisible]'; (or [divElementObject].className+='[classThatMakesDivElementInvisible]'; … you get the gist?)
    • Javascript DOM [divElementObject].innerHTML=”;

    … which we make happen today, after that HTML div is given the contents of each “slide” of the animation (or slideshow), separated, just for now, via a 4 second delay as per …


    var filmslidenumber=1, fromfilmslidenumber=0, tofilmslidenumber=0;

    function tanimation() {
    if (fromfilmslidenumber < tofilmslidenumber) {
    document.getElementById('dslideshow').innerHTML='<img style="border:8px dashed lightblue;" src=' + document.getElementById('tablefilmimg' + eval(1 + fromfilmslidenumber)).src + '></img>';
    fromfilmslidenumber++;
    setTimeout(tanimation, 4000);
    } else {
    document.getElementById('dslideshow').innerHTML='';
    }
    }

    function animation() {
    fromfilmslidenumber = 0;
    tofilmslidenumber = eval(-1 + filmslidenumber);
    document.getElementById('dslideshow').innerHTML='<img style="border:8px dashed lightblue;" src=' + document.getElementById('tablefilmimg1').src + '></img>';
    location.href='#dslideshow';
    fromfilmslidenumber++;
    setTimeout(tanimation, 4000);
    }

    function addtofilm() {
    var ptoh=elem.toDataURL('image/png',0);
    if (filmslidenumber == 1) {
    if (document.getElementById('eimg').innerHTML == '') {
    if (document.getElementById('divannotation')) {
    if (('' + document.getElementById('divannotation').style.top).indexOf('525') != -1) {
    document.getElementById('divannotation').style.top=eval(eval(('' + document.getElementById('divannotation').style.top).replace('px','')) + 240) + 'px';
    }
    }
    }
    document.getElementById('eimg').innerHTML='<table id=tablefilm><tr id=tablefilmtr><td id=tablefilmcell1><img id=tablefilmimg1 style="border:8px dashed lightgreen;" src=' + ptoh + '></img></td></tr><tr id=tablefilmfooter><td id=tablefilmfooter1><a href=#tablefilmfooter1>Slide</a> 1 of ...</td></tr></table>';
    } else {
    document.getElementById('tablefilmtr').innerHTML+='<td id=tablefilmcell' + filmslidenumber + '><img id=tablefilmimg' + filmslidenumber + ' style="border:8px dashed lightgreen;" src=' + ptoh + '></img></td>';
    document.getElementById('tablefilmfooter').innerHTML=document.getElementById('tablefilmfooter').innerHTML.replace(' ...',' <a href=#tablefilmfooter' + filmslidenumber + '>...</a>') + '<td id=tablefilmfooter' + filmslidenumber + '><a href=#tablefilmfooter1>Slide</a> ' + filmslidenumber + ' of ...</td>';
    }
    if (filmslidenumber == 2) {
    document.getElementById('daddtofilm').innerHTML+=' <input style=display:inline-block; type=button onclick=animation(); value="Play Animation" id=banimation></input>';
    }
    filmslidenumber++;
    }

    … helped out by additional HTML as per …


    document.write('<table style=width:100%;><tr><td><div id=dslideshow></div><h1 id=myh1 align="center">Feedback</h1></td><td style=width:90%; nowrap><div style=display:inline-block;width:100%;overflow-x:scroll; id=dviai><form style=display:none;width:100%;overflow-x:scroll; action=fairy_story_assistant.php method=GET target=fsa><input name=emoji id=iemoji value=></input><input type=submit id=isubm value=Submit></input></form><iframe style=display:none;width:100%;overflow-x:scroll; id=fsa name=fsa src=></iframe></div></td></tr></table>');

    … and some changed Javascript as per …


    document.getElementById('divannotation').innerHTML=document.getElementById('divannotation').innerHTML.replace('Annotations++','Annotations++ <input onclick="document.getElementById(' + "'" + 'canbet' + "'" + ').value=' + "'" + 'transparent' + "'" + ';" type=button value="Copy (via 2) and Paste (via 1) Parts of Canvas Above to Canvas Above"></input><br><div id=daddtofilm><input onclick="addtofilm();" value="Add to Animated Film" type="button" title="Make an Animation"></input></div>').replace('<input type="text" id="mycolour"','<input type="color" id="myrcolour" value="black" onchange="if (this.value.toLowerCase().indexOf(' + "'" + 'transparent' + "'" + ') == -1) { obeforetransparent=this.value; } document.getElementById(' + "'" + 'mycolour' + "'" + ').value=this.value;"></input> <input onblur="if (this.value.toLowercase().indexOf(' + "'" + 'transparent' + "'" + ') == -1) { obeforetransparent=this.value; }" type="text" id="mycolour"').replace('<input id="mycolour"','<input type="color" id="myrcolour" value="black" onchange="if (this.value.toLowerCase().indexOf(' + "'" + 'transparent' + "'" + ') == -1) { obeforetransparent=this.value; } document.getElementById(' + "'" + 'mycolour' + "'" + ').value=this.value;"></input> <input onblur="if (this.value.toLowerCase().indexOf(' + "'" + 'transparent' + "'" + ') == -1) { obeforetransparent=this.value; } " id="mycolour"').replace("</form>","<input type=hidden id=canbet value=></input><input type=hidden name=from id=from value=''></input></form>").replace("</form>","<input type=hidden name=cc id=cc value=''></input></form>").replace("</form>","<input type=hidden name=bcc id=bcc value=''></input></form>");

    Now to think about emailing these optional animations.

    Today, also, we’ve made the CSS much better suited to the mobile devices you may be using, by introducing the equivalent canvas onclick event logic mapped to the touchstart event, that mobile devices detect.

    Today’s changes just involved feedback.htm HTML and Javascript feedback functionality that changed from that last time in this way and which you can test for yourself at this live run link.


    Previous relevant Emoji Contact Us Feedback Copy and Paste Tutorial is shown below.

    Emoji Contact Us Feedback Copy and Paste Tutorial

    Emoji Contact Us Feedback Copy and Paste Tutorial

    We’ve got quite a variety of functional improvements on top of what was there already with yesterday’s Emoji Contact Us Feedback Cross-Browser Tutorial (optionally email) Feedback web application. These changes, today, in brief, involved …

    • copy and paste with the canvas element whose image representation forms the body of an email sent via this web application
    • in order to ensure the consistency of canvas (y or top) positioning we had quite a lot to do, such as …
      1. no longer placing the image that results from “Send Feedback and Show Body of Email as Image” up the top right, but now to under the canvas with a pink dashed border (for clarity)
      2. no longer making the emojis map (big) into the header h1 element but now in a table cell as per …

        <td style=width:90%; nowrap><div style=display:inline-block;width:100%;overflow-x:scroll; id=dviai><form style=display:none;width:100%;overflow-x:scroll; action=fairy_story_assistant.php method=GET target=fsa><input name=emoji id=iemoji value=></input><input type=submit id=isubm value=Submit></input></form><iframe style=display:none;width:100%;overflow-x:scroll; id=fsa name=fsa src=></iframe></div></td>

        … ensuring it takes up as little height as possible, but stretches out to the right as much as it likes, but you can scroll to those parts way out off the screen to the right
    • allowing some web browsers make use of their HTML5 input type=color colour wheel methods of defining annotation and canvas drawing foreground colour
    • inform the user, via a self-closing popup window, that the PHP mail has sent an email, the look of which has a little bit of “Android toast” about it

    So let’s talk about the “Copy (via 2) and Paste (via 1) Parts of Canvas Above to Canvas Above”. After a little dead end thinking pixel level thoughts might be the go … no … it was image level thoughts we needed, trapped at the canvas element’s onclick logic …

    • the Copy (via 2 click/touch) aspects via [canvasElement].toDataURL(‘image/png’,0) copies the whole canvas, but while we are at that we are recording the user’s last two click’s …
      1. The x coordinate where to start clipping
      2. The y coordinate where to start clipping
      3. The width of the clipped image
      4. The height of the clipped image

      … which we’ll come back to, and now to convert that into image data (for the statically defined HTML <img id=’myim’ style=’dispay:none;’ src=” title=” alt=”></img>), we …

      omyimgdata=elem.toDataURL('image/png',0);
      document.getElementById('myim').style.width=elem.style.width;
      document.getElementById('myim').style.height=elem.style.height;
      document.getElementById('myim').src=omyimgdata;

      omidatax=eval(Math.min(x,lastx));
      omidatay=eval(Math.min(y,lasty));
      omidataw=Math.abs(x - lastx);
      omidatah=Math.abs(y - lasty);

    • the Paste (via 1 click/touch) aspect using the “full might” of the [canvasContext].drawImage() calling incarnations as per …

      context.drawImage(document.getElementById('myim'),omidatax,omidatay,omidataw,omidatah,x,y,omidataw,omidatah);

    Code changes, today, involved the PHP email helper …

    • world.php, changed this way, whose job it is to help create the PHP mail created email attachments, in the form of image renderings on the canvas we use … supervised by …
    • feedback.htm HTML and Javascript feedback functionality that changed from that last time in this way and which you can test for yourself at this live run link

    Previous relevant Emoji Contact Us Feedback Cross-Browser Tutorial is shown below.

    Emoji Contact Us Feedback Cross-Browser Tutorial

    Emoji Contact Us Feedback Cross-Browser Tutorial

    Yesterday’s Emoji Contact Us Feedback Textarea Tutorial had us more integrated involving emojis with the HTML5 canvas element we use as the source for an image attachment to a potential email for use as Feedback, perhaps.

    There are cross-browser issues here.

    1. Firefox is not transferring the emojis to the canvas, at least for us.
    2. And Safari does not offer great two finger gesture options when hovering over the canvas, such as “Save Image As…”. So, today, we offer those Safari users the chance to be able to “Save Image As…” image (email attachment) download possibilities by offering a new button called “Send Feedback and Show Body of Email as Image”. Use this, and that image that results is downloadable.

    In order to allow for that last one, and not wrongly overlay the Annotations div element menus, we adjust the top (y) co-ordinate of the Annotations div element menus as per …


    if (document.getElementById('divannotation')) {
    if (('' + document.getElementById('divannotation').style.top).indexOf('485') != -1) {
    document.getElementById('divannotation').style.top=eval(eval(('' + document.getElementById('divannotation').style.top).replace('px','')) + 300) + 'px';
    }
    }

    … a technique that may fail for elements that do not define the top property, whether that be teamed or not (as for today) with position:absolute property …


    document.getElementById('divannotation').style.top='485px';

    A different child PHP helper to yesterday’s one needed work today …

    • world.php, changed this way, whose job it is to help create the PHP mail created email attachments, in the form of image renderings on the canvas we use … supervised by …
    • feedback.htm HTML and Javascript feedback functionality that changed from that last time in this way and which you can test for yourself at this live run link

    Previous relevant Emoji Contact Us Feedback Textarea Tutorial is shown below.

    Emoji Contact Us Feedback Textarea Tutorial

    Emoji Contact Us Feedback Textarea Tutorial

    Yesterday’s Emoji Contact Us Feedback Integration Tutorial started us down the road of trying to make emoji usage more functional with the annotation aspects of our Feedback (Contact Us type of) web application.

    We have a textarea HTML element currently in use as a means by which we collect textual data, that may go into the feedback, and then onto an email, perhaps. We’ve lately been preferring to use …

    • div contenteditable=true … in preference to …
    • textarea

    … and though we keep the textarea as the interfacing element of “textual data collection” for the user, today, it gets helped out by accompanying …

    • div contenteditable=true … and encompassing the textarea we have a new …
    • div … acting as a parent

    How come? Well, in our experience, when you mix up the keyboard character type of text with emoji HTML Entity “textual” data, the relationship between the textarea’s …

    • value property
    • innerHTML property

    … unique among elements, and really generally useful, stuffs up, or we stuff up, one of the two.

    But … and didn’t you just know there’d be a “but” … combine the content of the first “shadowing” div element with a complete rewrite of the textarea via the innerHTML property of the “encasing” second div (parent) element and you can go back to the conditions at the start of the web application, as far as the textarea is concerned, where you can place HTML Entity representations of that mix of textual data that may include emojis, into the textarea’s innerHTML via code like …


    // store current innards of the textarea
    var mtv=top.document.getElementById('myfeedback').value;
    // at to those textarea innards the current HTML Entity emoji data addition and place into the innerHTML of the "shadowing" div contenteditable=true element
    top.document.getElementById('dmyfeedback').innerHTML=mtv + cnotatend;
    // clear contents of textarea
    top.document.getElementById('myfeedback').value='';
    // repopulate textarea in an innerHTML (HTML Entity friendly) way by reinstating its whole (outerHTML) instantiation by setting the innerHTML of that textarea's encasing div element, and in between where > meets </textarea> place that same div contenteditable=true innerHTML where spaces map to (HTML Entity) &nbsp;
    top.document.getElementById('ddmyfeedback').innerHTML='<textarea style="color=lightgray;width:200px;" rows=6 cols=40 id="myfeedback" title="Feedback" value="" onchange=" pseudo_sentence=this.value; placetext(); " onblur=" pseudo_sentence=this.value; placetext(); ">' + mtv.replace(/\ /g,'&nbsp;') + cnotatend + '</textarea>';

    … all carried out with an HTML iframe hosted child PHP helper …

    • fairy_story_assistant.php, changed this way, whose job it is to get the great Emoji Terra website help us out, via its ideal permalink arrangements, with emoji search lookups, thanks … supervised by …
    • feedback.htm HTML and Javascript feedback functionality that changed from that last time in this way and which you can test for yourself at this live run link

    Previous relevant Emoji Contact Us Feedback Integration Tutorial is shown below.

    Emoji Contact Us Feedback Integration Tutorial

    Emoji Contact Us Feedback Integration Tutorial

    We’re revisiting the work of Contact Us Feedback Android Tutorial which features …

    • email
    • feedback
    • canvas

    … with some early days integration with the recent work of Emoji Name Search Fairy Story PHP Tutorial, because we think the addition of more sophisticated emoji search (and later, usage) functionality would be a good improvement. Who’s to know if we can do it, but we envisage, optimistically, to involve animation and more refined positioning possibilities.

    Hope you can hang around for the full journey that starts with feedback.htm HTML and Javascript feedback functionality that changed from that last time in this way and which you can test for yourself at this live run link.


    Previous relevant Contact Us Feedback Android Tutorial is shown below.

    Contact Us Feedback Android Tutorial

    Contact Us Feedback Android Tutorial

    A couple of days ago we presented Contact Us Feedback Primer Tutorial as shown below … and said …

    Maybe you remember reading about the recent Feedback functionality here at RJM Programming when we presented Feedback Email Attachment Iframe Tutorial. It struck us that it would be good to extend the “Contact Us” webpage here at RJM Programming by adding a “Feedback” form to the “Contact Us” now presented via an HTML select “dropdown” element.

    … well, we discovered down the track that the behaviour of the HTML a tag’s mailto: href parameter navigation needs to be nuanced for Android (mobile) usage.

    A bit of reading on this lead us in one direction and the useful link pulled us completely back into a good line, thanks, via the advice …

    window.top.location = “//example.com”;

    … but, for us, that goes (something like) …


    window.top.location = "mailto:fill.in@email.address?subject=blah&cc=&bcc=&body=Lots%20Of%20Blah";

    … presumably to get the external Android Mail app into the picture. On the way this link was useful, also, so, thanks.

    Trap for young players? (Am blushing)

    So for feedback functionality what changed for this Android fix (which also has trouble, perhaps, with inhouse Javascript functions called “capture”?!) was …

    So … pleeeeease don’t fall in the trap, like me?!


    Previous relevant Contact Us Feedback Primer Tutorial is shown below.

    Contact Us Feedback Primer Tutorial

    Contact Us Feedback Primer Tutorial

    Maybe you remember reading about the recent Feedback functionality here at RJM Programming when we presented Feedback Email Attachment Iframe Tutorial. It struck us that it would be good to extend the “Contact Us” webpage here at RJM Programming by adding a “Feedback” form to the “Contact Us” now presented via an HTML select “dropdown” element.

    You can see the gist of what is involved with today’s tutorial picture for the creation of a short worded feedback email, via your default email client (ie. an HTML a mailto: link is used), perhaps regarding a tutorial here at this blog, which can be chosen via an HTML select “dropdown” element populated from the RJM Programming Landing Page, the logic for which you can read about with Client Pre-emptive Iframe Crontab Curl Rotated Report Tutorial. As you would glean from this blog posting title, what we are involving here is …

      1. WordPress Blog’s MySql database
      2. curl call of PHP to extract blog posting information
      3. crontab scheduled execution of PHP to assemble this data into an updated HTML select “dropdown” element in the RJM Programming Landing Page
    • an HTML iframe element loads the Landing Page and the crontab/curl inspired PHP/MySql data is extracted (at that iframe’s onload event) and reworked to the purposes of this Feedback functionality

    So what changed here?

    • Contact_Us.html changed in the bold ways below …

      <div id="id4" style="height: 36px; left: 17px; position: absolute; top: 304px; width: 674px; z-index: 1; " class="style_SkipStroke_3">
      <div class="text-content style_External_674_96" style="padding: 0px; ">
      <div class="style_2">
      <!--p style="padding-bottom: 0pt; padding-top: 0pt; " class="Caption">Contact Us at RJM Programming</p-->
      <div style="padding-bottom: 0pt; padding-top: 0pt; " class="Caption"><select id=mysel onchange=" var huhs; var dds=document.getElementsByTagName('div'); for (var idds=0; idds<dds.length; idds++) { huhs=dds[idds].innerHTML.split('<div '); if (huhs.length == 1) { huhs=dds[idds].innerHTML.split('<img '); if (huhs.length > 5) { dds[idds].style.display='none'; } } } document.getElementById('mycrawler').style.display='none'; document.getElementById('widget2b').style.height='500px'; document.getElementById('widget2-frame').height='500px'; document.getElementById('widget2-frame').style.height='500px'; document.getElementById('widget2-frame').style.zIndex='5'; document.getElementById('widget2-frame').src=this.value; "><option value="//www.rjmprogramming.com.au/Contact_Us_files/widget2a_markup.html">Contact Us</option><option value="//www.rjmprogramming.com.au/HTMLCSS/feedback.html?contact=contact">Feedback</option></select> at RJM Programming</div>
      </div>
      </div>
      </div>
    • feedback.html HTML and Javascript feedback functionality changed from last time in this way
    • world.js external Javascript annotation functionality changed from last time in like this

    Maybe this is food for thought for your own “Contact Us” page, perhaps second only to “Landing Page” in popularity on today’s websites of the “net”.

    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.


    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.


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


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


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


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


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

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

Leave a Reply

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

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