SVG Emoji Favicon and Title Uniquify Tutorial

SVG Emoji Favicon and Title Uniquify Tutorial

SVG Emoji Favicon and Title Uniquify Tutorial

What’s “uniquify” in terms of Information Technology?

To turn an instance of a type into an instance of a new unique copy of the original type.

For us, it is a concept often called into play to separate one online viewer’s data from affecting the viewing of another’s data, or “settings”, concepts which cover the recent web browser tab icon SVG emoji ideas we talked about at the recent SVG Emoji Favicon and Title Tutorial. There we hadn’t coded with much thought to “personalizing” one “Emoji Menu” viewer’s web browser tab icon SVG emoji from another.

This “Emoji Menu” web browser tab icon SVG emoji creation work uses PHP to write out those favicon images (and yes, favicon images do not have to be named “favicon.svg” or “favicon.ico”), and we are choosing a guise of a user’s IP address as our “uniquifier” conduit means. You’ll see it being used in the latest draft


<?php
// emojiicon.php
// RJM Programming
// March, 2025

$usuffix='';
$iponl='';
$rma='';

function massage($inidea) {
if (isset($_GET['ididea'])) {
return str_replace("document.body", "document.getElementById('" . str_replace('+',' ',urldecode($_GET['ididea'])) . "')", $inidea);
}
return str_replace('(7 == 7)', '(56 == 67)',$inidea);
}

function server_remote_addr() {
global $iponl, $rma;
$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
if(preg_match('/(chromium)[ \/]([\w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ \/]([\w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ \/]([\w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ \/]([\w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ \/]([\w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ \/]([\w.]+)/', $ua))
$rma = '0'.$rma;
$rma=str_replace(':','_',$rma);
$iponl=massage(" onload=\" if (window.parent) { if (parent.document.body.outerHTML.split('>')[0].indexOf(' data-ip=') == -1) { if (7 == 7) { parent.document.body.title=('' + parent.document.body.title) + ' +++ _" . $rma . "'; } parent.document.body.setAttribute('data-ip', '_" . $rma . "'); } } \"");
return $rma;
}

if (isset($_GET['codepoint'])) {
if (strlen($_GET['codepoint']) > 0) {
if (isset($_GET['ishex']) || isset($_GET['tohex']) || isset($_GET['hex'])) {
$usuffix='_' . server_remote_addr();
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon' . $usuffix . '.svg', str_replace('🇦','🇦🇩','<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">&#x' . str_replace(',',';&#x',str_replace(';','',str_replace('&#','',str_replace('+',' ',urldecode($_GET['codepoint']))))) . ';</text></svg>'));
} else {
$usuffix='_' . server_remote_addr();
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon' . $usuffix . '.svg', '<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">&#' . str_replace(',',';&#',str_replace(';','',str_replace('&#','',str_replace('+',' ',urldecode($_GET['codepoint']))))) . ';</text></svg>');
}
} else if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon_' . server_remote_addr() . '.svg')) {
$usuffix='_' . server_remote_addr();
} else {
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon' . $usuffix . '.svg', '<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">X</text></svg>');
if ($iponl != '' && file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon_' . server_remote_addr() . '.svg')) {
$iponl=massage(" onload=\" if (window.parent) { if (parent.document.body.outerHTML.split('>')[0].indexOf(' data-ip=') == -1) { parent.document.body.setAttribute('data-ip', '_" . $rma . "'); parent.document.body.setAttribute('data-firstip', 'y'); } } \"");
}
}
} else if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon_' . server_remote_addr() . '.svg')) {
$usuffix='_' . server_remote_addr();
} else {
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon' . $usuffix . '.svg', '<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">X</text></svg>');
if ($iponl != '' && file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon_' . server_remote_addr() . '.svg')) {
$iponl=massage(" onload=\" if (window.parent) { if (parent.document.body.outerHTML.split('>')[0].indexOf(' data-ip=') == -1) { parent.document.body.setAttribute('data-ip', '_" . $rma . "'); parent.document.body.setAttribute('data-firstip', 'y'); } } \"");
}
}

echo "<html>
<head>
<link rel='icon' href='/emojiicon/favicon" . $usuffix . ".svg?rand=" . rand(0,3456789) . "' sizes='any' type='image/svg+xml'>
</head>
<body" . $iponl . ">
<h1>Emoji Icon - RJM Programming - March, 2025</h1>
</body>
</html>";
?>

… of emojiicon.php helping out the body element global data attribute using emoji_widget_idea.htm content live run.


Previous relevant SVG Emoji Favicon and Title Tutorial is shown below.

SVG Emoji Favicon and Title Tutorial

SVG Emoji Favicon and Title Tutorial

The recent SVG Network Clock Start Local Time Favicon Tutorial talked about …

  • SVG data basis …
  • emoji data content …
  • favicon web browser tab icon … SVG type not accepted by all browsers and platforms …
  • dynamism … and today we start with another offshoot of thought regarding this, as well as …
  • document.title also showing in the web browser tab icon … universally accepted …

… ideas we wanted to get into by writing a pretty simple generic PHP helper emojiicon.php, we got a great heads up from regarding its logic, thanks, to dynamically create favicon.svg, currently looking like …

… in our nominated folder (so, so far not catering for a lot of online traffic … we’ll see) …


<?php
// emojiicon.php
// RJM Programming
// March, 2025

if (isset($_GET['codepoint'])) {
if (strlen($_GET['codepoint']) > 0) {
if (isset($_GET['ishex']) || isset($_GET['tohex']) || isset($_GET['hex'])) {
//file_put_contents('xxx.xxx', str_replace('+',' ',urldecode($_GET['codepoint'])));
//file_put_contents('xx.xx', '<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">&#x' . str_replace(',',';&#x',str_replace(';','',str_replace('&#','',str_replace('+',' ',urldecode($_GET['codepoint']))))) . ';</text></svg>');
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon.svg', str_replace('🇦','🇦🇩','<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">&#x' . str_replace(',',';&#x',str_replace(';','',str_replace('&#','',str_replace('+',' ',urldecode($_GET['codepoint']))))) . ';</text></svg>'));
} else {
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'emojiicon' . DIRECTORY_SEPARATOR . 'favicon.svg', '<svg xmlns="http://www.w3.org/2000/svg"><text y="32" font-size="32">&#' . str_replace(',',';&#',str_replace(';','',str_replace('&#','',str_replace('+',' ',urldecode($_GET['codepoint']))))) . ';</text></svg>');
}
}
}

echo "<html>
<head>
<link rel='icon' href='/emojiicon/favicon.svg?rand=" . rand(0,3456789) . "' sizes='any' type='image/svg+xml'>
</head>
<body>
<h1>Emoji Icon - RJM Programming - March, 2025</h1>
</body>
</html>";
?>

… used in a changed emoji_widget_idea.htm content live run.


Previous relevant SVG Network Clock Start Local Time Favicon Tutorial is shown below.

SVG Network Clock Start Local Time Favicon Tutorial

SVG Network Clock Start Local Time Favicon Tutorial

Today we’re revisiting the SVG Network Clock we last talked about with SVG Network Clock Minimize Tutorial. Why?

Well, we were re-researching the topic of Favicon (those images on the tabs of your web browser tabs) that we talked about when we presented Gimp Favicon via Logo Primer Tutorial, but we realize now, things have moved on with the web browsers supporting SVG svg+xml “favicons” so much better these days, that we’d better “get with the plan”, so to speak (though it might be better if I give that a rest for a minute).












Okay, minutes up!

With increased usage of SVG svg+xml text element solutions for things around here lately, we wondered whether there was a dynamic way to start using these SVG favicons, in some way. Then we thought of our SVG Clock work. At first we thought a favicon that is a relevant timestamp, but realized the impost on the web server is too big for that, and so we set out to present a local start time of the SVG Clock for a user of this web application. The SVG favicon basis is so simple …


<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="32" height="32" version="1.1" xmlns="http://www.w3.org/2000/svg" style="background-color:white; letter-spacing:-1px; transform:scale(1,1.6);>
<text x="0%" y="65%" stroke="black" stroke-width="1" fill="red" font-size="16px">11:54</text>
</svg>

Stick the SVG file in Document Root folder, and replace “11:54” with the relevant timestamp and we’re away, right? Yes, sort of, but there is the little matter of the relevant favicon link statement existing as a non-dynamic call to that SVG in the head section of the webpage.

Bit onerous, huh? But, what did work for us was to have a static starting wrong favicon SVG link (in head) statement that now goes in the parental svg_clock.html SVG Network Clock

<head>


<link id='mylink' rel='icon' href='/faviJUNKcon.svg' sizes='any' type='image/svg+xml'>

</head>

… and set up the changed cldate.php PHP now called …

<body>

<script type='text/javascript'>
var pwo=null;
var analoguesuffix='';
var bothsuffix='';
if (document.URL.indexOf('analogue=') != -1) { analoguesuffix=' selected'; }
if (document.URL.indexOf('both=') != -1) { bothsuffix=' selected'; }
var pretzlist='';
var tzlist="<option value='Africa/Abidjan' data-geo='5.31666,-4.03334,GMT,CI,+0'>Africa/Abidjan</option><option value='Africa/Accra' data-geo='5.55,-0.21667,GMT,GH,+0'>Africa/Accra</option>"; // etcetera etcetera etcetera

if (tz != "") {
document.write("<h1 title='Clock clicks popup Colour Wheel, Separator click for Timezone Info, Separator right click for Google Geo Chart Map, Flag text click for Google Maps and right click for concatenated Google Map Chart' id=myh1>SVG Network Clock</h1><h3>RJM Programming <button title='- for here and toggle to + for to right' id=lhmode onclick='this.innerHTML=this.innerHTML.replace(String.fromCharCode(45),String.fromCharCode(93)).replace(String.fromCharCode(43),String.fromCharCode(45)).replace(String.fromCharCode(93),String.fromCharCode(43));'>-</button> January, 2020</h3><h4 onclick='woit(this.title);' id=myh4 title='" + sih + "'>Enter toggles fullscreen mode and thanks to The PHP Anthology Volume II: Applications by Harry Fuecks</h4><p>The <select id=mysel onchange=gonext(this.value);>" + ("<option value='GMT'>GMT</option><option value='localtime'>Localtime</option>" + setpretz() + tzlist).replace('>' + tz.substring(0,1).toUpperCase() + tz.substring(1) + '<',' selected>' + tz.substring(0,1).toUpperCase() + tz.substring(1) + '<') + "</select> <select style='display:inline-block;' onchange=\"locationhref=(document.URL.replace('analogue=','x=').replace('both=','y=') + ('&' + this.value + '=y').replace('&=y','')).replace('.html&','.html?').replace('.htm&','.htm?') + lh; lhit(prevmysel,this);\"><option value=''>digital clock</option><option value=analogue" + analoguesuffix + ">analogue clock</option><option value=both" + bothsuffix + ">digital and analogue clock</option></select> sponsored by SVG is<br><hr id=myhr style='height:3px;' title='Click here for any Daylight Saving Time information' onclick=\"window.open('http://www.timezoneconverter.com/cgi-bin/zoneinfo?tz=" + encodeURIComponent(tz) + "','_blank','top=50,left=50,width=500,height=500');\"><br><object id=myclock data='svg_clock.php?timezone=" + encodeURIComponent(tz + loct) + uprefix + "' width='" + nh + "' height='530' type='image/svg+xml' /></p>" + es);
} else {
document.write("<h1 title='Clock clicks popup Colour Wheel, Separator click for Timezone Info, Separator right click for Google Geo Chart Map, Flag text click for Google Maps and right click for concatenated Google Map Chart' id=myh1>SVG Network Clock</h1><h3>RJM Programming <button title='- for here and toggle to + for to right' id=lhmode onclick='this.innerHTML=this.innerHTML.replace(String.fromCharCode(45),String.fromCharCode(93)).replace(String.fromCharCode(43),String.fromCharCode(45)).replace(String.fromCharCode(93),String.fromCharCode(43));'>-</button> January, 2020</h3><h4 onclick='woit(this.title);' id=myh4 title='" + sih + "'>Enter toggles fullscreen mode and thanks to The PHP Anthology Volume II: Applications by Harry Fuecks</h4><p>The <select id=mysel onchange=gonext(this.value);>" + ("<option value='GMT'>GMT</option><option value='localtime'>Localtime</option>" + setpretz() + tzlist).replace('>' + tz.substring(0,1).toUpperCase() + tz.substring(1) + '<',' selected>' + tz.substring(0,1).toUpperCase() + tz.substring(1) + '<') + "</select> <select style='display:inline-block;' onchange=\"locationhref=(document.URL.replace('analogue=','x=').replace('both=','y=') + ('&' + this.value + '=y').replace('&=y','')).replace('.html&','.html?').replace('.htm&','.htm?') + lh; lhit(prevmysel,this);\"><option value=''>digital clock</option><option value=analogue" + analoguesuffix + ">analogue clock</option><option value=both" + bothsuffix + ">digital and analogue clock</option></select> sponsored by SVG is<br><br><br><object id=myclock data='svg_clock.php" + uprefix.replace('&','?') + "' width='" + nh + "' height='530' type='image/svg+xml' /></p>");
}
document.write("<iframe style=height:60vh; frameborder=0 id='loces' onload='getmelt(this);' src='cldate.php?localtime=y&firstcall=" + ('' + Intl.DateTimeFormat().resolvedOptions().timeZone) + '&nowis=' + ('0' + (new Date().getHours())).slice(-2) + ':' + ('0' + (new Date().getMinutes())).slice(-2) + "'></iframe>");
</script>
<!--iframe style=height:60vh; frameborder=0 id='loces' onload='getmelt(this);' src='cldate.php?localtime=y'></iframe-->

</body>

… “helper” code to create the amended favicon.svg and amend the parent to use the new favicon.svg as per …

<?php

$pdt="";

if (strpos(('' . $_SERVER['QUERY_STRING']), "localtime") !== false) {
if (strpos(('' . $_SERVER['QUERY_STRING']), "firstcall") !== false) {
if (strpos(('' . $_SERVER['QUERY_STRING']), "nowis=") !== false) {
if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg')) {
$fsvg=file_get_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg');
if (strpos($fsvg, '</text>') !== false) {
$curts=explode('>', explode('</text>', $fsvg)[0])[-1 + sizeof(explode('>', explode('</text>', $fsvg)[0]))];
if (strpos($fsvg, '>' . $curts . '</text>')) {
$pdt=" parent.document.title+=' you started at " . str_replace('+',' ',urldecode($_GET['nowis'])) . " local time'; parent.document.getElementById('myh1').innerHTML+='<font size=1> ... you started at " . str_replace('+',' ',urldecode($_GET['nowis'])) . " local time</font>'; ";
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg', str_replace('>' . $curts . '</text>', '>' . str_replace('+',' ',urldecode($_GET['nowis'])) . '</text>', $fsvg));
}
}
}
} else {
$localtime = localtime();
if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg')) {
$fsvg=file_get_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg');
if (strpos($fsvg, '</text>') !== false) {
$curts=explode('>', explode('</text>', $fsvg)[0])[-1 + sizeof(explode('>', explode('</text>', $fsvg)[0]))];
if (strpos($fsvg, '>' . $curts . '</text>')) {
$pdt=" parent.document.title+=' you started at " . substr(('0' . $localtime[2]),-2,2) . ':' . substr(('0' . $localtime[1]),-2,2) . " local time'; parent.document.getElementById('myh1').innerHTML+='<font size=1> ... you started at " . str_replace('+',' ',urldecode($_GET['nowis'])) . " local time</font>'; ";
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'favicon.svg', str_replace('>' . $curts . '</text>', '>' . substr(('0' . $localtime[2]),-2,2) . ':' . substr(('0' . $localtime[1]),-2,2) . '</text>', $fsvg));
}
}
}
}

}
echo "<html><head><script type='text/javascript'> var iwois=null; </script></head><body><div id=mydiv></div><script type='text/javascript'>
var asuff='" . $midbit . $csuff . "';
var adate = new Date();
var dow=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
var his=eval('' + adate.getHours());
var mis=eval('' + adate.getMinutes());
var sis=eval('' + adate.getSeconds());
var ssuff='';
if (('' + adate).indexOf(' GMT') != -1) { ssuff=' GMT' + ('' + adate).split(' GMT')[1]; }
if (1 == 1) {
document.getElementById('mydiv').innerHTML=dow[eval('' + adate.getDay())] + ' ' + ('0' + his).slice(-2) + ':' + ('0' + mis).slice(-2) + ':' + ('0' + sis).split('.')[0].slice(-2) + ' ' + ('0' + adate.getDate()).slice(-2) + ' ' + ('0' + eval(1 + eval('' + adate.getMonth()))).slice(-2).replace('01','Jan').replace('02','Feb').replace('03','Mar').replace('04','Apr').replace('05','May').replace('06','Jun').replace('07','Jul').replace('08','Aug').replace('09','Sep').replace('10','Oct').replace('11','Nov').replace('12','Dec') + ' ' + ('' + adate.getFullYear()) + ' ' + ssuff + asuff;
} else {
document.write(dow[eval('' + adate.getDay())] + ' ' + ('0' + his).slice(-2) + ':' + ('0' + mis).slice(-2) + ':' + ('0' + sis).split('.')[0].slice(-2) + ' ' + ('0' + adate.getDate()).slice(-2) + ' ' + ('0' + eval(1 + eval('' + adate.getMonth()))).slice(-2).replace('01','Jan').replace('02','Feb').replace('03','Mar').replace('04','Apr').replace('05','May').replace('06','Jun').replace('07','Jul').replace('08','Aug').replace('09','Sep').replace('10','Oct').replace('11','Nov').replace('12','Dec') + ' ' + ('' + adate.getFullYear()) + ' ' + ssuff + asuff);
}
var myl=parent.document.getElementById('mylink').href;
if (myl.indexOf('JUNK') != -1) { parent.document.getElementById('mylink').href='/favicon.svg?rand=" . rand(0, 4534567) . "'; " . $pdt . " }

</script></body></html>";
}

?>

Interesting, huh?!


Previous relevant SVG Network Clock Minimize Tutorial is shown below.

SVG Network Clock Minimize Tutorial

SVG Network Clock Minimize Tutorial

Today’s blog posting’s underlying SVG Network Clock web application (we last talked about with Colour Wheel Size and Spoke Colour Tutorial’>Colour Wheel Size and Spoke Colour Tutorial) shares a couple of commonalities with yesterday’s MAMP Timekeeping Web Application Visibility Tutorial, those being …

… those Page Visibility API ideas you might equate to “minimize” concepts, that originated when GUIs were left to deal with how to present the representation of an application when it is no longer front and center in front of the user as an opened up window. We’d “minimize” back down to the desktop icon or toolbar view of the application. Web browsers can have tabs for this equivalent purpose, and we can improve the usefulness of a web application that can still be useful when “minimized” out of the top viewing tab. Date and time themed web applications can be your more obvious candidate for usefulness here. Just present a form of “digital clock readout” and your web applications like our SVG Network Clock can still be a source of information, even when “minimized”. We think that is an improvement?!

As you might have noticed with the last application of Page Visibility API “smarts”, this API is not hard to use, but for the first time we can remember, making changes just to the changed HTML supervisor svg_clock.html SVG Network Clock supervisor HTML and Javascript, and only changed to see in a new external Javascript svg_clock.js helper, we saved coding time by being able to …

  • scrutinize the DOM …
  • within an “object” HTML element’s …
  • SVG … featuring in some new Javascript with its own Page Visibility API reference

    function huhcont() {
    var dtidea='';
    var dotwis=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
    if (document.title != origdtis || ishd == ishd.toUpperCase()) { setTimeout(huhcont, 1000); }
    ishd == ishd.toLowerCase();
    if (document.getElementById('myclock') && ('' + document.visibilityState) == 'hidden') {
    if (document.getElementById('myclock').contentDocument.documentElement.outerHTML.indexOf(' id="sclock"') != -1) {
    console.log('predtidea');
    dtidea=document.getElementById('myclock').contentDocument.documentElement.outerHTML.split(' id="sclock"')[1].split('<')[0].split('>')[1].trim();
    console.log('dtidea=' + dtidea + ' ... ' + document.URL);
    if (dtidea != '') {
    document.title=dtidea;
    } else if (document.URL.indexOf('timezone=') != -1) {
    document.title=('' + new Date().toLocaleString("en-US", {timeZone: (location.search.split('timezone=')[1] ? decodeURIComponent(location.search.split('timezone=')[1].split('&')[0]) : "")}) + ' ' + (location.search.split('timezone=')[1] ? decodeURIComponent(location.search.split('timezone=')[1].split('&')[0]) : "") + ' ' + (location.search.split('emflag=')[1] ? decodeURIComponent(location.search.split('emflag=')[1].split('&')[0]) : ""));
    } else {
    document.title=new Date().toLocaleString("en-US", {timeZone: "GMT"});
    }
    } else {
    console.log('Why?');
    }
    }
    }

    … where we’d like to thank this useful link, thanks, for the heads up

Interesting, huh?!


Previous relevant MAMP Timekeeping Web Application Desktop Application Tutorial is shown below.

MAMP Timekeeping Web Application Desktop Application Tutorial

MAMP Timekeeping Web Application Desktop Application Tutorial

We figured that an improvement on the progress with our Timekeeping web application of the recent MAMP Timekeeping Web Application Audio Broadcast Tutorial would be to mention what macOS or Mac OS X Desktop Application is topmost when the screenshot is taken. When thinking about solutions for this, there was not much time before thinking turned to …

  • Apple Script, which has its GUI Apple “look” … but also …
  • Apple Script PHP shell_exec and (macOS Terminal) command line accessible osascript command line “look” too

… and excellent resources such as this excellent one to read that made us realize a PHP codeline such as …

<?php

$tma="";
if (!file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'script.jxa')) {
// Thanks to https://stackoverflow.com/questions/5292204/macosx-get-foremost-window-title
$scris="var seApp = Application(\"System Events\");
var oProcess = seApp.processes.whose({frontmost: true})[0];
var appName = oProcess.displayedName();

var url;
var title;

switch(appName) {
case \"Safari\":
url = Application(appName).documents[0].url();
title = Application(appName).documents[0].name();
break;
case \"Opera\":
url = Application(appName).windows[0].activeTab().url();
title = Application(appName).windows[0].activeTab().name();
break;
case \"Google Chrome\":
url = Application(appName).windows[0].activeTab().url();
title = Application(appName).windows[0].activeTab().name();
break;
case \"Google Chrome Canary\", \"Chromium\":
url = Application(appName).windows[0].activeTab().url();
title = Application(appName).windows[0].activeTab().name();
break;
default:
title = oProcess.
windows().
find(w => w.attributes.byName(\"AXMain\").value() === true).
attributes.
byName(\"AXTitle\").
value()
}

JSON.stringify({
appname: appName,
url: url,
title: title
});";
file_put_contents($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'script.jxa', $scris);
}
$tma=shell_exec('osascript -l JavaScript ' . $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'script.jxa');

?>

… can glean such useful JSON results such as …


{"appname":"Safari","url":"http://localhost:8888/HTMLCSS/quarter_hour_timer.php?tz=Australia%2FSydney&qs=e&audiosave=%20-v%20Victoria%20%20-o%20out.aiff%20%20Screenshot%20%20at%20Monday%20July%2025%202022%2021%2030%20AEST","title":"‎localhost:8888/HTMLCSS/quarter_hour_timer.php?tz=Australia%2FSydney&qs=e&audiosave=%20-v%20Victoria%20%20-o%20out.aiff%20%20Screenshot%20%20at%20Monday%20July%2025%202022%2021%2030%20AEST"}

… well, it almost makes us speechless!

This change affected …

… and we hope you try it for yourself!


Previous relevant MAMP Timekeeping Web Application Audio Broadcast Tutorial is shown below.

MAMP Timekeeping Web Application Audio Broadcast Tutorial

MAMP Timekeeping Web Application Audio Broadcast Tutorial

We thought what could be a benefit to the Timekeeping web application of the recent MAMP Timekeeping Web Application Web Share Personalization Tutorial would be to …

  • offer an optional audio broadcasting piece of functionality … presented via a new 📢 (&#128226;) emoji button, that might accompany …
  • notifications

… when a screenshot is taken. As good as notifications are, it could be that the user is beavering away with their head down at work as the screenshot is taken, but welcome the audio queue that a Timekeeping screenshot has been taken. As well as that, with this new audio broadcasting, the *.aiff audio files created are available to share via email or SMS using the Web Share API interfacing code. This involved changes to …


Previous relevant MAMP Timekeeping Web Application Web Share Personalization Tutorial is shown below.

MAMP Timekeeping Web Application Web Share Personalization Tutorial

MAMP Timekeeping Web Application Web Share Personalization Tutorial

Your words, helped out by some computer derived detail data, can help personalize your work using the Quarter Hour Timekeeping web application of yesterday’s MAMP Timekeeping Web Application Web Share API Tutorial which, at least with the Safari browser (and a whole lot of other macOS conditions), now integrates with the Web Share API to attach images to prepared emails with a “body blurb”. It is that prepared “body blurb” we are trying to refine, today, should the user attach any of those Timekeeper screenshot files created via macOS screencapture command.

This is because these screenshot file names, by our convention, are of the format …


screen-yyyymmdd-hhmi.jpg

… within the macOS MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] folder (though the path to the file is unavailable to File API File object programmers).

That, teamed with the fact that individual user comments linked to any one quarter hour screenshot image has an ID attribute of the form …


tatd_yyyymmdd_hhmi

… and you have modified Javascript helping the user to tailor better personalized and detail email or SMS communications using the changed macos_say_record.js external Javascript via …


var wsadate=new Date();
var lfd=String.fromCharCode(10);

function getwsadate(dd, mm, yyyy, hh, mi) {
wsadate=new Date(yyyy, eval(-1 + eval('' + mm)), dd, hh, mi, 0, 0);
var outdstr=wsadate.toDateString() + ' ' + wsadate.toTimeString();
outdstr=outdstr.replace('Sun ', 'Sunday ').replace('Mon ', 'Monday ').replace('Tue ', 'Tuesday ').replace('Wed ', 'Wednesday ').replace('Thu ', 'Thursday ').replace('Fri ', 'Friday ').replace('Sat ', 'Saturday ');
outdstr=outdstr.replace(':00 ', ' ').replace(' Jan ', ' January ').replace(' Feb ', ' February ').replace(' Mar ', ' March ').replace(' Apr ', ' April ').replace(' Jun ', ' June ').replace(' Jul ', ' July ').replace(' Aug ', ' August ').replace(' Sep ', ' September ').replace(' Oct ', ' October ').replace(' Nov ', ' November ').replace(' Dec ', ' December ');
//console.log('tatd_' + yyyy + mm + dd + '_' + hh + mi);
if (document.getElementById('tatd_' + yyyy + mm + dd + '_' + hh + mi)) {
//console.log('yes tatd_' + yyyy + mm + dd + '_' + hh + mi);
if (document.getElementById('tatd_' + yyyy + mm + dd + '_' + hh + mi).value.trim() != '') {
outdstr+=' ' + String.fromCharCode(10) + '"' + document.getElementById('tatd_' + yyyy + mm + dd + '_' + hh + mi).value + '"';
} else if (document.getElementById('tatd_' + yyyy + mm + dd + '_' + hh + mi).innerHTML.trim() != '') {
outdstr+=' ' + String.fromCharCode(10) + '"' + document.getElementById('tatd_' + yyyy + mm + dd + '_' + hh + mi).innerHTML + '"';
}
}
lfd='';
return outdstr + String.fromCharCode(10);
}


async function atclick() {
const files = document.getElementById('files').files;
var moressi='', ifl=0, lessssi='';

if (files.length === 0) {
shareurl();
document.getElementById('output').textContent = 'No files selected.';
return;
} else {
for (ifl=0; ifl<files.length; ifl++) {
if (('' + files[ifl].name).indexOf('screen-') != -1) {
if (('' + files[ifl].name).split('screen-')[1].split('-')[0].length == 8) {
if (('' + files[ifl].name).split('screen-')[1].split('-')[1].split('.')[0].length == 4) {
moressi+=lfd + ' on ' + getwsadate(('' + files[ifl].name).split('screen-')[1].split('-')[0].slice(-2), ('' + files[ifl].name).split('screen-')[1].split('-')[0].slice(-4).substring(0,2), ('' + files[ifl].name).split('screen-')[1].split('-')[0].substring(0,4), ('' + files[ifl].name).split('screen-')[1].split('-')[1].split('.')[0].substring(0,2), ('' + files[ifl].name).split('screen-')[1].split('-')[1].split('.')[0].slice(-2));
}
}
}
}

}

lessssi=moressi;
while (lessssi.indexOf(String.fromCharCode(10)) != -1) {
lessssi=lessssi.replace(String.fromCharCode(10), ' ');
}


// feature detecting navigator.canShare() also implies
// the same for the navigator.share()
if (!navigator.canShare) {
//if (document.URL.indexOf('localhost') != -1) { alert('Can not share'); }
document.getElementById('output').textContent = `Your browser doesn't support the Web Share API.`;
return;
//} else {
//if (document.URL.indexOf('localhost') != -1) { alert('Can Share'); }
}

if (navigator.canShare({ files })) {
try {
console.log('Can share');
await navigator.share({
files,
title: 'Timekeeping screenshots' + lessssi + ' or media or documents',
text: 'Timekeeping screenshots' + moressi + ' perhaps?! Take a look at media or documents below' + String.fromCharCode(10) + String.fromCharCode(10)
});
document.getElementById('output').textContent = 'Shared!';
} catch (error) {
document.getElementById('output').textContent = `Error: ${error.message}`;
}
} else {
//if (document.URL.indexOf('localhost') != -1) { alert('Cannot share'); }
document.getElementById('output').textContent = `Your system doesn't support sharing these files.`;
}
lfd=String.fromCharCode(10);
}


Previous relevant MAMP Timekeeping Web Application Web Share API Tutorial is shown below.

MAMP Timekeeping Web Application Web Share API Tutorial

MAMP Timekeeping Web Application Web Share API Tutorial

Adding onto yesterday’s MAMP Timekeeping Web Application Audio Commentary Tutorial

  • Timekeeping Web Application newish Text to Audio (via macOS say via MAMP “Intranet feel”) … today, we have …
  • Timekeeping Web Application new Web Share API (public domain Document Root external Javascript Web Share API) Javascript logic

This got us decoupling what can become …

… but as we’ve warned before you may need all these for total success for the Timekeeping Quarter Hour Timer web application (that can screenshot, can create notification when screenshot taken, and have audio commentary, and share screenshot image(s) or Timekeeper URL) …


Previous relevant MAMP Timekeeping Web Application Audio Commentary Tutorial is shown below.

MAMP Timekeeping Web Application Audio Commentary Tutorial

MAMP Timekeeping Web Application Audio Commentary Tutorial

The recent MAMP Timekeeping Web Application PHP Notifications Tutorial‘s Timekeeping via Screenshots changed HTML and Javascript quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Web Application supervisor is another very suitable candidate for interfacing to our recent Webpage Audio Commentary functionality. Both …

… share an …

  • underlying macOS or Mac OS X operating system dependence …
  • underlying local web server such as MAMP …
  • downloaded into that local web server Document Root folder PHP code

… set of interest points for full and useful functionality, because of two macOS or Mac OS X commands, respectively …

We add the changed macos_say_record.js external Javascript call into the supervisory HTML and Javascript <head></head> webpage section via …


<script type='text/javascript' src='//www.rjmprogramming.com.au/macos_say_record.js?ongoing=1721156687576' defer></script>

… sitting up at the Document Root of your public domain, that “?ongoing=” based $_GET[‘ongoing’] argument deliberate, effectively asking the code to look out for “on the fly” HTML elements created within an execution run of the webpage.

We add some “smarts” to those global data attribute usage we talked about at Webpage macOS Say Audio Commentary Access Count Tutorial, allowing some “date extraction” templating via the supervisory HTML and Javascript array declaration as per


<script type='text/javascript'>
var commentary_array=['textarea', 'You can enter comments about this screenshot here %value%outerHTML%@yyyymmdd%hhmm%.', 'img', 'Timekeeper screenshot here %id%@yyyymmdd%hhmm%.'];
</script>

… where the first field describes an HTML element attribute to first look at, the optional second is a stand by attribute, followed by “date extraction” fields to match with numerical data found so as to substitute the blue parts with a “date and timestamp” string.


Previous relevant MAMP Timekeeping Web Application PHP Notifications Tutorial is shown below.

MAMP Timekeeping Web Application PHP Notifications Tutorial

MAMP Timekeeping Web Application PHP Notifications Tutorial

Today we’re revisiting the macOS (or Mac OS X) or Windows timekeeping web application of 2016’s Mac OS MAMP Timekeeping Web Application PHP Calendar Aesthetics Tutorial. Why? Well, given our recent work with Notifications API based web applications you can read about at Notification API Hidden Popup Tutorial, the timekeeping one is a great candidate for functionality improvement here, it being a web application that …

  • can work behind the scenes …
  • not necessarily frontmost … but benefitting from any …
  • notification reminders separate from web activities and webpage focus issues can help tell the user when they might want to turn back attention to the timekeeping screenshot recording

This needs PHP to work and it needs real access via PHP exec function to underlying operating system commands. When this happens, we still try to offer a public RJM Programming interface but this interface is far less useful if you have not downloaded to your local Apache/PHP/MySql local web server (such as a MAMP one) as per …

  1. the changed quarter_hour_timer.php (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage
  2. the unchanged (from tutorial below, supervisory HTML and Javascript) quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application
  3. the “how we got there” PHP notifications_ideas.php (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] subfolder) Notification API functionality PHP web application

… in what we like to call an “Intranet feeling” scenario.

Up at the public RJM Programming domain, as far as the Notification API functionality supervisor webpage goes, the changed HTML and Javascript notifications_ideas.html Notification API functionality HTML and Javascript web application is worth trying.


Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar Aesthetics Tutorial is shown below.

Mac OS MAMP Timekeeping Web Application PHP Calendar Aesthetics Tutorial

Mac OS MAMP Timekeeping Web Application PHP Calendar Aesthetics Tutorial

To finish up our revisit to the Timekeeping web application of the recent Mac OS MAMP Timekeeping Web Application PHP Calendar Iframe Tutorial we …

  • make some styling calendar tweaks

    <style>
    td { vertical-align: top; }
    #divmc { background-color: #ffffff; }
    p:not(:empty) { border: 1px dotted red; }
    td { text-align: center; vertical-align: top; }
    th { background-color: cyan; }
    #thyear { background-color: pink; }
    div { word-wrap: break-word; }
    .adaNOte { border: 3px solid pink; border-radius: 7px; }
    a.adate { border:2px solid transparent; background-color:lightgreen; border-radius:50px; }

    </style>
  • settle for mobile platforms never being able to screenshot, on this round of looking, and redirecting to the “Monthly Chronicler” web application (of (the unchanged) monthly_chronicler.html we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder)

    <script>
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|iPad|Opera Mini|IEMobile/i)) {
    document.write("<scri" + "pt> location.href='./monthly_chronicler.html'; </scr" + "ipt> <style> a.adate { border:1px solid green; background-color:#f0f0f0; border-radius:50px; } </style> <table id=mtable style=display:none;width:95%;><tr><th><input style=width:450px; placeholder='' id=iask type=text value=''></input><</th><th><input onclick=\" document.getElementById('mtable').style.display='none'; document.getElementById('mybod').style.opacity='1.0'; postask(document.getElementById('iask'));\" type=button value=OK></input></th><th><input onclick=\"document.getElementById('iask').value=''; document.getElementById('mtable').style.display='none'; document.getElementById('mybod').style.opacity='1.0'; \" type=button value=Cancel></input></th></tr></table>");
    }
    </script>

    … dumbing down, but working more reliably, using “Javascript writes Javascript” methodology

Again, feel free to try the changed quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage, is helped out by a “mobile platform check” changed quarter_hour_timer.php PHP (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) for you to try out on your MAMP macOS environment, or all showing up at an RJM Programming public domain webpage, in an iframe element, visible now.


Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar Windows Tutorial is shown below.

Mac OS MAMP Timekeeping Web Application PHP Calendar Windows Tutorial

Mac OS MAMP Timekeeping Web Application PHP Calendar Windows Tutorial

Did you notice that the “Timekeeping” PHP did not have to change for yesterday’s Mac OS MAMP Timekeeping Web Application PHP Calendar iCal Integration Tutorial?

But the PHP is the change agent for Windows (client) integration called quarter_hour_timer.php today …

<?php

// blah top
$lportbit=":8888";

$user_agent = $_SERVER["HTTP_USER_AGENT"];
function getOS() { // thanks to https://www.daniweb.com/programming/web-development/threads/495588/getting-users-os-info-out-of-server-http-user-agent
global $user_agent, $lportbit;
$os_platform = "win Unknown OS Platform";
$os_array = array(
'/windows nt 10/i' => 'Windows 10',
'/windows nt 6.3/i' => 'Windows 8.1',
'/windows nt 6.2/i' => 'Windows 8',
'/windows nt 6.1/i' => 'Windows 7',
'/windows nt 6.0/i' => 'Windows Vista',
'/windows nt 5.2/i' => 'Windows Server 2003/XP x64',
'/windows nt 5.1/i' => 'Windows XP',
'/windows xp/i' => 'Windows XP',
'/windows nt 5.0/i' => 'Windows 2000',
'/windows me/i' => 'Windows ME',
'/win98/i' => 'Windows 98',
'/win95/i' => 'Windows 95',
'/win16/i' => 'Windows 3.11',
'/macintosh|mac os x/i' => 'Mac OS X',
'/mac_powerpc/i' => 'Mac OS 9',
'/linux/i' => 'Linux',
'/ubuntu/i' => 'Ubuntu',
'/iphone/i' => 'iPhone',
'/ipod/i' => 'iPod',
'/ipad/i' => 'iPad',
'/android/i' => 'Android',
'/blackberry/i' => 'BlackBerry',
'/webos/i' => 'Mobile'
);

foreach ($os_array as $regex => $value) {

if (preg_match($regex, $user_agent)) {
$os_platform = $value;
}

}

return $os_platform;
}

$callornot="call ";
$precmds="";
$impreexe="screenCapture"; //"import";
$switches=""; //" -window root ";
if (substr(strtoupper(getOS()),0,3) === 'WIN') {
$lportbit="";
if (file_exists($_SERVER['DOCUMENT_ROOT'] . "\\" . $impreexe . ".exe")) {
$precmds=$_SERVER['DOCUMENT_ROOT'] . "\\";
} else {
foreach (glob("C:\\Users\\*\\" . $impreexe . ".exe") as $infl) {
$precmds=explode($impreexe . ".exe", $infl)[0];
}
}
}

// blah blah some other PHP functions

if (isset($_GET['yourta'])) {
// calendar work
} else if (isset($_GET['myta'])) {
// embed image metadata
} else if (isset($_POST['myta'])) {
// parse image metadata
} else if ($lportbit != "") {
exec("/usr/sbin/screencapture -Cd -tjpg " . $_SERVER['DOCUMENT_ROOT'] . "/screen-`date +\"%Y%m%d-%H%M\"`.jpg");
} else {
if (isset($_GET['tz'])) {
$tzis=str_replace('+','_',urldecode($_GET['tz']));
if (strpos($tzis, "/") !== false) { date_default_timezone_set($tzis); }
}
$dateis = date('Ymd-Hi');
if (file_exists($_SERVER['DOCUMENT_ROOT'] . "\\screenCapture.jpg")) {
exec('copy ' . '"' . $_SERVER['DOCUMENT_ROOT'] . "\\screenCapture.jpg" . '" "' . $_SERVER['DOCUMENT_ROOT'] . "\\screen-" . $dateis . '.jpg"');
// exec('erase ' . '"' . $_SERVER['DOCUMENT_ROOT'] . "\\screenCapture.jpg" . '"');
} else {
exec($callornot . '"' . $precmds . $impreexe . '.exe" ' . $switches . ' "' . $_SERVER['DOCUMENT_ROOT'] . "\\screen-" . $dateis . '.jpg"');
}
}

exit;

?>

… which you may glean has a Windows “fallback” position (with that “copy” codeline). Why? Well, we found a .Net framework “exe creation via bat” using ScreenCapture.bat (thanks to this useful link) created black screen shots. Probably a privilege thing or PHP exec thing, but we’ve opted for the workaround, which is just “Windows talk” …

  • write Windows batch scapcontinuous.bat as a continuous fifteen minute user of the .Net Framework (ScreenCapture.exe) derived from above
  • set up a task via “Task Schedular” (please ignore the warts ‘n all “garden path” schtask ideas in the video below) that has an action “C:\MAMP\htdocs\scapcontinuous.bat” and starts when the Windows user logs in and takes (successful) screen shots at 14 and 29 and 44 and 59 minutes (in the hour) times

Take a more detailed look at “warts ‘n all” crab progression towards the Windows (client) solution, below …


Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar iCal Integration Tutorial is shown below.

Mac OS MAMP Timekeeping Web Application PHP Calendar iCal Integration Tutorial

Mac OS MAMP Timekeeping Web Application PHP Calendar iCal Integration Tutorial

Yesterday’s Mac OS MAMP Timekeeping Web Application PHP Calendar Contenteditable Tutorial‘s “Calendar Past” improvements don’t have to be the end of the story regarding “calendar timings”. There is an Apple iCal standard interfacing format that can drive calendar integrations with many well known online Calendar applications.

You may recall us talking about this with Calendar Location Services Integration Tutorial and we tweak the changed ics_attachment.php (which we’d ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “PHP” subfolder) and its standalone ical creator to better integrate with the changed quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage.

This bit of functionality works (interfacing) both with MAMP and with the public RJM Programming domain incarnation of the Timekeeping web application, so that could be interesting. It can interface via …

… modes of use. In action, should you create an iCal file this way, the web application will download the resultant .ics file into your Downloads folder and to interface into your default online Calendar application double click that Downloads folder file to complete the Calendar integration …


function icalpostit(tl, tg) {
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!
var yyyy = today.getFullYear();
var hh = today.getHours();
var minm = today.getMinutes(); //January is 0!
//if (icalavailable) { alert('is ' + ('' + yyyy + ('00' + mm).slice(-2) + ('00' + dd).slice(-2) ) + ' >= ' + tl.substring(1)); }
if ((document.getElementById('yics').value.indexOf('all') != -1 || tl.substring(1) >= ('' + yyyy + ('00' + mm).slice(-2) + ('00' + dd).slice(-2) )) && icalavailable && document.getElementById('yics').value != '') {
if (document.getElementById('yics').value.indexOf('nw') != -1) {
icald=tl.substring(1) + ':' + ('00' + hh).slice(-2) + ('00' + minm).slice(-2) + '59';
icalg=tg;
if (icalwo != null) { icalwo.close(); icalwo=null; }
icalwo=window.open('../PHP/ics_attachment.php','_blank','top=100,left=100,width=740,height=800');
if (1 == 1) {
setTimeout(icalw, 3000);
} else {
icalwo.document.getElementById('datestart').value=icald;
icalwo.document.getElementById('dateend').value=icald;
icalwo.document.getElementById('eventwords').value=icalg.replace(/\<br\>/g, String.fromCharCode(10)).replace(/\<Br\>/g, String.fromCharCode(10)).replace(/\<BR\>/g, String.fromCharCode(10));
if (document.URL.indexOf('localhost') != -1) {
var jcald=icalg.replace(/\<br\>/g, String.fromCharCode(10)).replace(/\<Br\>/g, String.fromCharCode(10)).replace(/\<BR\>/g, String.fromCharCode(10)).replace(/\ \;>/g, ' ');
while (jcald.indexOf(String.fromCharCode(10)) != -1) { jcald=jcald.replace(String.fromCharCode(10),' '); }
icalwo.document.getElementById('title').value=jcald;
} else {
icalwo.document.getElementById('title').value='Calendar event at ' + icald;
}
icalwo.document.getElementById('description').value='Calendar event at ' + icald;
icalwo.document.getElementById('address').value=document.URL.split('?')[0].split('#')[0];
icalwo.document.getElementById('mmdatestart').value=icald.substring(4,6);
icalwo.document.getElementById('mmdateend').value=icald.substring(4,6);
icalwo.document.getElementById('dddatestart').value=icald.substring(6,8);
icalwo.document.getElementById('dddateend').value=icald.substring(6,8);
icalwo.document.getElementById('ssdatestart').value='59';
icalwo.document.getElementById('ssdateend').value='59';
icalwo.document.getElementById('yyyydatestart').value=icald.substring(0,4);
icalwo.document.getElementById('yyyydateend').value=icald.substring(0,4);
if ( ('' + today.getTimezoneOffset()).replace('null','').replace('undefined','') != '' ) {
//alert(('' + eval(eval('' + qd.getTimezoneOffset()) / 60.0)).replace('.00','').replace('.0',''));
icalwo.document.getElementById('tz').value=('' + eval(eval('' + today.getTimezoneOffset()) / 60.0)).replace('.00','').replace('.0','');
}
//icalwo.document.getElementById('pform').onsubmit=function() { window.opener.document.getElementById('icalstatus').innerHTML=' '; return true; };

}
} else if (document.getElementById('yics').value.indexOf('if') != -1) {
icald=tl.substring(1) + ':' + ('00' + hh).slice(-2) + ('00' + minm).slice(-2) + '59';
icalg=tg;
document.getElementById('divics').style.display='block';
document.getElementById('divics').style.width='100%';
document.getElementById('divics').style.height='800px';
document.getElementById('icslocit').style.display='block';
document.getElementById('icslocit').style.width='100%';
document.getElementById('icslocit').style.height='800px';
document.getElementById('icslocit').src='../PHP/ics_attachment.php?rand=' + Math.floor(Math.random() * 19876564);
} else {
var xzhr = new XMLHttpRequest();
var xform=new FormData();
xform.append('icald',tl.substring(1) + ':' + ('00' + hh).slice(-2) + ('00' + minm).slice(-2) + '59');
xform.append('icalc',tg);
xzhr.open('post','./quarter_hour_timer.php',true);
xzhr.send(xform);
}
}
}


Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar Contenteditable Tutorial is shown below.

Mac OS MAMP Timekeeping Web Application PHP Calendar Contenteditable Tutorial

Mac OS MAMP Timekeeping Web Application PHP Calendar Contenteditable Tutorial

We’ve spoken quite a bit in the past about the joys of involving the “contenteditable=true” attribute for HTML elements that have an “innerHTML” (ie. they have a formalized end tag arrangement eg. div, span, p, td, th etcetera) and with today’s work which extends that started with yesterday’s Mac OS MAMP Timekeeping Web Application PHP Calendar Past Tutorial it is the turn of a set of “p” elements it helps out today.

The scenario is that yesterday’s work did not allow for “orphaned screenshots” of the past be allowed to be brought back into play to “annotate them” and in so doing “give them a home”. This led us to …

  • allow for a new “Infill Earlier Days All Screenshots” button augment yesterday‘s “Infill Earlier Days Just Annotated Screenshots” button …
  • the pressing of that new “Infill Earlier Days All Screenshots” button causes all screenshot 15 minute entries relevant to the current year be displayed in the calendar … but then it occurred to us users might want to “annotate them” … but how? …
  • in the PHP we introduced code
    <?php

    if (isset($_GET['yourta'])) {
    $dru="http://" . $_SERVER['SERVER_NAME'] . "" . str_replace("~","",str_replace(":443~","",str_replace(":80~","",(":" . $_SERVER['SERVER_PORT'] . "~")))) . "/";
    $cet="";
    if (strlen($_GET['yourta']) != 0) { $cet=" contenteditable=true onblur=repostit(this); onfocus=wopen(event,false); "; }

    // blah blah blah
    $ccpre="" . $cet . " onclick=this.innerHTML+=String.fromCharCode(60)+String.fromCharCode(98)+String.fromCharCode(114)+String.fromCharCode(62); style=background-color:orange;background-repeat:no-repeat;background-size:contain;background-image:linear-gradient(rgba(255,255,255,0.3),rgba(255,255,255,0.3)),URL(" . $dru . str_replace('_','-',str_replace('itd_','screen-',$myf)) . ".jpg" . "); onmouseover=wopen(event,true); onmouseout=wopen(event,false); title=" . substr(str_replace('td','p',$cali),-4,2) . ":" . substr(str_replace('td','p',$cali),-2,2) . "++ id=" . str_replace('td','p',$cali) . ">";
    // blah blah blah
    }

    ?>
    … to, when an “orphaned” screen shot image is happened upon, allows …
  • contenteditable=true “does its stuff” turning might might have been a pretty unintelligent HTML element into a “textarea” type collector of user input, and then that onblur event logic’s “midair feeling” Ajax/FormData “recursive feeling” methodology …

    function repostit(ih) {
    var ihis=(ih.innerText || ih.contentWindow || ih.contentDocument);
    var pathpart=ih.id;
    if (ihis != '') {
    var xzhr = new XMLHttpRequest();
    var xform=new FormData();
    xform.append('myta',ihis);
    xform.append(pathpart.split('.')[0].replace('ip_','screen-').replace('_','-'),'');
    xzhr.open('post','./quarter_hour_timer.php',true);
    xzhr.send(xform);
    }
    }

    … which can cement that (newly user entered) annotation into future permanency in the “Yearly Report Calendar” section

… of the changed quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage, is helped out by a contenteditable=true changed quarter_hour_timer.php PHP (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) for you to try out on your MAMP macOS environment.


Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar Past Tutorial is shown below.

Mac OS MAMP Timekeeping Web Application PHP Calendar Past Tutorial

Mac OS MAMP Timekeeping Web Application PHP Calendar Past Tutorial

If you’ve been using the Timekeeping web application as of yesterday’s Mac OS MAMP Timekeeping Web Application PHP Calendar Tutorial you would have noticed a very …

  • first person
  • present tense

… feel to it all. Today, we improve on the latter “restrictiveness” issue, within yesterday’s “Yearly Report Calendar” new functionality, by looking back into the current calendar year’s “past” with respect to the date of using the web application, whether that be …

  • screen captures from days in the current calendar year’s “past”
  • text entries made and remembered (in window.localStorage) in the current calendar year’s “past”

… to infill and flesh out that “Yearly Report Calendar” better. This involved bringing over a lot of (the unchanged) monthly_chronicler.html‘s Javascript logic into the changed quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage, is helped out by a calendar’s past integrationally changed quarter_hour_timer.php PHP (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) for you to try out on your MAMP macOS environment.

<?php

// quarter_hour_timer.php
// RJM Programming
// December, 2021

if (isset($_GET['yourta'])) {
$dru="HTTP://" . $_SERVER['SERVER_NAME'] . "" . str_replace("~","",str_replace(":443~","",str_replace(":80~","",(":" . $_SERVER['SERVER_PORT'] . "~")))) . "/";
$contis=str_replace('+',' ',urldecode($_GET['yourta']));
//file_put_contents('xx.xx', $contis);
$htmlis='';
$myf='';
$backi='';
$cali='';
$taback='';
$bcontis="'" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $contis)))) . "'";
if (substr(($bcontis . ' '),0,3) == "' + ") { $bcontis=$bcontis.substr(3); }
if (substr((' ' . $bcontis),-3,3) == " + '") { $bcontis=$bcontis.substr(0,(-3 + strlen($bcontis))); }
foreach ($_GET as $name=>$val) {
if ($name != 'yourta') { // && $val == '') {
//echo $name;
$orig=$name;
$myf=$name;
for ($imh=12; $imh>=1; $imh--) {
for ($idd=31; $idd>=1; $idd--) {
//file_put_contents('xz.xz',$orig . ' Is ' . substr('00' . $imh,-2,2) . substr('00' . $idd,-2,2) . ' less than ' . $val);
if (substr('00' . $imh,-2,2) . substr('00' . $idd,-2,2) < $val) {
for ($ihh=0; $ihh<=23; $ihh++) {
for ($imm=0; $imm<=45; $imm+=15) {
//if ($ihh != 0 || $imm != 0) {
$myf=str_replace("0101_", substr('00' . $imh,-2,2) . substr('00' . $idd,-2,2) . "_",$orig);
$myf=str_replace("_0000", "_" . substr('00' . $ihh,-2,2) . substr('00' . $imm,-2,2),$myf);
//}
$taback=str_replace('-','_',str_replace('itd','tatd',$myf));
$backi=str_replace('-','_',str_replace('screen-','itd_',$myf));
$cali=str_replace('-','',str_replace('screen-','td',$myf));
$idcali=explode('-',explode('_',str_replace('screen-','td',str_replace('itd_','td',$myf)))[0])[0];

// Thanks to https://doc.bccnsoft.com/docs/php-docs-7-en/function.iptcembed.html

// Path to jpeg file
$path = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . str_replace('_','-',str_replace('itd_','screen-',$myf)) . '.jpg';
//file_put_contents('x.x',$path);
if (file_exists($path)) {
$capt = ""; // Thanks to https://www.php.net/manual/en/function.iptcparse.php
$size = getimagesize( $path, $info );
if (isset($info["APP13"])) {
//file_put_contents('xx.xx',$path);
if ($iptc = iptcparse( $info["APP13"] ) ) {
//file_put_contents('xxx.xxx',$path);
$capt = str_replace( "\000", "", $iptc["2#120"][0] );
//file_put_contents('xxxx.xxxx',$capt);
}
}
$bcontis="" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "";
$ccpre="<p onclick=this.innerHTML+=String.fromCharCode(60)+String.fromCharCode(98)+String.fromCharCode(114)+String.fromCharCode(62); style=background-color:orange;background-repeat:no-repeat;background-size:contain;background-image:linear-gradient(rgba(255,255,255,0.3),rgba(255,255,255,0.3)),URL(" . $dru . str_replace('_','-',str_replace('itd_','screen-',$myf)) . ".jpg" . "); onmouseover=wopen(event,true); onmouseout=wopen(event,false); title=" . substr(str_replace('td','p',$cali),-4,2) . ":" . substr(str_replace('td','p',$cali),-2,2) . "++ id=" . str_replace('td','p',$cali) . ">";
$ccpost="</p>";
$ccontis="<br><p style='background-color:orange; title='" . str_replace('td','p',$cali) . "' id=" . str_replace('td','p',$cali) . ">" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "<br>", str_replace("\r\n", "<br>", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "</p>";
//file_put_contents('xxxxx.xxxxx',$bcontis);
//file_put_contents('xxxxxx.xxxxxx',$taback . ' ... ' . $backi);
//file_put_contents('xxxxxxx.xxxxxxx',"parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "'; ");

}

if ($bcontis != "''" && $bcontis != "") {
if ($htmlis == '') {
$htmlis="<html><head><script type=text/javascript> var imois=null, iwo=null; function wopen(event,overvsout) { if (!overvsout) { if (imois == event.target) { imois=null; } return; } imois=event.target; setTimeout(postwopen, 2000); } function postwopen() { var pois=imois; if (pois.outerHTML.indexOf('URL(') != -1) { window.open(pois.outerHTML.split('URL(')[1].split(')')[0].replace(String.fromCharCode(34),'').replace(String.fromCharCode(34),''),'_blank','top=50,left=50,width=600,height=600'); } }</script></head><body onload=\" var huhg=''; if (parent.document.getElementById('" . $idcali . "')) { huhg='" . $ccpre . $bcontis . $ccpost . "'; while (huhg.indexOf(String.fromCharCode(10)) != -1) { huhg=huhg.replace(String.fromCharCode(10),'<br>'); } parent.document.getElementById('" . $idcali . "').innerHTML+=huhg; } \"></body></html>";
} else if (strpos($htmlis, $bcontis) === false) {
$htmlis=str_replace("+=huhg; }", "+=huhg; huhg='" . $ccpre . $bcontis . $ccpost . "'; while (huhg.indexOf(String.fromCharCode(10)) != -1) { huhg=huhg.replace(String.fromCharCode(10),'<br>'); } parent.document.getElementById('" . $idcali . "').innerHTML+=huhg; }", $htmlis);
}
}

}
}

if ($htmlis != "") { echo $htmlis; }

}
}
}
}
}
}

// blah else if blah else if blah

?>

… which you may notice implements a “long hover” window.open scenario (using non-mobile platforms) for screenshot images on the calendar by combining the use of …

  • global variables …

    var imois=null;
    var iwo=null;
  • onmouseover event logic …
    Call
    onmouseover=wopen(event,true);
  • setTimeout delays …
    Called

    function wopen(event,overvsout) {
    if (!overvsout) {
    if (imois == event.target) {
    imois=null;
    }
    return;
    }
    imois=event.target;
    setTimeout(postwopen, 2000);
    }


    function postwopen() { //pois) {
    if (imois) {
    var pois=imois;
    if (pois.outerHTML.indexOf('URL(') != -1) {
    if (iwo) { iwo.close(); iwo=null; }
    iwo = window.open(pois.outerHTML.split('URL(')[1].split(')')[0].replace(String.fromCharCode(34), '').replace(String.fromCharCode(34), ''), '_blank', 'top=50,left=50,width=600,height=600');
    }
    }
    }
  • onmouseout event logic …
    Call
    onmouseout=wopen(event,false);

… so that this logic is not responsible for clobbering the default “hover” shows of the “p” element “title” attribute with the onmouseover event for non-mobile platforms.


Previous relevant Mac OS MAMP Timekeeping Web Application PHP Calendar Tutorial is shown below.

Mac OS MAMP Timekeeping Web Application PHP Calendar Tutorial

Mac OS MAMP Timekeeping Web Application PHP Calendar Tutorial

Okay then, yesterday’s Mac OS MAMP Timekeeping Web Application PHP Image Metadata Tutorial “image metadata smarts” puts us in a position to get onto the “bells and whistles” side of our Timekeeping (macOS and Mac OS X only at this stage) web application. We channel the calendar display talents of Monthly Chronicler LocalStorage Tutorial in thought and act (its web application is opened in an iframe … hence our need to ask you to download monthly_chronicler.html to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) to offer a new (“reveal”) piece of details/summary hosted “Yearly Report Calendar” functionality.

<?php

// quarter_hour_timer.php
// RJM Programming
// December, 2021

// iptc_make_tag() function by Thies C. Arntzen
function iptc_make_tag($rec, $data, $value) {
$length = strlen($value);
$retval = chr(0x1C) . chr($rec) . chr($data);

if($length < 0x8000)
{
$retval .= chr($length >> 8) . chr($length & 0xFF);
}
else
{
$retval .= chr(0x80) .
chr(0x04) .
chr(($length >> 24) & 0xFF) .
chr(($length >> 16) & 0xFF) .
chr(($length >> 8) & 0xFF) .
chr($length & 0xFF);
}

return $retval . $value;
}

if (isset($_GET['myta'])) {
$dru="HTTP://" . $_SERVER['SERVER_NAME'] . "" . str_replace("~","",str_replace(":443~","",str_replace(":80~","",(":" . $_SERVER['SERVER_PORT'] . "~")))) . "/";
$contis=str_replace('+',' ',urldecode($_GET['myta']));
//file_put_contents('xx.xx', $contis);
$myf='';
$backi='';
$cali='';
$taback='';
$bcontis="'" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $contis)))) . "'";
if (substr(($bcontis . ' '),0,3) == "' + ") { $bcontis=$bcontis.substr(3); }
if (substr((' ' . $bcontis),-3,3) == " + '") { $bcontis=$bcontis.substr(0,(-3 + strlen($bcontis))); }
foreach ($_GET as $name=>$val) {
if ($name != 'myta' && $val == '') {
//echo $name;
$myf=$name;
$taback=str_replace('-','_',str_replace('itd','tatd',$myf));
$backi=str_replace('-','_',str_replace('screen-','itd_',$myf));
$cali=str_replace('-','',str_replace('screen-','td',$myf));
$idcali=explode('-',explode('_',str_replace('screen-','td',str_replace('itd_','td',$myf)))[0])[0];


// Thanks to https://doc.bccnsoft.com/docs/php-docs-7-en/function.iptcembed.html

// Path to jpeg file
$path = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . str_replace('_','-',str_replace('itd_','screen-',$myf)) . '.jpg';
//file_put_contents('x.x',$path);

$capt = ""; // Thanks to https://www.php.net/manual/en/function.iptcparse.php
$size = getimagesize( $path, $info );
if (isset($info["APP13"])) {
//file_put_contents('xx.xx',$path);
if ($iptc = iptcparse( $info["APP13"] ) ) {
//file_put_contents('xxx.xxx',$path);
$capt = str_replace( "\000", "", $iptc["2#120"][0] );
//file_put_contents('xxxx.xxxx',$capt);
}
}
$bcontis="" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "";
$ccpre="<p onclick=this.innerHTML+=String.fromCharCode(60)+String.fromCharCode(98)+String.fromCharCode(114)+String.fromCharCode(62); style=background-color:orange;background-size:contain;background-image:linear-gradient(rgba(255,255,255,0.3),rgba(255,255,255,0.3)),URL(" . $dru . str_replace('_','-',str_replace('itd_','screen-',$myf)) . ".jpg" . "); title=" . substr(str_replace('td','p',$cali),-4,2) . ":" . substr(str_replace('td','p',$cali),-2,2) . "++ id=" . str_replace('td','p',$cali) . ">";
$ccpost="</p>";
$ccontis="<br><p style='background-color:orange; title='" . str_replace('td','p',$cali) . "' id=" . str_replace('td','p',$cali) . ">" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "<br>", str_replace("\r\n", "<br>", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "</p>";

//file_put_contents('xxxxx.xxxxx',$bcontis);
//file_put_contents('xxxxxx.xxxxxx',$taback . ' ... ' . $backi);
//file_put_contents('xxxxxxx.xxxxxxx',"parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "'; ");

}
if ($bcontis != "''") { echo "<html><body onload=\" parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "'; if (parent.document.getElementById('" . $idcali . "')) { var huhg='" . $ccpre . "' + parent.document.getElementById('" . $taback . "').value + '" . $ccpost . "'; while (huhg.indexOf(String.fromCharCode(10)) != -1) { huhg=huhg.replace(String.fromCharCode(10),'<br>'); } parent.document.getElementById('" . $idcali . "').innerHTML+=huhg; } \"></body></html>"; }
}
} else if (isset($_POST['myta'])) {
$dru="HTTP://" . $_SERVER['SERVER_NAME'] . "" . str_replace("~","",str_replace(":443~","",str_replace(":80~","",(":" . $_SERVER['SERVER_PORT'] . "~")))) . "/";
$contis=str_replace('+',' ',urldecode($_POST['myta']));
//file_put_contents('xx.xx', $contis);
$myf='';
$backi='';
$cali='';
$bcontis="'" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $contis)))) . "'";


$ccpre="<p onclick=this.innerHTML+=String.fromCharCode(60)+String.fromCharCode(98)+String.fromCharCode(114)+String.fromCharCode(62); style=background-color:orange;background-size:contain;background-image:linear-gradient(rgba(255,255,255,0.3),rgba(255,255,255,0.3)),URL(" . $dru . str_replace('_','-',str_replace('itd_','screen-',$myf)) . ".jpg" . "); title=" . substr(str_replace('td','p',$cali),-4,2) . ":" . substr(str_replace('td','p',$cali),-2,2) . "++ id=" . str_replace('td','p',$cali) . ">";
$ccpost="</p>";
$ccontis="<br><p style='background-color:orange; title='" . str_replace('td','p',$cali) . "' id=" . str_replace('td','p',$cali) . ">" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "<br>", str_replace("\r\n", "<br>", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "</p>";


if (substr(($bcontis . ' '),0,3) == "' + ") { $bcontis=$bcontis.substr(3); }
if (substr((' ' . $bcontis),-3,3) == " + '") { $bcontis=$bcontis.substr(0,(-3 + strlen($bcontis))); }
foreach ($_POST as $name=>$val) {
if ($name != 'myta') {
$myf=$name;
$backi=str_replace('-','_',str_replace('screen-','itd_',$myf));
$taback=str_replace('tatd','tatd_',substr(str_replace('-','',str_replace('_','',str_replace('itd','tatd',str_replace('screen','tatd',$myf)))),0,12)) . '_' . substr(str_replace('-','',str_replace('_','',str_replace('itd','tatd',str_replace('screen','tatd',$myf)))),-4,4);
$pback=str_replace('tatd','ip',$taback);
$cali=str_replace('-','',str_replace('screen-','td',$myf));
$idcali=explode('-',explode('_',str_replace('screen-','td',str_replace('itd_','td',$myf)))[0])[0];


// Thanks to https://doc.bccnsoft.com/docs/php-docs-7-en/function.iptcembed.html

// Path to jpeg file
$path = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . $myf . '.jpg';

//file_put_contents('x.x', $path);

// Set the IPTC tags
$iptc = array(
'2#120' => $contis,
'2#116' => 'Copyright 2021, RJM Programming'
);

// Convert the IPTC tags into binary code
$data = '';

foreach($iptc as $tag => $string) {
$tag = substr($tag, 2);
$data .= iptc_make_tag(2, $tag, $string);
}

// Embed the IPTC data
$content = iptcembed($data, $path);

// Write the new image data out to the file.
$fp = fopen($path, "wb");
fwrite($fp, $content);
fclose($fp);

}
echo "<html><body onload=\" parent.document.getElementById('" . $backi . "').title=" . $bcontis . "; if (parent.document.getElementById('" . $idcali . "')) { var huhg='" . $ccpre . "' + parent.document.getElementById('" . $taback . "').value + '" . $ccpost . "'; if (parent.document.getElementById('" . $pback . "')) { huhg=parent.document.getElementById('" . $taback . "').value; } while (huhg.indexOf(String.fromCharCode(10)) != -1) { huhg=huhg.replace(String.fromCharCode(10),'<br>'); } if (parent.document.getElementById('" . $pback . "')) { parent.document.getElementById('" . $pback . "').innerHTML=huhg; } else { parent.document.getElementById('" . $idcali . "').innerHTML+=huhg; } } \"></body></html>";
}
} else {
exec("/usr/sbin/screencapture -Cd -tjpg /Applications/MAMP/htdocs/screen-`date +\"%Y%m%d-%H%M\"`.jpg");
}
exit;

?>

And so, again, our changed quarter_hour_timer.html (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage, is helped out by a calendar integrationally changed quarter_hour_timer.php PHP (we ask you to download to MAMP‘s $_SERVER[‘DOCUMENT_ROOT’] “HTMLCSS” subfolder) for you to try out on your MAMP macOS environment.


Previous relevant Mac OS MAMP Timekeeping Web Application PHP Image Metadata Tutorial is shown below.

Mac OS MAMP Timekeeping Web Application PHP Image Metadata Tutorial

Mac OS MAMP Timekeeping Web Application PHP Image Metadata Tutorial

In our opinion, what would make the day before yesterday’s Mac OS MAMP Timekeeping Web Application PHP Intranet Tutorial “Timekeeping Web Application” cooler would be to add to the intelligence of the screen capture images, ahead of other data related improvements to come.

We’ve spoken in the past about Exif in that respect but PHP has Iptc image metadata functions we can call on …

  • iptcembed to embed new metadata into an existant image from those associated “caption” textarea elements we offer
  • iptcparse to extract old metadata from an existant image into those associated “caption” textarea elements we offer

This metadata can be like a database source we use moving forward on this project, meaning the one image data entity can suffice for both visual and textual usage purposes.

And so our changed quarter_hour_timer.html Timekeeping Web Application suited to macOS (or Mac OS X) “screencapture” command line usage, is helped out by a much more usefully changed quarter_hour_timer.php PHP …

<?php

// quarter_hour_timer.php
// RJM Programming
// December, 2021

// iptc_make_tag() function by Thies C. Arntzen
function iptc_make_tag($rec, $data, $value) {
$length = strlen($value);
$retval = chr(0x1C) . chr($rec) . chr($data);

if($length < 0x8000)
{
$retval .= chr($length >> 8) . chr($length & 0xFF);
}
else
{
$retval .= chr(0x80) .
chr(0x04) .
chr(($length >> 24) & 0xFF) .
chr(($length >> 16) & 0xFF) .
chr(($length >> 8) & 0xFF) .
chr($length & 0xFF);
}

return $retval . $value;
}

if (isset($_GET['myta'])) {
$contis=str_replace('+',' ',urldecode($_GET['myta']));
//file_put_contents('xx.xx', $contis);
$myf='';
$backi='';
$taback='';
$bcontis="'" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $contis)))) . "'";
if (substr(($bcontis . ' '),0,3) == "' + ") { $bcontis=$bcontis.substr(3); }
if (substr((' ' . $bcontis),-3,3) == " + '") { $bcontis=$bcontis.substr(0,(-3 + strlen($bcontis))); }
foreach ($_GET as $name=>$val) {
if ($name != 'myta' && $val == '') {
//echo $name;
$myf=$name;
$taback=str_replace('-','_',str_replace('itd','tatd',$myf));
$backi=str_replace('-','_',str_replace('screen-','itd_',$myf));

// Thanks to https://doc.bccnsoft.com/docs/php-docs-7-en/function.iptcembed.html

// Path to jpeg file
$path = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . str_replace('_','-',str_replace('itd_','screen-',$myf)) . '.jpg';
//file_put_contents('x.x',$path);

$capt = ""; // Thanks to https://www.php.net/manual/en/function.iptcparse.php
$size = getimagesize( $path, $info );
if (isset($info["APP13"])) {
//file_put_contents('xx.xx',$path);
if ($iptc = iptcparse( $info["APP13"] ) ) {
//file_put_contents('xxx.xxx',$path);
$capt = str_replace( "\000", "", $iptc["2#120"][0] );
//file_put_contents('xxxx.xxxx',$capt);
}
}
$bcontis="" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $capt)))) . "";
//file_put_contents('xxxxx.xxxxx',$bcontis);
//file_put_contents('xxxxxx.xxxxxx',$taback . ' ... ' . $backi);
//file_put_contents('xxxxxxx.xxxxxxx',"parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "'; ");

}
if ($bcontis != "''") { echo "<html><body onload=\" parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "'; \"><p>parent.document.getElementById('" . $backi . "').title='" . $bcontis . "'; parent.document.getElementById('" . $taback . "').value='" . $bcontis . "';</p></body></html>"; }
}
} else if (isset($_POST['myta'])) {
$contis=str_replace('+',' ',urldecode($_POST['myta']));
//file_put_contents('xx.xx', $contis);
$myf='';
$backi='';
$bcontis="'" . str_replace(chr(34), "' + String.fromCharCode(34) + '", str_replace("\n", "' + String.fromCharCode(10) + '", str_replace("\r\n", "' + String.fromCharCode(10) + '", str_replace("'", "' + String.fromCharCode(39) + '", $contis)))) . "'";
if (substr(($bcontis . ' '),0,3) == "' + ") { $bcontis=$bcontis.substr(3); }
if (substr((' ' . $bcontis),-3,3) == " + '") { $bcontis=$bcontis.substr(0,(-3 + strlen($bcontis))); }
foreach ($_POST as $name=>$val) {
if ($name != 'myta') {
$myf=$name;
$backi=str_replace('-','_',str_replace('screen-','itd_',$myf));

// Thanks to https://doc.bccnsoft.com/docs/php-docs-7-en/function.iptcembed.html

// Path to jpeg file
$path = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . $myf . '.jpg';

//file_put_contents('x.x', $path);

// Set the IPTC tags
$iptc = array(
'2#120' => $contis,
'2#116' => 'Copyright 2021, RJM Programming'
);

// Convert the IPTC tags into binary code
$data = '';

foreach($iptc as $tag => $string) {
$tag = substr($tag, 2);
$data .= iptc_make_tag(2, $tag, $string);
}

// Embed the IPTC data
$content = iptcembed($data, $path);

// Write the new image data out to the file.
$fp = fopen($path, "wb");
fwrite($fp, $content);
fclose($fp);

}
echo "<html><body onload=\" parent.document.getElementById('" . $backi . "').title=" . $bcontis . "; \"></body></html>";
}
} else {
exec("/usr/sbin/screencapture -Cd -tjpg /Applications/MAMP/htdocs/screen-`date +\"%Y%m%d-%H%M\"`.jpg");
}
exit;

?>


Previous relevant Mac OS X MAMP Timekeeping Web Application Email Tutorial is shown below.

Mac OS X MAMP Timekeeping Web Application Email Tutorial

Mac OS X MAMP Timekeeping Web Application Email Tutorial

The practicalities of yesterday’s (Mac OS X MAMP Timekeeping Web Application Primer Tutorial) timekeeping Mac OS X Web Application, left as they are, would leave you with a somewhat useful web application whose use is only for the here and now, but what if you want it to be more accountable? Well, that is when we, here, at RJM Programming, like to use that tried and trusted email form of communication.

Today’s email methods spurn the use of server-side intervention, at least for now. So what is available to us as tools, if we don’t include Ajax nor jQuery in that list? Well, we have, to our minds …

  • mailto links (get us to the email client) +
  • the body section of that email can have a clipboard image pasted into it, for which we can utilize HTML5 canvas element’s toDataURL() method, teamed up with a window.open popup window of the toDataURL image data, which can be selected and copied, optionally, by the user themselves, should they wish this to make their email more self explanatory

We last discussed this thinking with Canvas Annotation Email Attachment Clipboard Tutorial.

We rely on the crontab functionality, being as there is no server-side help, to create the image file, whose contents eventually go to make up the contents that can be selected and copied and pasted by the user into the body section of the email (and sent off to whosoever they feel like sending it too, as you have the full power of the email client available to you with the interaction you have with an actual email client program).

Here is the HTML and Javascript quarter_hour_timer.html which changed to cater for today’s email functionality in this way, and, as per the Stop Press from yesterday, we’ll also have a live run link here today.


Previous relevant Mac OS X MAMP Timekeeping Web Application Primer Tutorial is shown below.

Mac OS X MAMP Timekeeping Web Application Primer Tutorial

Mac OS X MAMP Timekeeping Web Application Primer Tutorial

Sometimes when you program, especially for administrative type functionality, there are useful programs to write, that are able to become web applications, but in a limited set of platforms. So it is today with our timekeeping web application that relies on …

  • Mac OS X operating system +
  • Existance of [/usr/sbin/]screencapture +
  • crontab active and editable via crontab -e +
  • One of …
    1. MAMP installed to, in our case, /Applications/MAMP/htdocs/ (as is mentioned in the relevant crontab background task that snapshots the user’s screen every quarter hour) that maps to the MAMP web application URL http://localhost:8888/ … or …
    2. crontab directory mention that corresponds to a URL call of our web application like for our Google Chrome example (where the directory below, used, could be a place of your choosing (that matches what is in your crontab task entry)) …

      file:///Applications/MAMP/htdocs/quarter_hour_timer.html?localplace=

      … or just, via the web browser’s File -> Open File menu …

      file:///Applications/MAMP/htdocs/quarter_hour_timer.html

… pretty restrictive, huh? … but pretty useful for our quarter hour timekeeping purposes today.

We want to have a web application that is running at the user’s discretion, and when first fired up, looks for outputs from crontab tasks above …


0,15,30,45 * * * * /usr/sbin/screencapture -Cd -tjpg /Applications/MAMP/htdocs/screen-`date +"\%Y\%m\%d-\%H\%M"`.jpg

… for the current day in question and if existant show …

  1. a date and time stamp +
  2. the snapshot of what you were doing at the quarter hour, that is clickable to make bigger for more in depth viewing +
  3. an HTML textarea element in which you can optionally type in more specifics about that quarter hour

So, as much as we like to think of Mac OS X Terminal application’s BSD (a unix derivative) operating system, as being a lot like Linux, there are some commands and usage that …

  • adds Mac OS X specific command line functionality to a Linux or unix base set of functionality, like for today’s screencapture command … and we’ve included another such example, below, with the command say featuring in Mac OS X Text to English Speech Primer Tutorial as shown below
  • changes switches on Linux or unix commands
  • won’t have some Linux or unix commands that other platforms do

In the great tradition of behoving … we behove … we behove thee quarter_hour_timer.html if you like, my liege. On this occasion you’ll have gleaned that there is no live run link, because the RJM Programming web server is not Mac OS X … so command line screencapture has no meaning for a CentOS web server’s operating system command line. You’ll see in the code that rather than use “Client Pre-emptive Iframe” concepts to check for existence of crontab screen capture images, we, instead use the onerror event for HTML img elements to check for non-existance.

Stop Press

Just noticed that, perhaps, after all, a live run from the RJM Programming website can make sense if you have a Mac OS X laptop, for instance, that is running that suggested crontab entry as explained in tutorial above. That type of live run managed to latch on to our local crontab screencaptures on my MacBook Pro.


Previous relevant Mac OS X Text to English Speech Primer Tutorial is shown below.

Mac OS X Text to English Speech Primer Tutorial

Mac OS X Text to English Speech Primer Tutorial

We’ve got a few new ideas today …

  1. Text to English Speech via Mac OS X’s command line say command used by PHP via exec to make say.php (which is useful as a download to a Mac OS X laptop using MAMP) which, today, does not have a live run because the web server of domain rjmprogramming.com.au is a CentOS Linux server … Linux equivalent of Mac OS X’s say? … read here
  2. Trying to present this brought up the usual movie production problem with iMovie overlaying the audio on top of the video (though you may want to try, and you could start reading with this link) versus QuickTime Player talent to catch both audio and video tracks (and that we ended up using), but not of the “screen goings on”, alas versus MPlayer OSX Extended which can play separately but not two tracks on top and doesn’t do any reconstituting … so …
  3. Improved on our inhouse Video/Audio synchronizing efforts by allowing audio_video.html supervisor (changed in this way) be able to be called to press one of its preconceived synchronization buttons onload which we do with (the newly added) Macbeth Act 1 Scene 1 … in a small celebration of the Bard … who, am thinking (in that Falstaff way), would have got a huge chuckle out of “anonymous” instead of “anon” during the Three Witches scene … we had to do something to say Happy Birthday

Along the way we tried filming the MacBook Pro with the iPad to a YouTube

… but weren’t happy with the audio quality, alas (too/two).

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.

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

Background Image Foreground Content Tutorial

Background Image Foreground Content Tutorial

Background Image Foreground Content Tutorial

Further to yesterday’s Background Image User Interaction Visibility Tutorial, regarding today’s work adding the possibility for foreground HTML div content via a combination of contenteditable=true and onblur event logics, you might be inclined to observe that this current web application is very …

back to front

… about which we would …

  1. not be insulted
  2. observe that any web application “worth its salt” will mainly be “worth its salt” because of the “back” parts … ie. the data parts and/or the background display components

We find, generally speaking, it is the “back” of the project of most enduring interest, though the “front” …

  • has the most impact
  • is the easiest to tweak

The contenteditable=true HTML element attribute is soooooooo useful. It makes what you think of as a display only innerHTML type of HTML element into a …

  • onblur event sensitive means by which such an element can take on a lot of the appealing qualities of HTML input type=text and/or textarea elements …
  • interplay of such an element’s innerText (containing the < and > HTML, kind of counterintuitively) versus the innerHTML (containing the HTML entities &lt; and &gt;) in the onblur event contenteditable=true (HTML element like div) scenario

It’s small disadvantage is that the user may not be aware the foreground content via contenteditable=true and onblur event logics is there, available, and so we add a new User Interaction Menu dropdown option where, for the first time we can remember …

  • we don’t use a Javascript prompt window to ask, but, rather …
  • a window.open (seen on the other side as window.opener) new incarnation of our codebase …

    function askcont() {
    if (wo) {
    if (!wo.closed) {
    wo.close();
    wo=null;
    }
    }
    wo=window.open('./dappled_light.html?justtextarea=y', '_blank', 'top=100,left=100,width=600,height=600');
    wo.document.write('<textarea id=myta style="width:100%;height:100%;" onblur="window.opener.primarycontent(window.opener.document.getElementsByTagName(' + "'div'" + ')[0], this.value);" placeholder="' + wopl + '"></textarea>');
    }

    function primarycontent(divo, defid) {
    var dvih='';
    dvih=divo.innerText;
    if (defid != '') {
    if (defid.replace(' ','') == '') {
    dvih='';
    divo.innerHTML='';
    return '';
    } else if (defid != defid.trim()) {
    while (defid.indexOf(String.fromCharCode(10)) != -1) {
    defid=defid.replace(String.fromCharCode(10),'<br>');
    }
    if (defid.indexOf('<') != -1) {
    divo.innerHTML=divo.innerHTML + defid.trim().replace(/\<\;/g,'<').replace(/\>\;/g,'>');
    return '';
    } else {
    divo.innerHTML=divo.innerHTML + defid.trim();
    return '';
    }
    } else {
    while (defid.indexOf(String.fromCharCode(10)) != -1) {
    defid=defid.replace(String.fromCharCode(10),'<br>');
    }
    if (defid.indexOf('<') != -1) {
    divo.innerHTML=defid.replace(/\<\;/g,'<').replace(/\>\;/g,'>');
    return '';
    } else {
    divo.innerHTML=defid;
    return '';
    }
    }
    }
    if (('' + divo.innerText).replace(String.fromCharCode(10),'<').replace(' ','<').indexOf('<') != -1 && ('' + divo.innerText).replace(String.fromCharCode(10),'>').replace(' ','>').indexOf('>') != -1) {
    while (dvih.indexOf(String.fromCharCode(10)) != -1) {
    dvih=dvih.replace(String.fromCharCode(10), '<br>');
    }
    divo.innerHTML=dvih;
    } else {
    divo.innerHTML='';
    }
    return '';
    }

    function secondarycontent(divo, defid) {
    var dvih='';
    dvih=divo.innerText;
    if (defid != '') {
    if (defid.replace(' ','') == '') {
    dvih='';
    divo.innerHTML='';
    return '';
    } else if (defid != defid.trim()) {
    while (defid.indexOf(String.fromCharCode(10)) != -1) {
    defid=defid.replace(String.fromCharCode(10),'<br>');
    }
    if (defid.indexOf('<') != -1) {
    divo.innerHTML=divo.innerHTML + defid.trim().replace(/\<\;/g,'<').replace(/\>\;/g,'>');
    return '';
    } else {
    divo.innerHTML=divo.innerHTML + defid.trim();
    return '';
    }
    } else {
    while (defid.indexOf(String.fromCharCode(10)) != -1) {
    defid=defid.replace(String.fromCharCode(10),'<br>');
    }
    if (defid.indexOf('<') != -1) {
    divo.innerHTML=defid.replace(/\<\;/g,'<').replace(/\>\;/g,'>');
    return '';
    } else {
    divo.innerHTML=defid;
    return '';
    }
    }
    }
    if (('' + divo.innerText).replace(String.fromCharCode(10),'<').replace(' ','<').indexOf('<') != -1 && ('' + divo.innerText).replace(String.fromCharCode(10),'>').replace(' ','>').indexOf('>') != -1) {
    while (dvih.indexOf(String.fromCharCode(10)) != -1) {
    dvih=dvih.replace(String.fromCharCode(10), '<br>');
    }
    divo.innerHTML=dvih;
    } else {
    divo.innerHTML='';
    }
    return '';
    }

    … just presenting a textarea element which can be filled with user added foreground HTML and/or text data as that HTML div “innards” content

… in an eighth draft dappled_light.html Dappled Light web application.


Previous relevant Background Image User Interaction Visibility Tutorial is shown below.

Background Image User Interaction Visibility Tutorial

Background Image User Interaction Visibility Tutorial

We have a purpose around here of writing code with a view, when generic enough, to allow newbies a dynamic way to learn, and we do learn stuff ourselves performing these projects … so, thanks. That’s all fine and good, but then we wonder after a while if there are “content creators” not interested in the user interaction menu parts of yesterday’s Background Image Data URI Animation Tutorial‘s Dappled Light web application (after using them to get to a certain point)? Are such users being put off because up until now there was no way to turn off the user interaction menu occasional displays?

Just in cases we’ve thought about available “unused, so far functionality layers” we could apply for non-mobile and mobile users alike and came up with …

Concept Non-mobile applicability Mobile applicability
Double click (anywhere outside the interaction menu)
Toggles user interaction menu visibility status
Keyboard W
Makes user interaction menu invisible in subsequent cycles
✔ (anywhere) In menu textboxes
(tabbed out of)
Keyboard M
Makes user interaction menu visible in subsequent cycles
✔ (anywhere)

… for mobile keyboard relying on textbox onblur event logics (also working for non-mobile), and for non-mobile anywhere, a generic document.body onkeydown event logic as per …


function okd(evt) {
var char = evt.which || evt.keyCode;
switch (char) {
case 77: // M
titlenuance('block'); //alert('m detected');
break;

case 87: // W
titlenuance('none'); //alert('w detected');
break;

default:
break;
}
return true;
}

function titlenuance(inidc) {
if (inidc == 'none') {
if (document.title.indexOf('Dappled Light') != -1) {
document.title=String.fromCodePoint(10060) + ' Dappled Light' + document.title.split('Dappled Light')[1];
}
document.getElementsByTagName('div')[0].title=document.getElementsByTagName('div')[0].title.replace('(as the default at start, and currently)', '(as the default at start, but not currently)').replace('(as the default at start)', '(as the default at start, but not currently)');
document.getElementById('dstyles').innerHTML+='<style> body { background-color: rgb(240,240,240) !important; </style>';
} else {
if (document.title.indexOf('Dappled Light') != -1) {
document.title=String.fromCodePoint(10004) + ' Dappled Light' + document.title.split('Dappled Light')[1];
}
document.getElementsByTagName('div')[0].title=document.getElementsByTagName('div')[0].title.replace('(as the default at start, but not currently)', '(as the default at start, and currently)').replace('(as the default at start)', '(as the default at start, and currently)');
document.getElementById('dstyles').innerHTML+='<style> body { background-color: rgb(255,255,255) !important; </style>';
}
toorig=document.getElementsByTagName('div')[0].title;
seeingisbelieving=inidc;
document.getElementById('mc').setAttribute('data-sib', inidc);
return inidc;
}

… as ways to facilitate such user interaction control of this web application’s workings. As you might have surmised, especially pertinent for mobile users who do not see on hover HTML element titles …

  1. relevant information is added into first textbox marquee style placeholder wording …
  2. document.title (ie. wording in web browser tab) is prefixed by ❌ (if menu flagged as invisible) and the document.body background colour is darkened a little, else menu is visible (including when prefixed by ✔) and the document.body background colour is made to be white
  3. non-mobile users will see status in the document.body’s first div’s on hover title wording

… in a seventh draft dappled_light.html Dappled Light web application.


Previous relevant Background Image Data URI Sharing Long Term Recall Tutorial is shown below.

Background Image Data URI Sharing Long Term Recall Tutorial

Background Image Data URI Sharing Long Term Recall Tutorial

The implication of Background Image Data URI Sharing Tutorial‘s …

… effectively avoiding the need to ever need to use PHP file_get_contents to retrieve that /tmp/ content, which we found was quite a harrowing thing to try?!

… panning out to be a bug at our end (sorrrrrrrry), opens the door, today, to try out an idea we had regarding an email or SMS recipient’s “lived experience” regarding our Dappled Image Background Image Sharing web application when data URIs were involved with the originator piecing together their creation ahead of sending it to their chosen recipient.

You may have been reading this thread of postings earlier, and know we started using Document Root soft links, as per …

… meaning that our PHP helping legend_via_map.php changing in this way now starts creating Document Root soft links (as can happen on Linux and Unix and macOS) pointing back to the /tmp/ folder content, no longer a base64 data URI (as was the case with the Media YouTube Interfacer Interspersing Image Text Tutorial project style of legend_via_map.php interfacing usage) but actual image file contents

… to get around errors that could happen as the originator shaped to email or SMS a creation involving image data URI(s). The thing is, though, that our design only stores the /tmp/ (web server) content underpinning of the Document Root soft link for a couple of days in legend_via_map.php changing in this way

<?php

if (isset($_GET['getthisback']) || isset($_GET['andcleanup'])) {
if (isset($_GET['getthisback'])) {
$fnm=str_replace('+',' ',urldecode($_GET['getthisback']));
if (strpos($fnm, 'rjmprogramming.com.au/bigmedia_') !== false) {
//file_put_contents('xv.xv', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt');
if (!file_exists('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt')) {
//file_put_contents('xv0.xv0', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt');
echo "<html><body>Not Found is " . $fnm . "</body></html>";
} else {
//file_put_contents('xv1.xv1', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt vs ' . 'http://' . explode('//', $fnm)[1]);
$myfile = fopen('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt', "r") or die("Unable to open file!");
$img_file=fread($myfile,filesize('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt'));
fclose($myfile);
//file_put_contents('xv2.xv2', strlen($img_file) . ' /tmp/' . explode('.txt', basename($fnm))[0] . '.txt vs ' . 'http://' . explode('//', $fnm)[1]);
echo "<html><body><p id=pid>data:image/" . explode('.', $fnm)[-1 + sizeof(explode('.', $fnm))] . ';base64,' . base64_encode($img_file) . "</p></body></html>";
}
} else {
if (!file_exists($fnm)) {
echo "<html><body>Not found is " . $fnm . "</body></html>";
} else {
$myfile = fopen($fnm, "r") or die("Unable to open file!");
$img_file=fread($myfile,filesize($fnm));
fclose($myfile);
echo "<html><body><p id=pid>" . $img_file . "</p></body></html>";
}
}
}
if (isset($_GET['andcleanup'])) {
foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
$filemtime = filemtime($tfl);
if (time() - $filemtime >= 172800) {
unlink($tfl);
}
}
}

exit;
}

?>

… a period of time we consider generous for a recipient to attend to the communication’s link clicking, as interested. But what if that email or SMS link’s content has data URI content which a user may want to recall some days later? Well, we now add a new dropdown option …


Cache Data URIs (then Bookmark for later viewing)

… which instigates this Javascript when selecting …


alert('We are redirecting you to new webpage that is good to Bookmark (after a few seconds) for future reference, else image data URIs will be forgotten after a couple of days.');
location.href=document.URL.replace('cacheit=', 'cacheit=Y');

… and then accessing that debugged iframe (hosting the call to our helper PHP talked about above) onload event Javascript code …


function checkthis(iois) {
if (iois.src.indexOf('About_Us.htm') == -1) {
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }

if (aconto.body.innerHTML.toLowerCase().indexOf('not found is') != -1) {
aconto=aconto;
} else if (aconto.body.innerHTML.indexOf('</p>') != -1) {
dumappings.push(aconto.body.innerHTML.split('</p>')[0].split('>')[eval(-1 + aconto.body.innerHTML.split('</p>')[0].split('>').length)]);
if (numds == 2) {
duin=duin.replace(encodeURIComponent(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)])), encodeURIComponent(encodeURIComponent(dumappings[eval(-1 + dumappings.length)])));
} else {
while (duin.indexOf(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)])) != -1) {
duin=duin.replace(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)]), encodeURIComponent(dumappings[eval(-1 + dumappings.length)]));
}
while (duin.indexOf((dutmpfiles[eval(-1 + dutmpfiles.length)])) != -1) {
duin=duin.replace((dutmpfiles[eval(-1 + dutmpfiles.length)]), (dumappings[eval(-1 + dumappings.length)]));
}
}

}

}
}
}

… we are back with “originator data URI(s)” finding their way back to “recipient webpage data URI referencing background image” webpage data.

Then, should a recipient want to have the best chance of storing this scenario days out into the future we think it can work if …

  • the recipient just about immediately Bookmarks this webpage … perhaps supplying a better name (though we add document.URL length and current time snapshots to the webpage document title) …
  • later, for that recipient using that same web browser, we’re pretty sure within that two days of server retainment, no worries … and …
  • after those two days, even so (and we’re waiting ourselves, for two days to retest), we’re thinking should the recipient recall their scenario via (something like the Google Chrome) …

    Bookmarks -> Bookmark Manager -> Other Bookmarks -> (navigate to bottom bookmark named like ...) Dappled Light (11032 byte URL at Sun Apr 27 2025 14:07:35 GMT+1000 (Australian Eastern Standard Time)) - RJM Programming - April, 2025 ... thanks to https://stackoverflow.com/questions/20039765/how-to-apply-a-css-filter-to-a-background-image

    … that the web browser Cache will help out the recipient get back their background image data on the condition they haven’t cleared their web browser cache … that is

You can try emailing or SMSing to a recipient yourself with these new ideas in a fifth draft dappled_light.html Dappled Light web application.


Previous relevant Background Image Data URI Sharing Tutorial is shown below.

Background Image Data URI Sharing Tutorial

Background Image Data URI Sharing Tutorial

In yesterday’s Background Image Multiple Substances Tutorial we ended up with …

Email and SMS can fail when “substances” are data URIs. We see it as food for thought not attended to today.

… and today, we’re back with a solution involving …

  • for the originator (asking for a data URI into the mix of their creation) we’re now calling our helper PHP via Ajax (with a new twist)

    var zhr=null, zform=null;
    var dumappings=[], dutmpfiles=[];
    var duin='', numds=0;

    function nodu(inida) { // used as a wrapper before the email or SMS is sent off
    var outida=inida;
    for (var ia=0; ia<dumappings.length; ia++) {
    while (outida.indexOf(dumappings[ia]) != -1) {
    outida=outida.replace(dumappings[ia], dutmpfiles[ia]);
    }
    }
    return outida;
    }


    function showStuff() {
    if (zhr != null) {
    if (zhr.readyState == 4) {
    if (zhr.status == 200) {
    if (zhr.responseText.indexOf('</p>') != -1) {
    dutmpfiles.push(zhr.responseText.split('</p>')[0].split('>')[eval(-1 + zhr.responseText.split('</p>')[0].split('>').length)]);
    }
    zhr=null;
    }
    }
    }
    }


    function ajaxit(indu) {
    var urlis='//www.rjmprogramming.com.au/HTMLCSS/legend_via_map.php';
    zhr = new XMLHttpRequest();
    zform=new FormData();
    zform.append('urlbig', indu);
    dumappings.push(indu);
    zform.append('subject', '');
    zform.append('to', '');
    zform.append('cc', '');
    zform.append('bcc', '');
    zform.append('url', '');
    if (indu.indexOf('data:') == 0) {
    zform.append('softlink', indu.split('/')[1].split(';')[0].split(',')[0]);
    }

    zhr.open('post', urlis, true);
    zhr.onreadystatechange = showStuff;
    zhr.send(zform);
    }

    … meaning that our PHP helping legend_via_map.php changing in this way now starts creating Document Root soft links (as can happen on Linux and Unix and macOS) pointing back to the /tmp/ folder content, no longer a base64 data URI (as was the case with the Media YouTube Interfacer Interspersing Image Text Tutorial project style of legend_via_map.php interfacing usage) but actual image file contents
    <?php

    if ($_POST['to'] == '' && $_POST['subject'] == '' && $_POST['urlbig'] != '' && isset($_POST['bcc']) && isset($_POST['cc'])) {
    $vslook='';
    $vsind='0';
    if (strpos(('~' . $_POST['urlbig']), '~data') !== false) {
    if ($_POST['bcc'] == '') {
    foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
    if ($vslook == '') {
    $vslook=str_replace(' ','+',urldecode($_POST['urlbig']));
    }
    $versusind=explode('.', explode('bigmedia_', $tfl)[1])[0];
    if (isset($_POST['softlink']) && strpos($vslook, ';base64,') !== false) {
    if (file_get_contents($tfl) == base64_decode( explode(';base64,', $vslook)[1] )) {
    echo "<html><body><p id=pid style=display:none;>//www.rjmprogramming.com.au/" . basename($tfl) . "." . $_POST['softlink'] . "</p></body></html>";
    exit;
    }
    } else
    if (file_get_contents($tfl) == $vslook) {
    echo "<html><body><p id=pid style=display:none;>" . $tfl . "</p></body></html>";
    exit;
    }
    if (strlen($versusind) < strlen($vsind)) {
    $vsind=$vsind;
    } else if (strlen($versusind) > strlen($vsind)) {
    $vsind='' . (1 + intval($versusind));
    } else if ($versusind >= $vsind) {
    $vsind='' . (1 + intval($versusind));
    }
    $filemtime = filemtime($tfl);
    if (time() - $filemtime >= 172800) {
    unlink($tfl);
    }
    }
    if (isset($_POST['softlink'])) {
    file_put_contents('/tmp/bigmedia_' . $vsind . '.txt', base64_decode( explode(';base64,', str_replace(' ','+',urldecode($_POST['urlbig'])))[1] ) );
    if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink'])) {
    unlink($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink']);
    }
    exec('ln -s /tmp/bigmedia_' . $vsind . '.txt ' . $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink']);
    echo "<html><body><p id=pid style=display:none;>//www.rjmprogramming.com.au/bigmedia_" . $vsind . ".txt." . $_POST['softlink'] . "</p></body></html>";
    } else {

    file_put_contents('/tmp/bigmedia_' . $vsind . '.txt', str_replace(' ','+',urldecode($_POST['urlbig'])));
    echo "<html><body><p id=pid style=display:none;>/tmp/bigmedia_" . $vsind . ".txt</p></body></html>";
    }
    } else {
    if (strpos(strtolower($_POST['urlbig'] . '~'), ('%e2%80%a6~')) !== false || strpos(strtolower(urldecode($_POST['urlbig']) . '~'), (urldecode('%e2%80%a6') . '~')) !== false || 1 == 1) {
    if (file_exists('/tmp/bigmedia_' . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . '.txt')) {
    if ($_POST['cc'] == '1') {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    } else if (strlen($_POST['cc']) <= 1) {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    } else {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    }
    } else {
    foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
    if ($vslook == '') {
    $vslook=str_replace(' ','+',urldecode($_POST['urlbig']));
    }
    $thislook=file_get_contents($tfl);
    if (strpos($thislook, substr($vslook,0,(-13 + strlen($vslook)))) !== false) {
    if ($_POST['cc'] == '1') {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . $thislook . "'; parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    } else if (strlen($_POST['cc']) <= 1) {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    } else {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig0').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    }
    }
    $filemtime = filemtime($tfl);
    if (time() - $filemtime >= 172800) {
    unlink($tfl);
    }
    }
    }
    }
    }
    }
    exit;
    }

    ?>
    … effectively avoiding the need to ever need to use PHP file_get_contents to retrieve that /tmp/ content, which we found was quite a harrowing thing to try?!
  • for the receiver clicking an email or SMS link it used to be we’d map /tmp/*.txt mentions back to a data URI but now that is not needed anymore … phew!

You can try for yourself these new ideas in the fourth draft dappled_light.html Dappled Light web application.

Did you know?

We all benefit by building on what has been established before. We like it when “it feels like proof” trying something new, and verifying for yourself something you “were pretty sure was the case”. So it was today, for us, proving with a soft link usage that the mimetype assumed comes from the
ln -s [sourceFile] [targetFile]‘s [targetFile] very last file extension rather than any reference to [sourceFile] or it’s extension, and that the way you name the [sourceFile] does not have to reflect, file extension wise, that data that is in [sourceFile] necessarily.


Previous relevant Background Image Multiple Substances Tutorial is shown below.

Background Image Multiple Substances Tutorial

Background Image Multiple Substances Tutorial

Onto yesterday’s Background Image Substance Tutorial‘s work, today we allow for more CSS styling …

… as value adding propositions. To make the idea of multiple background images work we have to control …

  • a comma separated list of image “substances” for a CSS styling background: url([backgroundSubstance1]),url([backgroundSubstance2]) !important etcetera style of clause … to which we like to embellish via …
  • background-position and background-repeat … eg. background: url([backgroundSubstance1]) top left no-repeat,url([backgroundSubstance2]) bottom right no-repeat !important; … gets you so far, but to allow for …
  • opacity we prefix … eg. background: linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url([backgroundSubstance1]) top left no-repeat,linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url([backgroundSubstance2]) bottom right no-repeat !important; … the application of which is handled by the Javascript below, so as far as …
  • background-size goes we need Javascript to help out …

    var firsturl='//www.rjmprogramming.com.au/dappled_light.jpg', lastmultpos='', firstmultpos='top left', lasturl='', numb=2, actnumb=1;
    var prebrest=' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px ';
    var brest=' ' + firstmultpos + ' no-repeat';
    var blist='', bposlist='', bcomblist='';


    function dosize(dc) {
    var suffdc='';
    numb=2;
    while (actnumb > eval(numb * numb)) {
    numb++;
    }
    for (var ij=0; ij<actnumb; ij++) {
    if (suffdc == '') {
    suffdc=' !important; } .background-image { background-size: ' + ' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px';
    } else {
    suffdc+=',' + ' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px';
    }
    }
    return dc.replace(/url\(/g, 'linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url(') + suffdc;
    }

… in the third draft dappled_light.html Dappled Light web application.

Email and SMS can fail when “substances” are data URIs. We see it as food for thought not attended to today.


Previous relevant Background Image Substance Tutorial is shown below.

Background Image Substance Tutorial

Background Image Substance Tutorial

Yesterday’s Background Image CSS Primer Tutorial discussed …

  • style … but there’s also …
  • substance

… (ie. the image data source) to consider, embellishing yesterday’s …

an image

… break down of “substance” measures, as of and so yesterday.

We’re allowing for …

  • emoji 📁 (to 📂 and back) means by which user can browse for a local image file …

    var absare=[], iabs=0, kabs=0, jabs=0, acount=0, arwo=null,

    function arlook() { // via setInterval(arlook, 2000);
    if (arwo) {
    absare=arwo.document.getElementsByTagName('img');
    for (iabs=0; iabs<absare.length; iabs++) {
    if (('' + absare[iabs].id).indexOf('gb') == 0) {
    if (document.getElementById('myaudios').innerHTML.indexOf(absare[iabs].src) == -1) { // && absare[iabs].outerHTML.indexOf(' data-done') == -1) {
    document.getElementById('myaudios').innerHTML+=absare[iabs].outerHTML.replace('gb','gb' + acount).replace("<img ","<img style=display:none; data-duration=0 onloadedmetadata=\"this.setAttribute('data-duration','' + this.duration);\" ") + '<br>';
    document.getElementsByTagName('div')[0].style.backgroundImage='url(' + absare[iabs].src + ')';
    acount++;
    document.getElementById('alocal').innerHTML='📁';
    }
    }
    }
    }
    }

    … resolved to a data URI
  • first textbox means of image URL via …
    1. relative URL (to https://www.rjmprogramming.com.au that is) … or …
    2. absolute URL … or …
    3. data URI (have you ever noticed how Google Image searches of a Clip Art “Copy Image address” link so often results in such a data URI?)

… means by which a user can change their background image data source of display in the second draft dappled_light.html Dappled Light web application.

Note, too, with these changes, with all the functionality the first textbox has now, in order to make this information better disseminated for mobile users, we introduced a marquee-like “Eat at Joe’s” arrangement for it …


var origpl='', iorigpos=0, two=2;

function eatatjoes() { // via setInterval(eatatjoes, 100);
var atst='';
iorigpos+=two;
if (iorigpos >= eval('' + document.getElementById('mynum').placeholder.length)) {
iorigpos=0;
document.getElementById('mynum').placeholder=origpl;
} else {
atst=origpl.substring(0,iorigpos);
document.getElementById('mynum').placeholder=origpl.substring(iorigpos) + atst;
}
}


Previous relevant Background Image CSS Primer Tutorial is shown below.

Background Image CSS Primer Tutorial

Background Image CSS Primer Tutorial

There’s very little you miss out on, and a whole lot to gain, treating …

  • image data as one or more background images (to some other HTML element) … versus …
  • image data as one or more HTML img element(s)

For starters there are all the advantages involved with two webpage contributors stacked onto each other, both …

  • contributing to the display, as required … and …
  • able to be dynamically adjusted, in our favourite way, via Javascript DOM (or even serverside PHP ahead of all that clientside work)

… with background images, as we talked about with Multiple Background Image Blockquote Tutorial.

Today, the approach is CSS “hands on”. We select an image in this “first draft” dappled_light.html and load it up at the web server, using it as a background image, for an HTML div …


<style>
.background-image {
background-image: url('//www.rjmprogramming.com.au/dappled_light.jpg');
background-repeat: no-repeat;
background-size: contain;
}
</style>

… rather than document.body …


<div title='' class="background-image" style="width:100%;height:100%;"></div>

… via the great advice from this webpage.

From there on, our web application relies on how Javascript DOM can add HTML style element contributions into any old existing HTML element …


<div id=dstyles></div>

… dynamically to achieve dynamic display changes. Probably not needed, but makes us feel better coming back from a hashtag based URL from an email or SMS link is to add to the dynamic CSS clauses …


!important

Other than that, all pretty straightforward, and if working, can quickly allow a user to achieve a look vastly different to how they started, in a short time, and learn some CSS styling, perhaps, along the way.


Previous relevant Multiple Background Image Blockquote Tutorial is shown below.

Multiple Background Image Blockquote Tutorial

Multiple Background Image Blockquote Tutorial

Yesterday’s tutorial called Multiple Background Image Primer Tutorial, as shown below, made use of multiple background images. Today we find another use for them.

Today we offer an idea for styling of the HTML blockquote element (at this WordPress blog, for example).

We use separate background images for the opening and closing quote background images we put into play, and before we go further, we must thank the great CSS-Tricks website for this idea which was modified a little for our circumstances.

Think it is good to draw attention to the blockquote because it is usually used when important information is being imparted, and because that information is coming from a source offsite.

This multiple background image idea has great application for some of the “overlay” ideas that web designers often want to put into play. As far as this WordPress blog goes, its header.php changed as per the bold code below …


<style>
.
.
.

blockquote {
display: block;
padding: 18px;
border-top: 1px solid #e1cc89;
border-bottom: 1px solid #e1cc89;
margin: 5px;
text-indent: 4px;
background: url('closequote1.gif') bottom right no-repeat,url('openquote1.gif') top left no-repeat;
background-color: #faebbc;
}
blockquote p {
display: block;
padding: 18px;
margin: 5px;
text-indent: 4px;
background: url('closequote1.gif') bottom right no-repeat,url('openquote1.gif') top left no-repeat;
background-color: #faebbc;
}

.
.
.
</style>

Hope this tutorial is useful for you, or somebody with whom you want to share the information, and will leave you with an example, here, at this blog … How do I love thee? Let me count the ways. (Sonnet 43) by Elizabeth Barrett Browning

How do I love thee? Let me count the ways.
I love thee to the depth and breadth and height
My soul can reach, when feeling out of sight
For the ends of Being and ideal Grace.
I love thee to the level of everyday’s
Most quiet need, by sun and candle-light.
I love thee freely, as men strive for Right;
I love thee purely, as they turn from Praise.
I love thee with the passion put to use
In my old griefs, and with my childhood’s faith.
I love thee with a love I seemed to lose
With my lost saints – I love thee with the breath,
Smiles, tears, of all my life! – and, if God choose,
I shall but love thee better after death.


Previous relevant Multiple Background Image Primer Tutorial is shown below.

Multiple Background Image Primer Tutorial

Multiple Background Image Primer Tutorial

The last time we talked about the PHP web application called “Learning Programming” at this blog was with regard to some software integration that linked the “Learning Programming” web and (Android (at Google Play)) mobile application with this Blog web application with Xcode Learning Programming Blog Course Cookies Tutorial as shown below.

Today we do a bit of CSS working on the “Learning Programming” web and (Android) mobile application to add interest to the top functional area. Firstly thought of doing clipart or real photography to do a diploma border idea, but found that with the latter the mix of realia with stark web functionality was a bit jarring, and, on a first look, didn’t gel with any of the free clip art border image ideas out there, so plumped for a background image to the HTML table element involved, and realized, working with Paintbrush PNG image opacity (before it needs the CSS approach to opacity), that it would be okay to hive off that first image another one with a bit of transparent design to add a hint of educational paperwork to the project. Of course, an expert in graphic design would be throwing many more ideas at this, and implementing a great result, but am, today, showing you how multiple background images can be quite effective and refreshing … aaaaahhhhh.

So the Before Before vs After After infomercial today had these steps, roughly:

  • Show Before “Learning Programming” in Firefox web browser Before
  • Use Firebug to examine “Learning Programming” Firebug
  • Use Mac Grab application’s Selection tool to grab one for one copy of that area of webpage One for one
  • Use (Mac) Paintbrush application to:
    • Make transparent rectangle under web functionality of interest (with the HTML td element)
    • Save this image and make a copy
    • With the copy make an opaque thick blue border inside the rectangle of above
    • Draw in thinner paperwork/stationery lines
    • Give a slight 3d look by infilling those lines with a cyan 70% opacity rudimentary shadowing
    • Make all the orange areas transparent using the paintcan with a fully transparent colour selected
    • Save the second image
    • Paintbrush 1Paintbrush 2Paintbrush 3Paintbrush 4
  • Copy the images over to the website
  • Adjust “Learning Programming” PHP to change (the underlying HTML) as per bold bits below

    <style>
    #wrapperold h1{
    font:normal 24pt Arial;
    color:#FFFFFF;
    text-shadow: 0 1px 0 #ccc,
    0 2px 0 #c9c9c9,
    0 3px 0 #bbb,
    0 4px 0 #b9b9b9,
    0 5px 0 #aaa,
    0 6px 1px rgba(0,0,0,.1),
    0 0 5px rgba(0,0,0,.1),
    0 1px 3px rgba(0,0,0,.3),
    0 3px 5px rgba(0,0,0,.2),
    0 5px 10px rgba(0,0,0,.25),
    0 10px 10px rgba(0,0,0,.2),
    0 20px 20px rgba(0,0,0,.15);
    }

    #thehead {
    background: url('lp_background.png'),url('lp_background2.png') no-repeat;
    }

    </style>
  • Show After “Learning Programming” in Firefox web browser After and see it as a live run
  • Have a ham sandwich with rhubarb and vegemite followed by a lemon curry chaser

Why no Gimp? Good question. It’s a public holiday hereabouts, and well, Gimp’s off to Bondi Beach today! Where’s Gimp?

Am hoping you give multiple background images a go one day should it suit your porpoise purpose … the heat’s getting to moi me.


Previous relevant Xcode Learning Programming Blog Course Cookies Tutorial is shown below.

Xcode Learning Programming Blog Course Cookies Tutorial

Xcode Learning Programming Blog Course Cookies Tutorial

Today we continue to make use of the ideas from two previous tutorials called Xcode iOS Dynamic UIButton Primer Tutorial as below and Xcode iOS Mobile Project Exporting Primer Tutorial as shown way below, covering the Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue”) to create an iOS mobile app for our Learning Programming idea extended to include the option of Blog Course Postings, and using dynamic UIButton to …

  1. show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

… but this time we tidy up some loose ends such as …

  • fixing a lack of functionality within the iOS mobile app’s UIWebView contents cookie processing regarding the “last” course blog posting used, by setting up our own “Clayton’s” cookies (ie. we use PHP to simulate cookies without there being cookies – which don’t always work in UIWebView without some consideration … another approach is shown with this link)
  • fixing an annoying feature of the work whereby with mobile apps any scrolling jumps are quite annoying, and we stop this happening for mobile platforms
  • adding an extra link to allow navigation to the top of the blog course posting once nearing the bottom, especially as this can represent a lot of scrolling on occasions and because once you are down the bottom it would be good to also see what you have just viewed in some way shape or form (issues like this are considerations for the UX area of knowledge)

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small red circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code ) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”). By the way, the pink circle shows a new web page link (not the app this time) to link back to the mobile app from the web page iframe element and the orange circle shows the “Last” (Blog Course Posting) link which, in this mobile scenario, on an iPad, would use our PHP “Clayton’s” cookies system.

We test the new changes deployed on a real iPad device today, the idea of which is more than somewhat verging on great, as you can’t rely on simulators forever (by the way, with iOS 8 simulators we had problems and we needed to consult with this link … where you may notice that we ended up reverting to iOS version 7.1 simulators … thanks), though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable PHP programming source code for an iOS Web App’s UIWebView’s underlying content, that is used when the platform is a mobile one, while the pre-existant coursecookies.html is still okay for non-mobile platforms which still use real cookies:

… and there were changes needed for PHP code in wp-content/themes/twentyten/header.php (the bold parts of which are particularly relevant to the last modifications) because it establishes the header Javascript and two sections of code are involved …


var ourck=location.search.split('ck=')[1] ? location.search.split('ck=')[1].split('&')[0] : '';
var ourpp=location.search.split('pp=')[1] ? location.search.split('pp=')[1].split('&')[0] : '';
var ourpn=location.search.split('pn=')[1] ? location.search.split('pn=')[1].split('&')[0] : '';
var ourpage=location.search.split('page_id=')[1] ? location.search.split('page_id=')[1].split('&')[0] : '';
var ourp=location.search.split('p=')[1] ? location.search.split('p=')[1].split('&')[0] : '';
var ourcourseurl='';
var ourcoursetitle='';

var ua = navigator.userAgent;
var isiPad = /iPad/i.test(ua) || /iPhone OS 3_1_2/i.test(ua) || /Android/i.test(ua) || /iPhone OS 3_2_2/i.test(ua);

if (isiPad) {
<?php
//echo "n alert('*" . $_SERVER['REQUEST_URI'] . "*'); n";
if (strpos(($_SERVER['REQUEST_URI'] . "*"), "?p*") !== false) {
//echo "n alert('" . $_SERVER['QUERY_STRING'] . "'); n";

$cstuffis = "";

$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
if(preg_match('/(chromium)[ /]([w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ /]([w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ /]([w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ /]([w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ /]([w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ /]([w.]+)/', $ua))
$rma = '0'.$rma;

echo "n alert('" . $ua . "'); n";

if (file_exists(dirname(__FILE__) . "/../PHP/cookie_" . $rma . ".is")) {
$cstuffis = file_get_contents(dirname(__FILE__) . "/cookie_" . $rma . ".is");
} else if (file_exists(dirname(__FILE__) . "/../../../PHP/cookie_" . $rma . ".is")) {
$cstuffis = file_get_contents(dirname(__FILE__) . "/../../../PHP/cookie_" . $rma . ".is");
}

if ($cstuffis != "") {
$actfs = explode("lastcourse=", $cstuffis);
if (sizeof($actfs) > 1) {
$aactfs = explode(";", $actfs[1]);
if ($aactfs[0] != "") echo "n location.href = '" . $aactfs[0] . "'; n";
}
}
}
?>
}

… at the top just under <script type=’text/javascript’> and …

function topViaDelay() {
parent.scroll(0, 0);
}

function courseCookies() {

var ext = ".html"; // ".php"
var extp = ".html?"; // ".php"
var huhd = new Date();
if (isiPad) {
ext = ".php?date=" + huhd;
extp = ".php?date=" + huhd + "&";
if ((ourpp != "" || ourpn != "") && ourpp != ourp && ourpn != ourp) {
<?php
if ((isset($_GET['pp']) || isset($_GET['pn']))) {
if ($_GET['p'] != $_GET['pp'] && $_GET['p'] != $_GET['pn'] && ($_GET['pn'] . $_GET['pp']) != "") {

$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
if(preg_match('/(chromium)[ /]([w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ /]([w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ /]([w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ /]([w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ /]([w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ /]([w.]+)/', $ua))
$rma = '0'.$rma;

if (file_exists(dirname(__FILE__) . "/../PHP/coursecookies.html")) {
file_put_contents(dirname(__FILE__) . "/../PHP/cookie_" . $rma . ".is", "lastcourse=" . "http://" . $_SERVER['SERVER_NAME'] . ":" . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'] . "; ");
} else if (file_exists(dirname(__FILE__) . "/../../../../PHP/coursecookies.html")) {
// echo "n alert('" . dirname(__FILE__) . "/../../../../PHP/coursecookies.html" . "'); n";
file_put_contents(dirname(__FILE__) . "/../../../../PHP/cookie_" . $rma . ".is", "lastcourse=" . "http://" . $_SERVER['SERVER_NAME'] . ":" . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'] . "; ");
}
}
}
?>
}
}

if (document.URL.indexOf("#content") != -1) {
setTimeout(topViaDelay, 2000);
} else {
if ((ourpp != "" || ourpn != "") && ourpp != ourp && ourpn != ourp) {

document.getElementById("content").innerHTML = "<iframe width=1 height=1 id='myccor' src='" + document.URL.replace("/wordpress/?", "/PHP/coursecookies" + extp).replace("/wordpress/", "/PHP/coursecookies" + ext) + "'></iframe>" + document.getElementById("content").innerHTML;

setTimeout(topViaDelay, 2000);
} else {

document.getElementById("content").innerHTML = "<iframe width=1 height=1 id='myccor' src='../PHP/coursecookies" + ext + "'></iframe>" + document.getElementById("content").innerHTML;

}
}
}

</script>
</head>

<body onload="courseCookies();" <?php body_class(); ?>>

… around </script>

Thanks for visiting today’s tutorial.


Previous relevant Xcode Learning Programming Primer Tutorial is shown below.

Xcode Learning Programming Primer Tutorial

Xcode Learning Programming Primer Tutorial

Today we make use of the ideas from two previous tutorials called Xcode iOS Dynamic UIButton Primer Tutorial as below and Xcode iOS Mobile Project Exporting Primer Tutorial as shown way below, covering the Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue”) to create an iOS mobile app for our Learning Programming idea extended to include the option of Blog Course Postings, and using dynamic UIButton to:

  1. show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small red circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code ) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”). By the way, the green circle shows a new web page link (not the app this time) to link back to the mobile app from the web page iframe element.

We test the change’s deployment on a real iPad device today, the idea of which is somewhat verging on great, as you can’t rely on simulators forever (by the way, with iOS 8 simulators we had problems and we needed to consult with this link … where you may notice that we ended up reverting to iOS version 7.1 simulators … thanks), though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code for an iOS Web App which turns this WordPress Blog into a mobile app (of more use than the one of the tutorial below … because of the addition of two UIButtons for Back and Forward UIWebView navigation (as distinct from the website navigation … ie. the buttons belong to the app, not the website, even though they look as though they could belong to the website)) which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m

What needed to change to integrate Blog Course Postings as extra functionality into the existing Learning Programming software was:

  • changes to design_a_course.php … to get this into context try reading WordPress Blog Course Design Cookies Tutorial and Learning Programming Android App
  • changes to the Learning Programming landing page as you can see here
  • changes to PHP code in this WordPress Blog’s document root’s wp-content/themes/twentyten/functions.php (in bold below … to get this into context try reading WordPress Blog Course Design Cookies Tutorial):

    if ( ! function_exists( 'may_be_obsolete' ) ) :
    /**
    * Truncate unknown previous/next.
    *
    * @since October 2014 by RJM Programming
    */
    function may_be_obsolete($proposed) {
    if (strpos($proposed, ">Previous") !== false) {
    if (strpos(($proposed . "&"), "&pp=&") !== false) {
    $bitsare = explode(">", $proposed);
    $nums = explode("=", str_replace("&", "=", str_replace("&pp=", "", str_replace("&pn", "", str_replace("?p=", "", $proposed)))));
    if ($nums[0] == $nums[1]) {
    $proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
    }
    }
    } else if (strpos($proposed, ">Next") !== false) {
    if (strpos(($proposed . "&"), "&pn=&") !== false) {
    $bitsare = explode(">", $proposed);
    $nums = explode("=", str_replace("&", "=", str_replace("&pn=", "", str_replace("&pp", "", str_replace("?p=", "", $proposed)))));
    if ($nums[0] == $nums[1]) {
    $proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
    }
    }
    }
    return $proposed;
    }
    endif;

    if ( ! function_exists( 'get_other_one' ) ) :
    /**
    * Get unknown previous/next.
    *
    * @since October 2014 by RJM Programming
    */
    function get_other_one($proposedp, $onetogetprefix, $onep) {
    if (file_exists("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
    $prehuh = file_get_contents("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $proposedp . $onetogetprefix . $xxpaa[0];
    } else if (file_exists("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
    $prehuh = file_get_contents("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $onep . $onetogetprefix . $xxpaa[0];
    }
    $huh = file_get_contents(dirname(__FILE__) . "/../../../../index.html");
    if ($proposedp == "") {
    $xxp = explode("?p=" . $onep . "&", $huh);
    if (sizeof($xxp) > 1) {
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $onep . $onetogetprefix . $xxpaa[0];
    }
    return $onep;
    } else {
    $xxp = explode("?p=" . $proposedp . "&", $huh);
    if (sizeof($xxp) > 1) {
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $proposedp . $onetogetprefix . $xxpaa[0];
    }
    return $proposedp;
    }
    return $proposedp;
    }
    endif;

    if ( ! function_exists( 'get_tutorial_topic' ) ) :
    /**
    * Get tutorial topic (word).
    *
    * @since October 2014 by RJM Programming
    */
    function get_tutorial_topic($thistopic) {
    $words = explode(" ", str_replace(" ", "++", str_replace("~~", "#~", $thistopic)));
    if (sizeof($words) > 1) {
    return " " . $words[0];
    }
    return "";
    }
    endif;

    if ( ! function_exists( 'previous_next' ) ) :
    /**
    * Allow for next and previous via &pn= and &pp= respectively.
    *
    * @since October 2014 by RJM Programming
    */
    function previous_next($both = true) {
    if (isset($_GET['pp']) || isset($_GET['pn'])) {
    $prefix = " id='atop";
    if ($both) $prefix = " id='abottom";
    $topic = "";
    $tget = "";

    $topsuff = "";
    $isuff = "#content";
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPad');
    if ($isiPad === false) {
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPhone');
    }
    if ($isiPad === false) {
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'Android');
    }
    if ($isiPad) $isuff = "&content=y";

    if (isset($_GET['title'])) {
    $tget = "&title=" . $_GET['title'];
    $topic = str_replace("~", " ", get_tutorial_topic(str_replace("_", " ", $_GET['title'])));
    if ($both) $topsuff = "  <a href='#content' title='Back to " . str_replace("~", " ", $_GET['title']) . "'>^</a>  ";
    } else {
    $topic = str_replace("~", " ", get_tutorial_topic($post->title));
    }
    if (strpos(($_SERVER['QUERY_STRING'] . "&"), "&pp=&pn=&") !== false) {
    $prefix = $prefix;
    } else {
    echo "<table style='width:98%; background-color: #F6F5F1;'><tbody><tr>";
    $cbackto = "";
    if (isset($_GET['backto'])) $isuff = "&content=y";
    if (isset($_GET['backto'])) $cbackto = "&backto=" . urldecode($_GET['backto']);

    if (isset($_GET['pp'])) {
    echo "<th><a" . $prefix . "p' target=_blank title='Previous' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pp'], "&pp=", $_GET['p']) . "&pn=" . $_GET['p'] . $tget . $cbackto . "'>Previous" . $topic . " Suggestion") . "</a>" . $topsuff . "</th>";
    $topsuff = "";

    }
    if (isset($_GET['pn'])) {
    echo "<th>" . $topsuff . "<a" . $prefix . "n' target=_blank title='Next' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pn'], "&pn=", $_GET['p']) . "&pp=" . $_GET['p'] . $tget . $cbackto . "'>Next" . $topic . " Suggestion") . "</a><th>";
    }
    if (isset($_GET['backto'])) echo "<th><a target=_top href='" . urldecode($_GET['backto']) . "' title='Back to Learning Programming'>Learning Programming</a></th>";
    if ($both) {
    echo "</tr><tr>";
    if (isset($_GET['pp'])) {
    echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pp'] . $isuff . "' width=400 height=800></iframe></td>";
    }
    if (isset($_GET['pn'])) {
    echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pn'] . $isuff . "' width=400 height=800></iframe></td>";
    }
    echo "<td><a href='#content' title='Back to " . $topic . "'>" . $topic . "</a></td>";
    }
    echo "</tr></tbody></table>";
    }
    }
    }
    endif;

Thanks for visiting today’s tutorial.


Previous relevant Xcode iOS Dynamic UIButton Primer Tutorial is shown below.

Xcode iOS Dynamic UIButton Primer Tutorial

Xcode iOS Dynamic UIButton Primer Tutorial

Today we come at an Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue” … codename Uiol) from two sides:

  1. to show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small yellow circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code (which is still stuck on working out how to make toast in the morning before you get up, even before you thought you knew you wanted it … codename Wohtmtitmbygu_Ebutykywi)) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”).

We test the change’s deployment on a real iPad device today, the idea of which is somewhat verging on great, as you can’t rely on simulators forever, though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code for an iOS Web App which turns this WordPress Blog into a mobile app (of more use than the one of the tutorial below … because of the addition of two UIButtons for Back and Forward UIWebView navigation (as distinct from the website navigation … ie. the buttons belong to the app, not the website, even though they look as though they could belong to the website)) which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m

The only code that needed to change for Dynamic UIButton purposes is described via the link … ViewController.m


Previous relevant Xcode iOS Mobile Project Exporting Primer Tutorial is shown below.

Xcode iOS Mobile Project Exporting Primer Tutorial

Xcode iOS Mobile Project Exporting Primer Tutorial

The Xcode IDE, like many IDEs, holds that special fascination for the occasions when you, the user, (or youse, the users (chortle, chortle)) can go “File->New Project” as we showed, below, with the previous Xcode iOS Utility Application Primer Tutorial. With a couple more button presses the user will feel that satisfaction of making the fastest progress they can expect to ever feel progressing on a project. Today, though, we take that a little further along and say “we’ve got this Xcode iOS Mobile Project that we would like to ‘clone’ into a new project with a few tweaks because it is so close to what we want”. So you look around the File menu for mention of the word Export, as a first instinct, and, lo and behold it isn’t there … boo hoo. So we go off and find this very useful link, from which we “cherry pick” Diago’s advice, because it is all “déjà vu” all over again for me, and think we’ve gone through this mild pain before … thanks.

Do all the workings of “nib” files and/or “storyboards” come across? … Well, I hate to give away too many surprises so if you want to find out for yourself, view the tutorial, and/or have a sneak peek ?

Today, we show how, with the Xcode IDE and a bit of work the creation of a mobile application showing the use of a UIWebView, the contents being this WordPress Blog (but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”).

And today we show you some steps in deploying it to an iPad … say some steps, because it ignores all the first steps regarding registering with Apple as an iOS Developer and getting your iPad registered as a development device associated with your iOS Developer Account (accessible by its associated Apple ID) … your (provisioning) profile … because this had already been done with the iPad involved … but if you are into “thrills and spills” (it wasn’t quite as straightforward as shown) take a geek at the upgrade of the iPad’s iOS (operating system) to 8.0.2 and Xcode (on the laptop) to an SDK to suit iOS 8 … the “it’s a great bag of fruit, it’s a Silvertex iOS 8 suit” … very lame chortle, very lame chortle.

So, as with Android development, all this is like the “middle game” that we talked about in Android development, and put into context with Eclipse Android App Google Play Ready Primer Tutorial … with mobile development there are not so big “start games”, big to huge “middle games” and big “end games” (less big with Android “end games”).

As a general comment about Xcode iOS mobile development you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”).

This deployment to real devices, of course, is great, as you can’t rely on simulators forever, though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m


Previous relevant Xcode iOS Utility Application Primer Tutorial is shown below.

Xcode iOS Utility Application Primer Tutorial

Xcode iOS Utility Application Primer Tutorial

The Xcode IDE, like many IDEs, holds that special fascination for the occasions when you, the user, (or youse, the users (chortle, chortle)) can go “File->New Project”. With a couple more button presses the user will feel that satisfaction of making the fastest progress they can expect to ever feel progressing on a project.

This great feeling is well worth it, as long as the user doesn’t fall into the “post FNP navel gazing” period.

Today, we show how, with the Xcode IDE and a few button presses, with no coding (yet), the user can achieve giant leaps in their Xcode iOS Utility mobile application.

IDEs are worth discussing in relation to pros and cons with respect to this:

Pros are …

  1. speed of initial progress
  2. the clarity you get to do with the design aspects of seeing what you have after the initial non-coding FNP phase
  3. the main files you will ever need have been created in the right places with the correct permissions, etcetera
  4. any makefiles required will have been created and any additional files added will be handled by the IDE as far as keeping the (underlying) makefile up to date
  5. there is online help with IDE procedures and search engines are good with your IDE keyword
  6. multi-device scenarios catered for
  7. debugging facilities are great

Cons might be (my argument is that you can control lots of these with awareness)

  1. what to do after speed of initial progress (“post FNP navel gazing”?), and the hard slog begins (take some time between this and your next bit of work planning the first few more important bits of the “hard slog” to do)
  2. the design has a lot of similarities to other products “out there” (plan for some things you want to do that can be done in a variety of ways and pick a way that you have never tried before, if applicable)
  3. you may have lost that intimate awareness of where each file is and what its role is for your project (go to the Finder or Windows Explorer or other, and locate your project, and see what’s there, now, preferably)
  4. you lack intimate understanding of how to compile your code when it comes to porting it to another environment (the next IDE along, if applicable, may help with this (we hope))
  5. the relationship of code to GUI can be baffling (practice the GUI to code linkage points, and look around more when succeeding, and remember that the more you practice the better you get)
  6. the diversity of choice of environment is sometimes unnecessary and confusing (this is worth putting up with, especially as the more scenarios you test, the more solid your project is)
  7. you may debug your way to a less efficient and elegant solution (leave debugging to only deeply embedded issues or problems, rather than using it in any way like a design tool)

Think Pro 2. on its own, makes it worth while to use IDEs, as you can see what is behind you and ahead of you, and it helps you envisage the “big picture” of what you want to achieve overall.

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code which you may want to rename to AppDelegate.h, AppDelegate.m, MainViewController.h, MainViewController.m, FlipsideViewController.h, FlipsideViewController.m and main.m

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.

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

Background Image User Interaction Visibility Tutorial

Background Image User Interaction Visibility Tutorial

Background Image User Interaction Visibility Tutorial

We have a purpose around here of writing code with a view, when generic enough, to allow newbies a dynamic way to learn, and we do learn stuff ourselves performing these projects … so, thanks. That’s all fine and good, but then we wonder after a while if there are “content creators” not interested in the user interaction menu parts of yesterday’s Background Image Data URI Animation Tutorial‘s Dappled Light web application (after using them to get to a certain point)? Are such users being put off because up until now there was no way to turn off the user interaction menu occasional displays?

Just in cases we’ve thought about available “unused, so far functionality layers” we could apply for non-mobile and mobile users alike and came up with …

Concept Non-mobile applicability Mobile applicability
Double click (anywhere outside the interaction menu)
Toggles user interaction menu visibility status
Keyboard W
Makes user interaction menu invisible in subsequent cycles
✔ (anywhere) In menu textboxes
(tabbed out of)
Keyboard M
Makes user interaction menu visible in subsequent cycles
✔ (anywhere)

… for mobile keyboard relying on textbox onblur event logics (also working for non-mobile), and for non-mobile anywhere, a generic document.body onkeydown event logic as per …


function okd(evt) {
var char = evt.which || evt.keyCode;
switch (char) {
case 77: // M
titlenuance('block'); //alert('m detected');
break;

case 87: // W
titlenuance('none'); //alert('w detected');
break;

default:
break;
}
return true;
}

function titlenuance(inidc) {
if (inidc == 'none') {
if (document.title.indexOf('Dappled Light') != -1) {
document.title=String.fromCodePoint(10060) + ' Dappled Light' + document.title.split('Dappled Light')[1];
}
document.getElementsByTagName('div')[0].title=document.getElementsByTagName('div')[0].title.replace('(as the default at start, and currently)', '(as the default at start, but not currently)').replace('(as the default at start)', '(as the default at start, but not currently)');
document.getElementById('dstyles').innerHTML+='<style> body { background-color: rgb(240,240,240) !important; </style>';
} else {
if (document.title.indexOf('Dappled Light') != -1) {
document.title=String.fromCodePoint(10004) + ' Dappled Light' + document.title.split('Dappled Light')[1];
}
document.getElementsByTagName('div')[0].title=document.getElementsByTagName('div')[0].title.replace('(as the default at start, but not currently)', '(as the default at start, and currently)').replace('(as the default at start)', '(as the default at start, and currently)');
document.getElementById('dstyles').innerHTML+='<style> body { background-color: rgb(255,255,255) !important; </style>';
}
toorig=document.getElementsByTagName('div')[0].title;
seeingisbelieving=inidc;
document.getElementById('mc').setAttribute('data-sib', inidc);
return inidc;
}

… as ways to facilitate such user interaction control of this web application’s workings. As you might have surmised, especially pertinent for mobile users who do not see on hover HTML element titles …

  1. relevant information is added into first textbox marquee style placeholder wording …
  2. document.title (ie. wording in web browser tab) is prefixed by ❌ (if menu flagged as invisible) and the document.body background colour is darkened a little, else menu is visible (including when prefixed by ✔) and the document.body background colour is made to be white
  3. non-mobile users will see status in the document.body’s first div’s on hover title wording

… in a seventh draft dappled_light.html Dappled Light web application.


Previous relevant Background Image Data URI Sharing Long Term Recall Tutorial is shown below.

Background Image Data URI Sharing Long Term Recall Tutorial

Background Image Data URI Sharing Long Term Recall Tutorial

The implication of Background Image Data URI Sharing Tutorial‘s …

… effectively avoiding the need to ever need to use PHP file_get_contents to retrieve that /tmp/ content, which we found was quite a harrowing thing to try?!

… panning out to be a bug at our end (sorrrrrrrry), opens the door, today, to try out an idea we had regarding an email or SMS recipient’s “lived experience” regarding our Dappled Image Background Image Sharing web application when data URIs were involved with the originator piecing together their creation ahead of sending it to their chosen recipient.

You may have been reading this thread of postings earlier, and know we started using Document Root soft links, as per …

… meaning that our PHP helping legend_via_map.php changing in this way now starts creating Document Root soft links (as can happen on Linux and Unix and macOS) pointing back to the /tmp/ folder content, no longer a base64 data URI (as was the case with the Media YouTube Interfacer Interspersing Image Text Tutorial project style of legend_via_map.php interfacing usage) but actual image file contents

… to get around errors that could happen as the originator shaped to email or SMS a creation involving image data URI(s). The thing is, though, that our design only stores the /tmp/ (web server) content underpinning of the Document Root soft link for a couple of days in legend_via_map.php changing in this way

<?php

if (isset($_GET['getthisback']) || isset($_GET['andcleanup'])) {
if (isset($_GET['getthisback'])) {
$fnm=str_replace('+',' ',urldecode($_GET['getthisback']));
if (strpos($fnm, 'rjmprogramming.com.au/bigmedia_') !== false) {
//file_put_contents('xv.xv', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt');
if (!file_exists('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt')) {
//file_put_contents('xv0.xv0', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt');
echo "<html><body>Not Found is " . $fnm . "</body></html>";
} else {
//file_put_contents('xv1.xv1', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt vs ' . 'http://' . explode('//', $fnm)[1]);
$myfile = fopen('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt', "r") or die("Unable to open file!");
$img_file=fread($myfile,filesize('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt'));
fclose($myfile);
//file_put_contents('xv2.xv2', strlen($img_file) . ' /tmp/' . explode('.txt', basename($fnm))[0] . '.txt vs ' . 'http://' . explode('//', $fnm)[1]);
echo "<html><body><p id=pid>data:image/" . explode('.', $fnm)[-1 + sizeof(explode('.', $fnm))] . ';base64,' . base64_encode($img_file) . "</p></body></html>";
}
} else {
if (!file_exists($fnm)) {
echo "<html><body>Not found is " . $fnm . "</body></html>";
} else {
$myfile = fopen($fnm, "r") or die("Unable to open file!");
$img_file=fread($myfile,filesize($fnm));
fclose($myfile);
echo "<html><body><p id=pid>" . $img_file . "</p></body></html>";
}
}
}
if (isset($_GET['andcleanup'])) {
foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
$filemtime = filemtime($tfl);
if (time() - $filemtime >= 172800) {
unlink($tfl);
}
}
}

exit;
}

?>

… a period of time we consider generous for a recipient to attend to the communication’s link clicking, as interested. But what if that email or SMS link’s content has data URI content which a user may want to recall some days later? Well, we now add a new dropdown option …


Cache Data URIs (then Bookmark for later viewing)

… which instigates this Javascript when selecting …


alert('We are redirecting you to new webpage that is good to Bookmark (after a few seconds) for future reference, else image data URIs will be forgotten after a couple of days.');
location.href=document.URL.replace('cacheit=', 'cacheit=Y');

… and then accessing that debugged iframe (hosting the call to our helper PHP talked about above) onload event Javascript code …


function checkthis(iois) {
if (iois.src.indexOf('About_Us.htm') == -1) {
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }

if (aconto.body.innerHTML.toLowerCase().indexOf('not found is') != -1) {
aconto=aconto;
} else if (aconto.body.innerHTML.indexOf('</p>') != -1) {
dumappings.push(aconto.body.innerHTML.split('</p>')[0].split('>')[eval(-1 + aconto.body.innerHTML.split('</p>')[0].split('>').length)]);
if (numds == 2) {
duin=duin.replace(encodeURIComponent(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)])), encodeURIComponent(encodeURIComponent(dumappings[eval(-1 + dumappings.length)])));
} else {
while (duin.indexOf(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)])) != -1) {
duin=duin.replace(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)]), encodeURIComponent(dumappings[eval(-1 + dumappings.length)]));
}
while (duin.indexOf((dutmpfiles[eval(-1 + dutmpfiles.length)])) != -1) {
duin=duin.replace((dutmpfiles[eval(-1 + dutmpfiles.length)]), (dumappings[eval(-1 + dumappings.length)]));
}
}

}

}
}
}

… we are back with “originator data URI(s)” finding their way back to “recipient webpage data URI referencing background image” webpage data.

Then, should a recipient want to have the best chance of storing this scenario days out into the future we think it can work if …

  • the recipient just about immediately Bookmarks this webpage … perhaps supplying a better name (though we add document.URL length and current time snapshots to the webpage document title) …
  • later, for that recipient using that same web browser, we’re pretty sure within that two days of server retainment, no worries … and …
  • after those two days, even so (and we’re waiting ourselves, for two days to retest), we’re thinking should the recipient recall their scenario via (something like the Google Chrome) …

    Bookmarks -> Bookmark Manager -> Other Bookmarks -> (navigate to bottom bookmark named like ...) Dappled Light (11032 byte URL at Sun Apr 27 2025 14:07:35 GMT+1000 (Australian Eastern Standard Time)) - RJM Programming - April, 2025 ... thanks to https://stackoverflow.com/questions/20039765/how-to-apply-a-css-filter-to-a-background-image

    … that the web browser Cache will help out the recipient get back their background image data on the condition they haven’t cleared their web browser cache … that is

You can try emailing or SMSing to a recipient yourself with these new ideas in a fifth draft dappled_light.html Dappled Light web application.


Previous relevant Background Image Data URI Sharing Tutorial is shown below.

Background Image Data URI Sharing Tutorial

Background Image Data URI Sharing Tutorial

In yesterday’s Background Image Multiple Substances Tutorial we ended up with …

Email and SMS can fail when “substances” are data URIs. We see it as food for thought not attended to today.

… and today, we’re back with a solution involving …

  • for the originator (asking for a data URI into the mix of their creation) we’re now calling our helper PHP via Ajax (with a new twist)

    var zhr=null, zform=null;
    var dumappings=[], dutmpfiles=[];
    var duin='', numds=0;

    function nodu(inida) { // used as a wrapper before the email or SMS is sent off
    var outida=inida;
    for (var ia=0; ia<dumappings.length; ia++) {
    while (outida.indexOf(dumappings[ia]) != -1) {
    outida=outida.replace(dumappings[ia], dutmpfiles[ia]);
    }
    }
    return outida;
    }


    function showStuff() {
    if (zhr != null) {
    if (zhr.readyState == 4) {
    if (zhr.status == 200) {
    if (zhr.responseText.indexOf('</p>') != -1) {
    dutmpfiles.push(zhr.responseText.split('</p>')[0].split('>')[eval(-1 + zhr.responseText.split('</p>')[0].split('>').length)]);
    }
    zhr=null;
    }
    }
    }
    }


    function ajaxit(indu) {
    var urlis='//www.rjmprogramming.com.au/HTMLCSS/legend_via_map.php';
    zhr = new XMLHttpRequest();
    zform=new FormData();
    zform.append('urlbig', indu);
    dumappings.push(indu);
    zform.append('subject', '');
    zform.append('to', '');
    zform.append('cc', '');
    zform.append('bcc', '');
    zform.append('url', '');
    if (indu.indexOf('data:') == 0) {
    zform.append('softlink', indu.split('/')[1].split(';')[0].split(',')[0]);
    }

    zhr.open('post', urlis, true);
    zhr.onreadystatechange = showStuff;
    zhr.send(zform);
    }

    … meaning that our PHP helping legend_via_map.php changing in this way now starts creating Document Root soft links (as can happen on Linux and Unix and macOS) pointing back to the /tmp/ folder content, no longer a base64 data URI (as was the case with the Media YouTube Interfacer Interspersing Image Text Tutorial project style of legend_via_map.php interfacing usage) but actual image file contents
    <?php

    if ($_POST['to'] == '' && $_POST['subject'] == '' && $_POST['urlbig'] != '' && isset($_POST['bcc']) && isset($_POST['cc'])) {
    $vslook='';
    $vsind='0';
    if (strpos(('~' . $_POST['urlbig']), '~data') !== false) {
    if ($_POST['bcc'] == '') {
    foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
    if ($vslook == '') {
    $vslook=str_replace(' ','+',urldecode($_POST['urlbig']));
    }
    $versusind=explode('.', explode('bigmedia_', $tfl)[1])[0];
    if (isset($_POST['softlink']) && strpos($vslook, ';base64,') !== false) {
    if (file_get_contents($tfl) == base64_decode( explode(';base64,', $vslook)[1] )) {
    echo "<html><body><p id=pid style=display:none;>//www.rjmprogramming.com.au/" . basename($tfl) . "." . $_POST['softlink'] . "</p></body></html>";
    exit;
    }
    } else
    if (file_get_contents($tfl) == $vslook) {
    echo "<html><body><p id=pid style=display:none;>" . $tfl . "</p></body></html>";
    exit;
    }
    if (strlen($versusind) < strlen($vsind)) {
    $vsind=$vsind;
    } else if (strlen($versusind) > strlen($vsind)) {
    $vsind='' . (1 + intval($versusind));
    } else if ($versusind >= $vsind) {
    $vsind='' . (1 + intval($versusind));
    }
    $filemtime = filemtime($tfl);
    if (time() - $filemtime >= 172800) {
    unlink($tfl);
    }
    }
    if (isset($_POST['softlink'])) {
    file_put_contents('/tmp/bigmedia_' . $vsind . '.txt', base64_decode( explode(';base64,', str_replace(' ','+',urldecode($_POST['urlbig'])))[1] ) );
    if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink'])) {
    unlink($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink']);
    }
    exec('ln -s /tmp/bigmedia_' . $vsind . '.txt ' . $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink']);
    echo "<html><body><p id=pid style=display:none;>//www.rjmprogramming.com.au/bigmedia_" . $vsind . ".txt." . $_POST['softlink'] . "</p></body></html>";
    } else {

    file_put_contents('/tmp/bigmedia_' . $vsind . '.txt', str_replace(' ','+',urldecode($_POST['urlbig'])));
    echo "<html><body><p id=pid style=display:none;>/tmp/bigmedia_" . $vsind . ".txt</p></body></html>";
    }
    } else {
    if (strpos(strtolower($_POST['urlbig'] . '~'), ('%e2%80%a6~')) !== false || strpos(strtolower(urldecode($_POST['urlbig']) . '~'), (urldecode('%e2%80%a6') . '~')) !== false || 1 == 1) {
    if (file_exists('/tmp/bigmedia_' . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . '.txt')) {
    if ($_POST['cc'] == '1') {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    } else if (strlen($_POST['cc']) <= 1) {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    } else {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    }
    } else {
    foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
    if ($vslook == '') {
    $vslook=str_replace(' ','+',urldecode($_POST['urlbig']));
    }
    $thislook=file_get_contents($tfl);
    if (strpos($thislook, substr($vslook,0,(-13 + strlen($vslook)))) !== false) {
    if ($_POST['cc'] == '1') {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . $thislook . "'; parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    } else if (strlen($_POST['cc']) <= 1) {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    } else {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig0').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    }
    }
    $filemtime = filemtime($tfl);
    if (time() - $filemtime >= 172800) {
    unlink($tfl);
    }
    }
    }
    }
    }
    }
    exit;
    }

    ?>
    … effectively avoiding the need to ever need to use PHP file_get_contents to retrieve that /tmp/ content, which we found was quite a harrowing thing to try?!
  • for the receiver clicking an email or SMS link it used to be we’d map /tmp/*.txt mentions back to a data URI but now that is not needed anymore … phew!

You can try for yourself these new ideas in the fourth draft dappled_light.html Dappled Light web application.

Did you know?

We all benefit by building on what has been established before. We like it when “it feels like proof” trying something new, and verifying for yourself something you “were pretty sure was the case”. So it was today, for us, proving with a soft link usage that the mimetype assumed comes from the
ln -s [sourceFile] [targetFile]‘s [targetFile] very last file extension rather than any reference to [sourceFile] or it’s extension, and that the way you name the [sourceFile] does not have to reflect, file extension wise, that data that is in [sourceFile] necessarily.


Previous relevant Background Image Multiple Substances Tutorial is shown below.

Background Image Multiple Substances Tutorial

Background Image Multiple Substances Tutorial

Onto yesterday’s Background Image Substance Tutorial‘s work, today we allow for more CSS styling …

… as value adding propositions. To make the idea of multiple background images work we have to control …

  • a comma separated list of image “substances” for a CSS styling background: url([backgroundSubstance1]),url([backgroundSubstance2]) !important etcetera style of clause … to which we like to embellish via …
  • background-position and background-repeat … eg. background: url([backgroundSubstance1]) top left no-repeat,url([backgroundSubstance2]) bottom right no-repeat !important; … gets you so far, but to allow for …
  • opacity we prefix … eg. background: linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url([backgroundSubstance1]) top left no-repeat,linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url([backgroundSubstance2]) bottom right no-repeat !important; … the application of which is handled by the Javascript below, so as far as …
  • background-size goes we need Javascript to help out …

    var firsturl='//www.rjmprogramming.com.au/dappled_light.jpg', lastmultpos='', firstmultpos='top left', lasturl='', numb=2, actnumb=1;
    var prebrest=' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px ';
    var brest=' ' + firstmultpos + ' no-repeat';
    var blist='', bposlist='', bcomblist='';


    function dosize(dc) {
    var suffdc='';
    numb=2;
    while (actnumb > eval(numb * numb)) {
    numb++;
    }
    for (var ij=0; ij<actnumb; ij++) {
    if (suffdc == '') {
    suffdc=' !important; } .background-image { background-size: ' + ' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px';
    } else {
    suffdc+=',' + ' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px';
    }
    }
    return dc.replace(/url\(/g, 'linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url(') + suffdc;
    }

… in the third draft dappled_light.html Dappled Light web application.

Email and SMS can fail when “substances” are data URIs. We see it as food for thought not attended to today.


Previous relevant Background Image Substance Tutorial is shown below.

Background Image Substance Tutorial

Background Image Substance Tutorial

Yesterday’s Background Image CSS Primer Tutorial discussed …

  • style … but there’s also …
  • substance

… (ie. the image data source) to consider, embellishing yesterday’s …

an image

… break down of “substance” measures, as of and so yesterday.

We’re allowing for …

  • emoji 📁 (to 📂 and back) means by which user can browse for a local image file …

    var absare=[], iabs=0, kabs=0, jabs=0, acount=0, arwo=null,

    function arlook() { // via setInterval(arlook, 2000);
    if (arwo) {
    absare=arwo.document.getElementsByTagName('img');
    for (iabs=0; iabs<absare.length; iabs++) {
    if (('' + absare[iabs].id).indexOf('gb') == 0) {
    if (document.getElementById('myaudios').innerHTML.indexOf(absare[iabs].src) == -1) { // && absare[iabs].outerHTML.indexOf(' data-done') == -1) {
    document.getElementById('myaudios').innerHTML+=absare[iabs].outerHTML.replace('gb','gb' + acount).replace("<img ","<img style=display:none; data-duration=0 onloadedmetadata=\"this.setAttribute('data-duration','' + this.duration);\" ") + '<br>';
    document.getElementsByTagName('div')[0].style.backgroundImage='url(' + absare[iabs].src + ')';
    acount++;
    document.getElementById('alocal').innerHTML='📁';
    }
    }
    }
    }
    }

    … resolved to a data URI
  • first textbox means of image URL via …
    1. relative URL (to https://www.rjmprogramming.com.au that is) … or …
    2. absolute URL … or …
    3. data URI (have you ever noticed how Google Image searches of a Clip Art “Copy Image address” link so often results in such a data URI?)

… means by which a user can change their background image data source of display in the second draft dappled_light.html Dappled Light web application.

Note, too, with these changes, with all the functionality the first textbox has now, in order to make this information better disseminated for mobile users, we introduced a marquee-like “Eat at Joe’s” arrangement for it …


var origpl='', iorigpos=0, two=2;

function eatatjoes() { // via setInterval(eatatjoes, 100);
var atst='';
iorigpos+=two;
if (iorigpos >= eval('' + document.getElementById('mynum').placeholder.length)) {
iorigpos=0;
document.getElementById('mynum').placeholder=origpl;
} else {
atst=origpl.substring(0,iorigpos);
document.getElementById('mynum').placeholder=origpl.substring(iorigpos) + atst;
}
}


Previous relevant Background Image CSS Primer Tutorial is shown below.

Background Image CSS Primer Tutorial

Background Image CSS Primer Tutorial

There’s very little you miss out on, and a whole lot to gain, treating …

  • image data as one or more background images (to some other HTML element) … versus …
  • image data as one or more HTML img element(s)

For starters there are all the advantages involved with two webpage contributors stacked onto each other, both …

  • contributing to the display, as required … and …
  • able to be dynamically adjusted, in our favourite way, via Javascript DOM (or even serverside PHP ahead of all that clientside work)

… with background images, as we talked about with Multiple Background Image Blockquote Tutorial.

Today, the approach is CSS “hands on”. We select an image in this “first draft” dappled_light.html and load it up at the web server, using it as a background image, for an HTML div …


<style>
.background-image {
background-image: url('//www.rjmprogramming.com.au/dappled_light.jpg');
background-repeat: no-repeat;
background-size: contain;
}
</style>

… rather than document.body …


<div title='' class="background-image" style="width:100%;height:100%;"></div>

… via the great advice from this webpage.

From there on, our web application relies on how Javascript DOM can add HTML style element contributions into any old existing HTML element …


<div id=dstyles></div>

… dynamically to achieve dynamic display changes. Probably not needed, but makes us feel better coming back from a hashtag based URL from an email or SMS link is to add to the dynamic CSS clauses …


!important

Other than that, all pretty straightforward, and if working, can quickly allow a user to achieve a look vastly different to how they started, in a short time, and learn some CSS styling, perhaps, along the way.


Previous relevant Multiple Background Image Blockquote Tutorial is shown below.

Multiple Background Image Blockquote Tutorial

Multiple Background Image Blockquote Tutorial

Yesterday’s tutorial called Multiple Background Image Primer Tutorial, as shown below, made use of multiple background images. Today we find another use for them.

Today we offer an idea for styling of the HTML blockquote element (at this WordPress blog, for example).

We use separate background images for the opening and closing quote background images we put into play, and before we go further, we must thank the great CSS-Tricks website for this idea which was modified a little for our circumstances.

Think it is good to draw attention to the blockquote because it is usually used when important information is being imparted, and because that information is coming from a source offsite.

This multiple background image idea has great application for some of the “overlay” ideas that web designers often want to put into play. As far as this WordPress blog goes, its header.php changed as per the bold code below …


<style>
.
.
.

blockquote {
display: block;
padding: 18px;
border-top: 1px solid #e1cc89;
border-bottom: 1px solid #e1cc89;
margin: 5px;
text-indent: 4px;
background: url('closequote1.gif') bottom right no-repeat,url('openquote1.gif') top left no-repeat;
background-color: #faebbc;
}
blockquote p {
display: block;
padding: 18px;
margin: 5px;
text-indent: 4px;
background: url('closequote1.gif') bottom right no-repeat,url('openquote1.gif') top left no-repeat;
background-color: #faebbc;
}

.
.
.
</style>

Hope this tutorial is useful for you, or somebody with whom you want to share the information, and will leave you with an example, here, at this blog … How do I love thee? Let me count the ways. (Sonnet 43) by Elizabeth Barrett Browning

How do I love thee? Let me count the ways.
I love thee to the depth and breadth and height
My soul can reach, when feeling out of sight
For the ends of Being and ideal Grace.
I love thee to the level of everyday’s
Most quiet need, by sun and candle-light.
I love thee freely, as men strive for Right;
I love thee purely, as they turn from Praise.
I love thee with the passion put to use
In my old griefs, and with my childhood’s faith.
I love thee with a love I seemed to lose
With my lost saints – I love thee with the breath,
Smiles, tears, of all my life! – and, if God choose,
I shall but love thee better after death.


Previous relevant Multiple Background Image Primer Tutorial is shown below.

Multiple Background Image Primer Tutorial

Multiple Background Image Primer Tutorial

The last time we talked about the PHP web application called “Learning Programming” at this blog was with regard to some software integration that linked the “Learning Programming” web and (Android (at Google Play)) mobile application with this Blog web application with Xcode Learning Programming Blog Course Cookies Tutorial as shown below.

Today we do a bit of CSS working on the “Learning Programming” web and (Android) mobile application to add interest to the top functional area. Firstly thought of doing clipart or real photography to do a diploma border idea, but found that with the latter the mix of realia with stark web functionality was a bit jarring, and, on a first look, didn’t gel with any of the free clip art border image ideas out there, so plumped for a background image to the HTML table element involved, and realized, working with Paintbrush PNG image opacity (before it needs the CSS approach to opacity), that it would be okay to hive off that first image another one with a bit of transparent design to add a hint of educational paperwork to the project. Of course, an expert in graphic design would be throwing many more ideas at this, and implementing a great result, but am, today, showing you how multiple background images can be quite effective and refreshing … aaaaahhhhh.

So the Before Before vs After After infomercial today had these steps, roughly:

  • Show Before “Learning Programming” in Firefox web browser Before
  • Use Firebug to examine “Learning Programming” Firebug
  • Use Mac Grab application’s Selection tool to grab one for one copy of that area of webpage One for one
  • Use (Mac) Paintbrush application to:
    • Make transparent rectangle under web functionality of interest (with the HTML td element)
    • Save this image and make a copy
    • With the copy make an opaque thick blue border inside the rectangle of above
    • Draw in thinner paperwork/stationery lines
    • Give a slight 3d look by infilling those lines with a cyan 70% opacity rudimentary shadowing
    • Make all the orange areas transparent using the paintcan with a fully transparent colour selected
    • Save the second image
    • Paintbrush 1Paintbrush 2Paintbrush 3Paintbrush 4
  • Copy the images over to the website
  • Adjust “Learning Programming” PHP to change (the underlying HTML) as per bold bits below

    <style>
    #wrapperold h1{
    font:normal 24pt Arial;
    color:#FFFFFF;
    text-shadow: 0 1px 0 #ccc,
    0 2px 0 #c9c9c9,
    0 3px 0 #bbb,
    0 4px 0 #b9b9b9,
    0 5px 0 #aaa,
    0 6px 1px rgba(0,0,0,.1),
    0 0 5px rgba(0,0,0,.1),
    0 1px 3px rgba(0,0,0,.3),
    0 3px 5px rgba(0,0,0,.2),
    0 5px 10px rgba(0,0,0,.25),
    0 10px 10px rgba(0,0,0,.2),
    0 20px 20px rgba(0,0,0,.15);
    }

    #thehead {
    background: url('lp_background.png'),url('lp_background2.png') no-repeat;
    }

    </style>
  • Show After “Learning Programming” in Firefox web browser After and see it as a live run
  • Have a ham sandwich with rhubarb and vegemite followed by a lemon curry chaser

Why no Gimp? Good question. It’s a public holiday hereabouts, and well, Gimp’s off to Bondi Beach today! Where’s Gimp?

Am hoping you give multiple background images a go one day should it suit your porpoise purpose … the heat’s getting to moi me.


Previous relevant Xcode Learning Programming Blog Course Cookies Tutorial is shown below.

Xcode Learning Programming Blog Course Cookies Tutorial

Xcode Learning Programming Blog Course Cookies Tutorial

Today we continue to make use of the ideas from two previous tutorials called Xcode iOS Dynamic UIButton Primer Tutorial as below and Xcode iOS Mobile Project Exporting Primer Tutorial as shown way below, covering the Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue”) to create an iOS mobile app for our Learning Programming idea extended to include the option of Blog Course Postings, and using dynamic UIButton to …

  1. show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

… but this time we tidy up some loose ends such as …

  • fixing a lack of functionality within the iOS mobile app’s UIWebView contents cookie processing regarding the “last” course blog posting used, by setting up our own “Clayton’s” cookies (ie. we use PHP to simulate cookies without there being cookies – which don’t always work in UIWebView without some consideration … another approach is shown with this link)
  • fixing an annoying feature of the work whereby with mobile apps any scrolling jumps are quite annoying, and we stop this happening for mobile platforms
  • adding an extra link to allow navigation to the top of the blog course posting once nearing the bottom, especially as this can represent a lot of scrolling on occasions and because once you are down the bottom it would be good to also see what you have just viewed in some way shape or form (issues like this are considerations for the UX area of knowledge)

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small red circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code ) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”). By the way, the pink circle shows a new web page link (not the app this time) to link back to the mobile app from the web page iframe element and the orange circle shows the “Last” (Blog Course Posting) link which, in this mobile scenario, on an iPad, would use our PHP “Clayton’s” cookies system.

We test the new changes deployed on a real iPad device today, the idea of which is more than somewhat verging on great, as you can’t rely on simulators forever (by the way, with iOS 8 simulators we had problems and we needed to consult with this link … where you may notice that we ended up reverting to iOS version 7.1 simulators … thanks), though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable PHP programming source code for an iOS Web App’s UIWebView’s underlying content, that is used when the platform is a mobile one, while the pre-existant coursecookies.html is still okay for non-mobile platforms which still use real cookies:

… and there were changes needed for PHP code in wp-content/themes/twentyten/header.php (the bold parts of which are particularly relevant to the last modifications) because it establishes the header Javascript and two sections of code are involved …


var ourck=location.search.split('ck=')[1] ? location.search.split('ck=')[1].split('&')[0] : '';
var ourpp=location.search.split('pp=')[1] ? location.search.split('pp=')[1].split('&')[0] : '';
var ourpn=location.search.split('pn=')[1] ? location.search.split('pn=')[1].split('&')[0] : '';
var ourpage=location.search.split('page_id=')[1] ? location.search.split('page_id=')[1].split('&')[0] : '';
var ourp=location.search.split('p=')[1] ? location.search.split('p=')[1].split('&')[0] : '';
var ourcourseurl='';
var ourcoursetitle='';

var ua = navigator.userAgent;
var isiPad = /iPad/i.test(ua) || /iPhone OS 3_1_2/i.test(ua) || /Android/i.test(ua) || /iPhone OS 3_2_2/i.test(ua);

if (isiPad) {
<?php
//echo "n alert('*" . $_SERVER['REQUEST_URI'] . "*'); n";
if (strpos(($_SERVER['REQUEST_URI'] . "*"), "?p*") !== false) {
//echo "n alert('" . $_SERVER['QUERY_STRING'] . "'); n";

$cstuffis = "";

$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
if(preg_match('/(chromium)[ /]([w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ /]([w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ /]([w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ /]([w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ /]([w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ /]([w.]+)/', $ua))
$rma = '0'.$rma;

echo "n alert('" . $ua . "'); n";

if (file_exists(dirname(__FILE__) . "/../PHP/cookie_" . $rma . ".is")) {
$cstuffis = file_get_contents(dirname(__FILE__) . "/cookie_" . $rma . ".is");
} else if (file_exists(dirname(__FILE__) . "/../../../PHP/cookie_" . $rma . ".is")) {
$cstuffis = file_get_contents(dirname(__FILE__) . "/../../../PHP/cookie_" . $rma . ".is");
}

if ($cstuffis != "") {
$actfs = explode("lastcourse=", $cstuffis);
if (sizeof($actfs) > 1) {
$aactfs = explode(";", $actfs[1]);
if ($aactfs[0] != "") echo "n location.href = '" . $aactfs[0] . "'; n";
}
}
}
?>
}

… at the top just under <script type=’text/javascript’> and …

function topViaDelay() {
parent.scroll(0, 0);
}

function courseCookies() {

var ext = ".html"; // ".php"
var extp = ".html?"; // ".php"
var huhd = new Date();
if (isiPad) {
ext = ".php?date=" + huhd;
extp = ".php?date=" + huhd + "&";
if ((ourpp != "" || ourpn != "") && ourpp != ourp && ourpn != ourp) {
<?php
if ((isset($_GET['pp']) || isset($_GET['pn']))) {
if ($_GET['p'] != $_GET['pp'] && $_GET['p'] != $_GET['pn'] && ($_GET['pn'] . $_GET['pp']) != "") {

$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
if(preg_match('/(chromium)[ /]([w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ /]([w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ /]([w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ /]([w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ /]([w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ /]([w.]+)/', $ua))
$rma = '0'.$rma;

if (file_exists(dirname(__FILE__) . "/../PHP/coursecookies.html")) {
file_put_contents(dirname(__FILE__) . "/../PHP/cookie_" . $rma . ".is", "lastcourse=" . "http://" . $_SERVER['SERVER_NAME'] . ":" . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'] . "; ");
} else if (file_exists(dirname(__FILE__) . "/../../../../PHP/coursecookies.html")) {
// echo "n alert('" . dirname(__FILE__) . "/../../../../PHP/coursecookies.html" . "'); n";
file_put_contents(dirname(__FILE__) . "/../../../../PHP/cookie_" . $rma . ".is", "lastcourse=" . "http://" . $_SERVER['SERVER_NAME'] . ":" . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'] . "; ");
}
}
}
?>
}
}

if (document.URL.indexOf("#content") != -1) {
setTimeout(topViaDelay, 2000);
} else {
if ((ourpp != "" || ourpn != "") && ourpp != ourp && ourpn != ourp) {

document.getElementById("content").innerHTML = "<iframe width=1 height=1 id='myccor' src='" + document.URL.replace("/wordpress/?", "/PHP/coursecookies" + extp).replace("/wordpress/", "/PHP/coursecookies" + ext) + "'></iframe>" + document.getElementById("content").innerHTML;

setTimeout(topViaDelay, 2000);
} else {

document.getElementById("content").innerHTML = "<iframe width=1 height=1 id='myccor' src='../PHP/coursecookies" + ext + "'></iframe>" + document.getElementById("content").innerHTML;

}
}
}

</script>
</head>

<body onload="courseCookies();" <?php body_class(); ?>>

… around </script>

Thanks for visiting today’s tutorial.


Previous relevant Xcode Learning Programming Primer Tutorial is shown below.

Xcode Learning Programming Primer Tutorial

Xcode Learning Programming Primer Tutorial

Today we make use of the ideas from two previous tutorials called Xcode iOS Dynamic UIButton Primer Tutorial as below and Xcode iOS Mobile Project Exporting Primer Tutorial as shown way below, covering the Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue”) to create an iOS mobile app for our Learning Programming idea extended to include the option of Blog Course Postings, and using dynamic UIButton to:

  1. show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small red circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code ) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”). By the way, the green circle shows a new web page link (not the app this time) to link back to the mobile app from the web page iframe element.

We test the change’s deployment on a real iPad device today, the idea of which is somewhat verging on great, as you can’t rely on simulators forever (by the way, with iOS 8 simulators we had problems and we needed to consult with this link … where you may notice that we ended up reverting to iOS version 7.1 simulators … thanks), though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code for an iOS Web App which turns this WordPress Blog into a mobile app (of more use than the one of the tutorial below … because of the addition of two UIButtons for Back and Forward UIWebView navigation (as distinct from the website navigation … ie. the buttons belong to the app, not the website, even though they look as though they could belong to the website)) which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m

What needed to change to integrate Blog Course Postings as extra functionality into the existing Learning Programming software was:

  • changes to design_a_course.php … to get this into context try reading WordPress Blog Course Design Cookies Tutorial and Learning Programming Android App
  • changes to the Learning Programming landing page as you can see here
  • changes to PHP code in this WordPress Blog’s document root’s wp-content/themes/twentyten/functions.php (in bold below … to get this into context try reading WordPress Blog Course Design Cookies Tutorial):

    if ( ! function_exists( 'may_be_obsolete' ) ) :
    /**
    * Truncate unknown previous/next.
    *
    * @since October 2014 by RJM Programming
    */
    function may_be_obsolete($proposed) {
    if (strpos($proposed, ">Previous") !== false) {
    if (strpos(($proposed . "&"), "&pp=&") !== false) {
    $bitsare = explode(">", $proposed);
    $nums = explode("=", str_replace("&", "=", str_replace("&pp=", "", str_replace("&pn", "", str_replace("?p=", "", $proposed)))));
    if ($nums[0] == $nums[1]) {
    $proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
    }
    }
    } else if (strpos($proposed, ">Next") !== false) {
    if (strpos(($proposed . "&"), "&pn=&") !== false) {
    $bitsare = explode(">", $proposed);
    $nums = explode("=", str_replace("&", "=", str_replace("&pn=", "", str_replace("&pp", "", str_replace("?p=", "", $proposed)))));
    if ($nums[0] == $nums[1]) {
    $proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
    }
    }
    }
    return $proposed;
    }
    endif;

    if ( ! function_exists( 'get_other_one' ) ) :
    /**
    * Get unknown previous/next.
    *
    * @since October 2014 by RJM Programming
    */
    function get_other_one($proposedp, $onetogetprefix, $onep) {
    if (file_exists("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
    $prehuh = file_get_contents("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $proposedp . $onetogetprefix . $xxpaa[0];
    } else if (file_exists("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
    $prehuh = file_get_contents("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $onep . $onetogetprefix . $xxpaa[0];
    }
    $huh = file_get_contents(dirname(__FILE__) . "/../../../../index.html");
    if ($proposedp == "") {
    $xxp = explode("?p=" . $onep . "&", $huh);
    if (sizeof($xxp) > 1) {
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $onep . $onetogetprefix . $xxpaa[0];
    }
    return $onep;
    } else {
    $xxp = explode("?p=" . $proposedp . "&", $huh);
    if (sizeof($xxp) > 1) {
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $proposedp . $onetogetprefix . $xxpaa[0];
    }
    return $proposedp;
    }
    return $proposedp;
    }
    endif;

    if ( ! function_exists( 'get_tutorial_topic' ) ) :
    /**
    * Get tutorial topic (word).
    *
    * @since October 2014 by RJM Programming
    */
    function get_tutorial_topic($thistopic) {
    $words = explode(" ", str_replace(" ", "++", str_replace("~~", "#~", $thistopic)));
    if (sizeof($words) > 1) {
    return " " . $words[0];
    }
    return "";
    }
    endif;

    if ( ! function_exists( 'previous_next' ) ) :
    /**
    * Allow for next and previous via &pn= and &pp= respectively.
    *
    * @since October 2014 by RJM Programming
    */
    function previous_next($both = true) {
    if (isset($_GET['pp']) || isset($_GET['pn'])) {
    $prefix = " id='atop";
    if ($both) $prefix = " id='abottom";
    $topic = "";
    $tget = "";

    $topsuff = "";
    $isuff = "#content";
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPad');
    if ($isiPad === false) {
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPhone');
    }
    if ($isiPad === false) {
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'Android');
    }
    if ($isiPad) $isuff = "&content=y";

    if (isset($_GET['title'])) {
    $tget = "&title=" . $_GET['title'];
    $topic = str_replace("~", " ", get_tutorial_topic(str_replace("_", " ", $_GET['title'])));
    if ($both) $topsuff = "  <a href='#content' title='Back to " . str_replace("~", " ", $_GET['title']) . "'>^</a>  ";
    } else {
    $topic = str_replace("~", " ", get_tutorial_topic($post->title));
    }
    if (strpos(($_SERVER['QUERY_STRING'] . "&"), "&pp=&pn=&") !== false) {
    $prefix = $prefix;
    } else {
    echo "<table style='width:98%; background-color: #F6F5F1;'><tbody><tr>";
    $cbackto = "";
    if (isset($_GET['backto'])) $isuff = "&content=y";
    if (isset($_GET['backto'])) $cbackto = "&backto=" . urldecode($_GET['backto']);

    if (isset($_GET['pp'])) {
    echo "<th><a" . $prefix . "p' target=_blank title='Previous' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pp'], "&pp=", $_GET['p']) . "&pn=" . $_GET['p'] . $tget . $cbackto . "'>Previous" . $topic . " Suggestion") . "</a>" . $topsuff . "</th>";
    $topsuff = "";

    }
    if (isset($_GET['pn'])) {
    echo "<th>" . $topsuff . "<a" . $prefix . "n' target=_blank title='Next' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pn'], "&pn=", $_GET['p']) . "&pp=" . $_GET['p'] . $tget . $cbackto . "'>Next" . $topic . " Suggestion") . "</a><th>";
    }
    if (isset($_GET['backto'])) echo "<th><a target=_top href='" . urldecode($_GET['backto']) . "' title='Back to Learning Programming'>Learning Programming</a></th>";
    if ($both) {
    echo "</tr><tr>";
    if (isset($_GET['pp'])) {
    echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pp'] . $isuff . "' width=400 height=800></iframe></td>";
    }
    if (isset($_GET['pn'])) {
    echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pn'] . $isuff . "' width=400 height=800></iframe></td>";
    }
    echo "<td><a href='#content' title='Back to " . $topic . "'>" . $topic . "</a></td>";
    }
    echo "</tr></tbody></table>";
    }
    }
    }
    endif;

Thanks for visiting today’s tutorial.


Previous relevant Xcode iOS Dynamic UIButton Primer Tutorial is shown below.

Xcode iOS Dynamic UIButton Primer Tutorial

Xcode iOS Dynamic UIButton Primer Tutorial

Today we come at an Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue” … codename Uiol) from two sides:

  1. to show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small yellow circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code (which is still stuck on working out how to make toast in the morning before you get up, even before you thought you knew you wanted it … codename Wohtmtitmbygu_Ebutykywi)) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”).

We test the change’s deployment on a real iPad device today, the idea of which is somewhat verging on great, as you can’t rely on simulators forever, though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code for an iOS Web App which turns this WordPress Blog into a mobile app (of more use than the one of the tutorial below … because of the addition of two UIButtons for Back and Forward UIWebView navigation (as distinct from the website navigation … ie. the buttons belong to the app, not the website, even though they look as though they could belong to the website)) which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m

The only code that needed to change for Dynamic UIButton purposes is described via the link … ViewController.m


Previous relevant Xcode iOS Mobile Project Exporting Primer Tutorial is shown below.

Xcode iOS Mobile Project Exporting Primer Tutorial

Xcode iOS Mobile Project Exporting Primer Tutorial

The Xcode IDE, like many IDEs, holds that special fascination for the occasions when you, the user, (or youse, the users (chortle, chortle)) can go “File->New Project” as we showed, below, with the previous Xcode iOS Utility Application Primer Tutorial. With a couple more button presses the user will feel that satisfaction of making the fastest progress they can expect to ever feel progressing on a project. Today, though, we take that a little further along and say “we’ve got this Xcode iOS Mobile Project that we would like to ‘clone’ into a new project with a few tweaks because it is so close to what we want”. So you look around the File menu for mention of the word Export, as a first instinct, and, lo and behold it isn’t there … boo hoo. So we go off and find this very useful link, from which we “cherry pick” Diago’s advice, because it is all “déjà vu” all over again for me, and think we’ve gone through this mild pain before … thanks.

Do all the workings of “nib” files and/or “storyboards” come across? … Well, I hate to give away too many surprises so if you want to find out for yourself, view the tutorial, and/or have a sneak peek ?

Today, we show how, with the Xcode IDE and a bit of work the creation of a mobile application showing the use of a UIWebView, the contents being this WordPress Blog (but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”).

And today we show you some steps in deploying it to an iPad … say some steps, because it ignores all the first steps regarding registering with Apple as an iOS Developer and getting your iPad registered as a development device associated with your iOS Developer Account (accessible by its associated Apple ID) … your (provisioning) profile … because this had already been done with the iPad involved … but if you are into “thrills and spills” (it wasn’t quite as straightforward as shown) take a geek at the upgrade of the iPad’s iOS (operating system) to 8.0.2 and Xcode (on the laptop) to an SDK to suit iOS 8 … the “it’s a great bag of fruit, it’s a Silvertex iOS 8 suit” … very lame chortle, very lame chortle.

So, as with Android development, all this is like the “middle game” that we talked about in Android development, and put into context with Eclipse Android App Google Play Ready Primer Tutorial … with mobile development there are not so big “start games”, big to huge “middle games” and big “end games” (less big with Android “end games”).

As a general comment about Xcode iOS mobile development you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”).

This deployment to real devices, of course, is great, as you can’t rely on simulators forever, though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m


Previous relevant Xcode iOS Utility Application Primer Tutorial is shown below.

Xcode iOS Utility Application Primer Tutorial

Xcode iOS Utility Application Primer Tutorial

The Xcode IDE, like many IDEs, holds that special fascination for the occasions when you, the user, (or youse, the users (chortle, chortle)) can go “File->New Project”. With a couple more button presses the user will feel that satisfaction of making the fastest progress they can expect to ever feel progressing on a project.

This great feeling is well worth it, as long as the user doesn’t fall into the “post FNP navel gazing” period.

Today, we show how, with the Xcode IDE and a few button presses, with no coding (yet), the user can achieve giant leaps in their Xcode iOS Utility mobile application.

IDEs are worth discussing in relation to pros and cons with respect to this:

Pros are …

  1. speed of initial progress
  2. the clarity you get to do with the design aspects of seeing what you have after the initial non-coding FNP phase
  3. the main files you will ever need have been created in the right places with the correct permissions, etcetera
  4. any makefiles required will have been created and any additional files added will be handled by the IDE as far as keeping the (underlying) makefile up to date
  5. there is online help with IDE procedures and search engines are good with your IDE keyword
  6. multi-device scenarios catered for
  7. debugging facilities are great

Cons might be (my argument is that you can control lots of these with awareness)

  1. what to do after speed of initial progress (“post FNP navel gazing”?), and the hard slog begins (take some time between this and your next bit of work planning the first few more important bits of the “hard slog” to do)
  2. the design has a lot of similarities to other products “out there” (plan for some things you want to do that can be done in a variety of ways and pick a way that you have never tried before, if applicable)
  3. you may have lost that intimate awareness of where each file is and what its role is for your project (go to the Finder or Windows Explorer or other, and locate your project, and see what’s there, now, preferably)
  4. you lack intimate understanding of how to compile your code when it comes to porting it to another environment (the next IDE along, if applicable, may help with this (we hope))
  5. the relationship of code to GUI can be baffling (practice the GUI to code linkage points, and look around more when succeeding, and remember that the more you practice the better you get)
  6. the diversity of choice of environment is sometimes unnecessary and confusing (this is worth putting up with, especially as the more scenarios you test, the more solid your project is)
  7. you may debug your way to a less efficient and elegant solution (leave debugging to only deeply embedded issues or problems, rather than using it in any way like a design tool)

Think Pro 2. on its own, makes it worth while to use IDEs, as you can see what is behind you and ahead of you, and it helps you envisage the “big picture” of what you want to achieve overall.

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code which you may want to rename to AppDelegate.h, AppDelegate.m, MainViewController.h, MainViewController.m, FlipsideViewController.h, FlipsideViewController.m and main.m

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


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


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


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


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


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


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


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


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


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


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


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


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


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

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

Background Image Data URI Animation Tutorial

Background Image Data URI Animation Tutorial

Background Image Data URI Animation Tutorial

Regarding Background Image Data URI Sharing Long Term Recall Tutorial‘s “Dappled Light” web application …

  • background image (perhaps data URI based) can not only be applied to clobber the default image … but as of recently …
  • background image (perhaps data URI based) can form part of a multiple background image scenario … and as of today …
  • background image (perhaps data URI based) can form part of an animated background image scenario …

… though, as we found out at this useful link in the CSS scheme of “@keyframes” and “transitions” animation usage the “background” nor “background-image” are “animatable” leaving us to introduce new position: absolute HTML div elements into the equation and animate the (you guessed it, overlay fans) “opacity” CSS property.

You’d think, here, you might see an HTML input type=checkbox appearing with our remodelled user interactives, but we’ve instead used …

  • new emoji button with an animated border to indicate that what you choose local file wise, to follow, will be part of a background image animation … and if the user …
  • uses the keyboard in that first textbox to enter in a new image URL they can suffix a space to indicate they want that image to be a part of a background image animation scenario

… in a sixth draft dappled_light.html Dappled Light web application.


Previous relevant Background Image Data URI Sharing Long Term Recall Tutorial is shown below.

Background Image Data URI Sharing Long Term Recall Tutorial

Background Image Data URI Sharing Long Term Recall Tutorial

The implication of Background Image Data URI Sharing Tutorial‘s …

… effectively avoiding the need to ever need to use PHP file_get_contents to retrieve that /tmp/ content, which we found was quite a harrowing thing to try?!

… panning out to be a bug at our end (sorrrrrrrry), opens the door, today, to try out an idea we had regarding an email or SMS recipient’s “lived experience” regarding our Dappled Image Background Image Sharing web application when data URIs were involved with the originator piecing together their creation ahead of sending it to their chosen recipient.

You may have been reading this thread of postings earlier, and know we started using Document Root soft links, as per …

… meaning that our PHP helping legend_via_map.php changing in this way now starts creating Document Root soft links (as can happen on Linux and Unix and macOS) pointing back to the /tmp/ folder content, no longer a base64 data URI (as was the case with the Media YouTube Interfacer Interspersing Image Text Tutorial project style of legend_via_map.php interfacing usage) but actual image file contents

… to get around errors that could happen as the originator shaped to email or SMS a creation involving image data URI(s). The thing is, though, that our design only stores the /tmp/ (web server) content underpinning of the Document Root soft link for a couple of days in legend_via_map.php changing in this way

<?php

if (isset($_GET['getthisback']) || isset($_GET['andcleanup'])) {
if (isset($_GET['getthisback'])) {
$fnm=str_replace('+',' ',urldecode($_GET['getthisback']));
if (strpos($fnm, 'rjmprogramming.com.au/bigmedia_') !== false) {
//file_put_contents('xv.xv', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt');
if (!file_exists('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt')) {
//file_put_contents('xv0.xv0', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt');
echo "<html><body>Not Found is " . $fnm . "</body></html>";
} else {
//file_put_contents('xv1.xv1', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt vs ' . 'http://' . explode('//', $fnm)[1]);
$myfile = fopen('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt', "r") or die("Unable to open file!");
$img_file=fread($myfile,filesize('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt'));
fclose($myfile);
//file_put_contents('xv2.xv2', strlen($img_file) . ' /tmp/' . explode('.txt', basename($fnm))[0] . '.txt vs ' . 'http://' . explode('//', $fnm)[1]);
echo "<html><body><p id=pid>data:image/" . explode('.', $fnm)[-1 + sizeof(explode('.', $fnm))] . ';base64,' . base64_encode($img_file) . "</p></body></html>";
}
} else {
if (!file_exists($fnm)) {
echo "<html><body>Not found is " . $fnm . "</body></html>";
} else {
$myfile = fopen($fnm, "r") or die("Unable to open file!");
$img_file=fread($myfile,filesize($fnm));
fclose($myfile);
echo "<html><body><p id=pid>" . $img_file . "</p></body></html>";
}
}
}
if (isset($_GET['andcleanup'])) {
foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
$filemtime = filemtime($tfl);
if (time() - $filemtime >= 172800) {
unlink($tfl);
}
}
}

exit;
}

?>

… a period of time we consider generous for a recipient to attend to the communication’s link clicking, as interested. But what if that email or SMS link’s content has data URI content which a user may want to recall some days later? Well, we now add a new dropdown option …


Cache Data URIs (then Bookmark for later viewing)

… which instigates this Javascript when selecting …


alert('We are redirecting you to new webpage that is good to Bookmark (after a few seconds) for future reference, else image data URIs will be forgotten after a couple of days.');
location.href=document.URL.replace('cacheit=', 'cacheit=Y');

… and then accessing that debugged iframe (hosting the call to our helper PHP talked about above) onload event Javascript code …


function checkthis(iois) {
if (iois.src.indexOf('About_Us.htm') == -1) {
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }

if (aconto.body.innerHTML.toLowerCase().indexOf('not found is') != -1) {
aconto=aconto;
} else if (aconto.body.innerHTML.indexOf('</p>') != -1) {
dumappings.push(aconto.body.innerHTML.split('</p>')[0].split('>')[eval(-1 + aconto.body.innerHTML.split('</p>')[0].split('>').length)]);
if (numds == 2) {
duin=duin.replace(encodeURIComponent(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)])), encodeURIComponent(encodeURIComponent(dumappings[eval(-1 + dumappings.length)])));
} else {
while (duin.indexOf(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)])) != -1) {
duin=duin.replace(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)]), encodeURIComponent(dumappings[eval(-1 + dumappings.length)]));
}
while (duin.indexOf((dutmpfiles[eval(-1 + dutmpfiles.length)])) != -1) {
duin=duin.replace((dutmpfiles[eval(-1 + dutmpfiles.length)]), (dumappings[eval(-1 + dumappings.length)]));
}
}

}

}
}
}

… we are back with “originator data URI(s)” finding their way back to “recipient webpage data URI referencing background image” webpage data.

Then, should a recipient want to have the best chance of storing this scenario days out into the future we think it can work if …

  • the recipient just about immediately Bookmarks this webpage … perhaps supplying a better name (though we add document.URL length and current time snapshots to the webpage document title) …
  • later, for that recipient using that same web browser, we’re pretty sure within that two days of server retainment, no worries … and …
  • after those two days, even so (and we’re waiting ourselves, for two days to retest), we’re thinking should the recipient recall their scenario via (something like the Google Chrome) …

    Bookmarks -> Bookmark Manager -> Other Bookmarks -> (navigate to bottom bookmark named like ...) Dappled Light (11032 byte URL at Sun Apr 27 2025 14:07:35 GMT+1000 (Australian Eastern Standard Time)) - RJM Programming - April, 2025 ... thanks to https://stackoverflow.com/questions/20039765/how-to-apply-a-css-filter-to-a-background-image

    … that the web browser Cache will help out the recipient get back their background image data on the condition they haven’t cleared their web browser cache … that is

You can try emailing or SMSing to a recipient yourself with these new ideas in a fifth draft dappled_light.html Dappled Light web application.


Previous relevant Background Image Data URI Sharing Tutorial is shown below.

Background Image Data URI Sharing Tutorial

Background Image Data URI Sharing Tutorial

In yesterday’s Background Image Multiple Substances Tutorial we ended up with …

Email and SMS can fail when “substances” are data URIs. We see it as food for thought not attended to today.

… and today, we’re back with a solution involving …

  • for the originator (asking for a data URI into the mix of their creation) we’re now calling our helper PHP via Ajax (with a new twist)

    var zhr=null, zform=null;
    var dumappings=[], dutmpfiles=[];
    var duin='', numds=0;

    function nodu(inida) { // used as a wrapper before the email or SMS is sent off
    var outida=inida;
    for (var ia=0; ia<dumappings.length; ia++) {
    while (outida.indexOf(dumappings[ia]) != -1) {
    outida=outida.replace(dumappings[ia], dutmpfiles[ia]);
    }
    }
    return outida;
    }


    function showStuff() {
    if (zhr != null) {
    if (zhr.readyState == 4) {
    if (zhr.status == 200) {
    if (zhr.responseText.indexOf('</p>') != -1) {
    dutmpfiles.push(zhr.responseText.split('</p>')[0].split('>')[eval(-1 + zhr.responseText.split('</p>')[0].split('>').length)]);
    }
    zhr=null;
    }
    }
    }
    }


    function ajaxit(indu) {
    var urlis='//www.rjmprogramming.com.au/HTMLCSS/legend_via_map.php';
    zhr = new XMLHttpRequest();
    zform=new FormData();
    zform.append('urlbig', indu);
    dumappings.push(indu);
    zform.append('subject', '');
    zform.append('to', '');
    zform.append('cc', '');
    zform.append('bcc', '');
    zform.append('url', '');
    if (indu.indexOf('data:') == 0) {
    zform.append('softlink', indu.split('/')[1].split(';')[0].split(',')[0]);
    }

    zhr.open('post', urlis, true);
    zhr.onreadystatechange = showStuff;
    zhr.send(zform);
    }

    … meaning that our PHP helping legend_via_map.php changing in this way now starts creating Document Root soft links (as can happen on Linux and Unix and macOS) pointing back to the /tmp/ folder content, no longer a base64 data URI (as was the case with the Media YouTube Interfacer Interspersing Image Text Tutorial project style of legend_via_map.php interfacing usage) but actual image file contents
    <?php

    if ($_POST['to'] == '' && $_POST['subject'] == '' && $_POST['urlbig'] != '' && isset($_POST['bcc']) && isset($_POST['cc'])) {
    $vslook='';
    $vsind='0';
    if (strpos(('~' . $_POST['urlbig']), '~data') !== false) {
    if ($_POST['bcc'] == '') {
    foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
    if ($vslook == '') {
    $vslook=str_replace(' ','+',urldecode($_POST['urlbig']));
    }
    $versusind=explode('.', explode('bigmedia_', $tfl)[1])[0];
    if (isset($_POST['softlink']) && strpos($vslook, ';base64,') !== false) {
    if (file_get_contents($tfl) == base64_decode( explode(';base64,', $vslook)[1] )) {
    echo "<html><body><p id=pid style=display:none;>//www.rjmprogramming.com.au/" . basename($tfl) . "." . $_POST['softlink'] . "</p></body></html>";
    exit;
    }
    } else
    if (file_get_contents($tfl) == $vslook) {
    echo "<html><body><p id=pid style=display:none;>" . $tfl . "</p></body></html>";
    exit;
    }
    if (strlen($versusind) < strlen($vsind)) {
    $vsind=$vsind;
    } else if (strlen($versusind) > strlen($vsind)) {
    $vsind='' . (1 + intval($versusind));
    } else if ($versusind >= $vsind) {
    $vsind='' . (1 + intval($versusind));
    }
    $filemtime = filemtime($tfl);
    if (time() - $filemtime >= 172800) {
    unlink($tfl);
    }
    }
    if (isset($_POST['softlink'])) {
    file_put_contents('/tmp/bigmedia_' . $vsind . '.txt', base64_decode( explode(';base64,', str_replace(' ','+',urldecode($_POST['urlbig'])))[1] ) );
    if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink'])) {
    unlink($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink']);
    }
    exec('ln -s /tmp/bigmedia_' . $vsind . '.txt ' . $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink']);
    echo "<html><body><p id=pid style=display:none;>//www.rjmprogramming.com.au/bigmedia_" . $vsind . ".txt." . $_POST['softlink'] . "</p></body></html>";
    } else {

    file_put_contents('/tmp/bigmedia_' . $vsind . '.txt', str_replace(' ','+',urldecode($_POST['urlbig'])));
    echo "<html><body><p id=pid style=display:none;>/tmp/bigmedia_" . $vsind . ".txt</p></body></html>";
    }
    } else {
    if (strpos(strtolower($_POST['urlbig'] . '~'), ('%e2%80%a6~')) !== false || strpos(strtolower(urldecode($_POST['urlbig']) . '~'), (urldecode('%e2%80%a6') . '~')) !== false || 1 == 1) {
    if (file_exists('/tmp/bigmedia_' . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . '.txt')) {
    if ($_POST['cc'] == '1') {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    } else if (strlen($_POST['cc']) <= 1) {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    } else {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    }
    } else {
    foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
    if ($vslook == '') {
    $vslook=str_replace(' ','+',urldecode($_POST['urlbig']));
    }
    $thislook=file_get_contents($tfl);
    if (strpos($thislook, substr($vslook,0,(-13 + strlen($vslook)))) !== false) {
    if ($_POST['cc'] == '1') {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . $thislook . "'; parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    } else if (strlen($_POST['cc']) <= 1) {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    } else {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig0').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    }
    }
    $filemtime = filemtime($tfl);
    if (time() - $filemtime >= 172800) {
    unlink($tfl);
    }
    }
    }
    }
    }
    }
    exit;
    }

    ?>
    … effectively avoiding the need to ever need to use PHP file_get_contents to retrieve that /tmp/ content, which we found was quite a harrowing thing to try?!
  • for the receiver clicking an email or SMS link it used to be we’d map /tmp/*.txt mentions back to a data URI but now that is not needed anymore … phew!

You can try for yourself these new ideas in the fourth draft dappled_light.html Dappled Light web application.

Did you know?

We all benefit by building on what has been established before. We like it when “it feels like proof” trying something new, and verifying for yourself something you “were pretty sure was the case”. So it was today, for us, proving with a soft link usage that the mimetype assumed comes from the
ln -s [sourceFile] [targetFile]‘s [targetFile] very last file extension rather than any reference to [sourceFile] or it’s extension, and that the way you name the [sourceFile] does not have to reflect, file extension wise, that data that is in [sourceFile] necessarily.


Previous relevant Background Image Multiple Substances Tutorial is shown below.

Background Image Multiple Substances Tutorial

Background Image Multiple Substances Tutorial

Onto yesterday’s Background Image Substance Tutorial‘s work, today we allow for more CSS styling …

… as value adding propositions. To make the idea of multiple background images work we have to control …

  • a comma separated list of image “substances” for a CSS styling background: url([backgroundSubstance1]),url([backgroundSubstance2]) !important etcetera style of clause … to which we like to embellish via …
  • background-position and background-repeat … eg. background: url([backgroundSubstance1]) top left no-repeat,url([backgroundSubstance2]) bottom right no-repeat !important; … gets you so far, but to allow for …
  • opacity we prefix … eg. background: linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url([backgroundSubstance1]) top left no-repeat,linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url([backgroundSubstance2]) bottom right no-repeat !important; … the application of which is handled by the Javascript below, so as far as …
  • background-size goes we need Javascript to help out …

    var firsturl='//www.rjmprogramming.com.au/dappled_light.jpg', lastmultpos='', firstmultpos='top left', lasturl='', numb=2, actnumb=1;
    var prebrest=' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px ';
    var brest=' ' + firstmultpos + ' no-repeat';
    var blist='', bposlist='', bcomblist='';


    function dosize(dc) {
    var suffdc='';
    numb=2;
    while (actnumb > eval(numb * numb)) {
    numb++;
    }
    for (var ij=0; ij<actnumb; ij++) {
    if (suffdc == '') {
    suffdc=' !important; } .background-image { background-size: ' + ' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px';
    } else {
    suffdc+=',' + ' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px';
    }
    }
    return dc.replace(/url\(/g, 'linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url(') + suffdc;
    }

… in the third draft dappled_light.html Dappled Light web application.

Email and SMS can fail when “substances” are data URIs. We see it as food for thought not attended to today.


Previous relevant Background Image Substance Tutorial is shown below.

Background Image Substance Tutorial

Background Image Substance Tutorial

Yesterday’s Background Image CSS Primer Tutorial discussed …

  • style … but there’s also …
  • substance

… (ie. the image data source) to consider, embellishing yesterday’s …

an image

… break down of “substance” measures, as of and so yesterday.

We’re allowing for …

  • emoji 📁 (to 📂 and back) means by which user can browse for a local image file …

    var absare=[], iabs=0, kabs=0, jabs=0, acount=0, arwo=null,

    function arlook() { // via setInterval(arlook, 2000);
    if (arwo) {
    absare=arwo.document.getElementsByTagName('img');
    for (iabs=0; iabs<absare.length; iabs++) {
    if (('' + absare[iabs].id).indexOf('gb') == 0) {
    if (document.getElementById('myaudios').innerHTML.indexOf(absare[iabs].src) == -1) { // && absare[iabs].outerHTML.indexOf(' data-done') == -1) {
    document.getElementById('myaudios').innerHTML+=absare[iabs].outerHTML.replace('gb','gb' + acount).replace("<img ","<img style=display:none; data-duration=0 onloadedmetadata=\"this.setAttribute('data-duration','' + this.duration);\" ") + '<br>';
    document.getElementsByTagName('div')[0].style.backgroundImage='url(' + absare[iabs].src + ')';
    acount++;
    document.getElementById('alocal').innerHTML='📁';
    }
    }
    }
    }
    }

    … resolved to a data URI
  • first textbox means of image URL via …
    1. relative URL (to https://www.rjmprogramming.com.au that is) … or …
    2. absolute URL … or …
    3. data URI (have you ever noticed how Google Image searches of a Clip Art “Copy Image address” link so often results in such a data URI?)

… means by which a user can change their background image data source of display in the second draft dappled_light.html Dappled Light web application.

Note, too, with these changes, with all the functionality the first textbox has now, in order to make this information better disseminated for mobile users, we introduced a marquee-like “Eat at Joe’s” arrangement for it …


var origpl='', iorigpos=0, two=2;

function eatatjoes() { // via setInterval(eatatjoes, 100);
var atst='';
iorigpos+=two;
if (iorigpos >= eval('' + document.getElementById('mynum').placeholder.length)) {
iorigpos=0;
document.getElementById('mynum').placeholder=origpl;
} else {
atst=origpl.substring(0,iorigpos);
document.getElementById('mynum').placeholder=origpl.substring(iorigpos) + atst;
}
}


Previous relevant Background Image CSS Primer Tutorial is shown below.

Background Image CSS Primer Tutorial

Background Image CSS Primer Tutorial

There’s very little you miss out on, and a whole lot to gain, treating …

  • image data as one or more background images (to some other HTML element) … versus …
  • image data as one or more HTML img element(s)

For starters there are all the advantages involved with two webpage contributors stacked onto each other, both …

  • contributing to the display, as required … and …
  • able to be dynamically adjusted, in our favourite way, via Javascript DOM (or even serverside PHP ahead of all that clientside work)

… with background images, as we talked about with Multiple Background Image Blockquote Tutorial.

Today, the approach is CSS “hands on”. We select an image in this “first draft” dappled_light.html and load it up at the web server, using it as a background image, for an HTML div …


<style>
.background-image {
background-image: url('//www.rjmprogramming.com.au/dappled_light.jpg');
background-repeat: no-repeat;
background-size: contain;
}
</style>

… rather than document.body …


<div title='' class="background-image" style="width:100%;height:100%;"></div>

… via the great advice from this webpage.

From there on, our web application relies on how Javascript DOM can add HTML style element contributions into any old existing HTML element …


<div id=dstyles></div>

… dynamically to achieve dynamic display changes. Probably not needed, but makes us feel better coming back from a hashtag based URL from an email or SMS link is to add to the dynamic CSS clauses …


!important

Other than that, all pretty straightforward, and if working, can quickly allow a user to achieve a look vastly different to how they started, in a short time, and learn some CSS styling, perhaps, along the way.


Previous relevant Multiple Background Image Blockquote Tutorial is shown below.

Multiple Background Image Blockquote Tutorial

Multiple Background Image Blockquote Tutorial

Yesterday’s tutorial called Multiple Background Image Primer Tutorial, as shown below, made use of multiple background images. Today we find another use for them.

Today we offer an idea for styling of the HTML blockquote element (at this WordPress blog, for example).

We use separate background images for the opening and closing quote background images we put into play, and before we go further, we must thank the great CSS-Tricks website for this idea which was modified a little for our circumstances.

Think it is good to draw attention to the blockquote because it is usually used when important information is being imparted, and because that information is coming from a source offsite.

This multiple background image idea has great application for some of the “overlay” ideas that web designers often want to put into play. As far as this WordPress blog goes, its header.php changed as per the bold code below …


<style>
.
.
.

blockquote {
display: block;
padding: 18px;
border-top: 1px solid #e1cc89;
border-bottom: 1px solid #e1cc89;
margin: 5px;
text-indent: 4px;
background: url('closequote1.gif') bottom right no-repeat,url('openquote1.gif') top left no-repeat;
background-color: #faebbc;
}
blockquote p {
display: block;
padding: 18px;
margin: 5px;
text-indent: 4px;
background: url('closequote1.gif') bottom right no-repeat,url('openquote1.gif') top left no-repeat;
background-color: #faebbc;
}

.
.
.
</style>

Hope this tutorial is useful for you, or somebody with whom you want to share the information, and will leave you with an example, here, at this blog … How do I love thee? Let me count the ways. (Sonnet 43) by Elizabeth Barrett Browning

How do I love thee? Let me count the ways.
I love thee to the depth and breadth and height
My soul can reach, when feeling out of sight
For the ends of Being and ideal Grace.
I love thee to the level of everyday’s
Most quiet need, by sun and candle-light.
I love thee freely, as men strive for Right;
I love thee purely, as they turn from Praise.
I love thee with the passion put to use
In my old griefs, and with my childhood’s faith.
I love thee with a love I seemed to lose
With my lost saints – I love thee with the breath,
Smiles, tears, of all my life! – and, if God choose,
I shall but love thee better after death.


Previous relevant Multiple Background Image Primer Tutorial is shown below.

Multiple Background Image Primer Tutorial

Multiple Background Image Primer Tutorial

The last time we talked about the PHP web application called “Learning Programming” at this blog was with regard to some software integration that linked the “Learning Programming” web and (Android (at Google Play)) mobile application with this Blog web application with Xcode Learning Programming Blog Course Cookies Tutorial as shown below.

Today we do a bit of CSS working on the “Learning Programming” web and (Android) mobile application to add interest to the top functional area. Firstly thought of doing clipart or real photography to do a diploma border idea, but found that with the latter the mix of realia with stark web functionality was a bit jarring, and, on a first look, didn’t gel with any of the free clip art border image ideas out there, so plumped for a background image to the HTML table element involved, and realized, working with Paintbrush PNG image opacity (before it needs the CSS approach to opacity), that it would be okay to hive off that first image another one with a bit of transparent design to add a hint of educational paperwork to the project. Of course, an expert in graphic design would be throwing many more ideas at this, and implementing a great result, but am, today, showing you how multiple background images can be quite effective and refreshing … aaaaahhhhh.

So the Before Before vs After After infomercial today had these steps, roughly:

  • Show Before “Learning Programming” in Firefox web browser Before
  • Use Firebug to examine “Learning Programming” Firebug
  • Use Mac Grab application’s Selection tool to grab one for one copy of that area of webpage One for one
  • Use (Mac) Paintbrush application to:
    • Make transparent rectangle under web functionality of interest (with the HTML td element)
    • Save this image and make a copy
    • With the copy make an opaque thick blue border inside the rectangle of above
    • Draw in thinner paperwork/stationery lines
    • Give a slight 3d look by infilling those lines with a cyan 70% opacity rudimentary shadowing
    • Make all the orange areas transparent using the paintcan with a fully transparent colour selected
    • Save the second image
    • Paintbrush 1Paintbrush 2Paintbrush 3Paintbrush 4
  • Copy the images over to the website
  • Adjust “Learning Programming” PHP to change (the underlying HTML) as per bold bits below

    <style>
    #wrapperold h1{
    font:normal 24pt Arial;
    color:#FFFFFF;
    text-shadow: 0 1px 0 #ccc,
    0 2px 0 #c9c9c9,
    0 3px 0 #bbb,
    0 4px 0 #b9b9b9,
    0 5px 0 #aaa,
    0 6px 1px rgba(0,0,0,.1),
    0 0 5px rgba(0,0,0,.1),
    0 1px 3px rgba(0,0,0,.3),
    0 3px 5px rgba(0,0,0,.2),
    0 5px 10px rgba(0,0,0,.25),
    0 10px 10px rgba(0,0,0,.2),
    0 20px 20px rgba(0,0,0,.15);
    }

    #thehead {
    background: url('lp_background.png'),url('lp_background2.png') no-repeat;
    }

    </style>
  • Show After “Learning Programming” in Firefox web browser After and see it as a live run
  • Have a ham sandwich with rhubarb and vegemite followed by a lemon curry chaser

Why no Gimp? Good question. It’s a public holiday hereabouts, and well, Gimp’s off to Bondi Beach today! Where’s Gimp?

Am hoping you give multiple background images a go one day should it suit your porpoise purpose … the heat’s getting to moi me.


Previous relevant Xcode Learning Programming Blog Course Cookies Tutorial is shown below.

Xcode Learning Programming Blog Course Cookies Tutorial

Xcode Learning Programming Blog Course Cookies Tutorial

Today we continue to make use of the ideas from two previous tutorials called Xcode iOS Dynamic UIButton Primer Tutorial as below and Xcode iOS Mobile Project Exporting Primer Tutorial as shown way below, covering the Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue”) to create an iOS mobile app for our Learning Programming idea extended to include the option of Blog Course Postings, and using dynamic UIButton to …

  1. show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

… but this time we tidy up some loose ends such as …

  • fixing a lack of functionality within the iOS mobile app’s UIWebView contents cookie processing regarding the “last” course blog posting used, by setting up our own “Clayton’s” cookies (ie. we use PHP to simulate cookies without there being cookies – which don’t always work in UIWebView without some consideration … another approach is shown with this link)
  • fixing an annoying feature of the work whereby with mobile apps any scrolling jumps are quite annoying, and we stop this happening for mobile platforms
  • adding an extra link to allow navigation to the top of the blog course posting once nearing the bottom, especially as this can represent a lot of scrolling on occasions and because once you are down the bottom it would be good to also see what you have just viewed in some way shape or form (issues like this are considerations for the UX area of knowledge)

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small red circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code ) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”). By the way, the pink circle shows a new web page link (not the app this time) to link back to the mobile app from the web page iframe element and the orange circle shows the “Last” (Blog Course Posting) link which, in this mobile scenario, on an iPad, would use our PHP “Clayton’s” cookies system.

We test the new changes deployed on a real iPad device today, the idea of which is more than somewhat verging on great, as you can’t rely on simulators forever (by the way, with iOS 8 simulators we had problems and we needed to consult with this link … where you may notice that we ended up reverting to iOS version 7.1 simulators … thanks), though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable PHP programming source code for an iOS Web App’s UIWebView’s underlying content, that is used when the platform is a mobile one, while the pre-existant coursecookies.html is still okay for non-mobile platforms which still use real cookies:

… and there were changes needed for PHP code in wp-content/themes/twentyten/header.php (the bold parts of which are particularly relevant to the last modifications) because it establishes the header Javascript and two sections of code are involved …


var ourck=location.search.split('ck=')[1] ? location.search.split('ck=')[1].split('&')[0] : '';
var ourpp=location.search.split('pp=')[1] ? location.search.split('pp=')[1].split('&')[0] : '';
var ourpn=location.search.split('pn=')[1] ? location.search.split('pn=')[1].split('&')[0] : '';
var ourpage=location.search.split('page_id=')[1] ? location.search.split('page_id=')[1].split('&')[0] : '';
var ourp=location.search.split('p=')[1] ? location.search.split('p=')[1].split('&')[0] : '';
var ourcourseurl='';
var ourcoursetitle='';

var ua = navigator.userAgent;
var isiPad = /iPad/i.test(ua) || /iPhone OS 3_1_2/i.test(ua) || /Android/i.test(ua) || /iPhone OS 3_2_2/i.test(ua);

if (isiPad) {
<?php
//echo "n alert('*" . $_SERVER['REQUEST_URI'] . "*'); n";
if (strpos(($_SERVER['REQUEST_URI'] . "*"), "?p*") !== false) {
//echo "n alert('" . $_SERVER['QUERY_STRING'] . "'); n";

$cstuffis = "";

$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
if(preg_match('/(chromium)[ /]([w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ /]([w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ /]([w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ /]([w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ /]([w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ /]([w.]+)/', $ua))
$rma = '0'.$rma;

echo "n alert('" . $ua . "'); n";

if (file_exists(dirname(__FILE__) . "/../PHP/cookie_" . $rma . ".is")) {
$cstuffis = file_get_contents(dirname(__FILE__) . "/cookie_" . $rma . ".is");
} else if (file_exists(dirname(__FILE__) . "/../../../PHP/cookie_" . $rma . ".is")) {
$cstuffis = file_get_contents(dirname(__FILE__) . "/../../../PHP/cookie_" . $rma . ".is");
}

if ($cstuffis != "") {
$actfs = explode("lastcourse=", $cstuffis);
if (sizeof($actfs) > 1) {
$aactfs = explode(";", $actfs[1]);
if ($aactfs[0] != "") echo "n location.href = '" . $aactfs[0] . "'; n";
}
}
}
?>
}

… at the top just under <script type=’text/javascript’> and …

function topViaDelay() {
parent.scroll(0, 0);
}

function courseCookies() {

var ext = ".html"; // ".php"
var extp = ".html?"; // ".php"
var huhd = new Date();
if (isiPad) {
ext = ".php?date=" + huhd;
extp = ".php?date=" + huhd + "&";
if ((ourpp != "" || ourpn != "") && ourpp != ourp && ourpn != ourp) {
<?php
if ((isset($_GET['pp']) || isset($_GET['pn']))) {
if ($_GET['p'] != $_GET['pp'] && $_GET['p'] != $_GET['pn'] && ($_GET['pn'] . $_GET['pp']) != "") {

$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
if(preg_match('/(chromium)[ /]([w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ /]([w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ /]([w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ /]([w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ /]([w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ /]([w.]+)/', $ua))
$rma = '0'.$rma;

if (file_exists(dirname(__FILE__) . "/../PHP/coursecookies.html")) {
file_put_contents(dirname(__FILE__) . "/../PHP/cookie_" . $rma . ".is", "lastcourse=" . "http://" . $_SERVER['SERVER_NAME'] . ":" . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'] . "; ");
} else if (file_exists(dirname(__FILE__) . "/../../../../PHP/coursecookies.html")) {
// echo "n alert('" . dirname(__FILE__) . "/../../../../PHP/coursecookies.html" . "'); n";
file_put_contents(dirname(__FILE__) . "/../../../../PHP/cookie_" . $rma . ".is", "lastcourse=" . "http://" . $_SERVER['SERVER_NAME'] . ":" . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'] . "; ");
}
}
}
?>
}
}

if (document.URL.indexOf("#content") != -1) {
setTimeout(topViaDelay, 2000);
} else {
if ((ourpp != "" || ourpn != "") && ourpp != ourp && ourpn != ourp) {

document.getElementById("content").innerHTML = "<iframe width=1 height=1 id='myccor' src='" + document.URL.replace("/wordpress/?", "/PHP/coursecookies" + extp).replace("/wordpress/", "/PHP/coursecookies" + ext) + "'></iframe>" + document.getElementById("content").innerHTML;

setTimeout(topViaDelay, 2000);
} else {

document.getElementById("content").innerHTML = "<iframe width=1 height=1 id='myccor' src='../PHP/coursecookies" + ext + "'></iframe>" + document.getElementById("content").innerHTML;

}
}
}

</script>
</head>

<body onload="courseCookies();" <?php body_class(); ?>>

… around </script>

Thanks for visiting today’s tutorial.


Previous relevant Xcode Learning Programming Primer Tutorial is shown below.

Xcode Learning Programming Primer Tutorial

Xcode Learning Programming Primer Tutorial

Today we make use of the ideas from two previous tutorials called Xcode iOS Dynamic UIButton Primer Tutorial as below and Xcode iOS Mobile Project Exporting Primer Tutorial as shown way below, covering the Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue”) to create an iOS mobile app for our Learning Programming idea extended to include the option of Blog Course Postings, and using dynamic UIButton to:

  1. show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small red circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code ) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”). By the way, the green circle shows a new web page link (not the app this time) to link back to the mobile app from the web page iframe element.

We test the change’s deployment on a real iPad device today, the idea of which is somewhat verging on great, as you can’t rely on simulators forever (by the way, with iOS 8 simulators we had problems and we needed to consult with this link … where you may notice that we ended up reverting to iOS version 7.1 simulators … thanks), though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code for an iOS Web App which turns this WordPress Blog into a mobile app (of more use than the one of the tutorial below … because of the addition of two UIButtons for Back and Forward UIWebView navigation (as distinct from the website navigation … ie. the buttons belong to the app, not the website, even though they look as though they could belong to the website)) which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m

What needed to change to integrate Blog Course Postings as extra functionality into the existing Learning Programming software was:

  • changes to design_a_course.php … to get this into context try reading WordPress Blog Course Design Cookies Tutorial and Learning Programming Android App
  • changes to the Learning Programming landing page as you can see here
  • changes to PHP code in this WordPress Blog’s document root’s wp-content/themes/twentyten/functions.php (in bold below … to get this into context try reading WordPress Blog Course Design Cookies Tutorial):

    if ( ! function_exists( 'may_be_obsolete' ) ) :
    /**
    * Truncate unknown previous/next.
    *
    * @since October 2014 by RJM Programming
    */
    function may_be_obsolete($proposed) {
    if (strpos($proposed, ">Previous") !== false) {
    if (strpos(($proposed . "&"), "&pp=&") !== false) {
    $bitsare = explode(">", $proposed);
    $nums = explode("=", str_replace("&", "=", str_replace("&pp=", "", str_replace("&pn", "", str_replace("?p=", "", $proposed)))));
    if ($nums[0] == $nums[1]) {
    $proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
    }
    }
    } else if (strpos($proposed, ">Next") !== false) {
    if (strpos(($proposed . "&"), "&pn=&") !== false) {
    $bitsare = explode(">", $proposed);
    $nums = explode("=", str_replace("&", "=", str_replace("&pn=", "", str_replace("&pp", "", str_replace("?p=", "", $proposed)))));
    if ($nums[0] == $nums[1]) {
    $proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
    }
    }
    }
    return $proposed;
    }
    endif;

    if ( ! function_exists( 'get_other_one' ) ) :
    /**
    * Get unknown previous/next.
    *
    * @since October 2014 by RJM Programming
    */
    function get_other_one($proposedp, $onetogetprefix, $onep) {
    if (file_exists("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
    $prehuh = file_get_contents("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $proposedp . $onetogetprefix . $xxpaa[0];
    } else if (file_exists("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
    $prehuh = file_get_contents("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $onep . $onetogetprefix . $xxpaa[0];
    }
    $huh = file_get_contents(dirname(__FILE__) . "/../../../../index.html");
    if ($proposedp == "") {
    $xxp = explode("?p=" . $onep . "&", $huh);
    if (sizeof($xxp) > 1) {
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $onep . $onetogetprefix . $xxpaa[0];
    }
    return $onep;
    } else {
    $xxp = explode("?p=" . $proposedp . "&", $huh);
    if (sizeof($xxp) > 1) {
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $proposedp . $onetogetprefix . $xxpaa[0];
    }
    return $proposedp;
    }
    return $proposedp;
    }
    endif;

    if ( ! function_exists( 'get_tutorial_topic' ) ) :
    /**
    * Get tutorial topic (word).
    *
    * @since October 2014 by RJM Programming
    */
    function get_tutorial_topic($thistopic) {
    $words = explode(" ", str_replace(" ", "++", str_replace("~~", "#~", $thistopic)));
    if (sizeof($words) > 1) {
    return " " . $words[0];
    }
    return "";
    }
    endif;

    if ( ! function_exists( 'previous_next' ) ) :
    /**
    * Allow for next and previous via &pn= and &pp= respectively.
    *
    * @since October 2014 by RJM Programming
    */
    function previous_next($both = true) {
    if (isset($_GET['pp']) || isset($_GET['pn'])) {
    $prefix = " id='atop";
    if ($both) $prefix = " id='abottom";
    $topic = "";
    $tget = "";

    $topsuff = "";
    $isuff = "#content";
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPad');
    if ($isiPad === false) {
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPhone');
    }
    if ($isiPad === false) {
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'Android');
    }
    if ($isiPad) $isuff = "&content=y";

    if (isset($_GET['title'])) {
    $tget = "&title=" . $_GET['title'];
    $topic = str_replace("~", " ", get_tutorial_topic(str_replace("_", " ", $_GET['title'])));
    if ($both) $topsuff = "  <a href='#content' title='Back to " . str_replace("~", " ", $_GET['title']) . "'>^</a>  ";
    } else {
    $topic = str_replace("~", " ", get_tutorial_topic($post->title));
    }
    if (strpos(($_SERVER['QUERY_STRING'] . "&"), "&pp=&pn=&") !== false) {
    $prefix = $prefix;
    } else {
    echo "<table style='width:98%; background-color: #F6F5F1;'><tbody><tr>";
    $cbackto = "";
    if (isset($_GET['backto'])) $isuff = "&content=y";
    if (isset($_GET['backto'])) $cbackto = "&backto=" . urldecode($_GET['backto']);

    if (isset($_GET['pp'])) {
    echo "<th><a" . $prefix . "p' target=_blank title='Previous' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pp'], "&pp=", $_GET['p']) . "&pn=" . $_GET['p'] . $tget . $cbackto . "'>Previous" . $topic . " Suggestion") . "</a>" . $topsuff . "</th>";
    $topsuff = "";

    }
    if (isset($_GET['pn'])) {
    echo "<th>" . $topsuff . "<a" . $prefix . "n' target=_blank title='Next' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pn'], "&pn=", $_GET['p']) . "&pp=" . $_GET['p'] . $tget . $cbackto . "'>Next" . $topic . " Suggestion") . "</a><th>";
    }
    if (isset($_GET['backto'])) echo "<th><a target=_top href='" . urldecode($_GET['backto']) . "' title='Back to Learning Programming'>Learning Programming</a></th>";
    if ($both) {
    echo "</tr><tr>";
    if (isset($_GET['pp'])) {
    echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pp'] . $isuff . "' width=400 height=800></iframe></td>";
    }
    if (isset($_GET['pn'])) {
    echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pn'] . $isuff . "' width=400 height=800></iframe></td>";
    }
    echo "<td><a href='#content' title='Back to " . $topic . "'>" . $topic . "</a></td>";
    }
    echo "</tr></tbody></table>";
    }
    }
    }
    endif;

Thanks for visiting today’s tutorial.


Previous relevant Xcode iOS Dynamic UIButton Primer Tutorial is shown below.

Xcode iOS Dynamic UIButton Primer Tutorial

Xcode iOS Dynamic UIButton Primer Tutorial

Today we come at an Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue” … codename Uiol) from two sides:

  1. to show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small yellow circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code (which is still stuck on working out how to make toast in the morning before you get up, even before you thought you knew you wanted it … codename Wohtmtitmbygu_Ebutykywi)) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”).

We test the change’s deployment on a real iPad device today, the idea of which is somewhat verging on great, as you can’t rely on simulators forever, though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code for an iOS Web App which turns this WordPress Blog into a mobile app (of more use than the one of the tutorial below … because of the addition of two UIButtons for Back and Forward UIWebView navigation (as distinct from the website navigation … ie. the buttons belong to the app, not the website, even though they look as though they could belong to the website)) which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m

The only code that needed to change for Dynamic UIButton purposes is described via the link … ViewController.m


Previous relevant Xcode iOS Mobile Project Exporting Primer Tutorial is shown below.

Xcode iOS Mobile Project Exporting Primer Tutorial

Xcode iOS Mobile Project Exporting Primer Tutorial

The Xcode IDE, like many IDEs, holds that special fascination for the occasions when you, the user, (or youse, the users (chortle, chortle)) can go “File->New Project” as we showed, below, with the previous Xcode iOS Utility Application Primer Tutorial. With a couple more button presses the user will feel that satisfaction of making the fastest progress they can expect to ever feel progressing on a project. Today, though, we take that a little further along and say “we’ve got this Xcode iOS Mobile Project that we would like to ‘clone’ into a new project with a few tweaks because it is so close to what we want”. So you look around the File menu for mention of the word Export, as a first instinct, and, lo and behold it isn’t there … boo hoo. So we go off and find this very useful link, from which we “cherry pick” Diago’s advice, because it is all “déjà vu” all over again for me, and think we’ve gone through this mild pain before … thanks.

Do all the workings of “nib” files and/or “storyboards” come across? … Well, I hate to give away too many surprises so if you want to find out for yourself, view the tutorial, and/or have a sneak peek ?

Today, we show how, with the Xcode IDE and a bit of work the creation of a mobile application showing the use of a UIWebView, the contents being this WordPress Blog (but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”).

And today we show you some steps in deploying it to an iPad … say some steps, because it ignores all the first steps regarding registering with Apple as an iOS Developer and getting your iPad registered as a development device associated with your iOS Developer Account (accessible by its associated Apple ID) … your (provisioning) profile … because this had already been done with the iPad involved … but if you are into “thrills and spills” (it wasn’t quite as straightforward as shown) take a geek at the upgrade of the iPad’s iOS (operating system) to 8.0.2 and Xcode (on the laptop) to an SDK to suit iOS 8 … the “it’s a great bag of fruit, it’s a Silvertex iOS 8 suit” … very lame chortle, very lame chortle.

So, as with Android development, all this is like the “middle game” that we talked about in Android development, and put into context with Eclipse Android App Google Play Ready Primer Tutorial … with mobile development there are not so big “start games”, big to huge “middle games” and big “end games” (less big with Android “end games”).

As a general comment about Xcode iOS mobile development you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”).

This deployment to real devices, of course, is great, as you can’t rely on simulators forever, though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m


Previous relevant Xcode iOS Utility Application Primer Tutorial is shown below.

Xcode iOS Utility Application Primer Tutorial

Xcode iOS Utility Application Primer Tutorial

The Xcode IDE, like many IDEs, holds that special fascination for the occasions when you, the user, (or youse, the users (chortle, chortle)) can go “File->New Project”. With a couple more button presses the user will feel that satisfaction of making the fastest progress they can expect to ever feel progressing on a project.

This great feeling is well worth it, as long as the user doesn’t fall into the “post FNP navel gazing” period.

Today, we show how, with the Xcode IDE and a few button presses, with no coding (yet), the user can achieve giant leaps in their Xcode iOS Utility mobile application.

IDEs are worth discussing in relation to pros and cons with respect to this:

Pros are …

  1. speed of initial progress
  2. the clarity you get to do with the design aspects of seeing what you have after the initial non-coding FNP phase
  3. the main files you will ever need have been created in the right places with the correct permissions, etcetera
  4. any makefiles required will have been created and any additional files added will be handled by the IDE as far as keeping the (underlying) makefile up to date
  5. there is online help with IDE procedures and search engines are good with your IDE keyword
  6. multi-device scenarios catered for
  7. debugging facilities are great

Cons might be (my argument is that you can control lots of these with awareness)

  1. what to do after speed of initial progress (“post FNP navel gazing”?), and the hard slog begins (take some time between this and your next bit of work planning the first few more important bits of the “hard slog” to do)
  2. the design has a lot of similarities to other products “out there” (plan for some things you want to do that can be done in a variety of ways and pick a way that you have never tried before, if applicable)
  3. you may have lost that intimate awareness of where each file is and what its role is for your project (go to the Finder or Windows Explorer or other, and locate your project, and see what’s there, now, preferably)
  4. you lack intimate understanding of how to compile your code when it comes to porting it to another environment (the next IDE along, if applicable, may help with this (we hope))
  5. the relationship of code to GUI can be baffling (practice the GUI to code linkage points, and look around more when succeeding, and remember that the more you practice the better you get)
  6. the diversity of choice of environment is sometimes unnecessary and confusing (this is worth putting up with, especially as the more scenarios you test, the more solid your project is)
  7. you may debug your way to a less efficient and elegant solution (leave debugging to only deeply embedded issues or problems, rather than using it in any way like a design tool)

Think Pro 2. on its own, makes it worth while to use IDEs, as you can see what is behind you and ahead of you, and it helps you envisage the “big picture” of what you want to achieve overall.

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code which you may want to rename to AppDelegate.h, AppDelegate.m, MainViewController.h, MainViewController.m, FlipsideViewController.h, FlipsideViewController.m and main.m

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


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


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


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


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


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


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


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


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


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


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


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


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

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

Python List via PHP Revisit Tutorial

Python List via PHP Revisit Tutorial

Python List via PHP Revisit Tutorial

Back in 2014, with Python List Primer Tutorial … http://www.python.org/, there’s not much doubt we had more hair but does that stop you having bad hair days? Well, Google Crawl thinks not!

We got alerted to a webpage created back in 2014 that may have only been coded, seriously, regarding http: protocol usage, not working in the current day and age where https: protocol is pushed on content providers more and more. On an Apache web server’s website the default port used is different, as per …

Protocol Default Port
http: 80
https: 443

… and am not sure we catered for this back in 2014 … but these days?!

<?php

$htmlurl=str_replace(":80/","/",str_replace(":443/","/","http://" . $_SERVER['SERVER_NAME'] . ":" . $_SERVER['SERVER_PORT'] . "" . str_replace('.php','.html',explode('?',$_SERVER['REQUEST_URI'])[0])));
// Python helps write out the HTML in the middle, here ... and then ...
header("Location: " . $htmlurl);

?>

Anyway, Python syntax changes too, so it was our fault (sorrrrrrrrrrrry) we needed a changed listwork.py and an initial spurt and a second “embellishment” spurt set of goes improving on listwork.php‘s Python List supervising PHP web application you might feel like retrying.


Previous relevant Python List Primer Tutorial … http://www.python.org/ is shown below.

Python List Primer Tutorial ... http://www.python.org/

Python List Primer Tutorial ... http://www.python.org/

In this tutorial we examine some functionality code snippets suiting Python list data structure, in response to, really, and extending, a Yahoo Answers question. Lists, like tuples, are interesting in that different base data types that can’t cohabit an array can be part of a list, or tuple. This tutorial builds on the Python Primer Tutorial of previous times, presented below. Let’s see immediately below what Wikipedia says about the very interesting Python programming language.

Python is a programming language that lets you work more quickly and integrate your systems more effectively. You can learn to use Python and see almost immediate gains in productivity and lower maintenance costs.

In this primer tutorial you can see some list usage in Python for a Linux Bash session via the Mac laptop application Terminal.

Here is another Python tutorial called Python Processing Directory Filespec Primer Tutorial.

Link to downloadable Python programming source code which can be renamed to listwork.py here.

Want to see it as a live run? This is more problematic with cgi-bin default language of Perl and server-side language of PHP, as at our web server. However there is a way to redirect the output of a PHP exec call of the Python into some HTML and show that (easiest in the root directory of the website), and then this (kind of awkward (… but would be pretty easy to make it less awkward)) live run is possible. The programming PHP source code for this is listwork.php here. The Three P’s ride again (Perl is sick today, so rides as a hologram)! But she’s a gem (chortle, chortle).

Link to Python website … Home of Python … where quote up the top resides
Link to a very useful Python tuple tutorial which helped with this tutorial, so, thanks … Useful Python tuple tutorial
Link to Python jobs done … Python jobs done … personal experience
And yes, it’s true … the language name is a fond reference to Monty Python


Previous Python Primer Tutorial is shown below.

Python Primer Tutorial ... http://www.python.org/

Python Primer Tutorial ... http://www.python.org/

Have you heard of Python?

Python is a programming language that lets you work more quickly and integrate your systems more effectively. You can learn to use Python and see almost immediate gains in productivity and lower maintenance costs.

Have used it for Games Programming and it is great at parsing XML via the SAX API.

Python has some really interesting data structures such as tuples, lists, sets, dictionaries for instance … read more here.

In this primer tutorial you can see some snapshots showing examples of use.

Here is another Python tutorial called Python Processing Directory Filespec Primer Tutorial.

Link to Python website … Home of Python … where quote up the top resides
Link to Python jobs done … Python jobs done … personal experience
And yes, it’s true … the language name is a fond reference to Monty Python


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


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

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

Background Image Data URI Sharing Long Term Recall Tutorial

Background Image Data URI Sharing Long Term Recall Tutorial

Background Image Data URI Sharing Long Term Recall Tutorial

The implication of Background Image Data URI Sharing Tutorial‘s …

… effectively avoiding the need to ever need to use PHP file_get_contents to retrieve that /tmp/ content, which we found was quite a harrowing thing to try?!

… panning out to be a bug at our end (sorrrrrrrry), opens the door, today, to try out an idea we had regarding an email or SMS recipient’s “lived experience” regarding our Dappled Image Background Image Sharing web application when data URIs were involved with the originator piecing together their creation ahead of sending it to their chosen recipient.

You may have been reading this thread of postings earlier, and know we started using Document Root soft links, as per …

… meaning that our PHP helping legend_via_map.php changing in this way now starts creating Document Root soft links (as can happen on Linux and Unix and macOS) pointing back to the /tmp/ folder content, no longer a base64 data URI (as was the case with the Media YouTube Interfacer Interspersing Image Text Tutorial project style of legend_via_map.php interfacing usage) but actual image file contents

… to get around errors that could happen as the originator shaped to email or SMS a creation involving image data URI(s). The thing is, though, that our design only stores the /tmp/ (web server) content underpinning of the Document Root soft link for a couple of days in legend_via_map.php changing in this way

<?php

if (isset($_GET['getthisback']) || isset($_GET['andcleanup'])) {
if (isset($_GET['getthisback'])) {
$fnm=str_replace('+',' ',urldecode($_GET['getthisback']));
if (strpos($fnm, 'rjmprogramming.com.au/bigmedia_') !== false) {
//file_put_contents('xv.xv', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt');
if (!file_exists('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt')) {
//file_put_contents('xv0.xv0', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt');
echo "<html><body>Not Found is " . $fnm . "</body></html>";
} else {
//file_put_contents('xv1.xv1', '/tmp/' . explode('.txt', basename($fnm))[0] . '.txt vs ' . 'http://' . explode('//', $fnm)[1]);
$myfile = fopen('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt', "r") or die("Unable to open file!");
$img_file=fread($myfile,filesize('/tmp/' . explode('.txt', basename($fnm))[0] . '.txt'));
fclose($myfile);
//file_put_contents('xv2.xv2', strlen($img_file) . ' /tmp/' . explode('.txt', basename($fnm))[0] . '.txt vs ' . 'http://' . explode('//', $fnm)[1]);
echo "<html><body><p id=pid>data:image/" . explode('.', $fnm)[-1 + sizeof(explode('.', $fnm))] . ';base64,' . base64_encode($img_file) . "</p></body></html>";
}
} else {
if (!file_exists($fnm)) {
echo "<html><body>Not found is " . $fnm . "</body></html>";
} else {
$myfile = fopen($fnm, "r") or die("Unable to open file!");
$img_file=fread($myfile,filesize($fnm));
fclose($myfile);
echo "<html><body><p id=pid>" . $img_file . "</p></body></html>";
}
}
}
if (isset($_GET['andcleanup'])) {
foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
$filemtime = filemtime($tfl);
if (time() - $filemtime >= 172800) {
unlink($tfl);
}
}
}

exit;
}

?>

… a period of time we consider generous for a recipient to attend to the communication’s link clicking, as interested. But what if that email or SMS link’s content has data URI content which a user may want to recall some days later? Well, we now add a new dropdown option …


Cache Data URIs (then Bookmark for later viewing)

… which instigates this Javascript when selecting …


alert('We are redirecting you to new webpage that is good to Bookmark (after a few seconds) for future reference, else image data URIs will be forgotten after a couple of days.');
location.href=document.URL.replace('cacheit=', 'cacheit=Y');

… and then accessing that debugged iframe (hosting the call to our helper PHP talked about above) onload event Javascript code …


function checkthis(iois) {
if (iois.src.indexOf('About_Us.htm') == -1) {
var aconto = (iois.contentWindow || iois.contentDocument);
if (aconto != null) {
if (aconto.document) { aconto = aconto.document; }

if (aconto.body.innerHTML.toLowerCase().indexOf('not found is') != -1) {
aconto=aconto;
} else if (aconto.body.innerHTML.indexOf('</p>') != -1) {
dumappings.push(aconto.body.innerHTML.split('</p>')[0].split('>')[eval(-1 + aconto.body.innerHTML.split('</p>')[0].split('>').length)]);
if (numds == 2) {
duin=duin.replace(encodeURIComponent(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)])), encodeURIComponent(encodeURIComponent(dumappings[eval(-1 + dumappings.length)])));
} else {
while (duin.indexOf(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)])) != -1) {
duin=duin.replace(encodeURIComponent(dutmpfiles[eval(-1 + dutmpfiles.length)]), encodeURIComponent(dumappings[eval(-1 + dumappings.length)]));
}
while (duin.indexOf((dutmpfiles[eval(-1 + dutmpfiles.length)])) != -1) {
duin=duin.replace((dutmpfiles[eval(-1 + dutmpfiles.length)]), (dumappings[eval(-1 + dumappings.length)]));
}
}

}

}
}
}

… we are back with “originator data URI(s)” finding their way back to “recipient webpage data URI referencing background image” webpage data.

Then, should a recipient want to have the best chance of storing this scenario days out into the future we think it can work if …

  • the recipient just about immediately Bookmarks this webpage … perhaps supplying a better name (though we add document.URL length and current time snapshots to the webpage document title) …
  • later, for that recipient using that same web browser, we’re pretty sure within that two days of server retainment, no worries … and …
  • after those two days, even so (and we’re waiting ourselves, for two days to retest), we’re thinking should the recipient recall their scenario via (something like the Google Chrome) …

    Bookmarks -> Bookmark Manager -> Other Bookmarks -> (navigate to bottom bookmark named like ...) Dappled Light (11032 byte URL at Sun Apr 27 2025 14:07:35 GMT+1000 (Australian Eastern Standard Time)) - RJM Programming - April, 2025 ... thanks to https://stackoverflow.com/questions/20039765/how-to-apply-a-css-filter-to-a-background-image

    … that the web browser Cache will help out the recipient get back their background image data on the condition they haven’t cleared their web browser cache … that is

You can try emailing or SMSing to a recipient yourself with these new ideas in a fifth draft dappled_light.html Dappled Light web application.


Previous relevant Background Image Data URI Sharing Tutorial is shown below.

Background Image Data URI Sharing Tutorial

Background Image Data URI Sharing Tutorial

In yesterday’s Background Image Multiple Substances Tutorial we ended up with …

Email and SMS can fail when “substances” are data URIs. We see it as food for thought not attended to today.

… and today, we’re back with a solution involving …

  • for the originator (asking for a data URI into the mix of their creation) we’re now calling our helper PHP via Ajax (with a new twist)

    var zhr=null, zform=null;
    var dumappings=[], dutmpfiles=[];
    var duin='', numds=0;

    function nodu(inida) { // used as a wrapper before the email or SMS is sent off
    var outida=inida;
    for (var ia=0; ia<dumappings.length; ia++) {
    while (outida.indexOf(dumappings[ia]) != -1) {
    outida=outida.replace(dumappings[ia], dutmpfiles[ia]);
    }
    }
    return outida;
    }


    function showStuff() {
    if (zhr != null) {
    if (zhr.readyState == 4) {
    if (zhr.status == 200) {
    if (zhr.responseText.indexOf('</p>') != -1) {
    dutmpfiles.push(zhr.responseText.split('</p>')[0].split('>')[eval(-1 + zhr.responseText.split('</p>')[0].split('>').length)]);
    }
    zhr=null;
    }
    }
    }
    }


    function ajaxit(indu) {
    var urlis='//www.rjmprogramming.com.au/HTMLCSS/legend_via_map.php';
    zhr = new XMLHttpRequest();
    zform=new FormData();
    zform.append('urlbig', indu);
    dumappings.push(indu);
    zform.append('subject', '');
    zform.append('to', '');
    zform.append('cc', '');
    zform.append('bcc', '');
    zform.append('url', '');
    if (indu.indexOf('data:') == 0) {
    zform.append('softlink', indu.split('/')[1].split(';')[0].split(',')[0]);
    }

    zhr.open('post', urlis, true);
    zhr.onreadystatechange = showStuff;
    zhr.send(zform);
    }

    … meaning that our PHP helping legend_via_map.php changing in this way now starts creating Document Root soft links (as can happen on Linux and Unix and macOS) pointing back to the /tmp/ folder content, no longer a base64 data URI (as was the case with the Media YouTube Interfacer Interspersing Image Text Tutorial project style of legend_via_map.php interfacing usage) but actual image file contents
    <?php

    if ($_POST['to'] == '' && $_POST['subject'] == '' && $_POST['urlbig'] != '' && isset($_POST['bcc']) && isset($_POST['cc'])) {
    $vslook='';
    $vsind='0';
    if (strpos(('~' . $_POST['urlbig']), '~data') !== false) {
    if ($_POST['bcc'] == '') {
    foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
    if ($vslook == '') {
    $vslook=str_replace(' ','+',urldecode($_POST['urlbig']));
    }
    $versusind=explode('.', explode('bigmedia_', $tfl)[1])[0];
    if (isset($_POST['softlink']) && strpos($vslook, ';base64,') !== false) {
    if (file_get_contents($tfl) == base64_decode( explode(';base64,', $vslook)[1] )) {
    echo "<html><body><p id=pid style=display:none;>//www.rjmprogramming.com.au/" . basename($tfl) . "." . $_POST['softlink'] . "</p></body></html>";
    exit;
    }
    } else
    if (file_get_contents($tfl) == $vslook) {
    echo "<html><body><p id=pid style=display:none;>" . $tfl . "</p></body></html>";
    exit;
    }
    if (strlen($versusind) < strlen($vsind)) {
    $vsind=$vsind;
    } else if (strlen($versusind) > strlen($vsind)) {
    $vsind='' . (1 + intval($versusind));
    } else if ($versusind >= $vsind) {
    $vsind='' . (1 + intval($versusind));
    }
    $filemtime = filemtime($tfl);
    if (time() - $filemtime >= 172800) {
    unlink($tfl);
    }
    }
    if (isset($_POST['softlink'])) {
    file_put_contents('/tmp/bigmedia_' . $vsind . '.txt', base64_decode( explode(';base64,', str_replace(' ','+',urldecode($_POST['urlbig'])))[1] ) );
    if (file_exists($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink'])) {
    unlink($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink']);
    }
    exec('ln -s /tmp/bigmedia_' . $vsind . '.txt ' . $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . "bigmedia_" . $vsind . ".txt." . $_POST['softlink']);
    echo "<html><body><p id=pid style=display:none;>//www.rjmprogramming.com.au/bigmedia_" . $vsind . ".txt." . $_POST['softlink'] . "</p></body></html>";
    } else {

    file_put_contents('/tmp/bigmedia_' . $vsind . '.txt', str_replace(' ','+',urldecode($_POST['urlbig'])));
    echo "<html><body><p id=pid style=display:none;>/tmp/bigmedia_" . $vsind . ".txt</p></body></html>";
    }
    } else {
    if (strpos(strtolower($_POST['urlbig'] . '~'), ('%e2%80%a6~')) !== false || strpos(strtolower(urldecode($_POST['urlbig']) . '~'), (urldecode('%e2%80%a6') . '~')) !== false || 1 == 1) {
    if (file_exists('/tmp/bigmedia_' . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . '.txt')) {
    if ($_POST['cc'] == '1') {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    } else if (strlen($_POST['cc']) <= 1) {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    } else {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . file_get_contents('/tmp/bigmedia_' . $_POST['bcc'] . '.txt') . "'; \"><p id=pid style=display:none;>/tmp/bigmedia_" . trim(str_replace('+',' ',urldecode($_POST['bcc']))) . ".txt'</p></body></html>";
    }
    } else {
    foreach (glob('/tmp/bigmedia_*.txt') as $tfl) {
    if ($vslook == '') {
    $vslook=str_replace(' ','+',urldecode($_POST['urlbig']));
    }
    $thislook=file_get_contents($tfl);
    if (strpos($thislook, substr($vslook,0,(-13 + strlen($vslook)))) !== false) {
    if ($_POST['cc'] == '1') {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig').value='" . $thislook . "'; parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    } else if (strlen($_POST['cc']) <= 1) {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig" . $_POST['cc'] . "').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    } else {
    echo "<html><body onload=\" parent.document.getElementById('spareurlbig0').value='" . $thislook . "'; \"><p id=pid style=display:none;>" . $thislook . "</p></body></html>";
    }
    }
    $filemtime = filemtime($tfl);
    if (time() - $filemtime >= 172800) {
    unlink($tfl);
    }
    }
    }
    }
    }
    }
    exit;
    }

    ?>
    … effectively avoiding the need to ever need to use PHP file_get_contents to retrieve that /tmp/ content, which we found was quite a harrowing thing to try?!
  • for the receiver clicking an email or SMS link it used to be we’d map /tmp/*.txt mentions back to a data URI but now that is not needed anymore … phew!

You can try for yourself these new ideas in the fourth draft dappled_light.html Dappled Light web application.

Did you know?

We all benefit by building on what has been established before. We like it when “it feels like proof” trying something new, and verifying for yourself something you “were pretty sure was the case”. So it was today, for us, proving with a soft link usage that the mimetype assumed comes from the
ln -s [sourceFile] [targetFile]‘s [targetFile] very last file extension rather than any reference to [sourceFile] or it’s extension, and that the way you name the [sourceFile] does not have to reflect, file extension wise, that data that is in [sourceFile] necessarily.


Previous relevant Background Image Multiple Substances Tutorial is shown below.

Background Image Multiple Substances Tutorial

Background Image Multiple Substances Tutorial

Onto yesterday’s Background Image Substance Tutorial‘s work, today we allow for more CSS styling …

… as value adding propositions. To make the idea of multiple background images work we have to control …

  • a comma separated list of image “substances” for a CSS styling background: url([backgroundSubstance1]),url([backgroundSubstance2]) !important etcetera style of clause … to which we like to embellish via …
  • background-position and background-repeat … eg. background: url([backgroundSubstance1]) top left no-repeat,url([backgroundSubstance2]) bottom right no-repeat !important; … gets you so far, but to allow for …
  • opacity we prefix … eg. background: linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url([backgroundSubstance1]) top left no-repeat,linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url([backgroundSubstance2]) bottom right no-repeat !important; … the application of which is handled by the Javascript below, so as far as …
  • background-size goes we need Javascript to help out …

    var firsturl='//www.rjmprogramming.com.au/dappled_light.jpg', lastmultpos='', firstmultpos='top left', lasturl='', numb=2, actnumb=1;
    var prebrest=' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px ';
    var brest=' ' + firstmultpos + ' no-repeat';
    var blist='', bposlist='', bcomblist='';


    function dosize(dc) {
    var suffdc='';
    numb=2;
    while (actnumb > eval(numb * numb)) {
    numb++;
    }
    for (var ij=0; ij<actnumb; ij++) {
    if (suffdc == '') {
    suffdc=' !important; } .background-image { background-size: ' + ' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px';
    } else {
    suffdc+=',' + ' ' + eval(-15 + eval(screen.width / numb)) + 'px ' + eval(-15 + eval(screen.height / numb)) + 'px';
    }
    }
    return dc.replace(/url\(/g, 'linear-gradient(rgba(255,255,255,0.5),rgba(255,255,255,0.5)),url(') + suffdc;
    }

… in the third draft dappled_light.html Dappled Light web application.

Email and SMS can fail when “substances” are data URIs. We see it as food for thought not attended to today.


Previous relevant Background Image Substance Tutorial is shown below.

Background Image Substance Tutorial

Background Image Substance Tutorial

Yesterday’s Background Image CSS Primer Tutorial discussed …

  • style … but there’s also …
  • substance

… (ie. the image data source) to consider, embellishing yesterday’s …

an image

… break down of “substance” measures, as of and so yesterday.

We’re allowing for …

  • emoji 📁 (to 📂 and back) means by which user can browse for a local image file …

    var absare=[], iabs=0, kabs=0, jabs=0, acount=0, arwo=null,

    function arlook() { // via setInterval(arlook, 2000);
    if (arwo) {
    absare=arwo.document.getElementsByTagName('img');
    for (iabs=0; iabs<absare.length; iabs++) {
    if (('' + absare[iabs].id).indexOf('gb') == 0) {
    if (document.getElementById('myaudios').innerHTML.indexOf(absare[iabs].src) == -1) { // && absare[iabs].outerHTML.indexOf(' data-done') == -1) {
    document.getElementById('myaudios').innerHTML+=absare[iabs].outerHTML.replace('gb','gb' + acount).replace("<img ","<img style=display:none; data-duration=0 onloadedmetadata=\"this.setAttribute('data-duration','' + this.duration);\" ") + '<br>';
    document.getElementsByTagName('div')[0].style.backgroundImage='url(' + absare[iabs].src + ')';
    acount++;
    document.getElementById('alocal').innerHTML='📁';
    }
    }
    }
    }
    }

    … resolved to a data URI
  • first textbox means of image URL via …
    1. relative URL (to https://www.rjmprogramming.com.au that is) … or …
    2. absolute URL … or …
    3. data URI (have you ever noticed how Google Image searches of a Clip Art “Copy Image address” link so often results in such a data URI?)

… means by which a user can change their background image data source of display in the second draft dappled_light.html Dappled Light web application.

Note, too, with these changes, with all the functionality the first textbox has now, in order to make this information better disseminated for mobile users, we introduced a marquee-like “Eat at Joe’s” arrangement for it …


var origpl='', iorigpos=0, two=2;

function eatatjoes() { // via setInterval(eatatjoes, 100);
var atst='';
iorigpos+=two;
if (iorigpos >= eval('' + document.getElementById('mynum').placeholder.length)) {
iorigpos=0;
document.getElementById('mynum').placeholder=origpl;
} else {
atst=origpl.substring(0,iorigpos);
document.getElementById('mynum').placeholder=origpl.substring(iorigpos) + atst;
}
}


Previous relevant Background Image CSS Primer Tutorial is shown below.

Background Image CSS Primer Tutorial

Background Image CSS Primer Tutorial

There’s very little you miss out on, and a whole lot to gain, treating …

  • image data as one or more background images (to some other HTML element) … versus …
  • image data as one or more HTML img element(s)

For starters there are all the advantages involved with two webpage contributors stacked onto each other, both …

  • contributing to the display, as required … and …
  • able to be dynamically adjusted, in our favourite way, via Javascript DOM (or even serverside PHP ahead of all that clientside work)

… with background images, as we talked about with Multiple Background Image Blockquote Tutorial.

Today, the approach is CSS “hands on”. We select an image in this “first draft” dappled_light.html and load it up at the web server, using it as a background image, for an HTML div …


<style>
.background-image {
background-image: url('//www.rjmprogramming.com.au/dappled_light.jpg');
background-repeat: no-repeat;
background-size: contain;
}
</style>

… rather than document.body …


<div title='' class="background-image" style="width:100%;height:100%;"></div>

… via the great advice from this webpage.

From there on, our web application relies on how Javascript DOM can add HTML style element contributions into any old existing HTML element …


<div id=dstyles></div>

… dynamically to achieve dynamic display changes. Probably not needed, but makes us feel better coming back from a hashtag based URL from an email or SMS link is to add to the dynamic CSS clauses …


!important

Other than that, all pretty straightforward, and if working, can quickly allow a user to achieve a look vastly different to how they started, in a short time, and learn some CSS styling, perhaps, along the way.


Previous relevant Multiple Background Image Blockquote Tutorial is shown below.

Multiple Background Image Blockquote Tutorial

Multiple Background Image Blockquote Tutorial

Yesterday’s tutorial called Multiple Background Image Primer Tutorial, as shown below, made use of multiple background images. Today we find another use for them.

Today we offer an idea for styling of the HTML blockquote element (at this WordPress blog, for example).

We use separate background images for the opening and closing quote background images we put into play, and before we go further, we must thank the great CSS-Tricks website for this idea which was modified a little for our circumstances.

Think it is good to draw attention to the blockquote because it is usually used when important information is being imparted, and because that information is coming from a source offsite.

This multiple background image idea has great application for some of the “overlay” ideas that web designers often want to put into play. As far as this WordPress blog goes, its header.php changed as per the bold code below …


<style>
.
.
.

blockquote {
display: block;
padding: 18px;
border-top: 1px solid #e1cc89;
border-bottom: 1px solid #e1cc89;
margin: 5px;
text-indent: 4px;
background: url('closequote1.gif') bottom right no-repeat,url('openquote1.gif') top left no-repeat;
background-color: #faebbc;
}
blockquote p {
display: block;
padding: 18px;
margin: 5px;
text-indent: 4px;
background: url('closequote1.gif') bottom right no-repeat,url('openquote1.gif') top left no-repeat;
background-color: #faebbc;
}

.
.
.
</style>

Hope this tutorial is useful for you, or somebody with whom you want to share the information, and will leave you with an example, here, at this blog … How do I love thee? Let me count the ways. (Sonnet 43) by Elizabeth Barrett Browning

How do I love thee? Let me count the ways.
I love thee to the depth and breadth and height
My soul can reach, when feeling out of sight
For the ends of Being and ideal Grace.
I love thee to the level of everyday’s
Most quiet need, by sun and candle-light.
I love thee freely, as men strive for Right;
I love thee purely, as they turn from Praise.
I love thee with the passion put to use
In my old griefs, and with my childhood’s faith.
I love thee with a love I seemed to lose
With my lost saints – I love thee with the breath,
Smiles, tears, of all my life! – and, if God choose,
I shall but love thee better after death.


Previous relevant Multiple Background Image Primer Tutorial is shown below.

Multiple Background Image Primer Tutorial

Multiple Background Image Primer Tutorial

The last time we talked about the PHP web application called “Learning Programming” at this blog was with regard to some software integration that linked the “Learning Programming” web and (Android (at Google Play)) mobile application with this Blog web application with Xcode Learning Programming Blog Course Cookies Tutorial as shown below.

Today we do a bit of CSS working on the “Learning Programming” web and (Android) mobile application to add interest to the top functional area. Firstly thought of doing clipart or real photography to do a diploma border idea, but found that with the latter the mix of realia with stark web functionality was a bit jarring, and, on a first look, didn’t gel with any of the free clip art border image ideas out there, so plumped for a background image to the HTML table element involved, and realized, working with Paintbrush PNG image opacity (before it needs the CSS approach to opacity), that it would be okay to hive off that first image another one with a bit of transparent design to add a hint of educational paperwork to the project. Of course, an expert in graphic design would be throwing many more ideas at this, and implementing a great result, but am, today, showing you how multiple background images can be quite effective and refreshing … aaaaahhhhh.

So the Before Before vs After After infomercial today had these steps, roughly:

  • Show Before “Learning Programming” in Firefox web browser Before
  • Use Firebug to examine “Learning Programming” Firebug
  • Use Mac Grab application’s Selection tool to grab one for one copy of that area of webpage One for one
  • Use (Mac) Paintbrush application to:
    • Make transparent rectangle under web functionality of interest (with the HTML td element)
    • Save this image and make a copy
    • With the copy make an opaque thick blue border inside the rectangle of above
    • Draw in thinner paperwork/stationery lines
    • Give a slight 3d look by infilling those lines with a cyan 70% opacity rudimentary shadowing
    • Make all the orange areas transparent using the paintcan with a fully transparent colour selected
    • Save the second image
    • Paintbrush 1Paintbrush 2Paintbrush 3Paintbrush 4
  • Copy the images over to the website
  • Adjust “Learning Programming” PHP to change (the underlying HTML) as per bold bits below

    <style>
    #wrapperold h1{
    font:normal 24pt Arial;
    color:#FFFFFF;
    text-shadow: 0 1px 0 #ccc,
    0 2px 0 #c9c9c9,
    0 3px 0 #bbb,
    0 4px 0 #b9b9b9,
    0 5px 0 #aaa,
    0 6px 1px rgba(0,0,0,.1),
    0 0 5px rgba(0,0,0,.1),
    0 1px 3px rgba(0,0,0,.3),
    0 3px 5px rgba(0,0,0,.2),
    0 5px 10px rgba(0,0,0,.25),
    0 10px 10px rgba(0,0,0,.2),
    0 20px 20px rgba(0,0,0,.15);
    }

    #thehead {
    background: url('lp_background.png'),url('lp_background2.png') no-repeat;
    }

    </style>
  • Show After “Learning Programming” in Firefox web browser After and see it as a live run
  • Have a ham sandwich with rhubarb and vegemite followed by a lemon curry chaser

Why no Gimp? Good question. It’s a public holiday hereabouts, and well, Gimp’s off to Bondi Beach today! Where’s Gimp?

Am hoping you give multiple background images a go one day should it suit your porpoise purpose … the heat’s getting to moi me.


Previous relevant Xcode Learning Programming Blog Course Cookies Tutorial is shown below.

Xcode Learning Programming Blog Course Cookies Tutorial

Xcode Learning Programming Blog Course Cookies Tutorial

Today we continue to make use of the ideas from two previous tutorials called Xcode iOS Dynamic UIButton Primer Tutorial as below and Xcode iOS Mobile Project Exporting Primer Tutorial as shown way below, covering the Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue”) to create an iOS mobile app for our Learning Programming idea extended to include the option of Blog Course Postings, and using dynamic UIButton to …

  1. show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

… but this time we tidy up some loose ends such as …

  • fixing a lack of functionality within the iOS mobile app’s UIWebView contents cookie processing regarding the “last” course blog posting used, by setting up our own “Clayton’s” cookies (ie. we use PHP to simulate cookies without there being cookies – which don’t always work in UIWebView without some consideration … another approach is shown with this link)
  • fixing an annoying feature of the work whereby with mobile apps any scrolling jumps are quite annoying, and we stop this happening for mobile platforms
  • adding an extra link to allow navigation to the top of the blog course posting once nearing the bottom, especially as this can represent a lot of scrolling on occasions and because once you are down the bottom it would be good to also see what you have just viewed in some way shape or form (issues like this are considerations for the UX area of knowledge)

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small red circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code ) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”). By the way, the pink circle shows a new web page link (not the app this time) to link back to the mobile app from the web page iframe element and the orange circle shows the “Last” (Blog Course Posting) link which, in this mobile scenario, on an iPad, would use our PHP “Clayton’s” cookies system.

We test the new changes deployed on a real iPad device today, the idea of which is more than somewhat verging on great, as you can’t rely on simulators forever (by the way, with iOS 8 simulators we had problems and we needed to consult with this link … where you may notice that we ended up reverting to iOS version 7.1 simulators … thanks), though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable PHP programming source code for an iOS Web App’s UIWebView’s underlying content, that is used when the platform is a mobile one, while the pre-existant coursecookies.html is still okay for non-mobile platforms which still use real cookies:

… and there were changes needed for PHP code in wp-content/themes/twentyten/header.php (the bold parts of which are particularly relevant to the last modifications) because it establishes the header Javascript and two sections of code are involved …


var ourck=location.search.split('ck=')[1] ? location.search.split('ck=')[1].split('&')[0] : '';
var ourpp=location.search.split('pp=')[1] ? location.search.split('pp=')[1].split('&')[0] : '';
var ourpn=location.search.split('pn=')[1] ? location.search.split('pn=')[1].split('&')[0] : '';
var ourpage=location.search.split('page_id=')[1] ? location.search.split('page_id=')[1].split('&')[0] : '';
var ourp=location.search.split('p=')[1] ? location.search.split('p=')[1].split('&')[0] : '';
var ourcourseurl='';
var ourcoursetitle='';

var ua = navigator.userAgent;
var isiPad = /iPad/i.test(ua) || /iPhone OS 3_1_2/i.test(ua) || /Android/i.test(ua) || /iPhone OS 3_2_2/i.test(ua);

if (isiPad) {
<?php
//echo "n alert('*" . $_SERVER['REQUEST_URI'] . "*'); n";
if (strpos(($_SERVER['REQUEST_URI'] . "*"), "?p*") !== false) {
//echo "n alert('" . $_SERVER['QUERY_STRING'] . "'); n";

$cstuffis = "";

$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
if(preg_match('/(chromium)[ /]([w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ /]([w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ /]([w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ /]([w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ /]([w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ /]([w.]+)/', $ua))
$rma = '0'.$rma;

echo "n alert('" . $ua . "'); n";

if (file_exists(dirname(__FILE__) . "/../PHP/cookie_" . $rma . ".is")) {
$cstuffis = file_get_contents(dirname(__FILE__) . "/cookie_" . $rma . ".is");
} else if (file_exists(dirname(__FILE__) . "/../../../PHP/cookie_" . $rma . ".is")) {
$cstuffis = file_get_contents(dirname(__FILE__) . "/../../../PHP/cookie_" . $rma . ".is");
}

if ($cstuffis != "") {
$actfs = explode("lastcourse=", $cstuffis);
if (sizeof($actfs) > 1) {
$aactfs = explode(";", $actfs[1]);
if ($aactfs[0] != "") echo "n location.href = '" . $aactfs[0] . "'; n";
}
}
}
?>
}

… at the top just under <script type=’text/javascript’> and …

function topViaDelay() {
parent.scroll(0, 0);
}

function courseCookies() {

var ext = ".html"; // ".php"
var extp = ".html?"; // ".php"
var huhd = new Date();
if (isiPad) {
ext = ".php?date=" + huhd;
extp = ".php?date=" + huhd + "&";
if ((ourpp != "" || ourpn != "") && ourpp != ourp && ourpn != ourp) {
<?php
if ((isset($_GET['pp']) || isset($_GET['pn']))) {
if ($_GET['p'] != $_GET['pp'] && $_GET['p'] != $_GET['pn'] && ($_GET['pn'] . $_GET['pp']) != "") {

$rma = $_SERVER['REMOTE_ADDR'];
$ua = strtolower($_SERVER['HTTP_USER_AGENT']);
// you can add different browsers with the same way ..
if(preg_match('/(chromium)[ /]([w.]+)/', $ua))
$rma = '000000'.$rma;
elseif(preg_match('/(chrome)[ /]([w.]+)/', $ua))
$rma = '00000'.$rma;
elseif(preg_match('/(safari)[ /]([w.]+)/', $ua))
$rma = '0000'.$rma;
elseif(preg_match('/(opera)[ /]([w.]+)/', $ua))
$rma = '000'.$rma;
elseif(preg_match('/(msie)[ /]([w.]+)/', $ua))
$rma = '00'.$rma;
elseif(preg_match('/(mozilla)[ /]([w.]+)/', $ua))
$rma = '0'.$rma;

if (file_exists(dirname(__FILE__) . "/../PHP/coursecookies.html")) {
file_put_contents(dirname(__FILE__) . "/../PHP/cookie_" . $rma . ".is", "lastcourse=" . "http://" . $_SERVER['SERVER_NAME'] . ":" . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'] . "; ");
} else if (file_exists(dirname(__FILE__) . "/../../../../PHP/coursecookies.html")) {
// echo "n alert('" . dirname(__FILE__) . "/../../../../PHP/coursecookies.html" . "'); n";
file_put_contents(dirname(__FILE__) . "/../../../../PHP/cookie_" . $rma . ".is", "lastcourse=" . "http://" . $_SERVER['SERVER_NAME'] . ":" . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'] . "; ");
}
}
}
?>
}
}

if (document.URL.indexOf("#content") != -1) {
setTimeout(topViaDelay, 2000);
} else {
if ((ourpp != "" || ourpn != "") && ourpp != ourp && ourpn != ourp) {

document.getElementById("content").innerHTML = "<iframe width=1 height=1 id='myccor' src='" + document.URL.replace("/wordpress/?", "/PHP/coursecookies" + extp).replace("/wordpress/", "/PHP/coursecookies" + ext) + "'></iframe>" + document.getElementById("content").innerHTML;

setTimeout(topViaDelay, 2000);
} else {

document.getElementById("content").innerHTML = "<iframe width=1 height=1 id='myccor' src='../PHP/coursecookies" + ext + "'></iframe>" + document.getElementById("content").innerHTML;

}
}
}

</script>
</head>

<body onload="courseCookies();" <?php body_class(); ?>>

… around </script>

Thanks for visiting today’s tutorial.


Previous relevant Xcode Learning Programming Primer Tutorial is shown below.

Xcode Learning Programming Primer Tutorial

Xcode Learning Programming Primer Tutorial

Today we make use of the ideas from two previous tutorials called Xcode iOS Dynamic UIButton Primer Tutorial as below and Xcode iOS Mobile Project Exporting Primer Tutorial as shown way below, covering the Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue”) to create an iOS mobile app for our Learning Programming idea extended to include the option of Blog Course Postings, and using dynamic UIButton to:

  1. show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small red circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code ) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”). By the way, the green circle shows a new web page link (not the app this time) to link back to the mobile app from the web page iframe element.

We test the change’s deployment on a real iPad device today, the idea of which is somewhat verging on great, as you can’t rely on simulators forever (by the way, with iOS 8 simulators we had problems and we needed to consult with this link … where you may notice that we ended up reverting to iOS version 7.1 simulators … thanks), though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code for an iOS Web App which turns this WordPress Blog into a mobile app (of more use than the one of the tutorial below … because of the addition of two UIButtons for Back and Forward UIWebView navigation (as distinct from the website navigation … ie. the buttons belong to the app, not the website, even though they look as though they could belong to the website)) which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m

What needed to change to integrate Blog Course Postings as extra functionality into the existing Learning Programming software was:

  • changes to design_a_course.php … to get this into context try reading WordPress Blog Course Design Cookies Tutorial and Learning Programming Android App
  • changes to the Learning Programming landing page as you can see here
  • changes to PHP code in this WordPress Blog’s document root’s wp-content/themes/twentyten/functions.php (in bold below … to get this into context try reading WordPress Blog Course Design Cookies Tutorial):

    if ( ! function_exists( 'may_be_obsolete' ) ) :
    /**
    * Truncate unknown previous/next.
    *
    * @since October 2014 by RJM Programming
    */
    function may_be_obsolete($proposed) {
    if (strpos($proposed, ">Previous") !== false) {
    if (strpos(($proposed . "&"), "&pp=&") !== false) {
    $bitsare = explode(">", $proposed);
    $nums = explode("=", str_replace("&", "=", str_replace("&pp=", "", str_replace("&pn", "", str_replace("?p=", "", $proposed)))));
    if ($nums[0] == $nums[1]) {
    $proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
    }
    }
    } else if (strpos($proposed, ">Next") !== false) {
    if (strpos(($proposed . "&"), "&pn=&") !== false) {
    $bitsare = explode(">", $proposed);
    $nums = explode("=", str_replace("&", "=", str_replace("&pn=", "", str_replace("&pp", "", str_replace("?p=", "", $proposed)))));
    if ($nums[0] == $nums[1]) {
    $proposed = str_replace($bitsare[sizeof($bitsare) - 1], "", $proposed);
    }
    }
    }
    return $proposed;
    }
    endif;

    if ( ! function_exists( 'get_other_one' ) ) :
    /**
    * Get unknown previous/next.
    *
    * @since October 2014 by RJM Programming
    */
    function get_other_one($proposedp, $onetogetprefix, $onep) {
    if (file_exists("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
    $prehuh = file_get_contents("../PHP/" . $proposedp . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $proposedp . $onetogetprefix . $xxpaa[0];
    } else if (file_exists("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg")) {
    $prehuh = file_get_contents("../PHP/" . $onep . "_" . $_SERVER['REMOTE_ADDR'] . ".npg");
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $prehuh);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $onep . $onetogetprefix . $xxpaa[0];
    }
    $huh = file_get_contents(dirname(__FILE__) . "/../../../../index.html");
    if ($proposedp == "") {
    $xxp = explode("?p=" . $onep . "&", $huh);
    if (sizeof($xxp) > 1) {
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $onep . $onetogetprefix . $xxpaa[0];
    }
    return $onep;
    } else {
    $xxp = explode("?p=" . $proposedp . "&", $huh);
    if (sizeof($xxp) > 1) {
    $xxpa = explode(str_replace("&", "", $onetogetprefix), $xxp[1]);
    $xxpaa = explode("&", $xxpa[sizeof($xxpa) - 1]);
    return $proposedp . $onetogetprefix . $xxpaa[0];
    }
    return $proposedp;
    }
    return $proposedp;
    }
    endif;

    if ( ! function_exists( 'get_tutorial_topic' ) ) :
    /**
    * Get tutorial topic (word).
    *
    * @since October 2014 by RJM Programming
    */
    function get_tutorial_topic($thistopic) {
    $words = explode(" ", str_replace(" ", "++", str_replace("~~", "#~", $thistopic)));
    if (sizeof($words) > 1) {
    return " " . $words[0];
    }
    return "";
    }
    endif;

    if ( ! function_exists( 'previous_next' ) ) :
    /**
    * Allow for next and previous via &pn= and &pp= respectively.
    *
    * @since October 2014 by RJM Programming
    */
    function previous_next($both = true) {
    if (isset($_GET['pp']) || isset($_GET['pn'])) {
    $prefix = " id='atop";
    if ($both) $prefix = " id='abottom";
    $topic = "";
    $tget = "";

    $topsuff = "";
    $isuff = "#content";
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPad');
    if ($isiPad === false) {
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'iPhone');
    }
    if ($isiPad === false) {
    $isiPad = (bool) strpos($_SERVER['HTTP_USER_AGENT'],'Android');
    }
    if ($isiPad) $isuff = "&content=y";

    if (isset($_GET['title'])) {
    $tget = "&title=" . $_GET['title'];
    $topic = str_replace("~", " ", get_tutorial_topic(str_replace("_", " ", $_GET['title'])));
    if ($both) $topsuff = "  <a href='#content' title='Back to " . str_replace("~", " ", $_GET['title']) . "'>^</a>  ";
    } else {
    $topic = str_replace("~", " ", get_tutorial_topic($post->title));
    }
    if (strpos(($_SERVER['QUERY_STRING'] . "&"), "&pp=&pn=&") !== false) {
    $prefix = $prefix;
    } else {
    echo "<table style='width:98%; background-color: #F6F5F1;'><tbody><tr>";
    $cbackto = "";
    if (isset($_GET['backto'])) $isuff = "&content=y";
    if (isset($_GET['backto'])) $cbackto = "&backto=" . urldecode($_GET['backto']);

    if (isset($_GET['pp'])) {
    echo "<th><a" . $prefix . "p' target=_blank title='Previous' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pp'], "&pp=", $_GET['p']) . "&pn=" . $_GET['p'] . $tget . $cbackto . "'>Previous" . $topic . " Suggestion") . "</a>" . $topsuff . "</th>";
    $topsuff = "";

    }
    if (isset($_GET['pn'])) {
    echo "<th>" . $topsuff . "<a" . $prefix . "n' target=_blank title='Next' href='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . may_be_obsolete(get_other_one($_GET['pn'], "&pn=", $_GET['p']) . "&pp=" . $_GET['p'] . $tget . $cbackto . "'>Next" . $topic . " Suggestion") . "</a><th>";
    }
    if (isset($_GET['backto'])) echo "<th><a target=_top href='" . urldecode($_GET['backto']) . "' title='Back to Learning Programming'>Learning Programming</a></th>";
    if ($both) {
    echo "</tr><tr>";
    if (isset($_GET['pp'])) {
    echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pp'] . $isuff . "' width=400 height=800></iframe></td>";
    }
    if (isset($_GET['pn'])) {
    echo "<td><iframe src='" . str_replace("?" . $_SERVER['QUERY_STRING'], "", $_SERVER['REQUEST_URI']) . "?p=" . $_GET['pn'] . $isuff . "' width=400 height=800></iframe></td>";
    }
    echo "<td><a href='#content' title='Back to " . $topic . "'>" . $topic . "</a></td>";
    }
    echo "</tr></tbody></table>";
    }
    }
    }
    endif;

Thanks for visiting today’s tutorial.


Previous relevant Xcode iOS Dynamic UIButton Primer Tutorial is shown below.

Xcode iOS Dynamic UIButton Primer Tutorial

Xcode iOS Dynamic UIButton Primer Tutorial

Today we come at an Xcode iOS Mobile App issue (ie. the “UIWebView ‘on its lonesome’ issue” … codename Uiol) from two sides:

  1. to show you how to add a dynamic UIButton at loading (if you want to know … thanks to the great Open Source community for all the ideas emanating from this link)
  2. also is one way to solve the UIWebView “on its lonesome” issue (when pointing at URLs without total navigational integrity (ie. they have a tags with target=’_blank’ for instance)) … ‘(but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”)’ … mentioned in Xcode iOS Mobile Project Exporting Primer Tutorial as shown below

As a general comment about Xcode iOS mobile development (but please note that the idea of step 1. above circumvents the complication … by the way, the two small yellow circles in the tutorial picture are me showing you where the Back and Forward buttons are (rather than the code (which is still stuck on working out how to make toast in the morning before you get up, even before you thought you knew you wanted it … codename Wohtmtitmbygu_Ebutykywi)) … now that iOS 8 buttons have no background by default it is sometimes necessary to point them out) you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”).

We test the change’s deployment on a real iPad device today, the idea of which is somewhat verging on great, as you can’t rely on simulators forever, though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code for an iOS Web App which turns this WordPress Blog into a mobile app (of more use than the one of the tutorial below … because of the addition of two UIButtons for Back and Forward UIWebView navigation (as distinct from the website navigation … ie. the buttons belong to the app, not the website, even though they look as though they could belong to the website)) which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m

The only code that needed to change for Dynamic UIButton purposes is described via the link … ViewController.m


Previous relevant Xcode iOS Mobile Project Exporting Primer Tutorial is shown below.

Xcode iOS Mobile Project Exporting Primer Tutorial

Xcode iOS Mobile Project Exporting Primer Tutorial

The Xcode IDE, like many IDEs, holds that special fascination for the occasions when you, the user, (or youse, the users (chortle, chortle)) can go “File->New Project” as we showed, below, with the previous Xcode iOS Utility Application Primer Tutorial. With a couple more button presses the user will feel that satisfaction of making the fastest progress they can expect to ever feel progressing on a project. Today, though, we take that a little further along and say “we’ve got this Xcode iOS Mobile Project that we would like to ‘clone’ into a new project with a few tweaks because it is so close to what we want”. So you look around the File menu for mention of the word Export, as a first instinct, and, lo and behold it isn’t there … boo hoo. So we go off and find this very useful link, from which we “cherry pick” Diago’s advice, because it is all “déjà vu” all over again for me, and think we’ve gone through this mild pain before … thanks.

Do all the workings of “nib” files and/or “storyboards” come across? … Well, I hate to give away too many surprises so if you want to find out for yourself, view the tutorial, and/or have a sneak peek ?

Today, we show how, with the Xcode IDE and a bit of work the creation of a mobile application showing the use of a UIWebView, the contents being this WordPress Blog (but please know such a scenario is not good without also providing, at least, buttons for the equivalent functionality as the web browser’s back and forward buttons … remember, with UIWebView there is no address bar, and no multiple tabs nor windows … if your webpage has complete forward and backward navigational integrity that could suit a UIWebView “on its lonesome”).

And today we show you some steps in deploying it to an iPad … say some steps, because it ignores all the first steps regarding registering with Apple as an iOS Developer and getting your iPad registered as a development device associated with your iOS Developer Account (accessible by its associated Apple ID) … your (provisioning) profile … because this had already been done with the iPad involved … but if you are into “thrills and spills” (it wasn’t quite as straightforward as shown) take a geek at the upgrade of the iPad’s iOS (operating system) to 8.0.2 and Xcode (on the laptop) to an SDK to suit iOS 8 … the “it’s a great bag of fruit, it’s a Silvertex iOS 8 suit” … very lame chortle, very lame chortle.

So, as with Android development, all this is like the “middle game” that we talked about in Android development, and put into context with Eclipse Android App Google Play Ready Primer Tutorial … with mobile development there are not so big “start games”, big to huge “middle games” and big “end games” (less big with Android “end games”).

As a general comment about Xcode iOS mobile development you must try to get efficient at the linking (or “connecting”) of “nib” file and/or “storyboard” GUI objects to your ViewController.h code and for this, we’d really like to defer to a YouTube video we mentioned in a tutorial a long time back called Wish me luck … 1 of ?) iOS Hello World on iPhone 5 simulator … since then have worked out, with some web browsers, how to lob you at the exact bit, and am hoping you get straight to that bit with this link (please have sound up to hear of role of the “control” button “while dragging”).

This deployment to real devices, of course, is great, as you can’t rely on simulators forever, though the options in this field grow, as you can imagine, because it is impossible to keep up owning all the gadgetry you’d need as a programmer to test for everything with real devices. Don’t confuse this “middle game” “quality assurance” or “unit test” concept with the concept of an “end game” deployment as an Apple App Store app (where there are quite a few extra steps to undertake). When dealing with real devices you will need:

  • the device … doh, chortle, doh, chortle
  • the Mac OS X laptop that runs Xcode
  • the white lead that temporarily connects your iPad or iPhone or iPod mobile device with your Mac OS X laptop that runs Xcode
  • a lack of fear of all things “sync”
  • the iTunes device (up arrow eject) button to safely eject the device (similar functionality as Windows icon right-click Eject options (in Windows Explorer))

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code which you may want to rename to AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m and main.m


Previous relevant Xcode iOS Utility Application Primer Tutorial is shown below.

Xcode iOS Utility Application Primer Tutorial

Xcode iOS Utility Application Primer Tutorial

The Xcode IDE, like many IDEs, holds that special fascination for the occasions when you, the user, (or youse, the users (chortle, chortle)) can go “File->New Project”. With a couple more button presses the user will feel that satisfaction of making the fastest progress they can expect to ever feel progressing on a project.

This great feeling is well worth it, as long as the user doesn’t fall into the “post FNP navel gazing” period.

Today, we show how, with the Xcode IDE and a few button presses, with no coding (yet), the user can achieve giant leaps in their Xcode iOS Utility mobile application.

IDEs are worth discussing in relation to pros and cons with respect to this:

Pros are …

  1. speed of initial progress
  2. the clarity you get to do with the design aspects of seeing what you have after the initial non-coding FNP phase
  3. the main files you will ever need have been created in the right places with the correct permissions, etcetera
  4. any makefiles required will have been created and any additional files added will be handled by the IDE as far as keeping the (underlying) makefile up to date
  5. there is online help with IDE procedures and search engines are good with your IDE keyword
  6. multi-device scenarios catered for
  7. debugging facilities are great

Cons might be (my argument is that you can control lots of these with awareness)

  1. what to do after speed of initial progress (“post FNP navel gazing”?), and the hard slog begins (take some time between this and your next bit of work planning the first few more important bits of the “hard slog” to do)
  2. the design has a lot of similarities to other products “out there” (plan for some things you want to do that can be done in a variety of ways and pick a way that you have never tried before, if applicable)
  3. you may have lost that intimate awareness of where each file is and what its role is for your project (go to the Finder or Windows Explorer or other, and locate your project, and see what’s there, now, preferably)
  4. you lack intimate understanding of how to compile your code when it comes to porting it to another environment (the next IDE along, if applicable, may help with this (we hope))
  5. the relationship of code to GUI can be baffling (practice the GUI to code linkage points, and look around more when succeeding, and remember that the more you practice the better you get)
  6. the diversity of choice of environment is sometimes unnecessary and confusing (this is worth putting up with, especially as the more scenarios you test, the more solid your project is)
  7. you may debug your way to a less efficient and elegant solution (leave debugging to only deeply embedded issues or problems, rather than using it in any way like a design tool)

Think Pro 2. on its own, makes it worth while to use IDEs, as you can see what is behind you and ahead of you, and it helps you envisage the “big picture” of what you want to achieve overall.

Here is a link to some downloadable Xcode (on a Mac laptop) Objective-C programming source code which you may want to rename to AppDelegate.h, AppDelegate.m, MainViewController.h, MainViewController.m, FlipsideViewController.h, FlipsideViewController.m and main.m

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


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


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


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


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


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


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


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


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


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


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


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

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

Google Translate Image Input Primer Tutorial

Google Translate Image Input Primer Tutorial

Google Translate Image Input Primer Tutorial

Today’s tutorial brings together …

Opera web browser talents regarding … … meets … Google Translate talents regarding …
Image Screen Capture … copied to … Image option … Paste from clipboard

… as a means by which an image basis of input can have it’s extracted text be translated into languages other than it’s source via Google Translate. Please note, here, that the image basis does not have to be as “clear cut text” as today’s animated GIF translation example is showing.

Cute, huh?! Thanks, everybody!

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

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

HTML Template Tag Primer Tutorial

HTML Template Tag Primer Tutorial

HTML Template Tag Primer Tutorial

In amongst yesterday’s online newspaper readings a graph on the news.com.au article ‘We’ve never been asked’: Uncomfortable truth about immigration debate titled “Overseas migrant arrivals by country of birth” (A Flourish bar chart race) intrigued us. Wow, what a great interactive resource! We started using the web browser’s web inspector to start analyzing it, and found out it used at it’s heart the HTML …

template

… tag. Here it is in action …

Amazing, huh?! Well, we wanted to explore more about …

… to arrive at a “proof of concept” second draft HTML Template Experimenting web application, on our quest to understand how functionality can effectively “be packaged” into these template element types, and we’ll probably be returning to.

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

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