WordPress Emoji Menu Revamp Tutorial

WordPress Emoji Menu Revamp Tutorial

WordPress Emoji Menu Revamp Tutorial

We really like HTML iframe usage around here. In terms of …

Software Need Not Be Hard

… being our company byline, they tick a lot of boxes. You’ll read online, though, issues with security and whatnot regarding them, so, as with all these matters, it is better to read around. However, if you intend building up lots of web applications in your domain, online, HTML iframe elements …

  1. allow for chance to modularize …
  2. without it, necessarily, looking clunky … as well as …
  3. is a means to introduce onload event logic not tied to document.body onload event … like a chance to “reset” … as well as …
  4. can be a means, what we like to call “Client Pre-emptive Iframe” thinking, to test for the existence of a URL … as well as …
  5. the HTML iframe name attribute can tee up with second argument of Javascript window.open to think of “the dreaded popup window actually being the more acceptable iframe window (relatively speaking)” … as well as …
  6. the HTML iframe src attribute is a good Javascript DOM access point to use an iframe when you know the URL … versus …
  7. the HTML iframe srcdoc attribute is a good Javascript DOM access point to use an iframe when you know the content

Hence, iframe usage got front and centre when thinking on how to revamp the Emoji Menu arrangements, at this blog, talked about at WordPress Emoji Menu Primer Tutorial. That old arrangement opened new (second _blank arguments to window.open) to new windows, only, and felt a bit over the top, to us, especially because these Emoji Menus predominantly showcased Inhouse Web Applications. Why not, at least, involve HTML iframe elements into the mix?

That got us adjusting a WordPress “Emoji Menu” Page for “clicking the Emoji Menu, here at this blog (or in new window), purposes” scenario and then there was the changed emoji_widget_idea.htm standalone Emoji Menu web application we wrote for the “hovering over the Emoji Menu, here at this blog, purposes” scenario.

We think the filling in of webpage space to the right of the Emoji Menu dropdown element is more elegant. What do you think?


Previous relevant WordPress Emoji Menu Primer Tutorial is shown below.

WordPress Emoji Menu Primer Tutorial

WordPress Emoji Menu Primer Tutorial

The Emoji Menu concept mentioned in the previous Fixed Sticky Header Top Window Document Tutorial has been the inspiration to …

  • add a new WordPress primary menu level “Emoji Menu” option (via the WordPress administration section’s Add Page option) … that …
  • onclick calls a (WordPress) Page that is a select (dropdown) element size=9 (for non-mobile browser usefulness) whose innerHTML (ie. what you see) consists of emojis … and on a selection …
  • opens into a new webpage a web application from the RJM Programming domain … similarly for the …
  • onmouseover (hover (Ajax feeling functionality), for non-mobile browser usefulness) immediate display of a (smaller) select (dropdown) element directly below the “Emoji Menu” option heading … facilitated by a changed header.php coding change …

    <script type="text/javascript">
    function donow() {
    var sbitis='<select size=9 id="emojih" onchange=window.open(this.value,"_blank");><option title="Web Audio" style="cursor:pointer;text-decoration:none;font-size:36px;" target="iweb_audio" id="aweb_audio" value="//www.rjmprogramming.com.au/HTMLCSS/web_audio.htm">&#128266;</option><option title="Square Hr Tracing" style="cursor:pointer;text-decoration:none;font-size:36px;" target="isquare_hr_tracing" id="asquare_hr_tracing" value="//www.rjmprogramming.com.au/HTMLCSS/square_hr_tracing.htm">&#128207;</option><option title="Emoji Walk Animation" style="cursor:pointer;text-decoration:none;font-size:36px;" target="iemoji_walk_animation" id="aemoji_walk_animation" value="//www.rjmprogramming.com.au/HTMLCSS/emoji_walk_animation.htm">&#127939;&#127998;&#8205;&#9792;&#65039;</option><option title="Fruits" style="cursor:pointer;text-decoration:none;font-size:36px;" target="ifruits" id="afruits" value="//www.rjmprogramming.com.au/HTMLCSS/fruits.html">&#127820;</option><option title="Name Your Mascot" style="cursor:pointer;text-decoration:none;font-size:36px;" target="iname_your_mascot" id="aname_your_mascot" value="//www.rjmprogramming.com.au/HTMLCSS/name_your.html">&#128231;</option><option title="Sushi Train" style="cursor:pointer;text-decoration:none;font-size:36px;" target="isushi_train" id="asushi_train" value="//www.rjmprogramming.com.au/HTMLCSS/circuit.htm">&#127857;</option><option title="Flag Quiz" style="cursor:pointer;text-decoration:none;font-size:36px;" target="iflag_quiz" id="aflag_quiz" value="//www.rjmprogramming.com.au/HTMLCSS/flagquiz.htm">&#127462;&#127465;</option><option title="Emoji Overlay" style="cursor:pointer;text-decoration:none;font-size:36px;" target="iemoji_overlay" id="aemoji_overlay" value="//www.rjmprogramming.com.au/HTMLCSS/emoji_overlay.htm">&#128285;</option><option value="" selected></option></select>';
    sbitis='<iframe src="//www.rjmprogramming.com.au/HTMLCSS/emoji_widget_idea.htm"></iframe>';
    var isdone=0, is2done=0;
    if (document.getElementsByClassName){
    var x304x = document.getElementsByClassName('page-item-304');
    x304x[0].onmouseover = function() { var xl=document.getElementById('x2language'); xl.style.display = 'block'; };
    isdone = 1;
    var x46544x = document.getElementsByClassName('page-item-46575');
    x46544x[0].onmouseover = function() { if (this.innerHTML.replace('iframe ','select ').indexOf('select ') == -1) { this.innerHTML+=sbitis; } };
    is2done = 1;

    } else { // IE
    //var qis = document.getElementById("pick_content").contentWindow.document;
    var ilis = 0;
    var eleis, ele2is;
    var lisis = document.getElementsByTagName("li");
    while (eleis = lisis[ilis++]) {
    if (eleis.className == "page-item-304" && isdone == 0) {
    eleis.onmouseover = function() { var xl=document.getElementById('x2language'); xl.style.display = 'block'; };
    isdone = 1;
    }
    if (eleis.className.indexOf("page-item-46575") != -1 && is2done == 0) {
    eleis.onmouseover = function() { var xl2=document.getElementById('emojih'); xl2.style.display = 'block'; };
    is2done = 1;
    }

    }
    }
    }


    setTimeout(donow,2000);


    </script>

… that HTML iframe emoji_widget_idea.htm content (live run) preference above arising from our desire to add more flexibility to this content down the track.


Previous relevant Fixed Sticky Header Top Window Document Tutorial is shown below.

Fixed Sticky Header Top Window Document Tutorial

Fixed Sticky Header Top Window Document Tutorial

The recent Fixed Sticky Header Primer Tutorial involved …

  • a supervisory “emoji menu” web application hosting …
  • supervised iframe element hosted web applications

… and you may think, if all this is going on with web applications on the same domain, what’s the big deal? What could go wrong? (These words always bringing a knowing chuckle around here!)

For the most part, it’s true, there were no issues, but one “supervised iframe element hosted web application” we tried did not behave with all its functionality happening. Lo and behold, applying a web inspector showed up an error, with a codeline (in Javascript) that went …


mcp=parent.document.getElementById('lcp').value;

… and then we summed this up in two different strands of thought …

  • can we write a generic external piece of Javascript called just before </body> that can pluck out lines of code, with corresponding line codes, and see if “parent.document” or “top.document” occur in them and effectively “better debug” within an errorHandler function that further examines this “null” return error … which looking into is not as easy as first optimistically envisaged … versus …
  • get in there specifically with the web inspector, adjust the code of the “supervised iframe element hosted web application” and have it work being …
    1. additionally supervised this way … and more importantly …
    2. still work the way it used to unsupervised, as ever it has worked up to now

… via the simple (age old) paradigm, involving debugging (web applications, at the client level) via tools like (the web browser) Safari’s Web Inspector …

  • Using Web Inspector type tools:

    Identify the issue via …

    Error line
    Error line number
  • Using Web Inspector type tools:

    Fix the issue until no errors happen

And what would have been the better generic coding for a web application that may become a “supervised web application” (in different ways) into the future.

Don’t just …

if (window.top.document) {
if (window.top.document != window.document) {
document.getElementById('reout').style.height='250px';
if (window.top.document != window.parent.document) {
mcp=parent.document.getElementById('lcp').value;
rcp=top.document.getElementById('rcp').value;
lcp=top.document.getElementById('lcp').value;
// more logic here
} else {
mcp=parent.document.getElementById('mcp').value;
rcp=parent.document.getElementById('rcp').value;
lcp=parent.document.getElementById('lcp').value;
// more logic here
}
}
}
But do

if (top.window && parent.window) { // if (window.top.document) {
var plcp=parent.document.getElementById('lcp');
if (window.top.document != window.document) {
document.getElementById('reout').style.height='250px';
if (window.top.document != window.parent.document && parent.document.getElementById('lcp')) {
mcp=parent.document.getElementById('lcp').value;
rcp=top.document.getElementById('rcp').value;
lcp=top.document.getElementById('lcp').value;
// more logic here
} else if (parent.window && plcp) {
mcp=parent.document.getElementById('mcp').value;
rcp=parent.document.getElementById('rcp').value;
lcp=parent.document.getElementById('lcp').value;
// more logic here
}
}
}

… in other words, check window object existence, before you assume document object existence, with the changed emoji_slideshow.htm part within the emoji menu supervisor live run link’s changed fixed_top.html code.


Previous relevant Fixed Sticky Header Primer Tutorial is shown below.

Fixed Sticky Header Primer Tutorial

Fixed Sticky Header Primer Tutorial

Just like with the W3schools How To series inspired HTML and Javascript and CSS Survey Levelling Tutorial we have another W3schools inspired web application idea called “Sticky Header”.

To quote W3schools regarding the design aspects to the fixed_top.html “proof of concept” web application

On Scroll Sticky Header
The header will stick to the top when you reach its scroll position.
Scroll back up to remove the sticky effect.

Which takes us to what we wanted to try as an inhouse addition to functionality. We like emojis, as “text meets button design”. Hence, we also like the “text” emoji being like an “a” link “button”, for two biggish reasons …

  • emoji buttons save space
  • emoji buttons can look like images that can attract user attention, and be like an Internationizational improvement to your web application, given some careful consideration

… that lead us to want to have the “Sticky Header” contain an “emoji menu” of “emoji buttons”, the “onclick” events of which show content below the “Sticky Header” in a one row table that pushes the latest content to the left of that row (so that our hashtagging logic will still see the emojis along with the latest selected content), yet allow an intrepid user venture right to “uncontrolled lands of functionality” should they wish. We’re sticking left … chortle, chortle.


Previous relevant HTML and Javascript and CSS Survey Levelling Tutorial is shown below.

HTML and Javascript and CSS Survey Levelling Tutorial

HTML and Javascript and CSS Survey Levelling Tutorial

With the “terrestrial” side to Land Surveying (ie. that of the small distances kind), two “get out there and do it” skills spring to mind, those being …

  • performing a traverse via the use of a theodolite (or “total station”) (as the web application works the mathematics of, off the field book, with the previous HTML and Javascript and CSS Survey Traverse Tutorial) working out the (“X”,”Y”) of 2D “life” … and today, we add to that with …
  • performing a levelling run via the use of a level (or “total station”) …

… and with today’s web application we simulate, to some degree, minus “how to level a level”, looking through the “level” viewer towards a “surveying staff” (held level and straight) on a point of something you want to know the elevation (or (3D “life”) “Z”) of in terrestrial terms, relative to known elevations you will probably want to start pointing at (the “surveying staff” being on) with your first (often a known “datum”) …

  • Backsight … then …
  • (however many Inter Sights followed by a) Foresight (and then back to Backsight, as necessary)

… series of measurements (or “reading”) to derive “reduced levels” for each point the “surveying staff” visits. This, in most practice, involves alternately leapfrogging (each other, at different times) …

  • Land Surveyor recording and levelling the “level” … and a …
  • Chainperson levelling and straightening the “surveying staff”

… the “surveying staff” we simulate in our web application (somewhat) thanks to Cody.

That’s the “what” of the web application, but what about the “how” (let alone the who)? Here, we thank the great W3schools parallax ideas.

The “central CSS smart” of these parallax ideas is the idea of …


<style>
/* Create the parallax scrolling effect */
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: contain;
</style>

So take a look at parallax_example.html‘s live run link to see what we mean.


Previous relevant HTML and Javascript and CSS Survey Traverse Tutorial is shown below.

HTML and Javascript and CSS Survey Traverse Tutorial

HTML and Javascript and CSS Survey Traverse Tutorial

Here is a tutorial showing some client-side basics in HTML and Javascript and CSS all in the one HTML file, to simplify concepts. The tutorial subject matter is a webpage to perform Survey Traverse calculations. A Survey Traverse is:

Traverse is a method in the field of surveying to establish control networks.[1] It is also used in geodesy. Traverse networks involve placing survey stations along a line or path of travel, and then using the previously surveyed points as a base for observing the next point. Traverse networks have many advantages, including:

Less reconnaissance and organization needed;
While in other systems, which may require the survey to be performed along a rigid polygon shape, the traverse can change to any shape and thus can accommodate a great deal of different terrains;
Only a few observations need to be taken at each station, whereas in other survey networks a great deal of angular and linear observations need to be made and considered;
Traverse networks are free of the strength of figure considerations that happen in triangular systems;
Scale error does not add up as the traverse is performed. Azimuth swing errors can also be reduced by increasing the distance between stations.

The traverse is more accurate than triangulateration[2] (a combined function of the triangulation and trilateration practice).[3]

Let’s see some simple HTML in action in a tutorial …

Link to HTML “spiritual home” … at W3Schools has many tutorials.
Link to Survey Traverse live run … here.
Link to Survey Traverse live run (additional Google Line Chart functionality) here.
Link to Survey Traverse information … from Wikipedia from which quote above comes.
Link to some downloadable HTML code … rename to SurveyTraverse.html which packages up a lot of Javascript and a little bit of CSS … or JaCvasScriptS … not sure whether this would ever catch on.
Link to some downloadable PHP programming code (additional Google Line Chart functionality) … rename to SurveyTraverse.php

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

WordPress Blog Plus Searches Tutorial

WordPress Blog Plus Searches Tutorial

WordPress Blog Plus Searches Tutorial

After a few days of trying out the WordPress Blog (TwentyTen themed) search functionality (searching for GETME[space]) and creating Oldest link ideas from the recent WordPress Blog Getme Searches Tutorial we have come to two conclusions …

  • (though we dislike changing the premise of a modification, we’re going to) change the appending delimiting character from a space to a + (plus) character because it fits in better with previous functionalities offered … and all that withstanding …
  • we like the basic idea (of searching for the genesis of a search regarding this blog) and want to extend it to other non-GETME searches … to just have it that (all in TwentyTen theme’s header.php)

<?php echo ”

document.getElementById('s').placeholder='Space appended compares to whole posting content. One plus (+) after GETME (or, actually, now, any) search facilitates Oldest link.';

“; ?>

… and, in so doing, came up with a more robust …

<?php echo ”

function chkinodo() {
var mkh=0, lastahelsid='', lastahelstitle='';
var bihis='';
//if (document.URL.indexOf('&max=') != -1) { alert(0); }
if (document.URL.indexOf('s=') != -1 && document.URL.replace('&max=','wopenall=').indexOf('wopenall=') != -1 && document.URL.indexOf('ifnooldestdoone=') != -1 && document.URL.replace('&max=','paZge=').replace('/page','page=').indexOf('page=') == -1) {
bihis=document.body.innerHTML;
//if (document.URL.indexOf('&max=') != -1) { bihis=bihis.replace(/lder\ post/g, ''); }
var hels=document.getElementsByTagName('h1');
//if (document.URL.indexOf('&max=') != -1) { alert('' + hels.length + ' ... ' + document.getElementsByTagName('a').length); }
if (document.URL.indexOf('&paged=') != -1 && document.URL.indexOf('ifnooldestdoone=') != -1 && eval('' + hels.length) > 0 && document.body.innerHTML.indexOf('lder post') != -1 && document.URL.replace('&paged=','&max=').indexOf('&max=') != -1) {
location.href=document.URL.replace('&paged=' + document.URL.split('&paged=')[1].split('&')[0].split('#')[0], '&paged=' + eval(1 + eval('' + document.URL.split('&paged=')[1].split('&')[0].split('#')[0])));
return '';
} //else if (document.URL.indexOf('&paged=') != -1 && document.URL.indexOf('ifnooldestdoone=') != -1 && document.URL.indexOf('&max=') != -1) {
//alert('' + eval('' + hels.length) + ' nextpage=' + eval(1 + eval('' + document.URL.split('&paged=')[1].split('&')[0].split('#')[0])));
//alert(document.body.innerHTML.indexOf('lder post'));
//}
if (eval('' + hels.length) > 0 && (bihis.indexOf('lder post') == -1 || document.URL.indexOf('&max=') != -1)) {
//if (document.URL.indexOf('&max=') != -1) { alert(11); }
if (hels[0].innerHTML.indexOf('ldest') == -1) {
//if (document.URL.indexOf('&max=') != -1) { alert(111); }
if (hels[0].innerHTML.toLowerCase().indexOf('search result') != -1) {
//if (document.URL.indexOf('&max=') != -1) { alert(1111); }
var ahels=document.getElementsByTagName('a');
var asthere=false;
//hels[0].innerHTML+=',';
for (var jkh=0; jkh<ahels.length; jkh++) {
//if (document.URL.indexOf('&max=') != -1) { alert('jhk=' + jhk); }
if (('' + ahels[jkh].title).indexOf('Permalink to ') != -1) {
if (('' + ahels[jkh].outerHTML).indexOf(' id=') == -1) {
asthere=true;
ahels[jkh].id='mya' + mkh;
lastahelsid='' + ahels[jkh].id;
lastahelstitle='' + ('' + ahels[jkh].title).split('Permalink to ')[1];
mkh++;
} else {
asthere=true;
lastahelsid='' + ahels[jkh].id;
lastahelstitle='' + ('' + ahels[jkh].title).split('Permalink to ')[1];
}
}
}
if (!asthere) {
setTimeout(chkinodo, 5000);
}
}
}
if (lastahelsid != '' && lastahelstitle != '') {
hels[0].innerHTML+=' ... <a id=reposa href="#' + lastahelsid + '" title="' + lastahelstitle + '">Oldest</a> ';
if (document.URL.replace('&paged=','&max=').indexOf('&max=') != -1) {
if (document.getElementById('reposa')) {
document.getElementById('reposa').click();
} else {
location.href='#' + lastahelsid;
}
}
}
}
}
}

“; ?>

… better dealing with multiple page result sets, called into play better via …

<?php echo ”

function sipreradiocc() {
//if (document.getElementById('s').value.trim().indexOf('GETME') != -1) { alert(document.getElementById('s').value); }
if (document.getElementById('s').value.indexOf('++') == -1) {
if ((document.getElementById('s').value + '~').replace('_GETME','-GETME').indexOf('-GETME+~') != -1) {
//alert('yes');
if (document.URL.indexOf('?s=' + encodeURIComponent(document.getElementById('s').value.replace(/\+$/g,'')) + '&') == -1) {
location.href=document.URL.split('?')[0].split('#')[0].split('/ITblog')[0].split('/wordpress')[0] + '/ITblog/?s=' + encodeURIComponent(document.getElementById('s').value.replace(/\+$/g,'')) + '&wopenall=' + encodeURIComponent(document.getElementById('s').value.trim()) + '&ifnooldestdoone=y&paged=0';
}
} else if ((document.getElementById('s').value + '~~').replace('_GETME','-GETME').indexOf('+~~') != -1) {
//alert(document.getElementById('s').value + '~~');
if (document.URL.indexOf('?s=' + encodeURIComponent(document.getElementById('s').value.replace(/\+$/g,'')) + '&') == -1) {
location.href=document.URL.split('?')[0].split('#')[0].split('/ITblog')[0].split('/wordpress')[0] + '/ITblog/?s=' + encodeURIComponent(document.getElementById('s').value.replace(/\+$/g,'')) + '&max=256&step=256&ifnooldestdoone=y&paged=0#nav-below';
}
} //else if (document.getElementById('s').value.trim().indexOf('GETME') != -1) {
//alert('why ' + (document.getElementById('s').value + '~').replace('_GETME','-GETME'));
//}
}
}

“; ?>

… and ready for you to try yourself, sometime, we’re hoping, to get to “first mentions” of your search string(s) at this WordPress Blog’s search textbox.


Previous relevant WordPress Blog Getme Searches Tutorial is shown below.

WordPress Blog Getme Searches Tutorial

WordPress Blog Getme Searches Tutorial

We noted, looking at our Apache Status report, that fairly often readers of this blog, thanks, search for mention of a particular GETME file, it being our “source control” basis whereby …

  • first draft of a “source control” file, named cowsay.php as an example, would be called …

    cowsay.php_GETME
  • and then subsequent drafts use s rather than _ meaning a “second draft” would be called …

    cowsay.php-GETME

    … and a fourth …

    cowsay.php---GETME

You go through with a particularized search like that and you’d be looking for specific referencing, we reckon. And yet, once the project rolls along a search for cowsay.php_GETME as your example will land you on four or five or six mentioning tutorials, the way we do it around here. We want to tell a story, and build it up (but please do your own research regarding Google SEO before thinking this is such a good idea, as repeating content is quite often a no-no). But, like we’re intimating, such a particularized search result set like this may annoy many people looking for some quick, definitive answer.

Well, we think for some such searches, again using cowsay.php_GETME as an example, the adding and then clicking of …


Oldest

… and lobbing you in the direction of …


Python Cowsay API Primer Tutorial

… as the oldest mention of cowsay.php_GETME, could be a useful new feature … ie. getting to it’s genesis. Many people will be most interested going back to this genesis, but please note, in the case we’ve mentioned, using our “present as a book” emoji button (📖 &#128214;) functionality (reading like a book, functionality talked about with WordPress Blog Posting Thread Book Primer Tutorial) on the topmost (usually, but regarding hot off the press business “topmost that does not have the title WordPress Blog Getme Searches Tutorial“) link you are presented with would do a good job here too.

Okay, so how does a user start getting to this additional Oldest link creation logic? Well, in our changed bits on our WordPress blog TwentyTen themed header.php (a modus operandi also used for WordPress Blog Byline Zoom Fix Tutorial)

<?php echo ”

function sipreradiocc() {
//if (document.getElementById('s').value.trim().indexOf('GETME') != -1) { alert(document.getElementById('s').value); }
if ((document.getElementById('s').value + '~').replace('_GETME','-GETME').indexOf('-GETME ~') != -1) {
//alert('yes');
location.href=document.URL.split('?')[0].split('#')[0].split('/ITblog')[0].split('/wordpress')[0] + '/ITblog/?s=' + encodeURIComponent(document.getElementById('s').value.trim()) + '&wopenall=' + encodeURIComponent(document.getElementById('s').value.trim()) + '&ifnooldestdoone=y';
} //else if (document.getElementById('s').value.trim().indexOf('GETME') != -1) {
//alert('why ' + (document.getElementById('s').value + '~').replace('_GETME','-GETME'));
//}
}


function preradiocc() {
//document.title='' + (document.getElementById('s').value + '~').replace('_GETME','-GETME').indexOf('-GETME ~') + ' ... ' + (document.getElementById('s').value + '~').replace('_GETME','-GETME');
if ((document.getElementById('s').value + '~').replace('_GETME','-GETME').indexOf('-GETME ~') != -1) {
location.href=document.URL.split('?')[0].split('#')[0].split('/ITblog')[0].split('/wordpress')[0] + '/ITblog/?s=' + encodeURIComponent(document.getElementById('s').value.trim()) + '&wopenall=' + encodeURIComponent(document.getElementById('s').value.trim()) + '&ifnooldestdoone=y';
} else
if (document.getElementById('s').value != "" && radis != "") {
radiocc(radis);
}
}

“; ?>

… reading between the lines and taking into consideration a changed codeline in function precc …

<?php echo ”

document.getElementById('s').placeholder='Space appended compares to whole posting content. Spaces after GETME search facilitates Oldest link.';
setInterval(sipreradiocc, 5000);

“; ?>

… in conjunction with a new document.body onload Javascript function …

<?php echo ”

function chkinodo() {
var mkh=0, lastahelsid='', lastahelstitle='';
if (document.URL.indexOf('s=') != -1 && document.URL.indexOf('wopenall=') != -1 && document.URL.indexOf('ifnooldestdoone=') != -1 && document.URL.replace('/page','page=').indexOf('page=') == -1) {
var hels=document.getElementsByTagName('h1');
if (eval('' + hels.length) > 0 && document.body.innerHTML.indexOf('lder post') == -1) {
if (hels[0].innerHTML.indexOf('ldest') == -1) {
if (hels[0].innerHTML.toLowerCase().indexOf('search result') != -1) {
var ahels=document.getElementsByTagName('a');
for (var jkh=0; jkh<ahels.length; jkh++) {
if (('' + ahels[jkh].title).indexOf('Permalink to ') != -1) {
if (('' + ahels[jkh].outerHTML).indexOf(' id=') == -1) {
ahels[jkh].id='mya' + mkh;
lastahelsid='' + ahels[jkh].id;
lastahelstitle='' + ('' + ahels[jkh].title).split('Permalink to ')[1];
mkh++;
} else {
lastahelsid='' + ahels[jkh].id;
lastahelstitle='' + ('' + ahels[jkh].title).split('Permalink to ')[1];
}
}
}
}
}
if (lastahelsid != '' && lastahelstitle != '') {
hels[0].innerHTML+=' ... <a href="#' + lastahelsid + '" title="' + lastahelstitle + '">Oldest</a> ';
}
}
}
}

“; ?>

… the user just adds a trailing space to their entered GETME search textbox entry, to pre-empt the underlying HTML form navigation and, instead, do a navigation such as …


https://www.rjmprogramming.com.au/ITblog/?s=cowsay.php_GETME&wopenall=cowsay.php_GETME&ifnooldestdoone=y

… to, sometimes, see these new Oldest type hashtag link helpers.


Previous relevant WordPress Blog Byline Zoom Fix Tutorial is shown below.

WordPress Blog Byline Zoom Fix Tutorial

WordPress Blog Byline Zoom Fix Tutorial

That’s it! We’re doing something today regarding …

How on non-mobile, with this blog, the byline …
A “Dot Dot Dot” Information Technology Blog
… can mal-align as a user zooms in or out.

And we were doing things for the first time we can remember, regarding the fix, which we weren’t expecting. So …

For the first time we can remember …

  • for a position: absolute “overlay” scenerio … we did not use a left: 123px style of positioning … but, rather …
  • used a right: 45.6% style of positioning …
  • lining the byline’s right with the blog title’s right … more or less …
  • making the byline more central …
  • giving it more “wander room” as a user zooms in or out

Ever since the advent of “mobile” platforms, the idea of “zoom” has become more and more of a “mute point”, but not for “non-mobile”, as with this “kind of unusual” adding, via “overlay” idea, regarding HTML elements.

On this topic, we’d like to thank this excellent link which reminded us that “responsive design”‘s biggest friend is the percent (ie. “%”) unit of webpage measure!

By the way, even on “non-mobile”, the window.onresize event is triggered we found, but once there we struggled to do much about the mal-alignment zooming in or out was sometimes doing to the byline off to the left.

The new code (intervention, that made the difference), in good ol’ header.php?

<?php echo ”

function bylinedo() {
var ahuhrect=document.getElementById('access').getBoundingClientRect();
var huhrect=document.getElementById('ahomeis').getBoundingClientRect();
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i)) {
document.getElementById('ahomeis').innerHTML=document.getElementById('ahomeis').innerHTML.replace(' Blog', ' <span id=sbyline><font size=2><i><strong>... I.T.</strong></i></font></span> Blog');
} else {
//document.getElementById('hdgspan').innerHTML+='<span id=sbyline style="position:absolute;left:' + ahuhrect.left + 'px;top:' + eval(53 + eval('' + huhrect.top)) + 'px;"><font size=2><i><strong>A "Dot Dot Dot" Information Technology Blog</strong></i></font></span>';
//alert('sw=' + screen.width + ' al=' + ahuhrect.left + ' ... ' + eval(100 * eval('' + screen.width) / eval('' + ahuhrect.left)));
// Thanks to https://stackoverflow.com/questions/995914/catch-browsers-zoom-event-in-javascript
document.getElementById('hdgspan').innerHTML+='<span id=sbyline style="position:absolute;right:' + eval(100 * eval('' + huhrect.right) / eval('' + screen.width)) + '%;top:' + eval(53 + eval('' + huhrect.top)) + 'px;"><font size=2><i><strong>A "Dot Dot Dot" Information Technology Blog</strong></i></font></span>';
//window.onresize=function(){ alert(65); var bhuhrect=document.getElementById('access').getBoundingClientRect(); document.getElementById('hdgspan').style.left='' + bhuhrect.left + 'px'; };
}
}

“; ?>

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 Database, eLearning, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Inhouse Slideshow AlmaLinux Multiple Filtered Content Tutorial

Inhouse Slideshow AlmaLinux Multiple Filtered Content Tutorial

Inhouse Slideshow AlmaLinux Multiple Filtered Content Tutorial

Onto yesterday’s Inhouse Slideshow AlmaLinux Filtered Content Tutorial we did want to offer the user the chance to …

  • enter in more than one image filtering “verb” … space separated … as well as …
  • chance for user to establish their own arguments relevant to some of the “verbs”


substanceverb=ourprompt('Please enter word image filter idea(s), separated by space ... ' + String.fromCharCode(10) + String.fromCharCode(10) + 'emboss edge negedge sharpen boxblur negate colourizered colourizeblue colourizegreen colourize pixellate smooth contrast brightness sketchy mean_removal flipvertical fliphorizontal flip ' + String.fromCharCode(10) + String.fromCharCode(10) + ' ... or none for original, while comma separate your own arguments with no spaces in amongst those? Eg. emboss,array([-2,-1,3],[-1,4,3],[0,4,3]) brightness', '');

This involved making PHP function new_content recursive by nature (exemplified by)

<?php

$sanum++;
$saname=str_replace("arg0", "arg", "substancearg" . $sanum);
$curnum++;
if ($curnum >= $totnum) { $sanum=0; $curnum=0; $saname=str_replace("arg0", "arg", "substancearg" . $sanum); $curlist=$totlist; return file_get_contents($slidename); }
$curlist=str_replace('brightness','',$curlist);
return new_content(file_get_contents($slidename));

?>

… when these multiple filtering verbs are encountered. In this way, sometimes, rather than return a static value, function new_content might return it’s own recalled return value.

Again, coming from the serverside we decided to pack more into …

… you can try out for yourself with Blurb.


Previous relevant Inhouse Slideshow AlmaLinux Filtered Content Tutorial is shown below.

Inhouse Slideshow AlmaLinux Filtered Content Tutorial

Inhouse Slideshow AlmaLinux Filtered Content Tutorial

There’s …

… we’re using the great PHP GD library image filtering talents to open up to the user in “name”, that is, any numerical arguments fixed in a static way by us (and we’ll see about otherwise into the future).

The user can pick (so far one at a time, but we’ll review into the future) from …

… and some of the resultant effects can be quite startling.

Coming from the serverside we decided to pack more into …

… to make these optional and additional image filtering options to be available to users of Inhouse Slideshows (eg. Jenkins) hereabouts.

Did you know?

Keen observers will know that we (just about) always assemble a group of image screenshot slides into animated GIFs these days. And if you have read some oldish tutorials you will know, about RJM Programming history

  • for many years it was hosted on a CentOS Apache/PHP5/MySql Linux web server where we had both …
    1. disk inode count
    2. diskspace (in bytes)

    hair trigger issues to worry about for several years … until …

  • recently a migration to AlmaLinux Apache/PHP8/MySql Linux web server eased those worries in both senses

But, analogous (in motivation) to how programmers worked with limited amounts of memory in those early Windows and Mac OS X days, we switched tack using inhouse slideshow concepts (eating into the CentOS inode count, hence the push over that time, to get PHP zip help to have the one zipfile be used to zip/(temporarily)unzip the image slide files) in favour of (the one file) animated GIF paradigm. Do we change back? We (with consultation) are not that tempted because …

  • we’ve gotten better with animated GIF creation functionality …
  • though inhouse slideshow can have cute features, it is a pretty resource intensive way to go about things

… and so (with consultation) we’ll see … and Nala says to say “hear” … and Luna says to say “smell” (and she’s right in that that “smellorama” project is still on the go).


Previous relevant Inhouse Slideshow AlmaLinux CSS Style Tutorial is shown below.

Inhouse Slideshow AlmaLinux CSS Style Tutorial

Inhouse Slideshow AlmaLinux CSS Style Tutorial

Yes, we like, where possible, and we’ve invisaged it, we prefer to give the user “a stake” in …

  • less often how the web application functions … and/or …
  • how the web application looks

And under “looks” that can mean …

  • media content and/or …
  • CSS styling

… and today think “option twos” above regarding our recent Inhouse Slideshow “push”, started, this time around, because of …

  • PHP Zip deprecation … handled by each Inhouse Slideshow overseeing PHP (along with it’s new included ziphelper.php helper) … then …
  • new media creation dropdown options … as with yesterday’s Inhouse Slideshow AlmaLinux Media Tutorial … handled by each Inhouse Slideshow overseeing PHP and cowsay Python API interfacer and changed inhouse_slideshow.js Inhouse Slideshow external Javascript helper … and now, today …
  • new CSS Style dropdown option … handled by the changed inhouse_slideshow.js Inhouse Slideshow external Javascript helper only

Of course, that is what external Javascript design is all about. You adjust one code source only, to affect a whole lot of web applications, rather than the worry of many code source changes. We know which we prefer, as programmers?!

Is your way into programming via CSS styling? Perhaps it would tempt you if we pointed out that there are I.T. jobs out there asking for people with expert CSS styling skills. By this, you may understand it can be an art form transforming dreary looking HTML content into dynamic and vibrant looking webpages (all with the same content).

We’ve learnt most about CSS styling, fast, via web browser web inspectors and seeing an initial webpage look change before our eyes via tweaks applied dynamically. We recommend this highly, but don’t expect everyone to be that keen. In any case, we’re trying to channel that dynamism today, offering the user to see our Inhouse Slideshow change it’s look via user CSS Styling entries in a prompt window instigated by a new “Style” dropdown option.

CSS styling does well with webpages dynamically because, quite often, the Javascript DOM approach (where yourselectorpluscss contains CSS styling code) …


document.body.innerHTML+='<style> ' + yourselectorpluscss + ' </style>';

… will both do no harm to existant content as well as dynamically change webpage aesthetics instantly.

Regarding CSS we know we have much to learn and try regarding the …


selector { styling; }

Only the other day with cartoons we used (clauses like) …

<style>

td[id$='5'] { styling; }

</style>

… types of CSS clauses to mildly change the styling for each cartoon slide. After using this, for the first time, we wrote down for future tutorial ideas “write a web application helping users improve on their selector smarts”. But we think this Inhouse Slideshow opportunity might be a better dynamic approach for this.


Previous relevant Inhouse Slideshow AlmaLinux Media Tutorial is shown below.

Inhouse Slideshow AlmaLinux Media Tutorial

Inhouse Slideshow AlmaLinux Media Tutorial

The recent Inhouse Slideshow AlmaLinux Tutorial did help with PHP Zip deprecations, and today, this being Inhouse Slideshows, full of …

moving pictures

… we can add two more dropdown modus operandi options for …

  • Video
  • Animated GIF

… feeding it through to a changed latest draft cowsay.php media creator via slides via ffmpeg inhouse talent, called by our inhouse slideshow external Javascript helper …


function changeto(tvis) {
if (tvis.toLowerCase().indexOf('video') == 0) {
document.getElementById('divcowpf').innerHTML+='<input type=hidden name=fromindex id=fromindex value=y></input>';
document.getElementById('vlist').click();
document.getElementById('mycowifr').style.display='block';
document.getElementById('mycowifr').style.visibility='hidden';
document.getElementById('mycowifr').style.height='1px';
//document.getElementById('mycowifr').scrollIntoView();
//location.href='#mycowifr';
setTimeout(function(){ document.getElementById('mycowifr').scrollIntoView(); }, 8000);
} else if (tvis.toLowerCase().indexOf('animated gif') == 0) {
document.getElementById('divcowpf').innerHTML+='<input type=hidden name=fromindex id=fromindex value=y></input>';
document.getElementById('aglist').click();
document.getElementById('mycowifr').style.display='block';
document.getElementById('mycowifr').style.visibility='hidden';
document.getElementById('mycowifr').style.height='1px';
//document.getElementById('mycowifr').scrollIntoView();
//location.href='#mycowifr';
setTimeout(function(){ document.getElementById('mycowifr').scrollIntoView(); }, 8000);
} else
if (tvis.toLowerCase().indexOf('exif') == 0) {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?exif=y');
} else {
location.href=posturl(document.URL.split('#')[0].replace(/pdf\=/g, 'pdTf=') + '&exif=y');
}
} else if (tvis.toLowerCase().indexOf('pdf') == 0) {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?pdf=y');
} else {
location.href=posturl(document.URL.split('#')[0].replace(/exif\=/g, 'exTif=') + '&pdf=y');
}
} else if (tvis.toLowerCase().indexOf('emoji') == 0) {
//var borderis=prompt('Please enter comma separated HTML decimal entity(s) for your Emoji Border to slideshow. Can use an Emoji Menu entry.', '');
var bbsuffix=' Optionally append &[text|image]css=[CSSstyle] to change styling. Optionally justify some text via &[ul|uc|ur|ml|[mc]|mr|bl|bc|br]text=[someText%0AsecondLine] to change styling. Eg. ' + String.fromCodePoint(127958) + '&css=opacity:0.9;&textcss=font-size:20px;&ultext=Hello%0AThere ';
borderblurb='Please enter comma separated HTML decimal entity(s) for your Emoji Border to slideshow. Can use an Emoji Menu entry (eg. control-command-space for macOS or Mac OS X, logo key + . (period) for Windows, control+space for iOS, top left + for Android keyboard). ' + bbsuffix;
var borderis=prompt(borderblurb, '');
var emojiy='', emojisuffix='';
if (borderis == null) {
borderis='';
} else if (borderis.indexOf('&') != -1) {
if (borderis.split('&')[0].trim() == '') {
emojisuffix=encodeURIComponent(borderis.replace(/\%23[cC][iI][rR][cC][lL][eE]/g, '#circle').replace(/\%23[eE][lL][lL][iI][pP][sS][eE]/g, '#ellipse').replace(/\%23[tT][eE][xX][tT]/g, '#text').replace(/\%23[lL][iI][nN][eE]/g, '#line').replace(/\%23[pP][oO][lL][yY][lL][iI][nN][eE]/g, '#polyline').replace(/\%23[pP][oO][lL][yY][gG][oO][nN]/g, '#polygon').replace(/\%23/g, encodeURIComponent('%23')).replace(/\%23/g, encodeURIComponent('%23')).replace(/\%0a/g, encodeURIComponent('%0A')).replace(/\%0A/g, encodeURIComponent('%0A'))); //.replace(/\&/g,'%26').replace(/\=/g,'%3D');
borderis='';
} else {
emojisuffix=encodeURIComponent(borderis.replace(borderis.split('&')[0], '').replace(/\%23[cC][iI][rR][cC][lL][eE]/g, '#circle').replace(/\%23[eE][lL][lL][iI][pP][sS][eE]/g, '#ellipse').replace(/\%23[tT][eE][xX][tT]/g, '#text').replace(/\%23[lL][iI][nN][eE]/g, '#line').replace(/\%23[pP][oO][lL][yY][lL][iI][nN][eE]/g, '#polyline').replace(/\%23[pP][oO][lL][yY][gG][oO][nN]/g, '#polygon').replace(/\%23/g, encodeURIComponent('%23')).replace(/\%23/g, encodeURIComponent('%23')).replace(/\%0a/g, encodeURIComponent('%0A')).replace(/\%0A/g, encodeURIComponent('%0A'))); //.replace(/\&/g,'%26').replace(/\=/g,'%3D');
borderis=postbb(borderis.split('&')[0]);
}
} else {
borderis=postbb(borderis.split('&')[0]);
}
if ((borderis + emojisuffix) != '') { emojiy='emoji=' + encodeURIComponent(borderis) + emojisuffix; }
if (emojiy != '') {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?' + emojiy);
} else {
location.href=posturl(document.URL.split('#')[0].replace(/emoji\=/g, 'emojTi=') + '&' + emojiy);
}
}
} else {
if (document.URL.indexOf('exif=') != -1 || document.URL.indexOf('pdf=') != -1) {
location.href=posturl(document.URL.split('#')[0].replace(/exif\=/g, 'exTif=').replace(/pdf\=/g, 'pdTf='));
} else {
location.href=posturl(document.URL.split('#')[0] + '&eHuhxif=y');
}
}
}

… called by a changed example PHP inhouse slideshow creator web application.


Previous relevant Inhouse Slideshow AlmaLinux Tutorial is shown below.

Inhouse Slideshow AlmaLinux Tutorial

Inhouse Slideshow AlmaLinux Tutorial

Today we wanted to add so much more to our blog posting title. But, then, we also didn’t want to give the game away?! What a dilemma.

That blog posting title mentions …

  • AlmaLinux … as RJM Programming’s Apache/PHP/MySql web server “brand”, using …
  • PHP 8 … as distinct from the PHP 5’s of the CentOS web server days … and so we suppose we should expect issues like the dreaded …
  • Deprecation … of …
  • Zip … functionality … so sad seeing the early symptoms of this with …
  • Inhouse Slideshow presentations … (as last talked about with Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial) deprecation warnings

Surprising to us, trying to logically walk though a solution, currently up at our AlmaLinux web server here the PHP …


function_exists

… approach we have used successfully recently did not work here. Anyway, deprecated or non-existant it doesn’t matter, we decided to resort to good ol’ PHP exec methodologies in a new “inhouse slideshow” (featuring in a changed example PHP inhouse slideshow creator web application) call …

<?php

include($_SERVER['DOCUMENT_ROOT'] . "/ziphelper.php");

?>

… containing …


<?php
// ziphelper.php
// RJM Programming
// February, 2025

$gzip_read_output=null;
$gzip_open_handle=null;
$gzip_entry_filename='';
$gzip_filename='';
$gzip_entry_len=0;
$gzip_number=0;
$gzip_log_text='';
if (strpos($_SERVER['REQUEST_URI'], 'index.') !== false) {
$hereis='' . dirname(__FILE__) . explode("index.", $_SERVER['REQUEST_URI'])[0];
} else if (basename($_SERVER['SCRIPT_FILENAME']) != '') {
$hereis=explode(basename($_SERVER['SCRIPT_FILENAME']), realpath($_SERVER['SCRIPT_FILENAME']))[0];
} else {
$hereis='' . dirname(__FILE__) . str_replace('//','/',explode("?", $_SERVER['REQUEST_URI'])[0] . '/');
}
$zipisis='' . $hereis . 'slideshow_0.zip';
$alreadythere=false;

if (file_exists($zipisis)) {
$items = glob($hereis . "*[-_][0-9]*of.[jJgGpP][pPiInN]*");
foreach ($items as $key => $val) {
$alreadythere=true;
}
}

if (!function_exists("zip_entry_read")) {
function zip_entry_read($zip_read_output, $zip_entry_len) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_read_output, $gzip_entry_len;
return 'pork';
}
}

if (!function_exists("zip_entry_filesize")) {
function zip_entry_filesize($zip_read_filename) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_entry_filename;
return 'pork';
}
}

if (!function_exists("zip_read")) {
function zip_read($zip_oben_handle) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle;
return 'pork';
}
}

if (!function_exists("zip_open")) {
function zip_open($zip_filename) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_filename;
$gzip_filename=$zip_filename;
$gzip_number=0;
$gzip_open_handle='pork';
return 'pork';
}
}

if (!function_exists("zip_entry_name")) {
function zip_entry_name($zip_read_output) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_read_output;
return 'pork';
}
}

if (!function_exists("zip_entry_open")) {
function zip_entry_open($zip_open_handle, $zip_read_output, $inmode) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle, $gzip_read_output;
return 'pork';
}
}

if (!function_exists("zip_close")) {
function zip_close($zip_open_handle) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle;
return 'pork';
}
}

if (file_exists($zipisis)) {
if (!$alreadythere) {
file_put_contents($hereis . 'please.wait', "cd " . $hereis . ' ; unzip ' . $zipisis);
sleep(2);
exec("cd " . $hereis . ' ; unzip ' . $zipisis);
sleep(2);
unlink($hereis . 'please.wait');
//exec("cd " . $hereis . ' ; rm -f please.wait');
//if (1 == 1) {
//header('Location: ' . explode('?',$_SERVER['REQUEST_URI'])[0] . '?rand=' . rand(0,674532));
//exit;
//} else {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
//if (basename($_SERVER['SCRIPT_FILENAME']) == 'index.php') {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
//sleep(9);
//echo '<html><body onload="location.href=' . "'" . explode("?", $_SERVER['REQUEST_URI'])[0] . '?rand=' . rand(0,5645342) . "';\"></body></html>";
//exit;
} //else if (basename($_SERVER['SCRIPT_FILENAME']) == 'index.php') {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
}
?>

… as a first draft. We have much more to do trying to resurrect, if possible, some other inhouse PHP web applications we’ve based on the use of Zip in PHP. Pardon us, until tomorrow, while we have a little cry.


Previous relevant Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial

Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial

Crontab is that great scheduling tool that we make use of, a lot, on our RJM Programming Linux CentOS web server. But it’s not only …

  • the timing … of a procedure that is so good about crontab … it is, also, for us, it’s teaming with …
  • curl

… that means we can back up a “peer based” solution such as talked about with Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial (ie. done as a user is surfing the net with some PHP of ours) methodology should it fail. We think we have an occasionally failing one as far as the tidy up of zipped up inhouse slideshows goes. It could be to do with a search engine crawling operation, we have not found out for sure, but we’ve decided to write our own …

  • PHP … via …
  • crontab
  • curl

… based independent tidying up procedure we’ll run once an hour via crontab record …


*/53 * * * curl http://www.rjmprogramming.com.au/slideshow_zero.php

… arrangement. We realize the contents of this PHP procedure may bore some, but interest a few, and so here is what it amounted to …

<?php

// slideshow_zero.php
// Zip and Unzip Tidy Up
// RJM Programming
// Decemeber, 2022
set_time_limit(3600);

if (file_exists("slideshow_zero.txt")) {
unlink("slideshow_zero.txt");
}

if (file_exists("slideshow_zero.kkk")) {
unlink("slideshow_zero.kkk");
}

exec("find " . dirname(__FILE__) . DIRECTORY_SEPARATOR . " -name 'slideshow_0.zip' 2> /dev/null > " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txt");

$lines=file(dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txt");

$htmlis="<html><body><textarea>
</textarea></body></html>";

for ($i=0; $i<sizeof($lines); $i++) {
$lines[$i]=explode("\n", $lines[$i])[0];
if (file_exists(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) {
if (('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) == '38794') {
if (file_exists("slideshow_zero.txx")) {
unlink("slideshow_zero.txx");
}
exec("unzip -l " . $lines[$i] . " | grep '.jpg' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/ /s// /g' | sed '/ /s// /g' | sed '/ /s// /g' | sed '/ /s// /g' | cut -f4 -d' ' | grep '-' > " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txx");
if (file_exists("slideshow_zero.txx")) {
$sublines=file(dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txx");
for ($j=0; $j<sizeof($sublines); $j++) {
$sublines[$j]=explode(" ", explode("\n", $sublines[$j])[0])[0];
$fis=explode("slideshow_0.zip", $lines[$i])[0] . $sublines[$j];
if (file_exists($fis)) {
$md=filemtime($fis);
if ($md) {
if ((time() - $md) > 1200) {
if (file_exists("slideshow_zero.kkk")) {
exec("rm -f " . $fis); //file_put_contents("slideshow_zero.kkk", file_get_contents("slideshow_zero.kkk") . "rm -f " . $fis . "\n");
} else {
exec("rm -f " . $fis); //file_put_contents("slideshow_zero.kkk", "rm -f " . $fis . "\n");
}
}
}
}
}
}
} else if (1 == 3) {
if (file_exists("slideshow_zero.kkk")) {
file_put_contents("slideshow_zero.kkk", file_get_contents("slideshow_zero.kkk") . "# " . ('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) . " is not 38794 " . str_replace("slideshow_0.zip", "index.php", $lines[$i]) . "\n");
} else {
file_put_contents("slideshow_zero.kkk", "# " . ('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) . " is not 38794 " . str_replace("slideshow_0.zip", "index.php", $lines[$i]) . "\n");
}
}
}
}

if (file_exists("slideshow_zero.txx")) {
unlink("slideshow_zero.txx");
}

if (file_exists("slideshow_zero.txt")) {
unlink("slideshow_zero.txt");
}

if (file_exists("slideshow_zero.kkk")) {
unlink("slideshow_zero.kkk");
}

//echo $htmlis;
exit;

?>

… as that “ahhhhhhhh, what a relief” reliever of tension running the RJM Programming website. The subtext is, our inode limits are a concern!

We think another lesson here is that PHP can be a good alternative to scripting languages such as Korn Shell to create “operational” procedures, especially when you consider that curl means it can be like writing your “surfing the net” type of PHP (slideshow_zero.php) work.


Previous relevant Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial

Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial

The thing about yesterday’s Inhouse Slideshow Backup Tidy Up Report Tutorial is that …

  • it creates useful report content … but …
  • it is information we do not want everyone to be able to see (easily, shall we say) … and in the sense that …
  • the report is stored away from RJM Programming’s “public_html” folder (ie. its Apache/PHP/MySql “Document Root”) is good … but even with today’s work …
  • hidden from everybody who does not have access to the RJM Programming’s web server … but …
  • the administrator of the RJM Programming’s web server (yoo hoo!) wants a mechanism to view the report that does not involve some “arcane procedure” each time to view it

… and so we decided that because …


the administrator of the RJM Programming's web server = the administrator of this blog

… we’d like to organize a system that latches onto that “security footing” and only show a “broom emoji button” (🧹 &#129529;) way to access the report when the administrator of this blog is logged in. We can do this by amending our Twenty Ten theme’s good ol’ header.php as per (where the “function mlater” you may recall from the days of WordPress Blog Email Post Collaboration Ajax Image Tutorial) …

<?php

$fns="36";

function doisr() {
global $fns;
$inmb="";
if (('' . get_current_user_id()) != '0' && ('' . get_current_user_id()) == '1') {
if (file_exists('/tmp/slideshow_cleanup.txt')) {
$fns="24";
$inmb="<a style=font-size:24px; title='Inhouse Slideshow Tidy Up Report' onclick=\"var iswo=window.open('','_blank','top=100,left=100,height=600,width=730'); iswo.document.write('<html><head><title>Inhouse Slideshow Tidy Up Report</title></head><body><pre>" . str_replace("\n","<br>",file_get_contents('/tmp/slideshow_cleanup.txt')) . "</pre></body></html>'); \">&#129529;</a> ";
}
}
return str_replace("'","' + String.fromCharCode(39) + '",$inmb);
}


?>

… PHP affects some (PHP writes) Javascript below …

<?php

function mlater() {
if (1 == 1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i)) {
if (dbihis == '') { dbihis=document.body.innerHTML; }
var xstih=document.getElementById('site-title').innerHTML;
if (xstih.indexOf("up" + "top") == -1) {
document.getElementById('site-title').innerHTML+='<?php echo doisr(); ?>' + '<a id="avs" style="text-decoration:none;font-size:<?php global $fns; echo $fns; ?>px;" href=# onmouseover="getVisualSynopsis(event);" onmouseout="yehbut();" ontouchstart="getVisualSynopsis(event);" ontouchend="yehbut();" onclick=" uptop(); " title="... you can wait for the long hover functionality about Visual Synopsis (Slideshows)">&#127910;</a> <a style="cursor:pointer;text-decoration:none;font-size:<?php global $fns; echo $fns; ?>px;" onclick="diffphpfix(this);" title="Code Difference Functional Links">&#128214;</a> <a style="cursor:pointer;text-decoration:none;font-size:36px;" onclick="popselid();" title="Filter Content via Div ID">&#10135;</a> <a style="cursor:pointer;text-decoration:none;visibility:hidden;font-size:<?php global $fns; echo $fns; ?>px;" title="Blog post contents reduced to summary" id="eds" onclick="pre_details_summary();">&#10134;</a>' + printscreen(0);
if (document.URL.indexOf("visualsynopsis=") != -1) document.getElementById('avs').click();
}
}
}

?>


Previous relevant Inhouse Slideshow Backup Tidy Up Report Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Report Tutorial

Inhouse Slideshow Backup Tidy Up Report Tutorial

Yesterday’s Inhouse Slideshow Backup Tidy Up Tutorial presented a …

  • non-automated
  • user instigated
  • snapshot

… Inhouse Slideshow “tidying up” PHP web application. This web application is like a …

  • procedure … that a …
  • system operator

… might be interested in using. But not many “system operators” would continue putting up with such a modus operandi. We can improve by …

  • allowing any of …
    1. surfing the net
    2. curl
    3. command line

    … modes of use … allowing …

  • crontab scheduling via …

    */49 * * * * ksh -c "curl HTTP://www.rjmprogramming.com.au/slideshow_cleanup.php?all=all"

    … to allow for a …
  • scheduled report available … and make sure we …
  • disallow overlapping execution runs

… with our changed slideshow_cleanup.php “Inhouse Slideshow” unzipped image “tidyer upperer“.


Previous relevant Inhouse Slideshow Backup Tidy Up Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Tutorial

Inhouse Slideshow Backup Tidy Up Tutorial

There are two aspects to diskspace maintainence up at the web server for RJM Programming.

  • df -k /
  • df -i /
# diskspace
# inode count

… and it is often that inode count we are concerned about, and looking out for ways to reduce the number of files we create on the web server.

The Inhouse Slideshow ways of Inhouse Slideshow Mobile Google Crawl Tutorial

  • use zip files to “scrunch up” a series of image files into the one zip file … for the vast majority of time … but when asked to, by a user …
  • unzip the image files when required by a user wanting to see them … and then …
  • tidy up, after some delay in time

… but we want to design a PHP way to independently tidy up as a backup mechanism. And we say, with PHP code, that if such files have been on the web server longer than ten minutes, this PHP callable slideshow_cleanup.php code …

<?php

// slideshow_cleanup.php
// RJM Programming
// May, 2022

$cdis=dirname(__FILE__) . DIRECTORY_SEPARATOR;
exec("cd " . $cdis . "; find . -name 'slideshow_0.zip' 2> /dev/null > /tmp/slideshow_cleanup.txt");


$lines = file('/tmp/slideshow_cleanup.txt');
date_default_timezone_set('Australia/Perth');

foreach ($lines as $line_num => $line) {
$ji=0;
if (substr($line,0,1) == '.') { $ji=2; }
$thisdir=explode('slideshow_0.zip', $line)[0];
$uzc=shell_exec("unzip -l " . $cdis . substr($line, $ji));
foreach (glob($thisdir . '*-[0-9]*of.[jJpPgG][pPnNiI]*') as $zipmember) {
$ij=0;
if (substr($zipmember,0,1) == '.') { $ij=2; }
$thisfile=$cdis . substr($zipmember, $ij);
if (strpos($uzc, (' ' . explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij))[-1 + sizeof(explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij)))]) ) !== false) {
if ((time() - filectime($thisfile)) > 600) { // more than 10 minutes old
unlink($thisfile); //echo "analyze " . $thisfile . " " . (time() - filectime($thisfile)) . ' seconds ago ' . "\n";
}
}
}
foreach (glob($thisdir . '*-[0-9]{[0-9]*}.[jJpPgG][pPnNiI]*') as $zipmember) {
$ij=0;
if (substr($zipmember,0,1) == '.') { $ij=2; }
$thisfile=$cdis . substr($zipmember, $ij);
if (strpos($uzc, (' ' . explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij))[-1 + sizeof(explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij)))]) ) !== false) {
if ((time() - filectime($thisfile)) > 600) {
unlink($thisfile); //echo "Analyze " . $thisfile . " " . (time() - filectime($thisfile)) . ' seconds ago ' . "\n";
}
}
}
}


?>

… should do its thaing!


Previous relevant Inhouse Slideshow Mobile Google Crawl Tutorial is shown below.

Inhouse Slideshow Mobile Google Crawl Tutorial

Inhouse Slideshow Mobile Google Crawl Tutorial

The recent Inhouse Slideshow Mobile Tutorial did not satisfy all the “mobile usability” tests performed by the “Google Crawl” algorithm, failing on “Content wider than screen”, and you can read some background to this with Google Crawl Viewport Geographicals Tutorial. And so we try some refinements here today, with an idea to control on mobile platforms the max-width CSS property of the document.body of a Inhouse Slideshow webpage, which made up the URLs failing this test at the Google Search Console.

We were reading this great and useful link, thanks, and decided to see whether this stopping of scrolling in X on mobile platform versions of the Inhouse Slideshow webpages gels better with Google Search Console “Google Crawl” Mobility Usability algorithms.

Yet again, deployment of these changes is similar to that last time, and the times before that, as per …

Unit testing completed, the deployment, again, matches those ideas of the recent PDF Slideshow and Form Creation Helper Slideshow Tutorial … in that …

Here are changes we’ll be testing up at Google …


<head>
<script type='text/javascript'>
// Other Javascript code here ...
//
//
// Of relevance today bold below ...

function blater() {
var tdsare=document.getElementsByTagName('td');
var rectg=tdsare[2].getBoundingClientRect(); //document.getElementById('i0').getBoundingClientRect();
tdsare[2].style.borderRight='2px solid white';
document.body.style.backgroundImage="URL('" + document.getElementById('i0').src + "')";
var rl=eval('' + rectg.left);
rl+=eval('' + rectg.width);
rl+=10;
document.body.style.backgroundPosition=" " + rl + "px " + Math.floor(rectg.top) + "px";
document.body.style.backgroundRepeat="no-repeat";
document.body.style.backgroundClip="content-box";
}



function zoom_maybe() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
//document.getElementById('rfs').innerHTML='<style> html { zoom: .5; } </style>';
document.getElementById('rfs').innerHTML='<style> html { zoom: 0.4; body { max-width: 100%; max-height: 80vh; } table { max-width: <?php if (strpos($_SERVER['QUERY_STRING'],'exif=') !== false) { echo "100"; } else { echo "95"; } ?>%; max-height: 80vh; margin: auto; overflow-x: hidden; } </style>';
}
}


function nwpdf(iithis) {
if (('' + iithis.src).length > 0) {
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
window.open(iithis.src,'_blank');
}
}
}


function mytw() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.body.style.width='' + (window.orientation == 0 ? Math.floor(eval(2.5 * window.screen.width)) : window.screen.height) + 'px';
document.getElementById('myt').style.width='100%'; //'' + (window.orientation == 0 ? window.screen.width : window.screen.height) + 'px';
}
}



window.setInterval(function(){havealook(1)},2000);
</script>
<style>
td { vertical-align:top; }
@media only screen and (max-width: 800px) {
body { max-width: 100%; max-height: 80vh; } table { max-width: <?php if (strpos($_SERVER['QUERY_STRING'],'exif=') !== false) { echo "100"; } else { echo "95"; } ?>%; max-height: 80vh; margin: auto; overflow-x: hidden; }
}

</style>
</head>
<body onload=" mytw(); zoom_maybe(); if (document.URL.indexOf('pdf=') != -1) { document.getElementById('selmode').value='PDF Slideshow'; if (document.getElementById('tdfirst')) { document.getElementById('s0').style.width=document.getElementById('tdfirst').style.width; document.getElementById('s0').style.height=document.getElementById('tdfirst').style.height; } } if (document.URL.indexOf('exif=') != -1) { document.getElementById('selmode').value='Exif Slideshow'; if (document.getElementById('tdfirst')) { document.getElementById('s0').style.width=document.getElementById('tdfirst').style.width; document.getElementById('s0').style.height=document.getElementById('tdfirst').style.height; } } document.title=document.title + ' ' + lastone; ol(); ">


Previous relevant Inhouse Slideshow Mobile Tutorial is shown below.

Inhouse Slideshow Mobile Tutorial

Inhouse Slideshow Mobile Tutorial

The recent PDF Slideshow and Form Creation Helper Slideshow Tutorial changes were made on a MacBook Pro laptop. Did it show that we have put off until today, to look at that functionality with mobile platforms?!

In a “going off to the right table row of cells” arrangement like this, what are some considerations that improve the user experience (of our inhouse slideshows) for mobile platform users?

  • turn the “@” link into an “emoji button” as per ➡ ( &#10145; )
  • for both mobile and non-mobile, we’ve decided …
    1. UTF-8 meta …
      <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>

    2. <style>
      td { vertical-align:top; }
      </style>
    3. change the h4 element to be h2 to help with legibility
  • for mobile, we’ve decided …
    1. viewport …
      <meta name=”viewport” content=”width=device-width, initial-scale=0.4, minimum-scale=0.1, maximum-scale=8, user-scalable=yes”>

    2. <style>
      html { zoom: .5; }
      </style>
    3. iOS (ie. iPad and iPhone) PDF iframe elements have known scrolling issues, which we decided to bypass by opening these PDF creations in a new webpage window

Deployment of these changes is similar to that last time, and the times before that, as per …

Unit testing completed, the deployment, again, matches those ideas of the recent PDF Slideshow and Form Creation Helper Slideshow Tutorial … in that …


Previous relevant PDF Slideshow and Form Creation Helper Slideshow Tutorial is shown below.

PDF Slideshow and Form Creation Helper Slideshow Tutorial

PDF Slideshow and Form Creation Helper Slideshow Tutorial

The first “integration cab” off the rank for yesterday’s PDF Slideshow and Form Creation Helper Primer Tutorial underlying usefulness is with our Inhouse Slideshow arrangements last talked about at Inhouse Slideshow Design Exif Order Tutorial. That generic PHP code now has three display dropdown options of …

  • Slideshow
  • Exif Slideshow … and the new, as of today’s work …
  • PDF Slideshow

… that little bit different in that a PDF Slideshow occupies just the one table cell (rather than the many horizontal cells of the other display modes) and the resultant embedded PDF data vertically scrolls when multiple image slides are involved.

This new option also adds onto this “Inhouse Slideshow” functionality the chance to download and keep a PDF representation of that slideshow to your local system. Perhaps this makes this be of interest to you?!

The changed form_creator.php‘s live run is what gets integrated into the “Inhouse Slideshow” “sisterhood”. We say “sisterhood” because this “Inhouse Slideshow” is designed as a single PHP codefile “hived off” to a lot of other web server folders as their default “index.php” web browser default webpage in a “peer to peer” feeling arrangement. Such an arrangement asks a bit of the deployment arrangements, and we’ve talked about this before (with underlying links pointing to today’s work, should you be interested) …

Unit testing completed, the deployment, again, matches those ideas of the recent Inhouse Slideshow Design Exif Zip Tutorial … in that …

But when we say “Unit testing completed” above, we need to fill you in on a Fpdf issue we came across during unit testing of our changes. We were getting a …


FPDF Error: Not a JPEG file

… Fpdf error message choosing the new “PDF Slideshow” option on some, but not all, “Inhouse Slideshow” address bar URLs. And so the online research began as per …

… almost getting us there to a solution (and as far as the last link goes “that was before we posted the suggestion below”). Then we took one of the error messages at its word …


FPDF error: Not a JPEG file: ../Mac/Linux_drutil-238of.jpg

… and independently looked into the issue via Linux (or macOS command line) file command …


# cd $HOME/public_html/Mac
# ls -l Linux_dr*
-rw-r--r-- 1 owner group 724353 Oct 29 08:00 Linux_drutil-238of.jpg
-rw-r--r-- 1 owner group 132707 Oct 29 08:00 Linux_drutil-239of.jpg
-rw-r--r-- 1 owner group 109595 Oct 29 08:00 Linux_drutil-240of.jpg
# file Linux_drutil-238of.jpg
Linux_drutil-238of.jpg: PNG image data, 1280 x 800, 8-bit/color RGBA, non-interlaced
# file Linux_drutil-239of.jpg
Linux_drutil-239of.jpg: JPEG image data, JFIF standard 1.01
#

… when the penny dropped (about our (macOS) Paintbrush slideshow slide creation habits)! We quote our entry into “php – FPDF error: Not a JPEG file: http://10.11.201.93:81/webdocc/uploaded/tes3.jpg – Stack Overflow” …

Have found that constructing slideshows with Paintbrush on a MacBook Pro for years have sometimes been saving what “file jpeg_filename.jpg” determines is a PNG, as a JPEG, which is not the end of the world as far as the browsers go rendering this. Within FPDF’s fpdf.php I fixed my own shortcomings that were resulting in “FPDF Error: Not a JPEG file” via the kludgy “if($a[2]==3) { return $this->_parsepng($file); }” additional codeline below …

function _parsejpg($file)
{
// Extract info from a JPEG file
$a = getimagesize($file);
if(!$a)
$this->Error(‘Missing or incorrect image file: ‘.$file);
if($a[2]==3) { return $this->_parsepng($file); }
if($a[2]!=2)
$this->Error(‘Not a JPEG file: ‘.’ ‘.$a[2].’ ‘.$file);
if(!isset($a[‘channels’]) || $a[‘channels’]==3)
$colspace = ‘DeviceRGB’;
elseif($a[‘channels’]==4)
$colspace = ‘DeviceCMYK’;
else
$colspace = ‘DeviceGray’;
$bpc = isset($a[‘bits’]) ? $a[‘bits’] : 8;
$data = file_get_contents($file);
return array(‘w’=>$a[0], ‘h’=>$a[1], ‘cs’=>$colspace, ‘bpc’=>$bpc, ‘f’=>’DCTDecode’, ‘data’=>$data);
}

… and this change to Fpdf’s fpdf.php fixed the issue in our case for a lot of our previously erroneous “PDF Slideshow” displays of “Inhouse Slideshows”.


Previous relevant PDF Slideshow and Form Creation Helper Primer Tutorial is shown below.

PDF Slideshow and Form Creation Helper Primer Tutorial

PDF Slideshow and Form Creation Helper Primer Tutorial

Our recent work involving the great Fpdf creator of PDF files when we presented Ajax FormData Object No Body PHP PDF Tutorial has got us starting on a new PDF (PHP) web application we are starting out thinking will help with …

  • online forms (probably via thinking in terms of Fpdf open source programmers like Rick van Buuren and Clément Lavoillotte‘s excellent HTML table rendering ideas) via HTML table intermediate user interactions … and …
  • slideshows

… but we will not be surprised if the project branches out into other ideas. We’ll see over time.

We hope you come along for the trip starting with a bit of a proof of concept form_creator.php‘s live run for you to try, where we allow you to enter (and be able to change) some HTML table code (if that’s what you end up with?!) in a pink HTML textarea element, and that will become PDF should you click the underlying HTML form’s yellow submit button.

Hope to see you for tomorrow’s PDF writing developments here.

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, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Inhouse Slideshow AlmaLinux Filtered Content Tutorial

Inhouse Slideshow AlmaLinux Filtered Content Tutorial

Inhouse Slideshow AlmaLinux Filtered Content Tutorial

There’s …

… we’re using the great PHP GD library image filtering talents to open up to the user in “name”, that is, any numerical arguments fixed in a static way by us (and we’ll see about otherwise into the future).

The user can pick (so far one at a time, but we’ll review into the future) from …

… and some of the resultant effects can be quite startling.

Coming from the serverside we decided to pack more into …

… to make these optional and additional image filtering options to be available to users of Inhouse Slideshows (eg. Jenkins) hereabouts.

Did you know?

Keen observers will know that we (just about) always assemble a group of image screenshot slides into animated GIFs these days. And if you have read some oldish tutorials you will know, about RJM Programming history

  • for many years it was hosted on a CentOS Apache/PHP5/MySql Linux web server where we had both …
    1. disk inode count
    2. diskspace (in bytes)

    hair trigger issues to worry about for several years … until …

  • recently a migration to AlmaLinux Apache/PHP8/MySql Linux web server eased those worries in both senses

But, analogous (in motivation) to how programmers worked with limited amounts of memory in those early Windows and Mac OS X days, we switched tack using inhouse slideshow concepts (eating into the CentOS inode count, hence the push over that time, to get PHP zip help to have the one zipfile be used to zip/(temporarily)unzip the image slide files) in favour of (the one file) animated GIF paradigm. Do we change back? We (with consultation) are not that tempted because …

  • we’ve gotten better with animated GIF creation functionality …
  • though inhouse slideshow can have cute features, it is a pretty resource intensive way to go about things

… and so (with consultation) we’ll see … and Nala says to say “hear” … and Luna says to say “smell” (and she’s right in that that “smellorama” project is still on the go).


Previous relevant Inhouse Slideshow AlmaLinux CSS Style Tutorial is shown below.

Inhouse Slideshow AlmaLinux CSS Style Tutorial

Inhouse Slideshow AlmaLinux CSS Style Tutorial

Yes, we like, where possible, and we’ve invisaged it, we prefer to give the user “a stake” in …

  • less often how the web application functions … and/or …
  • how the web application looks

And under “looks” that can mean …

  • media content and/or …
  • CSS styling

… and today think “option twos” above regarding our recent Inhouse Slideshow “push”, started, this time around, because of …

  • PHP Zip deprecation … handled by each Inhouse Slideshow overseeing PHP (along with it’s new included ziphelper.php helper) … then …
  • new media creation dropdown options … as with yesterday’s Inhouse Slideshow AlmaLinux Media Tutorial … handled by each Inhouse Slideshow overseeing PHP and cowsay Python API interfacer and changed inhouse_slideshow.js Inhouse Slideshow external Javascript helper … and now, today …
  • new CSS Style dropdown option … handled by the changed inhouse_slideshow.js Inhouse Slideshow external Javascript helper only

Of course, that is what external Javascript design is all about. You adjust one code source only, to affect a whole lot of web applications, rather than the worry of many code source changes. We know which we prefer, as programmers?!

Is your way into programming via CSS styling? Perhaps it would tempt you if we pointed out that there are I.T. jobs out there asking for people with expert CSS styling skills. By this, you may understand it can be an art form transforming dreary looking HTML content into dynamic and vibrant looking webpages (all with the same content).

We’ve learnt most about CSS styling, fast, via web browser web inspectors and seeing an initial webpage look change before our eyes via tweaks applied dynamically. We recommend this highly, but don’t expect everyone to be that keen. In any case, we’re trying to channel that dynamism today, offering the user to see our Inhouse Slideshow change it’s look via user CSS Styling entries in a prompt window instigated by a new “Style” dropdown option.

CSS styling does well with webpages dynamically because, quite often, the Javascript DOM approach (where yourselectorpluscss contains CSS styling code) …


document.body.innerHTML+='<style> ' + yourselectorpluscss + ' </style>';

… will both do no harm to existant content as well as dynamically change webpage aesthetics instantly.

Regarding CSS we know we have much to learn and try regarding the …


selector { styling; }

Only the other day with cartoons we used (clauses like) …

<style>

td[id$='5'] { styling; }

</style>

… types of CSS clauses to mildly change the styling for each cartoon slide. After using this, for the first time, we wrote down for future tutorial ideas “write a web application helping users improve on their selector smarts”. But we think this Inhouse Slideshow opportunity might be a better dynamic approach for this.


Previous relevant Inhouse Slideshow AlmaLinux Media Tutorial is shown below.

Inhouse Slideshow AlmaLinux Media Tutorial

Inhouse Slideshow AlmaLinux Media Tutorial

The recent Inhouse Slideshow AlmaLinux Tutorial did help with PHP Zip deprecations, and today, this being Inhouse Slideshows, full of …

moving pictures

… we can add two more dropdown modus operandi options for …

  • Video
  • Animated GIF

… feeding it through to a changed latest draft cowsay.php media creator via slides via ffmpeg inhouse talent, called by our inhouse slideshow external Javascript helper …


function changeto(tvis) {
if (tvis.toLowerCase().indexOf('video') == 0) {
document.getElementById('divcowpf').innerHTML+='<input type=hidden name=fromindex id=fromindex value=y></input>';
document.getElementById('vlist').click();
document.getElementById('mycowifr').style.display='block';
document.getElementById('mycowifr').style.visibility='hidden';
document.getElementById('mycowifr').style.height='1px';
//document.getElementById('mycowifr').scrollIntoView();
//location.href='#mycowifr';
setTimeout(function(){ document.getElementById('mycowifr').scrollIntoView(); }, 8000);
} else if (tvis.toLowerCase().indexOf('animated gif') == 0) {
document.getElementById('divcowpf').innerHTML+='<input type=hidden name=fromindex id=fromindex value=y></input>';
document.getElementById('aglist').click();
document.getElementById('mycowifr').style.display='block';
document.getElementById('mycowifr').style.visibility='hidden';
document.getElementById('mycowifr').style.height='1px';
//document.getElementById('mycowifr').scrollIntoView();
//location.href='#mycowifr';
setTimeout(function(){ document.getElementById('mycowifr').scrollIntoView(); }, 8000);
} else
if (tvis.toLowerCase().indexOf('exif') == 0) {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?exif=y');
} else {
location.href=posturl(document.URL.split('#')[0].replace(/pdf\=/g, 'pdTf=') + '&exif=y');
}
} else if (tvis.toLowerCase().indexOf('pdf') == 0) {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?pdf=y');
} else {
location.href=posturl(document.URL.split('#')[0].replace(/exif\=/g, 'exTif=') + '&pdf=y');
}
} else if (tvis.toLowerCase().indexOf('emoji') == 0) {
//var borderis=prompt('Please enter comma separated HTML decimal entity(s) for your Emoji Border to slideshow. Can use an Emoji Menu entry.', '');
var bbsuffix=' Optionally append &[text|image]css=[CSSstyle] to change styling. Optionally justify some text via &[ul|uc|ur|ml|[mc]|mr|bl|bc|br]text=[someText%0AsecondLine] to change styling. Eg. ' + String.fromCodePoint(127958) + '&css=opacity:0.9;&textcss=font-size:20px;&ultext=Hello%0AThere ';
borderblurb='Please enter comma separated HTML decimal entity(s) for your Emoji Border to slideshow. Can use an Emoji Menu entry (eg. control-command-space for macOS or Mac OS X, logo key + . (period) for Windows, control+space for iOS, top left + for Android keyboard). ' + bbsuffix;
var borderis=prompt(borderblurb, '');
var emojiy='', emojisuffix='';
if (borderis == null) {
borderis='';
} else if (borderis.indexOf('&') != -1) {
if (borderis.split('&')[0].trim() == '') {
emojisuffix=encodeURIComponent(borderis.replace(/\%23[cC][iI][rR][cC][lL][eE]/g, '#circle').replace(/\%23[eE][lL][lL][iI][pP][sS][eE]/g, '#ellipse').replace(/\%23[tT][eE][xX][tT]/g, '#text').replace(/\%23[lL][iI][nN][eE]/g, '#line').replace(/\%23[pP][oO][lL][yY][lL][iI][nN][eE]/g, '#polyline').replace(/\%23[pP][oO][lL][yY][gG][oO][nN]/g, '#polygon').replace(/\%23/g, encodeURIComponent('%23')).replace(/\%23/g, encodeURIComponent('%23')).replace(/\%0a/g, encodeURIComponent('%0A')).replace(/\%0A/g, encodeURIComponent('%0A'))); //.replace(/\&/g,'%26').replace(/\=/g,'%3D');
borderis='';
} else {
emojisuffix=encodeURIComponent(borderis.replace(borderis.split('&')[0], '').replace(/\%23[cC][iI][rR][cC][lL][eE]/g, '#circle').replace(/\%23[eE][lL][lL][iI][pP][sS][eE]/g, '#ellipse').replace(/\%23[tT][eE][xX][tT]/g, '#text').replace(/\%23[lL][iI][nN][eE]/g, '#line').replace(/\%23[pP][oO][lL][yY][lL][iI][nN][eE]/g, '#polyline').replace(/\%23[pP][oO][lL][yY][gG][oO][nN]/g, '#polygon').replace(/\%23/g, encodeURIComponent('%23')).replace(/\%23/g, encodeURIComponent('%23')).replace(/\%0a/g, encodeURIComponent('%0A')).replace(/\%0A/g, encodeURIComponent('%0A'))); //.replace(/\&/g,'%26').replace(/\=/g,'%3D');
borderis=postbb(borderis.split('&')[0]);
}
} else {
borderis=postbb(borderis.split('&')[0]);
}
if ((borderis + emojisuffix) != '') { emojiy='emoji=' + encodeURIComponent(borderis) + emojisuffix; }
if (emojiy != '') {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?' + emojiy);
} else {
location.href=posturl(document.URL.split('#')[0].replace(/emoji\=/g, 'emojTi=') + '&' + emojiy);
}
}
} else {
if (document.URL.indexOf('exif=') != -1 || document.URL.indexOf('pdf=') != -1) {
location.href=posturl(document.URL.split('#')[0].replace(/exif\=/g, 'exTif=').replace(/pdf\=/g, 'pdTf='));
} else {
location.href=posturl(document.URL.split('#')[0] + '&eHuhxif=y');
}
}
}

… called by a changed example PHP inhouse slideshow creator web application.


Previous relevant Inhouse Slideshow AlmaLinux Tutorial is shown below.

Inhouse Slideshow AlmaLinux Tutorial

Inhouse Slideshow AlmaLinux Tutorial

Today we wanted to add so much more to our blog posting title. But, then, we also didn’t want to give the game away?! What a dilemma.

That blog posting title mentions …

  • AlmaLinux … as RJM Programming’s Apache/PHP/MySql web server “brand”, using …
  • PHP 8 … as distinct from the PHP 5’s of the CentOS web server days … and so we suppose we should expect issues like the dreaded …
  • Deprecation … of …
  • Zip … functionality … so sad seeing the early symptoms of this with …
  • Inhouse Slideshow presentations … (as last talked about with Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial) deprecation warnings

Surprising to us, trying to logically walk though a solution, currently up at our AlmaLinux web server here the PHP …


function_exists

… approach we have used successfully recently did not work here. Anyway, deprecated or non-existant it doesn’t matter, we decided to resort to good ol’ PHP exec methodologies in a new “inhouse slideshow” (featuring in a changed example PHP inhouse slideshow creator web application) call …

<?php

include($_SERVER['DOCUMENT_ROOT'] . "/ziphelper.php");

?>

… containing …


<?php
// ziphelper.php
// RJM Programming
// February, 2025

$gzip_read_output=null;
$gzip_open_handle=null;
$gzip_entry_filename='';
$gzip_filename='';
$gzip_entry_len=0;
$gzip_number=0;
$gzip_log_text='';
if (strpos($_SERVER['REQUEST_URI'], 'index.') !== false) {
$hereis='' . dirname(__FILE__) . explode("index.", $_SERVER['REQUEST_URI'])[0];
} else if (basename($_SERVER['SCRIPT_FILENAME']) != '') {
$hereis=explode(basename($_SERVER['SCRIPT_FILENAME']), realpath($_SERVER['SCRIPT_FILENAME']))[0];
} else {
$hereis='' . dirname(__FILE__) . str_replace('//','/',explode("?", $_SERVER['REQUEST_URI'])[0] . '/');
}
$zipisis='' . $hereis . 'slideshow_0.zip';
$alreadythere=false;

if (file_exists($zipisis)) {
$items = glob($hereis . "*[-_][0-9]*of.[jJgGpP][pPiInN]*");
foreach ($items as $key => $val) {
$alreadythere=true;
}
}

if (!function_exists("zip_entry_read")) {
function zip_entry_read($zip_read_output, $zip_entry_len) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_read_output, $gzip_entry_len;
return 'pork';
}
}

if (!function_exists("zip_entry_filesize")) {
function zip_entry_filesize($zip_read_filename) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_entry_filename;
return 'pork';
}
}

if (!function_exists("zip_read")) {
function zip_read($zip_oben_handle) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle;
return 'pork';
}
}

if (!function_exists("zip_open")) {
function zip_open($zip_filename) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_filename;
$gzip_filename=$zip_filename;
$gzip_number=0;
$gzip_open_handle='pork';
return 'pork';
}
}

if (!function_exists("zip_entry_name")) {
function zip_entry_name($zip_read_output) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_read_output;
return 'pork';
}
}

if (!function_exists("zip_entry_open")) {
function zip_entry_open($zip_open_handle, $zip_read_output, $inmode) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle, $gzip_read_output;
return 'pork';
}
}

if (!function_exists("zip_close")) {
function zip_close($zip_open_handle) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle;
return 'pork';
}
}

if (file_exists($zipisis)) {
if (!$alreadythere) {
file_put_contents($hereis . 'please.wait', "cd " . $hereis . ' ; unzip ' . $zipisis);
sleep(2);
exec("cd " . $hereis . ' ; unzip ' . $zipisis);
sleep(2);
unlink($hereis . 'please.wait');
//exec("cd " . $hereis . ' ; rm -f please.wait');
//if (1 == 1) {
//header('Location: ' . explode('?',$_SERVER['REQUEST_URI'])[0] . '?rand=' . rand(0,674532));
//exit;
//} else {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
//if (basename($_SERVER['SCRIPT_FILENAME']) == 'index.php') {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
//sleep(9);
//echo '<html><body onload="location.href=' . "'" . explode("?", $_SERVER['REQUEST_URI'])[0] . '?rand=' . rand(0,5645342) . "';\"></body></html>";
//exit;
} //else if (basename($_SERVER['SCRIPT_FILENAME']) == 'index.php') {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
}
?>

… as a first draft. We have much more to do trying to resurrect, if possible, some other inhouse PHP web applications we’ve based on the use of Zip in PHP. Pardon us, until tomorrow, while we have a little cry.


Previous relevant Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial

Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial

Crontab is that great scheduling tool that we make use of, a lot, on our RJM Programming Linux CentOS web server. But it’s not only …

  • the timing … of a procedure that is so good about crontab … it is, also, for us, it’s teaming with …
  • curl

… that means we can back up a “peer based” solution such as talked about with Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial (ie. done as a user is surfing the net with some PHP of ours) methodology should it fail. We think we have an occasionally failing one as far as the tidy up of zipped up inhouse slideshows goes. It could be to do with a search engine crawling operation, we have not found out for sure, but we’ve decided to write our own …

  • PHP … via …
  • crontab
  • curl

… based independent tidying up procedure we’ll run once an hour via crontab record …


*/53 * * * curl http://www.rjmprogramming.com.au/slideshow_zero.php

… arrangement. We realize the contents of this PHP procedure may bore some, but interest a few, and so here is what it amounted to …

<?php

// slideshow_zero.php
// Zip and Unzip Tidy Up
// RJM Programming
// Decemeber, 2022
set_time_limit(3600);

if (file_exists("slideshow_zero.txt")) {
unlink("slideshow_zero.txt");
}

if (file_exists("slideshow_zero.kkk")) {
unlink("slideshow_zero.kkk");
}

exec("find " . dirname(__FILE__) . DIRECTORY_SEPARATOR . " -name 'slideshow_0.zip' 2> /dev/null > " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txt");

$lines=file(dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txt");

$htmlis="<html><body><textarea>
</textarea></body></html>";

for ($i=0; $i<sizeof($lines); $i++) {
$lines[$i]=explode("\n", $lines[$i])[0];
if (file_exists(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) {
if (('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) == '38794') {
if (file_exists("slideshow_zero.txx")) {
unlink("slideshow_zero.txx");
}
exec("unzip -l " . $lines[$i] . " | grep '.jpg' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/ /s// /g' | sed '/ /s// /g' | sed '/ /s// /g' | sed '/ /s// /g' | cut -f4 -d' ' | grep '-' > " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txx");
if (file_exists("slideshow_zero.txx")) {
$sublines=file(dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txx");
for ($j=0; $j<sizeof($sublines); $j++) {
$sublines[$j]=explode(" ", explode("\n", $sublines[$j])[0])[0];
$fis=explode("slideshow_0.zip", $lines[$i])[0] . $sublines[$j];
if (file_exists($fis)) {
$md=filemtime($fis);
if ($md) {
if ((time() - $md) > 1200) {
if (file_exists("slideshow_zero.kkk")) {
exec("rm -f " . $fis); //file_put_contents("slideshow_zero.kkk", file_get_contents("slideshow_zero.kkk") . "rm -f " . $fis . "\n");
} else {
exec("rm -f " . $fis); //file_put_contents("slideshow_zero.kkk", "rm -f " . $fis . "\n");
}
}
}
}
}
}
} else if (1 == 3) {
if (file_exists("slideshow_zero.kkk")) {
file_put_contents("slideshow_zero.kkk", file_get_contents("slideshow_zero.kkk") . "# " . ('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) . " is not 38794 " . str_replace("slideshow_0.zip", "index.php", $lines[$i]) . "\n");
} else {
file_put_contents("slideshow_zero.kkk", "# " . ('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) . " is not 38794 " . str_replace("slideshow_0.zip", "index.php", $lines[$i]) . "\n");
}
}
}
}

if (file_exists("slideshow_zero.txx")) {
unlink("slideshow_zero.txx");
}

if (file_exists("slideshow_zero.txt")) {
unlink("slideshow_zero.txt");
}

if (file_exists("slideshow_zero.kkk")) {
unlink("slideshow_zero.kkk");
}

//echo $htmlis;
exit;

?>

… as that “ahhhhhhhh, what a relief” reliever of tension running the RJM Programming website. The subtext is, our inode limits are a concern!

We think another lesson here is that PHP can be a good alternative to scripting languages such as Korn Shell to create “operational” procedures, especially when you consider that curl means it can be like writing your “surfing the net” type of PHP (slideshow_zero.php) work.


Previous relevant Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial

Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial

The thing about yesterday’s Inhouse Slideshow Backup Tidy Up Report Tutorial is that …

  • it creates useful report content … but …
  • it is information we do not want everyone to be able to see (easily, shall we say) … and in the sense that …
  • the report is stored away from RJM Programming’s “public_html” folder (ie. its Apache/PHP/MySql “Document Root”) is good … but even with today’s work …
  • hidden from everybody who does not have access to the RJM Programming’s web server … but …
  • the administrator of the RJM Programming’s web server (yoo hoo!) wants a mechanism to view the report that does not involve some “arcane procedure” each time to view it

… and so we decided that because …


the administrator of the RJM Programming's web server = the administrator of this blog

… we’d like to organize a system that latches onto that “security footing” and only show a “broom emoji button” (🧹 &#129529;) way to access the report when the administrator of this blog is logged in. We can do this by amending our Twenty Ten theme’s good ol’ header.php as per (where the “function mlater” you may recall from the days of WordPress Blog Email Post Collaboration Ajax Image Tutorial) …

<?php

$fns="36";

function doisr() {
global $fns;
$inmb="";
if (('' . get_current_user_id()) != '0' && ('' . get_current_user_id()) == '1') {
if (file_exists('/tmp/slideshow_cleanup.txt')) {
$fns="24";
$inmb="<a style=font-size:24px; title='Inhouse Slideshow Tidy Up Report' onclick=\"var iswo=window.open('','_blank','top=100,left=100,height=600,width=730'); iswo.document.write('<html><head><title>Inhouse Slideshow Tidy Up Report</title></head><body><pre>" . str_replace("\n","<br>",file_get_contents('/tmp/slideshow_cleanup.txt')) . "</pre></body></html>'); \">&#129529;</a> ";
}
}
return str_replace("'","' + String.fromCharCode(39) + '",$inmb);
}


?>

… PHP affects some (PHP writes) Javascript below …

<?php

function mlater() {
if (1 == 1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i)) {
if (dbihis == '') { dbihis=document.body.innerHTML; }
var xstih=document.getElementById('site-title').innerHTML;
if (xstih.indexOf("up" + "top") == -1) {
document.getElementById('site-title').innerHTML+='<?php echo doisr(); ?>' + '<a id="avs" style="text-decoration:none;font-size:<?php global $fns; echo $fns; ?>px;" href=# onmouseover="getVisualSynopsis(event);" onmouseout="yehbut();" ontouchstart="getVisualSynopsis(event);" ontouchend="yehbut();" onclick=" uptop(); " title="... you can wait for the long hover functionality about Visual Synopsis (Slideshows)">&#127910;</a> <a style="cursor:pointer;text-decoration:none;font-size:<?php global $fns; echo $fns; ?>px;" onclick="diffphpfix(this);" title="Code Difference Functional Links">&#128214;</a> <a style="cursor:pointer;text-decoration:none;font-size:36px;" onclick="popselid();" title="Filter Content via Div ID">&#10135;</a> <a style="cursor:pointer;text-decoration:none;visibility:hidden;font-size:<?php global $fns; echo $fns; ?>px;" title="Blog post contents reduced to summary" id="eds" onclick="pre_details_summary();">&#10134;</a>' + printscreen(0);
if (document.URL.indexOf("visualsynopsis=") != -1) document.getElementById('avs').click();
}
}
}

?>


Previous relevant Inhouse Slideshow Backup Tidy Up Report Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Report Tutorial

Inhouse Slideshow Backup Tidy Up Report Tutorial

Yesterday’s Inhouse Slideshow Backup Tidy Up Tutorial presented a …

  • non-automated
  • user instigated
  • snapshot

… Inhouse Slideshow “tidying up” PHP web application. This web application is like a …

  • procedure … that a …
  • system operator

… might be interested in using. But not many “system operators” would continue putting up with such a modus operandi. We can improve by …

  • allowing any of …
    1. surfing the net
    2. curl
    3. command line

    … modes of use … allowing …

  • crontab scheduling via …

    */49 * * * * ksh -c "curl HTTP://www.rjmprogramming.com.au/slideshow_cleanup.php?all=all"

    … to allow for a …
  • scheduled report available … and make sure we …
  • disallow overlapping execution runs

… with our changed slideshow_cleanup.php “Inhouse Slideshow” unzipped image “tidyer upperer“.


Previous relevant Inhouse Slideshow Backup Tidy Up Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Tutorial

Inhouse Slideshow Backup Tidy Up Tutorial

There are two aspects to diskspace maintainence up at the web server for RJM Programming.

  • df -k /
  • df -i /
# diskspace
# inode count

… and it is often that inode count we are concerned about, and looking out for ways to reduce the number of files we create on the web server.

The Inhouse Slideshow ways of Inhouse Slideshow Mobile Google Crawl Tutorial

  • use zip files to “scrunch up” a series of image files into the one zip file … for the vast majority of time … but when asked to, by a user …
  • unzip the image files when required by a user wanting to see them … and then …
  • tidy up, after some delay in time

… but we want to design a PHP way to independently tidy up as a backup mechanism. And we say, with PHP code, that if such files have been on the web server longer than ten minutes, this PHP callable slideshow_cleanup.php code …

<?php

// slideshow_cleanup.php
// RJM Programming
// May, 2022

$cdis=dirname(__FILE__) . DIRECTORY_SEPARATOR;
exec("cd " . $cdis . "; find . -name 'slideshow_0.zip' 2> /dev/null > /tmp/slideshow_cleanup.txt");


$lines = file('/tmp/slideshow_cleanup.txt');
date_default_timezone_set('Australia/Perth');

foreach ($lines as $line_num => $line) {
$ji=0;
if (substr($line,0,1) == '.') { $ji=2; }
$thisdir=explode('slideshow_0.zip', $line)[0];
$uzc=shell_exec("unzip -l " . $cdis . substr($line, $ji));
foreach (glob($thisdir . '*-[0-9]*of.[jJpPgG][pPnNiI]*') as $zipmember) {
$ij=0;
if (substr($zipmember,0,1) == '.') { $ij=2; }
$thisfile=$cdis . substr($zipmember, $ij);
if (strpos($uzc, (' ' . explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij))[-1 + sizeof(explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij)))]) ) !== false) {
if ((time() - filectime($thisfile)) > 600) { // more than 10 minutes old
unlink($thisfile); //echo "analyze " . $thisfile . " " . (time() - filectime($thisfile)) . ' seconds ago ' . "\n";
}
}
}
foreach (glob($thisdir . '*-[0-9]{[0-9]*}.[jJpPgG][pPnNiI]*') as $zipmember) {
$ij=0;
if (substr($zipmember,0,1) == '.') { $ij=2; }
$thisfile=$cdis . substr($zipmember, $ij);
if (strpos($uzc, (' ' . explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij))[-1 + sizeof(explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij)))]) ) !== false) {
if ((time() - filectime($thisfile)) > 600) {
unlink($thisfile); //echo "Analyze " . $thisfile . " " . (time() - filectime($thisfile)) . ' seconds ago ' . "\n";
}
}
}
}


?>

… should do its thaing!


Previous relevant Inhouse Slideshow Mobile Google Crawl Tutorial is shown below.

Inhouse Slideshow Mobile Google Crawl Tutorial

Inhouse Slideshow Mobile Google Crawl Tutorial

The recent Inhouse Slideshow Mobile Tutorial did not satisfy all the “mobile usability” tests performed by the “Google Crawl” algorithm, failing on “Content wider than screen”, and you can read some background to this with Google Crawl Viewport Geographicals Tutorial. And so we try some refinements here today, with an idea to control on mobile platforms the max-width CSS property of the document.body of a Inhouse Slideshow webpage, which made up the URLs failing this test at the Google Search Console.

We were reading this great and useful link, thanks, and decided to see whether this stopping of scrolling in X on mobile platform versions of the Inhouse Slideshow webpages gels better with Google Search Console “Google Crawl” Mobility Usability algorithms.

Yet again, deployment of these changes is similar to that last time, and the times before that, as per …

Unit testing completed, the deployment, again, matches those ideas of the recent PDF Slideshow and Form Creation Helper Slideshow Tutorial … in that …

Here are changes we’ll be testing up at Google …


<head>
<script type='text/javascript'>
// Other Javascript code here ...
//
//
// Of relevance today bold below ...

function blater() {
var tdsare=document.getElementsByTagName('td');
var rectg=tdsare[2].getBoundingClientRect(); //document.getElementById('i0').getBoundingClientRect();
tdsare[2].style.borderRight='2px solid white';
document.body.style.backgroundImage="URL('" + document.getElementById('i0').src + "')";
var rl=eval('' + rectg.left);
rl+=eval('' + rectg.width);
rl+=10;
document.body.style.backgroundPosition=" " + rl + "px " + Math.floor(rectg.top) + "px";
document.body.style.backgroundRepeat="no-repeat";
document.body.style.backgroundClip="content-box";
}



function zoom_maybe() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
//document.getElementById('rfs').innerHTML='<style> html { zoom: .5; } </style>';
document.getElementById('rfs').innerHTML='<style> html { zoom: 0.4; body { max-width: 100%; max-height: 80vh; } table { max-width: <?php if (strpos($_SERVER['QUERY_STRING'],'exif=') !== false) { echo "100"; } else { echo "95"; } ?>%; max-height: 80vh; margin: auto; overflow-x: hidden; } </style>';
}
}


function nwpdf(iithis) {
if (('' + iithis.src).length > 0) {
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
window.open(iithis.src,'_blank');
}
}
}


function mytw() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.body.style.width='' + (window.orientation == 0 ? Math.floor(eval(2.5 * window.screen.width)) : window.screen.height) + 'px';
document.getElementById('myt').style.width='100%'; //'' + (window.orientation == 0 ? window.screen.width : window.screen.height) + 'px';
}
}



window.setInterval(function(){havealook(1)},2000);
</script>
<style>
td { vertical-align:top; }
@media only screen and (max-width: 800px) {
body { max-width: 100%; max-height: 80vh; } table { max-width: <?php if (strpos($_SERVER['QUERY_STRING'],'exif=') !== false) { echo "100"; } else { echo "95"; } ?>%; max-height: 80vh; margin: auto; overflow-x: hidden; }
}

</style>
</head>
<body onload=" mytw(); zoom_maybe(); if (document.URL.indexOf('pdf=') != -1) { document.getElementById('selmode').value='PDF Slideshow'; if (document.getElementById('tdfirst')) { document.getElementById('s0').style.width=document.getElementById('tdfirst').style.width; document.getElementById('s0').style.height=document.getElementById('tdfirst').style.height; } } if (document.URL.indexOf('exif=') != -1) { document.getElementById('selmode').value='Exif Slideshow'; if (document.getElementById('tdfirst')) { document.getElementById('s0').style.width=document.getElementById('tdfirst').style.width; document.getElementById('s0').style.height=document.getElementById('tdfirst').style.height; } } document.title=document.title + ' ' + lastone; ol(); ">


Previous relevant Inhouse Slideshow Mobile Tutorial is shown below.

Inhouse Slideshow Mobile Tutorial

Inhouse Slideshow Mobile Tutorial

The recent PDF Slideshow and Form Creation Helper Slideshow Tutorial changes were made on a MacBook Pro laptop. Did it show that we have put off until today, to look at that functionality with mobile platforms?!

In a “going off to the right table row of cells” arrangement like this, what are some considerations that improve the user experience (of our inhouse slideshows) for mobile platform users?

  • turn the “@” link into an “emoji button” as per ➡ ( &#10145; )
  • for both mobile and non-mobile, we’ve decided …
    1. UTF-8 meta …
      <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>

    2. <style>
      td { vertical-align:top; }
      </style>
    3. change the h4 element to be h2 to help with legibility
  • for mobile, we’ve decided …
    1. viewport …
      <meta name=”viewport” content=”width=device-width, initial-scale=0.4, minimum-scale=0.1, maximum-scale=8, user-scalable=yes”>

    2. <style>
      html { zoom: .5; }
      </style>
    3. iOS (ie. iPad and iPhone) PDF iframe elements have known scrolling issues, which we decided to bypass by opening these PDF creations in a new webpage window

Deployment of these changes is similar to that last time, and the times before that, as per …

Unit testing completed, the deployment, again, matches those ideas of the recent PDF Slideshow and Form Creation Helper Slideshow Tutorial … in that …


Previous relevant PDF Slideshow and Form Creation Helper Slideshow Tutorial is shown below.

PDF Slideshow and Form Creation Helper Slideshow Tutorial

PDF Slideshow and Form Creation Helper Slideshow Tutorial

The first “integration cab” off the rank for yesterday’s PDF Slideshow and Form Creation Helper Primer Tutorial underlying usefulness is with our Inhouse Slideshow arrangements last talked about at Inhouse Slideshow Design Exif Order Tutorial. That generic PHP code now has three display dropdown options of …

  • Slideshow
  • Exif Slideshow … and the new, as of today’s work …
  • PDF Slideshow

… that little bit different in that a PDF Slideshow occupies just the one table cell (rather than the many horizontal cells of the other display modes) and the resultant embedded PDF data vertically scrolls when multiple image slides are involved.

This new option also adds onto this “Inhouse Slideshow” functionality the chance to download and keep a PDF representation of that slideshow to your local system. Perhaps this makes this be of interest to you?!

The changed form_creator.php‘s live run is what gets integrated into the “Inhouse Slideshow” “sisterhood”. We say “sisterhood” because this “Inhouse Slideshow” is designed as a single PHP codefile “hived off” to a lot of other web server folders as their default “index.php” web browser default webpage in a “peer to peer” feeling arrangement. Such an arrangement asks a bit of the deployment arrangements, and we’ve talked about this before (with underlying links pointing to today’s work, should you be interested) …

Unit testing completed, the deployment, again, matches those ideas of the recent Inhouse Slideshow Design Exif Zip Tutorial … in that …

But when we say “Unit testing completed” above, we need to fill you in on a Fpdf issue we came across during unit testing of our changes. We were getting a …


FPDF Error: Not a JPEG file

… Fpdf error message choosing the new “PDF Slideshow” option on some, but not all, “Inhouse Slideshow” address bar URLs. And so the online research began as per …

… almost getting us there to a solution (and as far as the last link goes “that was before we posted the suggestion below”). Then we took one of the error messages at its word …


FPDF error: Not a JPEG file: ../Mac/Linux_drutil-238of.jpg

… and independently looked into the issue via Linux (or macOS command line) file command …


# cd $HOME/public_html/Mac
# ls -l Linux_dr*
-rw-r--r-- 1 owner group 724353 Oct 29 08:00 Linux_drutil-238of.jpg
-rw-r--r-- 1 owner group 132707 Oct 29 08:00 Linux_drutil-239of.jpg
-rw-r--r-- 1 owner group 109595 Oct 29 08:00 Linux_drutil-240of.jpg
# file Linux_drutil-238of.jpg
Linux_drutil-238of.jpg: PNG image data, 1280 x 800, 8-bit/color RGBA, non-interlaced
# file Linux_drutil-239of.jpg
Linux_drutil-239of.jpg: JPEG image data, JFIF standard 1.01
#

… when the penny dropped (about our (macOS) Paintbrush slideshow slide creation habits)! We quote our entry into “php – FPDF error: Not a JPEG file: http://10.11.201.93:81/webdocc/uploaded/tes3.jpg – Stack Overflow” …

Have found that constructing slideshows with Paintbrush on a MacBook Pro for years have sometimes been saving what “file jpeg_filename.jpg” determines is a PNG, as a JPEG, which is not the end of the world as far as the browsers go rendering this. Within FPDF’s fpdf.php I fixed my own shortcomings that were resulting in “FPDF Error: Not a JPEG file” via the kludgy “if($a[2]==3) { return $this->_parsepng($file); }” additional codeline below …

function _parsejpg($file)
{
// Extract info from a JPEG file
$a = getimagesize($file);
if(!$a)
$this->Error(‘Missing or incorrect image file: ‘.$file);
if($a[2]==3) { return $this->_parsepng($file); }
if($a[2]!=2)
$this->Error(‘Not a JPEG file: ‘.’ ‘.$a[2].’ ‘.$file);
if(!isset($a[‘channels’]) || $a[‘channels’]==3)
$colspace = ‘DeviceRGB’;
elseif($a[‘channels’]==4)
$colspace = ‘DeviceCMYK’;
else
$colspace = ‘DeviceGray’;
$bpc = isset($a[‘bits’]) ? $a[‘bits’] : 8;
$data = file_get_contents($file);
return array(‘w’=>$a[0], ‘h’=>$a[1], ‘cs’=>$colspace, ‘bpc’=>$bpc, ‘f’=>’DCTDecode’, ‘data’=>$data);
}

… and this change to Fpdf’s fpdf.php fixed the issue in our case for a lot of our previously erroneous “PDF Slideshow” displays of “Inhouse Slideshows”.


Previous relevant PDF Slideshow and Form Creation Helper Primer Tutorial is shown below.

PDF Slideshow and Form Creation Helper Primer Tutorial

PDF Slideshow and Form Creation Helper Primer Tutorial

Our recent work involving the great Fpdf creator of PDF files when we presented Ajax FormData Object No Body PHP PDF Tutorial has got us starting on a new PDF (PHP) web application we are starting out thinking will help with …

  • online forms (probably via thinking in terms of Fpdf open source programmers like Rick van Buuren and Clément Lavoillotte‘s excellent HTML table rendering ideas) via HTML table intermediate user interactions … and …
  • slideshows

… but we will not be surprised if the project branches out into other ideas. We’ll see over time.

We hope you come along for the trip starting with a bit of a proof of concept form_creator.php‘s live run for you to try, where we allow you to enter (and be able to change) some HTML table code (if that’s what you end up with?!) in a pink HTML textarea element, and that will become PDF should you click the underlying HTML form’s yellow submit button.

Hope to see you for tomorrow’s PDF writing developments here.

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, Operating System, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Microsoft 365 on iOS Install Primer Tutorial

Microsoft 365 on iOS Install Primer Tutorial

Microsoft 365 on iOS Install Primer Tutorial

Is it meaningful to …

Document Process

… on a device the size of an iPhone? We’ll leave the answer up to you, but we would say …

  • a lot of the world’s population is asked, at various points of their life … to work with …
  • documents and letters or spreadsheets or presentations or book publications … to us, under the umbrella term …
  • Document Processing

… and we figure there will be times you are out and about, cornered to deal with an issue, and want some access to professional document editing smarts. Here we’ve talked about Open Source ways (such as with Word to HTML to CSV Delimitation Primer Tutorial below) that did not involve any Microsoft Office functionality, and we still use LibreOffice around here on our MacBook Air (using macOS), for these purposes. But what about the iPhone or iPad (on iOS) regarding this thinking, and embracing the expertise of Microsoft in the Document Processing arena?

Well, we came across the, initially free, Microsoft 365 product (for iOS), that might fit the requirements of a lot of iPhone or iPad users out there.

It certainly looks the part and wherever Microsoft meets iOS has got to be a crossover reason to celebrate … right?!


Previous relevant Word to HTML to CSV Delimitation Primer Tutorial is shown below.

Word to HTML to CSV Delimitation Primer Tutorial

Word to HTML to CSV Delimitation Primer Tutorial

The modern document applications allow conversion to HTML. What happens during that process, exactly? Well, that’s “under the hood” stuff. A little background, though, and context …

  • Why would you want to convert, say a Word file, to HTML (using, perhaps, LibreOffice, in our case, or Microsoft Word)? … well, as a mere mortal programmer …
  • (any form of) text is easier to deal with for “mere mortal programmer” languages we might want to use like …
  • PHP … is very good at the delimiter processing bits that allow the programmer be useful …
  • converting … the data into other guises, the one that interested us being …
  • CSV (comma separated value) data … to be fed into spreadsheet applications like Excel or LibreOffice’s one … and then create charts

… and to do useful delimiter work in PHP you need to know, or suss out, “what happens”, or evidence of that … think hex dumps (where $dr is a PHP variable containing an HTML file record) …

<?php

echo bin2hex($dr) . "\n";
// ... gave, in our case, output such as ...
// c2a020c2a020c2a020c2a020c2a020c2a020c2a020c2a020c2a020c2a020c2a020c2a020c2a020c2a020c2a020c2a020c2a020546f74616c207c20c2a020c2a02036302c30333220c2a020c2a020c2a03130302e3030

?>

And so we line up all the useful contributors …

  1. CP3O
  2. C2A0
  3. R2D2
  4. … … …

Hang on?! What’s with C2A0? And for that matter, the pitiful “am typing” simulation “… … … “?!

Well, we asked around, and got to this useful link telling us these are non-ascii characters describing a …


Non-breaking space

… scenario programmers of HTML will know can be those …


&nbsp;

… HTML entities in your webpage content. Well, now, at least to us, that all makes sense. But, for our job, that could be the tip of the “UTF-8 headache” situation! We know we’re only interested in ascii data characters for the conversion job we are trying to do. Is there a way to simplify this “middleperson” HTML data content? Well, this other useful link … got us to use …

<?php

$dr=preg_replace('/[\x7F-\xFF]/ui', '', $dr);

?>

… helped us with …

  1. sanity
  2. simplification

… as far as the PHP delimitation logic went. This was an inhouse job, but we’ll show you a skeletal of how we used …

  • input Word report … we are calling from_word_to_html.html … say …
  • containing spreadsheetable data …
  • we wanted to extract into …
  • individual CSV files … ready to …
  • open as useful spreadsheets … and perhaps onto some chart production …
  • processing via command line command …

    php dostuff.php

    … where that PHP is (very informally) …
  • dostuff.php

… in case these ideas interest you?!

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, GUI, Installers, iOS, Operating System, Software, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , | Leave a comment

Inhouse Slideshow AlmaLinux CSS Style Tutorial

Inhouse Slideshow AlmaLinux CSS Style Tutorial

Inhouse Slideshow AlmaLinux CSS Style Tutorial

Yes, we like, where possible, and we’ve invisaged it, we prefer to give the user “a stake” in …

  • less often how the web application functions … and/or …
  • how the web application looks

And under “looks” that can mean …

  • media content and/or …
  • CSS styling

… and today think “option twos” above regarding our recent Inhouse Slideshow “push”, started, this time around, because of …

  • PHP Zip deprecation … handled by each Inhouse Slideshow overseeing PHP (along with it’s new included ziphelper.php helper) … then …
  • new media creation dropdown options … as with yesterday’s Inhouse Slideshow AlmaLinux Media Tutorial … handled by each Inhouse Slideshow overseeing PHP and cowsay Python API interfacer and changed inhouse_slideshow.js Inhouse Slideshow external Javascript helper … and now, today …
  • new CSS Style dropdown option … handled by the changed inhouse_slideshow.js Inhouse Slideshow external Javascript helper only

Of course, that is what external Javascript design is all about. You adjust one code source only, to affect a whole lot of web applications, rather than the worry of many code source changes. We know which we prefer, as programmers?!

Is your way into programming via CSS styling? Perhaps it would tempt you if we pointed out that there are I.T. jobs out there asking for people with expert CSS styling skills. By this, you may understand it can be an art form transforming dreary looking HTML content into dynamic and vibrant looking webpages (all with the same content).

We’ve learnt most about CSS styling, fast, via web browser web inspectors and seeing an initial webpage look change before our eyes via tweaks applied dynamically. We recommend this highly, but don’t expect everyone to be that keen. In any case, we’re trying to channel that dynamism today, offering the user to see our Inhouse Slideshow change it’s look via user CSS Styling entries in a prompt window instigated by a new “Style” dropdown option.

CSS styling does well with webpages dynamically because, quite often, the Javascript DOM approach (where yourselectorpluscss contains CSS styling code) …


document.body.innerHTML+='<style> ' + yourselectorpluscss + ' </style>';

… will both do no harm to existant content as well as dynamically change webpage aesthetics instantly.

Regarding CSS we know we have much to learn and try regarding the …


selector { styling; }

Only the other day with cartoons we used (clauses like) …

<style>

td[id$='5'] { styling; }

</style>

… types of CSS clauses to mildly change the styling for each cartoon slide. After using this, for the first time, we wrote down for future tutorial ideas “write a web application helping users improve on their selector smarts”. But we think this Inhouse Slideshow opportunity might be a better dynamic approach for this.


Previous relevant Inhouse Slideshow AlmaLinux Media Tutorial is shown below.

Inhouse Slideshow AlmaLinux Media Tutorial

Inhouse Slideshow AlmaLinux Media Tutorial

The recent Inhouse Slideshow AlmaLinux Tutorial did help with PHP Zip deprecations, and today, this being Inhouse Slideshows, full of …

moving pictures

… we can add two more dropdown modus operandi options for …

  • Video
  • Animated GIF

… feeding it through to a changed latest draft cowsay.php media creator via slides via ffmpeg inhouse talent, called by our inhouse slideshow external Javascript helper …


function changeto(tvis) {
if (tvis.toLowerCase().indexOf('video') == 0) {
document.getElementById('divcowpf').innerHTML+='<input type=hidden name=fromindex id=fromindex value=y></input>';
document.getElementById('vlist').click();
document.getElementById('mycowifr').style.display='block';
document.getElementById('mycowifr').style.visibility='hidden';
document.getElementById('mycowifr').style.height='1px';
//document.getElementById('mycowifr').scrollIntoView();
//location.href='#mycowifr';
setTimeout(function(){ document.getElementById('mycowifr').scrollIntoView(); }, 8000);
} else if (tvis.toLowerCase().indexOf('animated gif') == 0) {
document.getElementById('divcowpf').innerHTML+='<input type=hidden name=fromindex id=fromindex value=y></input>';
document.getElementById('aglist').click();
document.getElementById('mycowifr').style.display='block';
document.getElementById('mycowifr').style.visibility='hidden';
document.getElementById('mycowifr').style.height='1px';
//document.getElementById('mycowifr').scrollIntoView();
//location.href='#mycowifr';
setTimeout(function(){ document.getElementById('mycowifr').scrollIntoView(); }, 8000);
} else
if (tvis.toLowerCase().indexOf('exif') == 0) {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?exif=y');
} else {
location.href=posturl(document.URL.split('#')[0].replace(/pdf\=/g, 'pdTf=') + '&exif=y');
}
} else if (tvis.toLowerCase().indexOf('pdf') == 0) {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?pdf=y');
} else {
location.href=posturl(document.URL.split('#')[0].replace(/exif\=/g, 'exTif=') + '&pdf=y');
}
} else if (tvis.toLowerCase().indexOf('emoji') == 0) {
//var borderis=prompt('Please enter comma separated HTML decimal entity(s) for your Emoji Border to slideshow. Can use an Emoji Menu entry.', '');
var bbsuffix=' Optionally append &[text|image]css=[CSSstyle] to change styling. Optionally justify some text via &[ul|uc|ur|ml|[mc]|mr|bl|bc|br]text=[someText%0AsecondLine] to change styling. Eg. ' + String.fromCodePoint(127958) + '&css=opacity:0.9;&textcss=font-size:20px;&ultext=Hello%0AThere ';
borderblurb='Please enter comma separated HTML decimal entity(s) for your Emoji Border to slideshow. Can use an Emoji Menu entry (eg. control-command-space for macOS or Mac OS X, logo key + . (period) for Windows, control+space for iOS, top left + for Android keyboard). ' + bbsuffix;
var borderis=prompt(borderblurb, '');
var emojiy='', emojisuffix='';
if (borderis == null) {
borderis='';
} else if (borderis.indexOf('&') != -1) {
if (borderis.split('&')[0].trim() == '') {
emojisuffix=encodeURIComponent(borderis.replace(/\%23[cC][iI][rR][cC][lL][eE]/g, '#circle').replace(/\%23[eE][lL][lL][iI][pP][sS][eE]/g, '#ellipse').replace(/\%23[tT][eE][xX][tT]/g, '#text').replace(/\%23[lL][iI][nN][eE]/g, '#line').replace(/\%23[pP][oO][lL][yY][lL][iI][nN][eE]/g, '#polyline').replace(/\%23[pP][oO][lL][yY][gG][oO][nN]/g, '#polygon').replace(/\%23/g, encodeURIComponent('%23')).replace(/\%23/g, encodeURIComponent('%23')).replace(/\%0a/g, encodeURIComponent('%0A')).replace(/\%0A/g, encodeURIComponent('%0A'))); //.replace(/\&/g,'%26').replace(/\=/g,'%3D');
borderis='';
} else {
emojisuffix=encodeURIComponent(borderis.replace(borderis.split('&')[0], '').replace(/\%23[cC][iI][rR][cC][lL][eE]/g, '#circle').replace(/\%23[eE][lL][lL][iI][pP][sS][eE]/g, '#ellipse').replace(/\%23[tT][eE][xX][tT]/g, '#text').replace(/\%23[lL][iI][nN][eE]/g, '#line').replace(/\%23[pP][oO][lL][yY][lL][iI][nN][eE]/g, '#polyline').replace(/\%23[pP][oO][lL][yY][gG][oO][nN]/g, '#polygon').replace(/\%23/g, encodeURIComponent('%23')).replace(/\%23/g, encodeURIComponent('%23')).replace(/\%0a/g, encodeURIComponent('%0A')).replace(/\%0A/g, encodeURIComponent('%0A'))); //.replace(/\&/g,'%26').replace(/\=/g,'%3D');
borderis=postbb(borderis.split('&')[0]);
}
} else {
borderis=postbb(borderis.split('&')[0]);
}
if ((borderis + emojisuffix) != '') { emojiy='emoji=' + encodeURIComponent(borderis) + emojisuffix; }
if (emojiy != '') {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?' + emojiy);
} else {
location.href=posturl(document.URL.split('#')[0].replace(/emoji\=/g, 'emojTi=') + '&' + emojiy);
}
}
} else {
if (document.URL.indexOf('exif=') != -1 || document.URL.indexOf('pdf=') != -1) {
location.href=posturl(document.URL.split('#')[0].replace(/exif\=/g, 'exTif=').replace(/pdf\=/g, 'pdTf='));
} else {
location.href=posturl(document.URL.split('#')[0] + '&eHuhxif=y');
}
}
}

… called by a changed example PHP inhouse slideshow creator web application.


Previous relevant Inhouse Slideshow AlmaLinux Tutorial is shown below.

Inhouse Slideshow AlmaLinux Tutorial

Inhouse Slideshow AlmaLinux Tutorial

Today we wanted to add so much more to our blog posting title. But, then, we also didn’t want to give the game away?! What a dilemma.

That blog posting title mentions …

  • AlmaLinux … as RJM Programming’s Apache/PHP/MySql web server “brand”, using …
  • PHP 8 … as distinct from the PHP 5’s of the CentOS web server days … and so we suppose we should expect issues like the dreaded …
  • Deprecation … of …
  • Zip … functionality … so sad seeing the early symptoms of this with …
  • Inhouse Slideshow presentations … (as last talked about with Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial) deprecation warnings

Surprising to us, trying to logically walk though a solution, currently up at our AlmaLinux web server here the PHP …


function_exists

… approach we have used successfully recently did not work here. Anyway, deprecated or non-existant it doesn’t matter, we decided to resort to good ol’ PHP exec methodologies in a new “inhouse slideshow” (featuring in a changed example PHP inhouse slideshow creator web application) call …

<?php

include($_SERVER['DOCUMENT_ROOT'] . "/ziphelper.php");

?>

… containing …


<?php
// ziphelper.php
// RJM Programming
// February, 2025

$gzip_read_output=null;
$gzip_open_handle=null;
$gzip_entry_filename='';
$gzip_filename='';
$gzip_entry_len=0;
$gzip_number=0;
$gzip_log_text='';
if (strpos($_SERVER['REQUEST_URI'], 'index.') !== false) {
$hereis='' . dirname(__FILE__) . explode("index.", $_SERVER['REQUEST_URI'])[0];
} else if (basename($_SERVER['SCRIPT_FILENAME']) != '') {
$hereis=explode(basename($_SERVER['SCRIPT_FILENAME']), realpath($_SERVER['SCRIPT_FILENAME']))[0];
} else {
$hereis='' . dirname(__FILE__) . str_replace('//','/',explode("?", $_SERVER['REQUEST_URI'])[0] . '/');
}
$zipisis='' . $hereis . 'slideshow_0.zip';
$alreadythere=false;

if (file_exists($zipisis)) {
$items = glob($hereis . "*[-_][0-9]*of.[jJgGpP][pPiInN]*");
foreach ($items as $key => $val) {
$alreadythere=true;
}
}

if (!function_exists("zip_entry_read")) {
function zip_entry_read($zip_read_output, $zip_entry_len) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_read_output, $gzip_entry_len;
return 'pork';
}
}

if (!function_exists("zip_entry_filesize")) {
function zip_entry_filesize($zip_read_filename) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_entry_filename;
return 'pork';
}
}

if (!function_exists("zip_read")) {
function zip_read($zip_oben_handle) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle;
return 'pork';
}
}

if (!function_exists("zip_open")) {
function zip_open($zip_filename) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_filename;
$gzip_filename=$zip_filename;
$gzip_number=0;
$gzip_open_handle='pork';
return 'pork';
}
}

if (!function_exists("zip_entry_name")) {
function zip_entry_name($zip_read_output) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_read_output;
return 'pork';
}
}

if (!function_exists("zip_entry_open")) {
function zip_entry_open($zip_open_handle, $zip_read_output, $inmode) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle, $gzip_read_output;
return 'pork';
}
}

if (!function_exists("zip_close")) {
function zip_close($zip_open_handle) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle;
return 'pork';
}
}

if (file_exists($zipisis)) {
if (!$alreadythere) {
file_put_contents($hereis . 'please.wait', "cd " . $hereis . ' ; unzip ' . $zipisis);
sleep(2);
exec("cd " . $hereis . ' ; unzip ' . $zipisis);
sleep(2);
unlink($hereis . 'please.wait');
//exec("cd " . $hereis . ' ; rm -f please.wait');
//if (1 == 1) {
//header('Location: ' . explode('?',$_SERVER['REQUEST_URI'])[0] . '?rand=' . rand(0,674532));
//exit;
//} else {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
//if (basename($_SERVER['SCRIPT_FILENAME']) == 'index.php') {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
//sleep(9);
//echo '<html><body onload="location.href=' . "'" . explode("?", $_SERVER['REQUEST_URI'])[0] . '?rand=' . rand(0,5645342) . "';\"></body></html>";
//exit;
} //else if (basename($_SERVER['SCRIPT_FILENAME']) == 'index.php') {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
}
?>

… as a first draft. We have much more to do trying to resurrect, if possible, some other inhouse PHP web applications we’ve based on the use of Zip in PHP. Pardon us, until tomorrow, while we have a little cry.


Previous relevant Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial

Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial

Crontab is that great scheduling tool that we make use of, a lot, on our RJM Programming Linux CentOS web server. But it’s not only …

  • the timing … of a procedure that is so good about crontab … it is, also, for us, it’s teaming with …
  • curl

… that means we can back up a “peer based” solution such as talked about with Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial (ie. done as a user is surfing the net with some PHP of ours) methodology should it fail. We think we have an occasionally failing one as far as the tidy up of zipped up inhouse slideshows goes. It could be to do with a search engine crawling operation, we have not found out for sure, but we’ve decided to write our own …

  • PHP … via …
  • crontab
  • curl

… based independent tidying up procedure we’ll run once an hour via crontab record …


*/53 * * * curl http://www.rjmprogramming.com.au/slideshow_zero.php

… arrangement. We realize the contents of this PHP procedure may bore some, but interest a few, and so here is what it amounted to …

<?php

// slideshow_zero.php
// Zip and Unzip Tidy Up
// RJM Programming
// Decemeber, 2022
set_time_limit(3600);

if (file_exists("slideshow_zero.txt")) {
unlink("slideshow_zero.txt");
}

if (file_exists("slideshow_zero.kkk")) {
unlink("slideshow_zero.kkk");
}

exec("find " . dirname(__FILE__) . DIRECTORY_SEPARATOR . " -name 'slideshow_0.zip' 2> /dev/null > " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txt");

$lines=file(dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txt");

$htmlis="<html><body><textarea>
</textarea></body></html>";

for ($i=0; $i<sizeof($lines); $i++) {
$lines[$i]=explode("\n", $lines[$i])[0];
if (file_exists(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) {
if (('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) == '38794') {
if (file_exists("slideshow_zero.txx")) {
unlink("slideshow_zero.txx");
}
exec("unzip -l " . $lines[$i] . " | grep '.jpg' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/ /s// /g' | sed '/ /s// /g' | sed '/ /s// /g' | sed '/ /s// /g' | cut -f4 -d' ' | grep '-' > " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txx");
if (file_exists("slideshow_zero.txx")) {
$sublines=file(dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txx");
for ($j=0; $j<sizeof($sublines); $j++) {
$sublines[$j]=explode(" ", explode("\n", $sublines[$j])[0])[0];
$fis=explode("slideshow_0.zip", $lines[$i])[0] . $sublines[$j];
if (file_exists($fis)) {
$md=filemtime($fis);
if ($md) {
if ((time() - $md) > 1200) {
if (file_exists("slideshow_zero.kkk")) {
exec("rm -f " . $fis); //file_put_contents("slideshow_zero.kkk", file_get_contents("slideshow_zero.kkk") . "rm -f " . $fis . "\n");
} else {
exec("rm -f " . $fis); //file_put_contents("slideshow_zero.kkk", "rm -f " . $fis . "\n");
}
}
}
}
}
}
} else if (1 == 3) {
if (file_exists("slideshow_zero.kkk")) {
file_put_contents("slideshow_zero.kkk", file_get_contents("slideshow_zero.kkk") . "# " . ('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) . " is not 38794 " . str_replace("slideshow_0.zip", "index.php", $lines[$i]) . "\n");
} else {
file_put_contents("slideshow_zero.kkk", "# " . ('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) . " is not 38794 " . str_replace("slideshow_0.zip", "index.php", $lines[$i]) . "\n");
}
}
}
}

if (file_exists("slideshow_zero.txx")) {
unlink("slideshow_zero.txx");
}

if (file_exists("slideshow_zero.txt")) {
unlink("slideshow_zero.txt");
}

if (file_exists("slideshow_zero.kkk")) {
unlink("slideshow_zero.kkk");
}

//echo $htmlis;
exit;

?>

… as that “ahhhhhhhh, what a relief” reliever of tension running the RJM Programming website. The subtext is, our inode limits are a concern!

We think another lesson here is that PHP can be a good alternative to scripting languages such as Korn Shell to create “operational” procedures, especially when you consider that curl means it can be like writing your “surfing the net” type of PHP (slideshow_zero.php) work.


Previous relevant Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial

Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial

The thing about yesterday’s Inhouse Slideshow Backup Tidy Up Report Tutorial is that …

  • it creates useful report content … but …
  • it is information we do not want everyone to be able to see (easily, shall we say) … and in the sense that …
  • the report is stored away from RJM Programming’s “public_html” folder (ie. its Apache/PHP/MySql “Document Root”) is good … but even with today’s work …
  • hidden from everybody who does not have access to the RJM Programming’s web server … but …
  • the administrator of the RJM Programming’s web server (yoo hoo!) wants a mechanism to view the report that does not involve some “arcane procedure” each time to view it

… and so we decided that because …


the administrator of the RJM Programming's web server = the administrator of this blog

… we’d like to organize a system that latches onto that “security footing” and only show a “broom emoji button” (🧹 &#129529;) way to access the report when the administrator of this blog is logged in. We can do this by amending our Twenty Ten theme’s good ol’ header.php as per (where the “function mlater” you may recall from the days of WordPress Blog Email Post Collaboration Ajax Image Tutorial) …

<?php

$fns="36";

function doisr() {
global $fns;
$inmb="";
if (('' . get_current_user_id()) != '0' && ('' . get_current_user_id()) == '1') {
if (file_exists('/tmp/slideshow_cleanup.txt')) {
$fns="24";
$inmb="<a style=font-size:24px; title='Inhouse Slideshow Tidy Up Report' onclick=\"var iswo=window.open('','_blank','top=100,left=100,height=600,width=730'); iswo.document.write('<html><head><title>Inhouse Slideshow Tidy Up Report</title></head><body><pre>" . str_replace("\n","<br>",file_get_contents('/tmp/slideshow_cleanup.txt')) . "</pre></body></html>'); \">&#129529;</a> ";
}
}
return str_replace("'","' + String.fromCharCode(39) + '",$inmb);
}


?>

… PHP affects some (PHP writes) Javascript below …

<?php

function mlater() {
if (1 == 1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i)) {
if (dbihis == '') { dbihis=document.body.innerHTML; }
var xstih=document.getElementById('site-title').innerHTML;
if (xstih.indexOf("up" + "top") == -1) {
document.getElementById('site-title').innerHTML+='<?php echo doisr(); ?>' + '<a id="avs" style="text-decoration:none;font-size:<?php global $fns; echo $fns; ?>px;" href=# onmouseover="getVisualSynopsis(event);" onmouseout="yehbut();" ontouchstart="getVisualSynopsis(event);" ontouchend="yehbut();" onclick=" uptop(); " title="... you can wait for the long hover functionality about Visual Synopsis (Slideshows)">&#127910;</a> <a style="cursor:pointer;text-decoration:none;font-size:<?php global $fns; echo $fns; ?>px;" onclick="diffphpfix(this);" title="Code Difference Functional Links">&#128214;</a> <a style="cursor:pointer;text-decoration:none;font-size:36px;" onclick="popselid();" title="Filter Content via Div ID">&#10135;</a> <a style="cursor:pointer;text-decoration:none;visibility:hidden;font-size:<?php global $fns; echo $fns; ?>px;" title="Blog post contents reduced to summary" id="eds" onclick="pre_details_summary();">&#10134;</a>' + printscreen(0);
if (document.URL.indexOf("visualsynopsis=") != -1) document.getElementById('avs').click();
}
}
}

?>


Previous relevant Inhouse Slideshow Backup Tidy Up Report Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Report Tutorial

Inhouse Slideshow Backup Tidy Up Report Tutorial

Yesterday’s Inhouse Slideshow Backup Tidy Up Tutorial presented a …

  • non-automated
  • user instigated
  • snapshot

… Inhouse Slideshow “tidying up” PHP web application. This web application is like a …

  • procedure … that a …
  • system operator

… might be interested in using. But not many “system operators” would continue putting up with such a modus operandi. We can improve by …

  • allowing any of …
    1. surfing the net
    2. curl
    3. command line

    … modes of use … allowing …

  • crontab scheduling via …

    */49 * * * * ksh -c "curl HTTP://www.rjmprogramming.com.au/slideshow_cleanup.php?all=all"

    … to allow for a …
  • scheduled report available … and make sure we …
  • disallow overlapping execution runs

… with our changed slideshow_cleanup.php “Inhouse Slideshow” unzipped image “tidyer upperer“.


Previous relevant Inhouse Slideshow Backup Tidy Up Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Tutorial

Inhouse Slideshow Backup Tidy Up Tutorial

There are two aspects to diskspace maintainence up at the web server for RJM Programming.

  • df -k /
  • df -i /
# diskspace
# inode count

… and it is often that inode count we are concerned about, and looking out for ways to reduce the number of files we create on the web server.

The Inhouse Slideshow ways of Inhouse Slideshow Mobile Google Crawl Tutorial

  • use zip files to “scrunch up” a series of image files into the one zip file … for the vast majority of time … but when asked to, by a user …
  • unzip the image files when required by a user wanting to see them … and then …
  • tidy up, after some delay in time

… but we want to design a PHP way to independently tidy up as a backup mechanism. And we say, with PHP code, that if such files have been on the web server longer than ten minutes, this PHP callable slideshow_cleanup.php code …

<?php

// slideshow_cleanup.php
// RJM Programming
// May, 2022

$cdis=dirname(__FILE__) . DIRECTORY_SEPARATOR;
exec("cd " . $cdis . "; find . -name 'slideshow_0.zip' 2> /dev/null > /tmp/slideshow_cleanup.txt");


$lines = file('/tmp/slideshow_cleanup.txt');
date_default_timezone_set('Australia/Perth');

foreach ($lines as $line_num => $line) {
$ji=0;
if (substr($line,0,1) == '.') { $ji=2; }
$thisdir=explode('slideshow_0.zip', $line)[0];
$uzc=shell_exec("unzip -l " . $cdis . substr($line, $ji));
foreach (glob($thisdir . '*-[0-9]*of.[jJpPgG][pPnNiI]*') as $zipmember) {
$ij=0;
if (substr($zipmember,0,1) == '.') { $ij=2; }
$thisfile=$cdis . substr($zipmember, $ij);
if (strpos($uzc, (' ' . explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij))[-1 + sizeof(explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij)))]) ) !== false) {
if ((time() - filectime($thisfile)) > 600) { // more than 10 minutes old
unlink($thisfile); //echo "analyze " . $thisfile . " " . (time() - filectime($thisfile)) . ' seconds ago ' . "\n";
}
}
}
foreach (glob($thisdir . '*-[0-9]{[0-9]*}.[jJpPgG][pPnNiI]*') as $zipmember) {
$ij=0;
if (substr($zipmember,0,1) == '.') { $ij=2; }
$thisfile=$cdis . substr($zipmember, $ij);
if (strpos($uzc, (' ' . explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij))[-1 + sizeof(explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij)))]) ) !== false) {
if ((time() - filectime($thisfile)) > 600) {
unlink($thisfile); //echo "Analyze " . $thisfile . " " . (time() - filectime($thisfile)) . ' seconds ago ' . "\n";
}
}
}
}


?>

… should do its thaing!


Previous relevant Inhouse Slideshow Mobile Google Crawl Tutorial is shown below.

Inhouse Slideshow Mobile Google Crawl Tutorial

Inhouse Slideshow Mobile Google Crawl Tutorial

The recent Inhouse Slideshow Mobile Tutorial did not satisfy all the “mobile usability” tests performed by the “Google Crawl” algorithm, failing on “Content wider than screen”, and you can read some background to this with Google Crawl Viewport Geographicals Tutorial. And so we try some refinements here today, with an idea to control on mobile platforms the max-width CSS property of the document.body of a Inhouse Slideshow webpage, which made up the URLs failing this test at the Google Search Console.

We were reading this great and useful link, thanks, and decided to see whether this stopping of scrolling in X on mobile platform versions of the Inhouse Slideshow webpages gels better with Google Search Console “Google Crawl” Mobility Usability algorithms.

Yet again, deployment of these changes is similar to that last time, and the times before that, as per …

Unit testing completed, the deployment, again, matches those ideas of the recent PDF Slideshow and Form Creation Helper Slideshow Tutorial … in that …

Here are changes we’ll be testing up at Google …


<head>
<script type='text/javascript'>
// Other Javascript code here ...
//
//
// Of relevance today bold below ...

function blater() {
var tdsare=document.getElementsByTagName('td');
var rectg=tdsare[2].getBoundingClientRect(); //document.getElementById('i0').getBoundingClientRect();
tdsare[2].style.borderRight='2px solid white';
document.body.style.backgroundImage="URL('" + document.getElementById('i0').src + "')";
var rl=eval('' + rectg.left);
rl+=eval('' + rectg.width);
rl+=10;
document.body.style.backgroundPosition=" " + rl + "px " + Math.floor(rectg.top) + "px";
document.body.style.backgroundRepeat="no-repeat";
document.body.style.backgroundClip="content-box";
}



function zoom_maybe() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
//document.getElementById('rfs').innerHTML='<style> html { zoom: .5; } </style>';
document.getElementById('rfs').innerHTML='<style> html { zoom: 0.4; body { max-width: 100%; max-height: 80vh; } table { max-width: <?php if (strpos($_SERVER['QUERY_STRING'],'exif=') !== false) { echo "100"; } else { echo "95"; } ?>%; max-height: 80vh; margin: auto; overflow-x: hidden; } </style>';
}
}


function nwpdf(iithis) {
if (('' + iithis.src).length > 0) {
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
window.open(iithis.src,'_blank');
}
}
}


function mytw() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.body.style.width='' + (window.orientation == 0 ? Math.floor(eval(2.5 * window.screen.width)) : window.screen.height) + 'px';
document.getElementById('myt').style.width='100%'; //'' + (window.orientation == 0 ? window.screen.width : window.screen.height) + 'px';
}
}



window.setInterval(function(){havealook(1)},2000);
</script>
<style>
td { vertical-align:top; }
@media only screen and (max-width: 800px) {
body { max-width: 100%; max-height: 80vh; } table { max-width: <?php if (strpos($_SERVER['QUERY_STRING'],'exif=') !== false) { echo "100"; } else { echo "95"; } ?>%; max-height: 80vh; margin: auto; overflow-x: hidden; }
}

</style>
</head>
<body onload=" mytw(); zoom_maybe(); if (document.URL.indexOf('pdf=') != -1) { document.getElementById('selmode').value='PDF Slideshow'; if (document.getElementById('tdfirst')) { document.getElementById('s0').style.width=document.getElementById('tdfirst').style.width; document.getElementById('s0').style.height=document.getElementById('tdfirst').style.height; } } if (document.URL.indexOf('exif=') != -1) { document.getElementById('selmode').value='Exif Slideshow'; if (document.getElementById('tdfirst')) { document.getElementById('s0').style.width=document.getElementById('tdfirst').style.width; document.getElementById('s0').style.height=document.getElementById('tdfirst').style.height; } } document.title=document.title + ' ' + lastone; ol(); ">


Previous relevant Inhouse Slideshow Mobile Tutorial is shown below.

Inhouse Slideshow Mobile Tutorial

Inhouse Slideshow Mobile Tutorial

The recent PDF Slideshow and Form Creation Helper Slideshow Tutorial changes were made on a MacBook Pro laptop. Did it show that we have put off until today, to look at that functionality with mobile platforms?!

In a “going off to the right table row of cells” arrangement like this, what are some considerations that improve the user experience (of our inhouse slideshows) for mobile platform users?

  • turn the “@” link into an “emoji button” as per ➡ ( &#10145; )
  • for both mobile and non-mobile, we’ve decided …
    1. UTF-8 meta …
      <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>

    2. <style>
      td { vertical-align:top; }
      </style>
    3. change the h4 element to be h2 to help with legibility
  • for mobile, we’ve decided …
    1. viewport …
      <meta name=”viewport” content=”width=device-width, initial-scale=0.4, minimum-scale=0.1, maximum-scale=8, user-scalable=yes”>

    2. <style>
      html { zoom: .5; }
      </style>
    3. iOS (ie. iPad and iPhone) PDF iframe elements have known scrolling issues, which we decided to bypass by opening these PDF creations in a new webpage window

Deployment of these changes is similar to that last time, and the times before that, as per …

Unit testing completed, the deployment, again, matches those ideas of the recent PDF Slideshow and Form Creation Helper Slideshow Tutorial … in that …


Previous relevant PDF Slideshow and Form Creation Helper Slideshow Tutorial is shown below.

PDF Slideshow and Form Creation Helper Slideshow Tutorial

PDF Slideshow and Form Creation Helper Slideshow Tutorial

The first “integration cab” off the rank for yesterday’s PDF Slideshow and Form Creation Helper Primer Tutorial underlying usefulness is with our Inhouse Slideshow arrangements last talked about at Inhouse Slideshow Design Exif Order Tutorial. That generic PHP code now has three display dropdown options of …

  • Slideshow
  • Exif Slideshow … and the new, as of today’s work …
  • PDF Slideshow

… that little bit different in that a PDF Slideshow occupies just the one table cell (rather than the many horizontal cells of the other display modes) and the resultant embedded PDF data vertically scrolls when multiple image slides are involved.

This new option also adds onto this “Inhouse Slideshow” functionality the chance to download and keep a PDF representation of that slideshow to your local system. Perhaps this makes this be of interest to you?!

The changed form_creator.php‘s live run is what gets integrated into the “Inhouse Slideshow” “sisterhood”. We say “sisterhood” because this “Inhouse Slideshow” is designed as a single PHP codefile “hived off” to a lot of other web server folders as their default “index.php” web browser default webpage in a “peer to peer” feeling arrangement. Such an arrangement asks a bit of the deployment arrangements, and we’ve talked about this before (with underlying links pointing to today’s work, should you be interested) …

Unit testing completed, the deployment, again, matches those ideas of the recent Inhouse Slideshow Design Exif Zip Tutorial … in that …

But when we say “Unit testing completed” above, we need to fill you in on a Fpdf issue we came across during unit testing of our changes. We were getting a …


FPDF Error: Not a JPEG file

… Fpdf error message choosing the new “PDF Slideshow” option on some, but not all, “Inhouse Slideshow” address bar URLs. And so the online research began as per …

… almost getting us there to a solution (and as far as the last link goes “that was before we posted the suggestion below”). Then we took one of the error messages at its word …


FPDF error: Not a JPEG file: ../Mac/Linux_drutil-238of.jpg

… and independently looked into the issue via Linux (or macOS command line) file command …


# cd $HOME/public_html/Mac
# ls -l Linux_dr*
-rw-r--r-- 1 owner group 724353 Oct 29 08:00 Linux_drutil-238of.jpg
-rw-r--r-- 1 owner group 132707 Oct 29 08:00 Linux_drutil-239of.jpg
-rw-r--r-- 1 owner group 109595 Oct 29 08:00 Linux_drutil-240of.jpg
# file Linux_drutil-238of.jpg
Linux_drutil-238of.jpg: PNG image data, 1280 x 800, 8-bit/color RGBA, non-interlaced
# file Linux_drutil-239of.jpg
Linux_drutil-239of.jpg: JPEG image data, JFIF standard 1.01
#

… when the penny dropped (about our (macOS) Paintbrush slideshow slide creation habits)! We quote our entry into “php – FPDF error: Not a JPEG file: http://10.11.201.93:81/webdocc/uploaded/tes3.jpg – Stack Overflow” …

Have found that constructing slideshows with Paintbrush on a MacBook Pro for years have sometimes been saving what “file jpeg_filename.jpg” determines is a PNG, as a JPEG, which is not the end of the world as far as the browsers go rendering this. Within FPDF’s fpdf.php I fixed my own shortcomings that were resulting in “FPDF Error: Not a JPEG file” via the kludgy “if($a[2]==3) { return $this->_parsepng($file); }” additional codeline below …

function _parsejpg($file)
{
// Extract info from a JPEG file
$a = getimagesize($file);
if(!$a)
$this->Error(‘Missing or incorrect image file: ‘.$file);
if($a[2]==3) { return $this->_parsepng($file); }
if($a[2]!=2)
$this->Error(‘Not a JPEG file: ‘.’ ‘.$a[2].’ ‘.$file);
if(!isset($a[‘channels’]) || $a[‘channels’]==3)
$colspace = ‘DeviceRGB’;
elseif($a[‘channels’]==4)
$colspace = ‘DeviceCMYK’;
else
$colspace = ‘DeviceGray’;
$bpc = isset($a[‘bits’]) ? $a[‘bits’] : 8;
$data = file_get_contents($file);
return array(‘w’=>$a[0], ‘h’=>$a[1], ‘cs’=>$colspace, ‘bpc’=>$bpc, ‘f’=>’DCTDecode’, ‘data’=>$data);
}

… and this change to Fpdf’s fpdf.php fixed the issue in our case for a lot of our previously erroneous “PDF Slideshow” displays of “Inhouse Slideshows”.


Previous relevant PDF Slideshow and Form Creation Helper Primer Tutorial is shown below.

PDF Slideshow and Form Creation Helper Primer Tutorial

PDF Slideshow and Form Creation Helper Primer Tutorial

Our recent work involving the great Fpdf creator of PDF files when we presented Ajax FormData Object No Body PHP PDF Tutorial has got us starting on a new PDF (PHP) web application we are starting out thinking will help with …

  • online forms (probably via thinking in terms of Fpdf open source programmers like Rick van Buuren and Clément Lavoillotte‘s excellent HTML table rendering ideas) via HTML table intermediate user interactions … and …
  • slideshows

… but we will not be surprised if the project branches out into other ideas. We’ll see over time.

We hope you come along for the trip starting with a bit of a proof of concept form_creator.php‘s live run for you to try, where we allow you to enter (and be able to change) some HTML table code (if that’s what you end up with?!) in a pink HTML textarea element, and that will become PDF should you click the underlying HTML form’s yellow submit button.

Hope to see you for tomorrow’s PDF writing developments here.

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

Inhouse Slideshow AlmaLinux Media Tutorial

Inhouse Slideshow AlmaLinux Media Tutorial

Inhouse Slideshow AlmaLinux Media Tutorial

The recent Inhouse Slideshow AlmaLinux Tutorial did help with PHP Zip deprecations, and today, this being Inhouse Slideshows, full of …

moving pictures

… we can add two more dropdown modus operandi options for …

  • Video
  • Animated GIF

… feeding it through to a changed latest draft cowsay.php media creator via slides via ffmpeg inhouse talent, called by our inhouse slideshow external Javascript helper …


function changeto(tvis) {
if (tvis.toLowerCase().indexOf('video') == 0) {
document.getElementById('divcowpf').innerHTML+='<input type=hidden name=fromindex id=fromindex value=y></input>';
document.getElementById('vlist').click();
document.getElementById('mycowifr').style.display='block';
document.getElementById('mycowifr').style.visibility='hidden';
document.getElementById('mycowifr').style.height='1px';
//document.getElementById('mycowifr').scrollIntoView();
//location.href='#mycowifr';
setTimeout(function(){ document.getElementById('mycowifr').scrollIntoView(); }, 8000);
} else if (tvis.toLowerCase().indexOf('animated gif') == 0) {
document.getElementById('divcowpf').innerHTML+='<input type=hidden name=fromindex id=fromindex value=y></input>';
document.getElementById('aglist').click();
document.getElementById('mycowifr').style.display='block';
document.getElementById('mycowifr').style.visibility='hidden';
document.getElementById('mycowifr').style.height='1px';
//document.getElementById('mycowifr').scrollIntoView();
//location.href='#mycowifr';
setTimeout(function(){ document.getElementById('mycowifr').scrollIntoView(); }, 8000);
} else
if (tvis.toLowerCase().indexOf('exif') == 0) {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?exif=y');
} else {
location.href=posturl(document.URL.split('#')[0].replace(/pdf\=/g, 'pdTf=') + '&exif=y');
}
} else if (tvis.toLowerCase().indexOf('pdf') == 0) {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?pdf=y');
} else {
location.href=posturl(document.URL.split('#')[0].replace(/exif\=/g, 'exTif=') + '&pdf=y');
}
} else if (tvis.toLowerCase().indexOf('emoji') == 0) {
//var borderis=prompt('Please enter comma separated HTML decimal entity(s) for your Emoji Border to slideshow. Can use an Emoji Menu entry.', '');
var bbsuffix=' Optionally append &[text|image]css=[CSSstyle] to change styling. Optionally justify some text via &[ul|uc|ur|ml|[mc]|mr|bl|bc|br]text=[someText%0AsecondLine] to change styling. Eg. ' + String.fromCodePoint(127958) + '&css=opacity:0.9;&textcss=font-size:20px;&ultext=Hello%0AThere ';
borderblurb='Please enter comma separated HTML decimal entity(s) for your Emoji Border to slideshow. Can use an Emoji Menu entry (eg. control-command-space for macOS or Mac OS X, logo key + . (period) for Windows, control+space for iOS, top left + for Android keyboard). ' + bbsuffix;
var borderis=prompt(borderblurb, '');
var emojiy='', emojisuffix='';
if (borderis == null) {
borderis='';
} else if (borderis.indexOf('&') != -1) {
if (borderis.split('&')[0].trim() == '') {
emojisuffix=encodeURIComponent(borderis.replace(/\%23[cC][iI][rR][cC][lL][eE]/g, '#circle').replace(/\%23[eE][lL][lL][iI][pP][sS][eE]/g, '#ellipse').replace(/\%23[tT][eE][xX][tT]/g, '#text').replace(/\%23[lL][iI][nN][eE]/g, '#line').replace(/\%23[pP][oO][lL][yY][lL][iI][nN][eE]/g, '#polyline').replace(/\%23[pP][oO][lL][yY][gG][oO][nN]/g, '#polygon').replace(/\%23/g, encodeURIComponent('%23')).replace(/\%23/g, encodeURIComponent('%23')).replace(/\%0a/g, encodeURIComponent('%0A')).replace(/\%0A/g, encodeURIComponent('%0A'))); //.replace(/\&/g,'%26').replace(/\=/g,'%3D');
borderis='';
} else {
emojisuffix=encodeURIComponent(borderis.replace(borderis.split('&')[0], '').replace(/\%23[cC][iI][rR][cC][lL][eE]/g, '#circle').replace(/\%23[eE][lL][lL][iI][pP][sS][eE]/g, '#ellipse').replace(/\%23[tT][eE][xX][tT]/g, '#text').replace(/\%23[lL][iI][nN][eE]/g, '#line').replace(/\%23[pP][oO][lL][yY][lL][iI][nN][eE]/g, '#polyline').replace(/\%23[pP][oO][lL][yY][gG][oO][nN]/g, '#polygon').replace(/\%23/g, encodeURIComponent('%23')).replace(/\%23/g, encodeURIComponent('%23')).replace(/\%0a/g, encodeURIComponent('%0A')).replace(/\%0A/g, encodeURIComponent('%0A'))); //.replace(/\&/g,'%26').replace(/\=/g,'%3D');
borderis=postbb(borderis.split('&')[0]);
}
} else {
borderis=postbb(borderis.split('&')[0]);
}
if ((borderis + emojisuffix) != '') { emojiy='emoji=' + encodeURIComponent(borderis) + emojisuffix; }
if (emojiy != '') {
if (document.URL.indexOf('?') == -1) {
location.href=posturl(document.URL.split('#')[0] + '?' + emojiy);
} else {
location.href=posturl(document.URL.split('#')[0].replace(/emoji\=/g, 'emojTi=') + '&' + emojiy);
}
}
} else {
if (document.URL.indexOf('exif=') != -1 || document.URL.indexOf('pdf=') != -1) {
location.href=posturl(document.URL.split('#')[0].replace(/exif\=/g, 'exTif=').replace(/pdf\=/g, 'pdTf='));
} else {
location.href=posturl(document.URL.split('#')[0] + '&eHuhxif=y');
}
}
}

… called by a changed example PHP inhouse slideshow creator web application.


Previous relevant Inhouse Slideshow AlmaLinux Tutorial is shown below.

Inhouse Slideshow AlmaLinux Tutorial

Inhouse Slideshow AlmaLinux Tutorial

Today we wanted to add so much more to our blog posting title. But, then, we also didn’t want to give the game away?! What a dilemma.

That blog posting title mentions …

  • AlmaLinux … as RJM Programming’s Apache/PHP/MySql web server “brand”, using …
  • PHP 8 … as distinct from the PHP 5’s of the CentOS web server days … and so we suppose we should expect issues like the dreaded …
  • Deprecation … of …
  • Zip … functionality … so sad seeing the early symptoms of this with …
  • Inhouse Slideshow presentations … (as last talked about with Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial) deprecation warnings

Surprising to us, trying to logically walk though a solution, currently up at our AlmaLinux web server here the PHP …


function_exists

… approach we have used successfully recently did not work here. Anyway, deprecated or non-existant it doesn’t matter, we decided to resort to good ol’ PHP exec methodologies in a new “inhouse slideshow” (featuring in a changed example PHP inhouse slideshow creator web application) call …

<?php

include($_SERVER['DOCUMENT_ROOT'] . "/ziphelper.php");

?>

… containing …


<?php
// ziphelper.php
// RJM Programming
// February, 2025

$gzip_read_output=null;
$gzip_open_handle=null;
$gzip_entry_filename='';
$gzip_filename='';
$gzip_entry_len=0;
$gzip_number=0;
$gzip_log_text='';
if (strpos($_SERVER['REQUEST_URI'], 'index.') !== false) {
$hereis='' . dirname(__FILE__) . explode("index.", $_SERVER['REQUEST_URI'])[0];
} else if (basename($_SERVER['SCRIPT_FILENAME']) != '') {
$hereis=explode(basename($_SERVER['SCRIPT_FILENAME']), realpath($_SERVER['SCRIPT_FILENAME']))[0];
} else {
$hereis='' . dirname(__FILE__) . str_replace('//','/',explode("?", $_SERVER['REQUEST_URI'])[0] . '/');
}
$zipisis='' . $hereis . 'slideshow_0.zip';
$alreadythere=false;

if (file_exists($zipisis)) {
$items = glob($hereis . "*[-_][0-9]*of.[jJgGpP][pPiInN]*");
foreach ($items as $key => $val) {
$alreadythere=true;
}
}

if (!function_exists("zip_entry_read")) {
function zip_entry_read($zip_read_output, $zip_entry_len) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_read_output, $gzip_entry_len;
return 'pork';
}
}

if (!function_exists("zip_entry_filesize")) {
function zip_entry_filesize($zip_read_filename) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_entry_filename;
return 'pork';
}
}

if (!function_exists("zip_read")) {
function zip_read($zip_oben_handle) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle;
return 'pork';
}
}

if (!function_exists("zip_open")) {
function zip_open($zip_filename) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_filename;
$gzip_filename=$zip_filename;
$gzip_number=0;
$gzip_open_handle='pork';
return 'pork';
}
}

if (!function_exists("zip_entry_name")) {
function zip_entry_name($zip_read_output) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_read_output;
return 'pork';
}
}

if (!function_exists("zip_entry_open")) {
function zip_entry_open($zip_open_handle, $zip_read_output, $inmode) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle, $gzip_read_output;
return 'pork';
}
}

if (!function_exists("zip_close")) {
function zip_close($zip_open_handle) {
global $gzip_filename, $gzip_number, $gzip_log_text, $gzip_open_handle;
return 'pork';
}
}

if (file_exists($zipisis)) {
if (!$alreadythere) {
file_put_contents($hereis . 'please.wait', "cd " . $hereis . ' ; unzip ' . $zipisis);
sleep(2);
exec("cd " . $hereis . ' ; unzip ' . $zipisis);
sleep(2);
unlink($hereis . 'please.wait');
//exec("cd " . $hereis . ' ; rm -f please.wait');
//if (1 == 1) {
//header('Location: ' . explode('?',$_SERVER['REQUEST_URI'])[0] . '?rand=' . rand(0,674532));
//exit;
//} else {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
//if (basename($_SERVER['SCRIPT_FILENAME']) == 'index.php') {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
//sleep(9);
//echo '<html><body onload="location.href=' . "'" . explode("?", $_SERVER['REQUEST_URI'])[0] . '?rand=' . rand(0,5645342) . "';\"></body></html>";
//exit;
} //else if (basename($_SERVER['SCRIPT_FILENAME']) == 'index.php') {
//sleep(60);
//exec("cd " . $hereis . ' ; rm -f ' . $hereis . '*[-_][0-9]*of.[jJgGpP][pPiInN]*');
//}
}
?>

… as a first draft. We have much more to do trying to resurrect, if possible, some other inhouse PHP web applications we’ve based on the use of Zip in PHP. Pardon us, until tomorrow, while we have a little cry.


Previous relevant Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial

Inhouse Slideshow Backup Tidy Up Crontab Curl PHP Tutorial

Crontab is that great scheduling tool that we make use of, a lot, on our RJM Programming Linux CentOS web server. But it’s not only …

  • the timing … of a procedure that is so good about crontab … it is, also, for us, it’s teaming with …
  • curl

… that means we can back up a “peer based” solution such as talked about with Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial (ie. done as a user is surfing the net with some PHP of ours) methodology should it fail. We think we have an occasionally failing one as far as the tidy up of zipped up inhouse slideshows goes. It could be to do with a search engine crawling operation, we have not found out for sure, but we’ve decided to write our own …

  • PHP … via …
  • crontab
  • curl

… based independent tidying up procedure we’ll run once an hour via crontab record …


*/53 * * * curl http://www.rjmprogramming.com.au/slideshow_zero.php

… arrangement. We realize the contents of this PHP procedure may bore some, but interest a few, and so here is what it amounted to …

<?php

// slideshow_zero.php
// Zip and Unzip Tidy Up
// RJM Programming
// Decemeber, 2022
set_time_limit(3600);

if (file_exists("slideshow_zero.txt")) {
unlink("slideshow_zero.txt");
}

if (file_exists("slideshow_zero.kkk")) {
unlink("slideshow_zero.kkk");
}

exec("find " . dirname(__FILE__) . DIRECTORY_SEPARATOR . " -name 'slideshow_0.zip' 2> /dev/null > " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txt");

$lines=file(dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txt");

$htmlis="<html><body><textarea>
</textarea></body></html>";

for ($i=0; $i<sizeof($lines); $i++) {
$lines[$i]=explode("\n", $lines[$i])[0];
if (file_exists(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) {
if (('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) == '38794') {
if (file_exists("slideshow_zero.txx")) {
unlink("slideshow_zero.txx");
}
exec("unzip -l " . $lines[$i] . " | grep '.jpg' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/^ /s///g' | sed '/ /s// /g' | sed '/ /s// /g' | sed '/ /s// /g' | sed '/ /s// /g' | cut -f4 -d' ' | grep '-' > " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txx");
if (file_exists("slideshow_zero.txx")) {
$sublines=file(dirname(__FILE__) . DIRECTORY_SEPARATOR . "slideshow_zero.txx");
for ($j=0; $j<sizeof($sublines); $j++) {
$sublines[$j]=explode(" ", explode("\n", $sublines[$j])[0])[0];
$fis=explode("slideshow_0.zip", $lines[$i])[0] . $sublines[$j];
if (file_exists($fis)) {
$md=filemtime($fis);
if ($md) {
if ((time() - $md) > 1200) {
if (file_exists("slideshow_zero.kkk")) {
exec("rm -f " . $fis); //file_put_contents("slideshow_zero.kkk", file_get_contents("slideshow_zero.kkk") . "rm -f " . $fis . "\n");
} else {
exec("rm -f " . $fis); //file_put_contents("slideshow_zero.kkk", "rm -f " . $fis . "\n");
}
}
}
}
}
}
} else if (1 == 3) {
if (file_exists("slideshow_zero.kkk")) {
file_put_contents("slideshow_zero.kkk", file_get_contents("slideshow_zero.kkk") . "# " . ('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) . " is not 38794 " . str_replace("slideshow_0.zip", "index.php", $lines[$i]) . "\n");
} else {
file_put_contents("slideshow_zero.kkk", "# " . ('' . filesize(str_replace("slideshow_0.zip", "index.php", $lines[$i]))) . " is not 38794 " . str_replace("slideshow_0.zip", "index.php", $lines[$i]) . "\n");
}
}
}
}

if (file_exists("slideshow_zero.txx")) {
unlink("slideshow_zero.txx");
}

if (file_exists("slideshow_zero.txt")) {
unlink("slideshow_zero.txt");
}

if (file_exists("slideshow_zero.kkk")) {
unlink("slideshow_zero.kkk");
}

//echo $htmlis;
exit;

?>

… as that “ahhhhhhhh, what a relief” reliever of tension running the RJM Programming website. The subtext is, our inode limits are a concern!

We think another lesson here is that PHP can be a good alternative to scripting languages such as Korn Shell to create “operational” procedures, especially when you consider that curl means it can be like writing your “surfing the net” type of PHP (slideshow_zero.php) work.


Previous relevant Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial

Inhouse Slideshow Backup Tidy Up Report Viewing Tutorial

The thing about yesterday’s Inhouse Slideshow Backup Tidy Up Report Tutorial is that …

  • it creates useful report content … but …
  • it is information we do not want everyone to be able to see (easily, shall we say) … and in the sense that …
  • the report is stored away from RJM Programming’s “public_html” folder (ie. its Apache/PHP/MySql “Document Root”) is good … but even with today’s work …
  • hidden from everybody who does not have access to the RJM Programming’s web server … but …
  • the administrator of the RJM Programming’s web server (yoo hoo!) wants a mechanism to view the report that does not involve some “arcane procedure” each time to view it

… and so we decided that because …


the administrator of the RJM Programming's web server = the administrator of this blog

… we’d like to organize a system that latches onto that “security footing” and only show a “broom emoji button” (🧹 &#129529;) way to access the report when the administrator of this blog is logged in. We can do this by amending our Twenty Ten theme’s good ol’ header.php as per (where the “function mlater” you may recall from the days of WordPress Blog Email Post Collaboration Ajax Image Tutorial) …

<?php

$fns="36";

function doisr() {
global $fns;
$inmb="";
if (('' . get_current_user_id()) != '0' && ('' . get_current_user_id()) == '1') {
if (file_exists('/tmp/slideshow_cleanup.txt')) {
$fns="24";
$inmb="<a style=font-size:24px; title='Inhouse Slideshow Tidy Up Report' onclick=\"var iswo=window.open('','_blank','top=100,left=100,height=600,width=730'); iswo.document.write('<html><head><title>Inhouse Slideshow Tidy Up Report</title></head><body><pre>" . str_replace("\n","<br>",file_get_contents('/tmp/slideshow_cleanup.txt')) . "</pre></body></html>'); \">&#129529;</a> ";
}
}
return str_replace("'","' + String.fromCharCode(39) + '",$inmb);
}


?>

… PHP affects some (PHP writes) Javascript below …

<?php

function mlater() {
if (1 == 1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i)) {
if (dbihis == '') { dbihis=document.body.innerHTML; }
var xstih=document.getElementById('site-title').innerHTML;
if (xstih.indexOf("up" + "top") == -1) {
document.getElementById('site-title').innerHTML+='<?php echo doisr(); ?>' + '<a id="avs" style="text-decoration:none;font-size:<?php global $fns; echo $fns; ?>px;" href=# onmouseover="getVisualSynopsis(event);" onmouseout="yehbut();" ontouchstart="getVisualSynopsis(event);" ontouchend="yehbut();" onclick=" uptop(); " title="... you can wait for the long hover functionality about Visual Synopsis (Slideshows)">&#127910;</a> <a style="cursor:pointer;text-decoration:none;font-size:<?php global $fns; echo $fns; ?>px;" onclick="diffphpfix(this);" title="Code Difference Functional Links">&#128214;</a> <a style="cursor:pointer;text-decoration:none;font-size:36px;" onclick="popselid();" title="Filter Content via Div ID">&#10135;</a> <a style="cursor:pointer;text-decoration:none;visibility:hidden;font-size:<?php global $fns; echo $fns; ?>px;" title="Blog post contents reduced to summary" id="eds" onclick="pre_details_summary();">&#10134;</a>' + printscreen(0);
if (document.URL.indexOf("visualsynopsis=") != -1) document.getElementById('avs').click();
}
}
}

?>


Previous relevant Inhouse Slideshow Backup Tidy Up Report Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Report Tutorial

Inhouse Slideshow Backup Tidy Up Report Tutorial

Yesterday’s Inhouse Slideshow Backup Tidy Up Tutorial presented a …

  • non-automated
  • user instigated
  • snapshot

… Inhouse Slideshow “tidying up” PHP web application. This web application is like a …

  • procedure … that a …
  • system operator

… might be interested in using. But not many “system operators” would continue putting up with such a modus operandi. We can improve by …

  • allowing any of …
    1. surfing the net
    2. curl
    3. command line

    … modes of use … allowing …

  • crontab scheduling via …

    */49 * * * * ksh -c "curl HTTP://www.rjmprogramming.com.au/slideshow_cleanup.php?all=all"

    … to allow for a …
  • scheduled report available … and make sure we …
  • disallow overlapping execution runs

… with our changed slideshow_cleanup.php “Inhouse Slideshow” unzipped image “tidyer upperer“.


Previous relevant Inhouse Slideshow Backup Tidy Up Tutorial is shown below.

Inhouse Slideshow Backup Tidy Up Tutorial

Inhouse Slideshow Backup Tidy Up Tutorial

There are two aspects to diskspace maintainence up at the web server for RJM Programming.

  • df -k /
  • df -i /
# diskspace
# inode count

… and it is often that inode count we are concerned about, and looking out for ways to reduce the number of files we create on the web server.

The Inhouse Slideshow ways of Inhouse Slideshow Mobile Google Crawl Tutorial

  • use zip files to “scrunch up” a series of image files into the one zip file … for the vast majority of time … but when asked to, by a user …
  • unzip the image files when required by a user wanting to see them … and then …
  • tidy up, after some delay in time

… but we want to design a PHP way to independently tidy up as a backup mechanism. And we say, with PHP code, that if such files have been on the web server longer than ten minutes, this PHP callable slideshow_cleanup.php code …

<?php

// slideshow_cleanup.php
// RJM Programming
// May, 2022

$cdis=dirname(__FILE__) . DIRECTORY_SEPARATOR;
exec("cd " . $cdis . "; find . -name 'slideshow_0.zip' 2> /dev/null > /tmp/slideshow_cleanup.txt");


$lines = file('/tmp/slideshow_cleanup.txt');
date_default_timezone_set('Australia/Perth');

foreach ($lines as $line_num => $line) {
$ji=0;
if (substr($line,0,1) == '.') { $ji=2; }
$thisdir=explode('slideshow_0.zip', $line)[0];
$uzc=shell_exec("unzip -l " . $cdis . substr($line, $ji));
foreach (glob($thisdir . '*-[0-9]*of.[jJpPgG][pPnNiI]*') as $zipmember) {
$ij=0;
if (substr($zipmember,0,1) == '.') { $ij=2; }
$thisfile=$cdis . substr($zipmember, $ij);
if (strpos($uzc, (' ' . explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij))[-1 + sizeof(explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij)))]) ) !== false) {
if ((time() - filectime($thisfile)) > 600) { // more than 10 minutes old
unlink($thisfile); //echo "analyze " . $thisfile . " " . (time() - filectime($thisfile)) . ' seconds ago ' . "\n";
}
}
}
foreach (glob($thisdir . '*-[0-9]{[0-9]*}.[jJpPgG][pPnNiI]*') as $zipmember) {
$ij=0;
if (substr($zipmember,0,1) == '.') { $ij=2; }
$thisfile=$cdis . substr($zipmember, $ij);
if (strpos($uzc, (' ' . explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij))[-1 + sizeof(explode(DIRECTORY_SEPARATOR, substr($zipmember, $ij)))]) ) !== false) {
if ((time() - filectime($thisfile)) > 600) {
unlink($thisfile); //echo "Analyze " . $thisfile . " " . (time() - filectime($thisfile)) . ' seconds ago ' . "\n";
}
}
}
}


?>

… should do its thaing!


Previous relevant Inhouse Slideshow Mobile Google Crawl Tutorial is shown below.

Inhouse Slideshow Mobile Google Crawl Tutorial

Inhouse Slideshow Mobile Google Crawl Tutorial

The recent Inhouse Slideshow Mobile Tutorial did not satisfy all the “mobile usability” tests performed by the “Google Crawl” algorithm, failing on “Content wider than screen”, and you can read some background to this with Google Crawl Viewport Geographicals Tutorial. And so we try some refinements here today, with an idea to control on mobile platforms the max-width CSS property of the document.body of a Inhouse Slideshow webpage, which made up the URLs failing this test at the Google Search Console.

We were reading this great and useful link, thanks, and decided to see whether this stopping of scrolling in X on mobile platform versions of the Inhouse Slideshow webpages gels better with Google Search Console “Google Crawl” Mobility Usability algorithms.

Yet again, deployment of these changes is similar to that last time, and the times before that, as per …

Unit testing completed, the deployment, again, matches those ideas of the recent PDF Slideshow and Form Creation Helper Slideshow Tutorial … in that …

Here are changes we’ll be testing up at Google …


<head>
<script type='text/javascript'>
// Other Javascript code here ...
//
//
// Of relevance today bold below ...

function blater() {
var tdsare=document.getElementsByTagName('td');
var rectg=tdsare[2].getBoundingClientRect(); //document.getElementById('i0').getBoundingClientRect();
tdsare[2].style.borderRight='2px solid white';
document.body.style.backgroundImage="URL('" + document.getElementById('i0').src + "')";
var rl=eval('' + rectg.left);
rl+=eval('' + rectg.width);
rl+=10;
document.body.style.backgroundPosition=" " + rl + "px " + Math.floor(rectg.top) + "px";
document.body.style.backgroundRepeat="no-repeat";
document.body.style.backgroundClip="content-box";
}



function zoom_maybe() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
//document.getElementById('rfs').innerHTML='<style> html { zoom: .5; } </style>';
document.getElementById('rfs').innerHTML='<style> html { zoom: 0.4; body { max-width: 100%; max-height: 80vh; } table { max-width: <?php if (strpos($_SERVER['QUERY_STRING'],'exif=') !== false) { echo "100"; } else { echo "95"; } ?>%; max-height: 80vh; margin: auto; overflow-x: hidden; } </style>';
}
}


function nwpdf(iithis) {
if (('' + iithis.src).length > 0) {
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
window.open(iithis.src,'_blank');
}
}
}


function mytw() {
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
document.body.style.width='' + (window.orientation == 0 ? Math.floor(eval(2.5 * window.screen.width)) : window.screen.height) + 'px';
document.getElementById('myt').style.width='100%'; //'' + (window.orientation == 0 ? window.screen.width : window.screen.height) + 'px';
}
}



window.setInterval(function(){havealook(1)},2000);
</script>
<style>
td { vertical-align:top; }
@media only screen and (max-width: 800px) {
body { max-width: 100%; max-height: 80vh; } table { max-width: <?php if (strpos($_SERVER['QUERY_STRING'],'exif=') !== false) { echo "100"; } else { echo "95"; } ?>%; max-height: 80vh; margin: auto; overflow-x: hidden; }
}

</style>
</head>
<body onload=" mytw(); zoom_maybe(); if (document.URL.indexOf('pdf=') != -1) { document.getElementById('selmode').value='PDF Slideshow'; if (document.getElementById('tdfirst')) { document.getElementById('s0').style.width=document.getElementById('tdfirst').style.width; document.getElementById('s0').style.height=document.getElementById('tdfirst').style.height; } } if (document.URL.indexOf('exif=') != -1) { document.getElementById('selmode').value='Exif Slideshow'; if (document.getElementById('tdfirst')) { document.getElementById('s0').style.width=document.getElementById('tdfirst').style.width; document.getElementById('s0').style.height=document.getElementById('tdfirst').style.height; } } document.title=document.title + ' ' + lastone; ol(); ">


Previous relevant Inhouse Slideshow Mobile Tutorial is shown below.

Inhouse Slideshow Mobile Tutorial

Inhouse Slideshow Mobile Tutorial

The recent PDF Slideshow and Form Creation Helper Slideshow Tutorial changes were made on a MacBook Pro laptop. Did it show that we have put off until today, to look at that functionality with mobile platforms?!

In a “going off to the right table row of cells” arrangement like this, what are some considerations that improve the user experience (of our inhouse slideshows) for mobile platform users?

  • turn the “@” link into an “emoji button” as per ➡ ( &#10145; )
  • for both mobile and non-mobile, we’ve decided …
    1. UTF-8 meta …
      <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>

    2. <style>
      td { vertical-align:top; }
      </style>
    3. change the h4 element to be h2 to help with legibility
  • for mobile, we’ve decided …
    1. viewport …
      <meta name=”viewport” content=”width=device-width, initial-scale=0.4, minimum-scale=0.1, maximum-scale=8, user-scalable=yes”>

    2. <style>
      html { zoom: .5; }
      </style>
    3. iOS (ie. iPad and iPhone) PDF iframe elements have known scrolling issues, which we decided to bypass by opening these PDF creations in a new webpage window

Deployment of these changes is similar to that last time, and the times before that, as per …

Unit testing completed, the deployment, again, matches those ideas of the recent PDF Slideshow and Form Creation Helper Slideshow Tutorial … in that …


Previous relevant PDF Slideshow and Form Creation Helper Slideshow Tutorial is shown below.

PDF Slideshow and Form Creation Helper Slideshow Tutorial

PDF Slideshow and Form Creation Helper Slideshow Tutorial

The first “integration cab” off the rank for yesterday’s PDF Slideshow and Form Creation Helper Primer Tutorial underlying usefulness is with our Inhouse Slideshow arrangements last talked about at Inhouse Slideshow Design Exif Order Tutorial. That generic PHP code now has three display dropdown options of …

  • Slideshow
  • Exif Slideshow … and the new, as of today’s work …
  • PDF Slideshow

… that little bit different in that a PDF Slideshow occupies just the one table cell (rather than the many horizontal cells of the other display modes) and the resultant embedded PDF data vertically scrolls when multiple image slides are involved.

This new option also adds onto this “Inhouse Slideshow” functionality the chance to download and keep a PDF representation of that slideshow to your local system. Perhaps this makes this be of interest to you?!

The changed form_creator.php‘s live run is what gets integrated into the “Inhouse Slideshow” “sisterhood”. We say “sisterhood” because this “Inhouse Slideshow” is designed as a single PHP codefile “hived off” to a lot of other web server folders as their default “index.php” web browser default webpage in a “peer to peer” feeling arrangement. Such an arrangement asks a bit of the deployment arrangements, and we’ve talked about this before (with underlying links pointing to today’s work, should you be interested) …

Unit testing completed, the deployment, again, matches those ideas of the recent Inhouse Slideshow Design Exif Zip Tutorial … in that …

But when we say “Unit testing completed” above, we need to fill you in on a Fpdf issue we came across during unit testing of our changes. We were getting a …


FPDF Error: Not a JPEG file

… Fpdf error message choosing the new “PDF Slideshow” option on some, but not all, “Inhouse Slideshow” address bar URLs. And so the online research began as per …

… almost getting us there to a solution (and as far as the last link goes “that was before we posted the suggestion below”). Then we took one of the error messages at its word …


FPDF error: Not a JPEG file: ../Mac/Linux_drutil-238of.jpg

… and independently looked into the issue via Linux (or macOS command line) file command …


# cd $HOME/public_html/Mac
# ls -l Linux_dr*
-rw-r--r-- 1 owner group 724353 Oct 29 08:00 Linux_drutil-238of.jpg
-rw-r--r-- 1 owner group 132707 Oct 29 08:00 Linux_drutil-239of.jpg
-rw-r--r-- 1 owner group 109595 Oct 29 08:00 Linux_drutil-240of.jpg
# file Linux_drutil-238of.jpg
Linux_drutil-238of.jpg: PNG image data, 1280 x 800, 8-bit/color RGBA, non-interlaced
# file Linux_drutil-239of.jpg
Linux_drutil-239of.jpg: JPEG image data, JFIF standard 1.01
#

… when the penny dropped (about our (macOS) Paintbrush slideshow slide creation habits)! We quote our entry into “php – FPDF error: Not a JPEG file: http://10.11.201.93:81/webdocc/uploaded/tes3.jpg – Stack Overflow” …

Have found that constructing slideshows with Paintbrush on a MacBook Pro for years have sometimes been saving what “file jpeg_filename.jpg” determines is a PNG, as a JPEG, which is not the end of the world as far as the browsers go rendering this. Within FPDF’s fpdf.php I fixed my own shortcomings that were resulting in “FPDF Error: Not a JPEG file” via the kludgy “if($a[2]==3) { return $this->_parsepng($file); }” additional codeline below …

function _parsejpg($file)
{
// Extract info from a JPEG file
$a = getimagesize($file);
if(!$a)
$this->Error(‘Missing or incorrect image file: ‘.$file);
if($a[2]==3) { return $this->_parsepng($file); }
if($a[2]!=2)
$this->Error(‘Not a JPEG file: ‘.’ ‘.$a[2].’ ‘.$file);
if(!isset($a[‘channels’]) || $a[‘channels’]==3)
$colspace = ‘DeviceRGB’;
elseif($a[‘channels’]==4)
$colspace = ‘DeviceCMYK’;
else
$colspace = ‘DeviceGray’;
$bpc = isset($a[‘bits’]) ? $a[‘bits’] : 8;
$data = file_get_contents($file);
return array(‘w’=>$a[0], ‘h’=>$a[1], ‘cs’=>$colspace, ‘bpc’=>$bpc, ‘f’=>’DCTDecode’, ‘data’=>$data);
}

… and this change to Fpdf’s fpdf.php fixed the issue in our case for a lot of our previously erroneous “PDF Slideshow” displays of “Inhouse Slideshows”.


Previous relevant PDF Slideshow and Form Creation Helper Primer Tutorial is shown below.

PDF Slideshow and Form Creation Helper Primer Tutorial

PDF Slideshow and Form Creation Helper Primer Tutorial

Our recent work involving the great Fpdf creator of PDF files when we presented Ajax FormData Object No Body PHP PDF Tutorial has got us starting on a new PDF (PHP) web application we are starting out thinking will help with …

  • online forms (probably via thinking in terms of Fpdf open source programmers like Rick van Buuren and Clément Lavoillotte‘s excellent HTML table rendering ideas) via HTML table intermediate user interactions … and …
  • slideshows

… but we will not be surprised if the project branches out into other ideas. We’ll see over time.

We hope you come along for the trip starting with a bit of a proof of concept form_creator.php‘s live run for you to try, where we allow you to enter (and be able to change) some HTML table code (if that’s what you end up with?!) in a pink HTML textarea element, and that will become PDF should you click the underlying HTML form’s yellow submit button.

Hope to see you for tomorrow’s PDF writing developments here.

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, Operating System, Tutorials | Tagged , , , , , , , , , , , , , , , , | Leave a comment

WordPress Blog Web Share API Sharing Tutorial

WordPress Blog Web Share API Sharing Tutorial

WordPress Blog Web Share API Sharing Tutorial

It was pretty exciting discovering a bit about the Web Share API we first talked about with MAMP Timekeeping Web Application Web Share API Tutorial some time ago now. It has two modus operandi talents …

  • sharing links in many communication choices, such as, on this macOS MacBook Air (out of the box) …
    1. Mail
    2. Messages
    3. AirDrop
    4. Notes
    5. Reminders
  • sharing documents as attachments in many communication choices, such as, on this macOS MacBook Air (out of the box) …
    1. Mail
    2. Messages
    3. AirDrop
    4. Notes
    5. Reminders

Alas, this Web Share API, across the browsers and platforms, is only reliable about the first modus operandi above, for which we add to this WordPress Blog’s functionality via, in the TwentyTen Theme’s header.php …

Calling the Web Share API
<?php

echo "<script type=text/javascript src=/web_share_api_test.js?populate=as_necessary9876&rand=" . rand(0,786756) . " defer>/script>";

?>
New emoji button 👥 (&#128101;) up the top for URL link sharing via the Web Share API
<?php echo ”

function mlater() {
if (onlok) {
if (1 == 1 || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPod|Opera Mini|IEMobile/i)) {
if (dbihis == '') { dbihis=document.body.innerHTML; }
var xstih=document.getElementById('site-title').innerHTML;
if (xstih.indexOf("up" + "top") == -1) {
document.getElementById('site-title').innerHTML+='<?php echo doisr(); ?>' + '<a id="avs" style="text-decoration:none;font-size:<?php global $fns; echo $fns; ?>px;" href=# onmouseover="getVisualSynopsis(event);" onmouseout="yehbut();" ontouchstart="getVisualSynopsis(event);" ontouchend="yehbut();" onclick=" uptop(); " title="... you can wait for the long hover functionality about Visual Synopsis (Slideshows)">&#127910;</a> <button onclick="atclick();" id="share" type="button" title="Share your media or documents or link!" style="display:inline-block;">&#128101;</button> <a style="cursor:pointer;text-decoration:none;font-size:<?php global $fns; echo $fns; ?>px;" onclick="diffphpfix(this);" title="Code Difference Functional Links">&#128214;</a> <a style="cursor:pointer;text-decoration:none;font-size: 22px;" onclick="popselid();" title="Filter Content via Div ID">&#10135;</a> <a style="cursor:pointer;text-decoration:none;visibility:hidden;font-size:<?php global $fns; echo $fns; ?>px;" title="Blog post contents reduced to summary" id="eds" onclick="pre_details_summary();">&#10134;</a>' + printscreen(0);
if (document.URL.indexOf("visualsynopsis=") != -1) document.getElementById('avs').click();
}
}
}
}

“; ?>
But a great feature Safari web browsers allow for is a Right Click option Share…
Allowing an attachment of the media right clicked on be modelled to the user after their communication choice is selected.

That last option is so good, but don’t expect email subject fields be filled out for you. Apparently that is a security issue. Otherwise, the contextual aspects to sharing on this WordPress Blog have been improved considerably via the changed web_share_api.js external Javascript usage.


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.

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