Walking Trip …

Walking Trip

Walking Trip

Offenbach's Suite ... Warts 'n All

Offenbach's Suite ... Warts 'n All

 📅  

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

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

Apple CarPlay Primer Tutorial

Apple CarPlay Primer Tutorial

Apple CarPlay Primer Tutorial

The recent Shower Songs Mobile Out and About Usage Tips Tutorial …

  • inhouse Radio Play via the Google wooooorrrrllllddd’s YouTube API interfacing Shower Songs “out and about” Bluetooth off advice (quite obviously to avoid any risk of bluejacking … cough, cough) is an interesting contrast to today’s …
  • Polestar car Apple CarPlay music playing ambivalent about Bluetooth but working off an Apple White Lead connection from iOS (iPhone or iPad) to the Polestar USB jack …

    Apple CarPlay … operates through either a wired connection or a wireless connection, never a mix of both for data transfer..

… as another music playing idea. You may wonder, as we did initially, would a system of playing music like Apple CarPlay also allow you to browse on a web browser? Sensibly, no, the functionality is targeted towards setting up music playing, and not distracting otherwise from driving the car!

Spotify and Apple Music are two such options on offer, in these conditions, for Apple CarPlay.

Here’s Google search’s findings regarding Apple CarPlay …

Apple CarPlay is a smarter, safer way to use your iPhone on your car dashboard, allowing you to get directions, make calls, send messages, and listen to music while staying focused on the road. You can explore official features and compatibility via the Apple CarPlay Page.

… reminding us about it’s communication skills, as well.


Previous relevant Shower Songs Mobile Out and About Usage Tips Tutorial is shown below.

Shower Songs Mobile Out and About Usage Tips Tutorial

Shower Songs Mobile Out and About Usage Tips Tutorial

We stumbled upon something regarding out and about mobile device Shower Songs “radio play” usage of …

  • our inhouse Shower Songs (last talked about at Shower Songs Audio and Video Remembering Tutorial (where a new YouTube temporary playlist play scenario paradigm is discussed if it’s the visuals you want as well)) “radio play” (ie. audio only)
  • out and about (using mobile data but not WiFi, perhaps Bluetooth off, volume reasonable)
  • not being charged

… scenarios. We were at first amazed but got back to “WiFi Land” doing research about our use of an iPhone’s Control Center screen (we know of, as the one with the Torch) to avoid having to effectively be touching the iPhone screen to keep it awake semi regularly (that “awake” state the ideal state for our Shower Songs “radio play” executions). We succeeded on a car trip with this but back at “WiFi Land” our research …

When out and about with an iPhone are there any benefits to having the Control Center screen on while looping music is playing?

Is it so that if you have the torch screen open when out and about with an iPhone even if it is not charging it will not fall asleep?

Is it so that if you have the Control Center screen open when out and about with an iPhone even if it is not charging it will not fall asleep?

On iphone what is the torch screen called?

Is it so that if you have the Control Center screen open when out and about with an iPhone even if it is not charging the screen will fade less?

Is it so that if you have the Control Center screen while wirelessly charging an iPhone in the car the screen will fade less frequently?

… filled with “No” led us, for a couple of days, to thinking this must have been a figment of our imagination. But, today, out and about, this time not in a car, but under those conditions above, it happened again. The use of the iPhone’s Control Center screen helped not have to keep the iPhone awake at semi-regular intervals. Perhaps our Shower Songs YouTube API methodologies (not recognized as “Media” in many car Bluetooth systems, for instance) do not exactly fit in with your typical scenario all the references above are saying “No” to? Who knows? But below is our (tweaked via experience) advice regarding our inhouse Shower Songs “radio play” out and about on a mobile device …

  1. on a well charged (ahead of time) mobile device (such as an iPhone with iOS, that all the technical terminology below references) out and about (using mobile data but not WiFi) and not being charged
  2. close unnecessary apps you have open that are not the web browser you are going to use to …
  3. if you are in a car we often find it best turning Bluetooth off and use the iPhone speakers (with a decent volume applied)
  4. open our inhouse Shower Songs web application in a mobile web browser application
  5. arrange the playlist with it’s emergent red buttons you can tap as they arrive if you are impatient (perhaps leaving some unselected)
  6. once satisfied with your ordering and music is playing …
  7. in our iPhone’s case, swipe down and left from top right, to reveal that iPhone’s Control Center display (with the Torch!)
  8. especially as you have Shower Songs “radio play, just music” happening feel free to dim the display brightness … because we got a “Yes” combating, somewhat, one of the issues cited above … finally …

    Is it so that if you have an iPhone Control Center screen open dimming it helps with burning in issues and uses less power?
  9. to loop and continuously play with much less need to “tap to wake” (but if you do, just unswipe the Control Center to tweak the Shower Songs music play settings, as required, or if the connection drops (hence the “perhaps leaving some unselected” advice above))

  10. Previous relevant Shower Songs Audio and Video Remembering Tutorial is shown below.

    Shower Songs Audio and Video Remembering Tutorial

    Shower Songs Audio and Video Remembering Tutorial

    Further to yesterday’s Shower Songs Temporary YouTube Playlist Tutorial, another player in integration to …

    • Shower Songs “was just audio” … but, as of yesterday …
    • “can also include video” … via a YouTube temporary playlist play scenario

    … is … doh! … the Shower Songs web application itself. It needs to, to our minds …

    1. offer what used to be just a “-” part to an HTML element into an HTML button element starting with …

      - 📹

      (as “just audio”) but now, via a click, able to toggle to …

      + 📹

      (as “can also include video”) … and then …
    2. via new Javascript …

      function toggleav(obut) {
      var alst=[], alstc='', alstcd='', yestothis=true;
      if (obut.innerHTML.substring(0,1) == '-') {
      obut.innerHTML='+ 📹';
      var aisare=document.getElementsByTagName('a');
      for (var ii=0; ii<aisare.length; ii++) {
      //alert(aisare[ii].href);
      if (aisare[ii].href.replace('youtubeid=','?v=').replace('/embed/','?v=').indexOf('?v=') != -1) {
      if (alst.indexOf(aisare[ii].href.replace('youtubeid=','?v=').replace('/embed/','?v=').split('?v=')[1].substring(0,11)) == -1 && aisare[ii].href.replace('youtubeid=','?v=').replace('/embed/','?v=').split('?v=')[1].trim() != '') {
      alst.push(aisare[ii].href.replace('youtubeid=','?v=').replace('/embed/','?v=').split('?v=')[1].substring(0,11));
      yestothis=true;
      if (eval('' + tas.length) > 0) {
      if (tas.indexOf(('000' + eval(1 + ii)).slice(-3)) == -1) {
      yestothis=false;
      }
      }
      if (yestothis) {
      alstc+=alstcd + aisare[ii].href.replace('youtubeid=','?v=').replace('/embed/','?v=').split('?v=')[1].substring(0,11);
      alstcd=',';
      }
      //alert('' + alst.length + ': ' + aisare[ii].href.replace('youtubeid=','?v=').replace('/embed/','?v=').split('?v=')[1].substring(0,11));
      }
      }
      }
      //if (eval('' + tas.length) > 0) {
      //} else {
      if (alstc != '') {
      //window.open('//www.youtube.com/watch_videos?video_ids=' + alstc + ',PtR4cWb4HNg', '_blank', 'top=50,left=' + eval(-600 + screen.width) + ',width=600,height=800');
      try {
      window.localStorage.removeItem('song_list_' + alstc + ',PtR4cWb4HNg');
      } catch(jygf) { }
      window.localStorage.setItem('song_list_' + alstc + ',PtR4cWb4HNg', 'https://www.rjmprogramming.com.au/' + alstc + ',PtR4cWb4HNg');

      window.open('//www.rjmprogramming.com.au/' + alstc + ',PtR4cWb4HNg', '_blank', 'top=50,left=' + eval(-600 + screen.width) + ',width=600,height=800');
      }
      //}
      //console.warn(tas);
      //console.warn(taids);
      //console.warn(vidminus);
      //console.warn(vidplus);
      } else if (obut.innerHTML.substring(0,1) == '+') {
      obut.innerHTML='- &#x1F4F9;';
      }
      }

      … be able to open a new popup window to the right which is a YouTube temporary playlist play scenario webpage, as well as remember this, and recreate this, for the next time

    … in a changed shower_songs.html Shower Songs web application, helped out by the changed ytaudioonly.js external Javascript helper.


    Previous relevant Shower Songs Temporary YouTube Playlist Tutorial is shown below.

    Shower Songs Temporary YouTube Playlist Tutorial

    Shower Songs Temporary YouTube Playlist Tutorial

    We break with our normal transmission, because we read something …

    … Luuunnnaa?! Sarcasm does not look good on you (though lilac green’s not bad). And wipe that sardonic grin off your breakfast bowl food rearrangements you’ve just made?!

    Now where were we? Oh yes … we read something from Can a youtube playlist be created via a web browser add bar url?, thanks, we think can add …

    A feather to our boa constrictor … Luuunnnaa?! … get off the keyboard now … don’t you have some bone to pick, or that book about Dogma (tee hee) to read?!w

    … on that Shower Songs YouTube embedded iframe inhouse playlist concept, further to Shower Songs Playlist Subset Revisit Tutorial. Some people, like Luna today, may want to bypass our Shower Songs just audio paradigm to dynamically create a temporary YouTube playlist and play video and audio together in a playlist in sequential order.

    Anyway, we tweaked stuff to start the ball rolling making this be a possibility, as well as involving YouTube video ID PtR4cWb4HNg in the list to spark this concept into action. And later we’ll explain maybe why PtR4cWb4HNg should lead the comma separated list.

    … where those last two’s blurb now goes

    Radio Play via comma separate YouTube 11 character IDs or search ideas for an inhouse playlist (if any in a comma separated list is PtR4cWb4HNg temporary YouTube playlist audio and video play can be attempted) … 7 such uses Shower Songs … egs. Tragedy,Boogie Wonderland,Down Among the Dead Men flash … random … Tragedy ,Imagine*3,Breezin … ordered 5 … Tragedy ,Pina Colada Song,Fast Car … audio … Tragedy ,Galveston,Fix You … audio ordered,

    Did You Know?

    If at the time of launching (and deploying) into making one of these temporary YouTube playlists and you are logged into your own YouTube channel, more possibilities present, and today’s tutorial animated GIF shows a bit of this (though we found out about the virtue of putting PtR4cWb4HNg first later, alas).

    The playlist gets played, and on non-mobile it may start itself. For each track you can use the Save button down near the bottom to save to a new (where we are recommending PtR4cWb4HNg to go first) or pre-existing public or private playlist. Okay, so you have this new YouTube playlist.

    Once in a YouTube playlist, you can loop (through the playlist again) and/or shuffle (the playlist) with that video and audio play.

    Why PtR4cWb4HNg? 💬🦆 Come On!


    Previous relevant Shower Songs Playlist Subset Revisit Tutorial is shown below.

    Shower Songs Playlist Subset Revisit Tutorial

    Shower Songs Playlist Subset Revisit Tutorial

    The recent Javascript Console Warning Conditionals Tutorial‘s crabwise response to YouTube API iOS Shower Song Subset Looping Tutorial‘s functionality helped us come to the conclusion that we would open a new window for these “Playlist Subsets” of our inhouse Shower Songs web application.

    With this in mind we allowed for incoming URLs with playlists less than 7 in length at the document.body onload Javascript as partly shown below …


    function inlistcheck() {
    var kok=0, nomore=false;
    var inlistis=location.search.split('thelist=')[1] ? decodeURIComponent(location.search.split('thelist=')[1].split('&')[0]) : "";
    var intlistis=(document.URL + ('#' + location.hash)).split('thetlist=')[1] ? decodeURIComponent((document.URL + ('#' + location.hash)).split('thetlist=')[1].split('#')[0]) : "";
    //alert(intlistis);
    var inlistisa=inlistis.split(',');
    var intlistisa=intlistis.split('|');
    if (eval('' + inlistisa.length) > 0) {
    if (eval('' + intlistisa.length) >= 2 && eval('' + inlistisa.length) >= 2 && eval('' + intlistisa.length) <= 6 && eval('' + inlistisa.length) <= 6) {
    if (eval('' + intlistisa.length) == 2) {
    inlistisa.push(inlistisa[0]);
    intlistisa.push(intlistisa[0]);
    inlistisa.push(inlistisa[1]);
    intlistisa.push(intlistisa[1]);
    inlistisa.push(inlistisa[0]);
    intlistisa.push(intlistisa[0]);
    inlistisa.push(inlistisa[1]);
    intlistisa.push(intlistisa[1]);
    inlistisa.push(('cGdz3GNhEQ4').replace('cGdz3GNhEQ4','3wxyN3z9PL4'));
    intlistisa.push(('Luna and Nala in the Park').replace('Luna and Nala in the Park','Nothing`s Gonna Stop Us Now-Starship-1987'));
    } else if (eval('' + intlistisa.length) == 3) {
    inlistisa.push(inlistisa[0]);
    intlistisa.push(intlistisa[0]);
    inlistisa.push(inlistisa[1]);
    intlistisa.push(intlistisa[1]);
    inlistisa.push(inlistisa[2]);
    intlistisa.push(intlistisa[2]);
    inlistisa.push(('cGdz3GNhEQ4').replace('cGdz3GNhEQ4','3wxyN3z9PL4'));
    intlistisa.push(('Luna and Nala in the Park').replace('Luna and Nala in the Park','Nothing`s Gonna Stop Us Now-Starship-1987'));
    } else {
    while (eval('' + intlistisa.length) < 7) {
    inlistisa.push(('cGdz3GNhEQ4').replace('cGdz3GNhEQ4','3wxyN3z9PL4'));
    intlistisa.push(('Luna and Nala in the Park').replace('Luna and Nala in the Park','Nothing`s Gonna Stop Us Now-Starship-1987'));
    }
    }
    } else if (eval('' + inlistisa.length) >= 2 && eval('' + inlistisa.length) <= 6) {
    if (eval('' + inlistisa.length) == 2) {
    inlistisa.push(inlistisa[0]);
    inlistisa.push(inlistisa[1]);
    inlistisa.push(inlistisa[0]);
    inlistisa.push(inlistisa[1]);
    inlistisa.push(('cGdz3GNhEQ4').replace('cGdz3GNhEQ4','3wxyN3z9PL4'));
    } else if (eval('' + inlistisa.length) == 3) {
    inlistisa.push(inlistisa[0]);
    inlistisa.push(inlistisa[1]);
    inlistisa.push(inlistisa[2]);
    inlistisa.push(('cGdz3GNhEQ4').replace('cGdz3GNhEQ4','3wxyN3z9PL4'));
    } else {
    while (eval('' + inlistisa.length) < 7) {
    inlistisa.push(('cGdz3GNhEQ4').replace('cGdz3GNhEQ4','3wxyN3z9PL4'));
    }
    }
    } else if (eval('' + intlistisa.length) == 1 && eval('' + inlistisa.length) == 1) {
    if (intlistisa[0].trim() != '' && eval('' + encodeURIComponent(inlistisa[0]).length) == 11 && eval('' + (inlistisa[0] + ',').replace(/[AEIMQUYcgkosw048]\,$/g,'z').length) == 11) {
    inlistisa.push(inlistisa[0]);
    intlistisa.push(intlistisa[0]);
    inlistisa.push(inlistisa[0]);
    intlistisa.push(intlistisa[0]);
    inlistisa.push(inlistisa[0]);
    intlistisa.push(intlistisa[0]);
    inlistisa.push(inlistisa[0]);
    intlistisa.push(intlistisa[0]);
    inlistisa.push(inlistisa[0]);
    intlistisa.push(intlistisa[0]);
    inlistisa.push(inlistisa[0]);
    intlistisa.push(intlistisa[0]);
    }
    }

    if (eval('' + intlistisa.length) >= 7 && eval('' + inlistisa.length) >= 7) {
    // rest of if follows
    }
    // rest of function inlistcheck() follows
    }

    … in a changed shower_songs.html external Javascript powered Shower Songs web application.

    Did You Know?

    A few attempts we made failed to “curb the enthusiasm” of the parent window left behind by the new window.open window of these Playlist Subsets the user defines, until we did something we can not recall ever doing before, namely …


    var tdsarea=document.getElementsByTagName('td');
    for (var iopj=eval(-1 + tdsarea.length); iopj>=0; iopj--) {
    tdsarea[iopj].innerHTML=tdsarea[iopj].innerText;
    }

    … to not only be “curbing it’s enthusiasm to play” but also making that parent window end up being a “display snapshot only” of what had been going on before the user set up more than one “L=loop” looping textarea functionalities that defines a playlist subset scenario where that new window takes on the role of “enthusiastic play”.


    Previous relevant Javascript Console Warning Conditionals Tutorial is shown below.

    Javascript Console Warning Conditionals Tutorial

    Javascript Console Warning Conditionals Tutorial

    Yesterday’s YouTube API iOS Shower Song Subset Looping Tutorial‘s …

    • want to “move on” to a new song … via …
    • add to an “individual song looping subset” with another “individual looping song” … and it also serves another “arcane usage” to our mind, we explain below …
    • out and about using a laptop lassooed to a mobile (or just the mobile itself) using mobile data (rather than Wi-Fi) this web browser Shower Songs web application depends on a connection as a song starts and if you have run out of never before tapped buttons to choose from (and the web application has lost it’s connection) it can become an impotent web application, sometimes, so that to add to the web application’s possibilities of button tapping, and often reawakening it, the better, we figure

    … work did not function for as many scenarios as we would like. This problem requires Javascript web browser clientside debugging via a Web Browser web inspector “Developer” style of debugging (ie. deep and meaningful).

    When it gets to the “deep and meaningful” we mean “comparing” console tab “good versus bad” types of reporting, which becomes untenable if too much is already being reported in our favourite “reporting tool conduit” for us …


    console.warn([some messaging text]);

    … you can read more about at YouTube API Caller Phase Two Console Warning Tutorial. Over the three window hierarchies, over quite some time, we’ve filled console.warn web inspector tab with so much information it is untenable for what we have to do debugging the issues above.

    And so, today, we’re showing a “conditional approach” to controlling “console.warn” logging via “grandchild level” substitution of all “console.warn(” for “consolewarn(” and then the new Javascript function …


    function consolewarn(inms) {
    if (window.self != window.parent) {
    if (('' + top.document.URL).indexOf('consolewarnoptinall') != -1 || ('' + top.document.URL).indexOf('consolewarnoptingrandchild') != -1) {
    console.warn(inms);
    }
    } else if (('' + document.URL).indexOf('consolewarnoptoutall') == -1) {
    console.warn(inms);
    }
    }

    … and at the “parent level” substitution of all “console.warn(” for “consolewarn(” and then the new Javascript function …


    function consolewarn(inms) {
    if (window.self != window.parent) {
    if (('' + top.document.URL).indexOf('consolewarnoptinall') != -1 || ('' + top.document.URL).indexOf('consolewarnoptinchild') != -1) {
    console.warn(inms);
    }
    } else if (('' + document.URL).indexOf('consolewarnoptoutall') == -1) {
    console.warn(inms);
    }
    }

    … as an address bar controlling URL via, for example …


    https://www.rjmprogramming.com.au/HTMLCSS/shower_songs.html?consolewarnoptinchild=y

    … means by which we can better hone in on the debugging issues as they arrive, so that self contained relevance fits on the one screen, and the Clear Console icon becomes an additional friend to our work, within …


    Previous relevant YouTube API iOS Shower Song Subset Looping Tutorial is shown below.

    YouTube API iOS Shower Song Subset Looping Tutorial

    YouTube API iOS Shower Song Subset Looping Tutorial

    You’d think we’d be done with ablutions at this blog, but ingen mΓ₯te … Luna (aka MΓ₯ne) says … there’s all manner of molekylΓ¦r interesse out there in and out of the fjords …

    It’s not just H and the 2 and the O … it’s the art of the rollerulle.

    … or so says “The Lu” (aka “Toalettet”) anyway!

    Today’s Shower Songs tweak involves it’s “individual song looping” thinking. It occurred to us, that it’s use by a user might be what they want, it becomes a bit inflexible should they either …

    • want to “move on” to a new song … via …
    • add to an “individual song looping subset” with another “individual looping song” … and it also serves another “arcane usage” to our mind, we explain below …
    • out and about using a laptop lassooed to a mobile (or just the mobile itself) using mobile data (rather than Wi-Fi) this web browser Shower Songs web application depends on a connection as a song starts and if you have run out of never before tapped buttons to choose from (and the web application has lost it’s connection) it can become an impotent web application, sometimes, so that to add to the web applications’s possibilities of button tapping, and often reawakening it, the better, we figure

    And so, moving on from yesterday’s YouTube API iOS Shortcuts Shower Song Tutorial code that changed involved …


    Previous relevant YouTube API iOS Shortcuts Shower Song Tutorial is shown below.

    YouTube API iOS Shortcuts Shower Song Tutorial

    YouTube API iOS Shortcuts Shower Song Tutorial

    Yesterday’s non-mobile YouTube API Command Line Shower Song Names Tutorial based work begs the question, for us …

    At least, on “mobile” iOS (which we have access to) can any “command line” feel of playlists ending up at our Shower Songs web application be arranged?

    Pretty pithy, huh?! Before we launch into the great iOS Shortcuts app (we’ve talked about before at Shortcuts iOS App Email Arrival Sounds Tutorial) helping here, let’s outline some other simpler ideas you might want to try yourself in the DIY range of ideas …

    • open one of these inhouse Radio Play (YouTube API song playlist and sequencing and loop supporting changed for today’s work swipe_media.html Tabular Single Row Media Gallery or Shower Songs) web applications on a web browser on an iOS device (eg. iPhone or iPad) … and at the juncture where your desired playlist is implemented … use Share icon menu of choices to …
      1. Add to Home Screen … with a tailored (Playlist) Title … this being our preferred option to future proof the remembering … but also available is …
      2. Add Bookmark … or …
      3. Add Favourite
      4. Make your web browser’s opening Home Page be a URL of interest (like one of these playlists) within that web browser app’s Settings area
    • as well as the Shower Songs (as well as Tabular Single Row Media Gallery) web application (with Playlists of 7) can have a dropdown be populated ready to choose and replay that Playlist (that can be email or SMS shared with a recipient)

    Okay, all that being said, the great Shortcuts iOS app can serve two purposes a bit “above and beyond this” …

    1. you can DIY build an iOS feeling and “hybrid looking” amalgum of iOS and “old days” dialog box “desktop feeling” personalized application(s) …
    2. the act of constructing any one is sure to inspire other iOS automation ideas you might have

    We’re sure lots of you more aux fait with the great iOS Shortcuts app can do better than the “bit kludgy” effort we came up with, and that is the joy of programming, huh?! It can come down to …

    • what you think is the most efficient …
    • you feel you can handle … and …
    • end up with a better automated solution … but …
    • it’s not “all about efficiency” always … it’s also learning about new methodologies you might have to spend more time discovering the ins and outs about

    As a case in point, it will be hard to stop yours truly just (iOS mobile) opening the relevant Radio Play web application in a web browser, and going from there (with Bookmarks and Favourites), but there you go?! In this case, perhaps yes, but you should see all the other Messaging and automation possibilities that a peruse of the iOS Shortcuts app can open up to you!

    Todays’ animated GIF presentation shows our endeavours “warts and all” (latching onto, intervention wise, when a user taps the Music mobile app icon) for your perusal.


    Previous relevant YouTube API Command Line Shower Song Names Tutorial is shown below.

    YouTube API Command Line Shower Song Names Tutorial

    YouTube API Command Line Shower Song Names Tutorial

    Yesterday’s YouTube API Command Line Shower Songs Tutorial‘s Operating System command line modes of access brought us to another issue.

    Can a list of seven non-YouTube-ID comma separated values (ie. YouTube song search basis strings) be entered and still end up at the Shower Songs web application?

    Well, yes, that’s possible if an intervention point can be arranged. After all, the command line prompt goes …

    Radio Play via comma separate YouTube 11 character IDs or search ideas for a playlist … 7 for Shower Songs … egs. Tragedy,Boogie Wonderland,Down Among the Dead Men … random … Tragedy ,Imagine*3,Breezin … ordered 5 … Tragedy ,Pina Colada Son,Fast Car … audio … Tragedy ,Galveston,Fix You … audio ordered, and go.

    … begging the question “What happens if we enter, at the command line …”


    play
    Tragedy ,Pina Colada Song,Fast Car,Breezin,Galveston,Fix You,Imagine

    … ? Well, after our “better interfacing changes” to the swipe_media.html Tabular Single Row Media Gallery web application changes …


    var ytlistis=location.search.split('youtube=')[1] ? anotherdecodeURIComponent(location.search.split('youtube=')[1].split('&')[0]) : '';


    function anotherdecodeURIComponent(inplis) {
    var thisplist=decodeURIComponent(inplis);


    if (eval((thisplist + ',').replace(/[AEIMQUYcgkosw048]\,/g,'z').length) == 77 && eval(('' + thisplist).length) == 83 && eval(('' + encodeURIComponent(thisplist.replace(/\,/g,''))).length) == 77 && eval(('' + thisplist.split(',').length)) == 7) {
    window.open('//www.rjmprogramming.com.au/HTMLCSS/shower_songs.html?thelist=' + thisplist.trim(),'_blank','top=50,left=' + eval(-800 + screen.width) + ',width=800,height=800');
    }

    return thisplist;
    }

    … which mapped to URL …


    https://www.rjmprogramming.com.au/HTMLCSS/shower_songs.html?thelist=OiwDHHcHPh0,FXG_I_tf_i4,AIOAlaACuv4,G1QjyskJ9jw,HhKZLhxFFUY,k4V3Mo61fJM,MBIyH4WhOWg

    … and that’s where “our fun” (chortle, chortle) began (yeh, right … after a Goose Chase with it being the seventh one) because that seventh YouTube video ID (involved with YouTube “Imagine” search (and something about this rings a bell)) comes back with …

    This content can’t be played on your mobile browser. Get the YouTube app to start watching.

    Ouch?! What to do? Looking optimistically on this, it’s good to discover it now (yeh, right).

    Anyway, we mapped such unplayables to Nothing’s Gonna Stop Us Now – Starship – 1987 in …

    … as our means to a solution.


    Previous relevant YouTube API Command Line Shower Songs Tutorial is shown below.

    YouTube API Command Line Shower Songs Tutorial

    YouTube API Command Line Shower Songs Tutorial

    Today, we’re combining the concepts behind …

    • the recent YouTube API Caller Radio Play Doctype Meta Tutorial‘s means by which …
      1. macOS
      2. Windows

      … command line “command verb” …

      play

      … can call our “Radio Play” YouTube API interfacing means to play music …

      • sequentially
      • continuously looping (through a set of songs) or just the one song looping

      … adding into those previous arrangements the capability to call the Shower Songs web application under conditions we outlined in …

    • the work of the day before yesterday’s Shower Songs Delimitation Hashtag Tutorial

    … involving changed …

    1. macOS (building on the changed play.sh shell script) …

      #!/bin/bash
      rest=""
      if [ -z "$1" ]; then
      echo "Radio Play via comma separate YouTube 11 character IDs or search ideas for a playlist ... 7 such uses Shower Songs ... egs. Tragedy,Boogie Wonderland,Down Among the Dead Men flash ... random ... Tragedy ,Imagine*3,Breezin ... ordered 5 ... Tragedy ,Pina Colada Song,Fast Car ... audio ... Tragedy ,Galveston,Fix You ... audio ordered, and go."
      read ans
      else
      preans="$1"
      ans="$1 $2 $3 $4 $5 $6 $7 $8 $9"
      while [ ! -z "$9" ]; do
      shift
      rest="${rest} $9"
      done
      ans="$ans${rest}"
      fi
      if [ ! -z "$ans" ]; then
      commas_only="${ans//[^,]}"
      if [ "${#preans}" == "83" ]; then
      if [ "${#commas_only}" == "6" ]; then
      open "https://www.rjmprogramming.com.au/$1"
      else
      open "https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html $ans"
      fi
      else

      open "https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html $ans"
      fi
      fi
      exit
    2. Windows (building on the changed play.bat script) …

      @echo off
      rem play.bat
      rem RJM Programming
      rem November, 2025

      set passed=
      set rest=
      set seven=0

      if trick==trick%1 (
      set /p ans=Radio Play via comma separate YouTube 11 character IDs or search ideas for a playlist ... 7 for Shower Songs ... egs. Tragedy,Boogie Wonderland,Down Among the Dead Men ... random ... Tragedy ,Imagine*3,Breezin ... ordered 5 ... Tragedy ,Pina Colada Son,Fast Car ... audio ... Tragedy ,Galveston,Fix You ... audio ordered, and go.
      set ansplus="%ans% "

      if "%ansplus:~12,1%"=="," (
      if "%ansplus:~24,1%"=="," (
      if "%ansplus:~36,1%"=="," (
      if "%ansplus:~48,1%"=="," (
      if "%ansplus:~60,1%"=="," (
      if "%ansplus:~72,1%"=="," (
      if "%ansplus:~84,1%"==" " (
      set seven=7
      explorer.exe "https://www.rjmprogramming.com.au/HTMLCSS/shower_songs.html?thelist=%ans%"
      goto :end
      ) else (
      set seven=6
      )
      ) else (
      set seven=5
      )
      ) else (
      set seven=4
      )
      ) else (
      set seven=3
      )
      ) else (
      set seven=2
      )
      ) else (
      set seven=1
      )
      ) else (
      set seven=0
      )


      ) else (
      set ans="%1"

      set ansplus="%1,%2,%3,%4,%5,%6,%7 %8 "

      if "%ansplus:~12,1%"=="," (
      if "%ansplus:~24,1%"=="," (
      if "%ansplus:~36,1%"=="," (
      if "%ansplus:~48,1%"=="," (
      if "%ansplus:~60,1%"=="," (
      if "%ansplus:~72,1%"=="," (
      if trick==trick%8 (
      set seven=7
      explorer.exe "https://www.rjmprogramming.com.au/HTMLCSS/shower_songs.html?thelist=%1,%2,%3,%4,%5,%6,%7"
      goto :end
      ) else (
      set seven=6
      )
      ) else (
      set seven=5
      )
      ) else (
      set seven=4
      )
      ) else (
      set seven=3
      )
      ) else (
      set seven=2
      )
      ) else (
      set seven=1
      )
      ) else (
      set seven=0
      )


      set passed=yes
      if trick==trick%2 goto :loop
      set ans="%ans%,%2"
      if trick==trick%3 goto :loop
      set ans="%ans%,%3"
      if trick==trick%4 goto :loop
      set ans="%ans%,%4"
      if trick==trick%5 goto :loop
      set ans="%ans%,%5"
      if trick==trick%6 goto :loop
      set ans="%ans%,%6"
      if trick==trick%7 goto :loop
      set ans="%ans%,%7"
      if trick==trick%8 goto :loop
      set ans="%ans%,%8"
      if trick==trick%9 goto :loop
      set ans="%ans%,%9"
      explorer.exe "https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html %ans:"=%"
      :loop
      if "%9"=="" (
      @echo off
      ) else (
      shift
      set rest="%rest% %9"
      goto :loop
      )
      set ans="%ans%%rest%"
      set ans=%ans:"=%
      explorer.exe "https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html %ans%"
      )
      if trick==trick%passed% (
      set ans=%ans:"=%
      if "%ans:,=%"=="%ans%" (
      echo "Nothing to do."
      ) else (
      explorer.exe "https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html %ans%"
      )
      )
      rem exit
      :end

    … and involving, if you are on macOS or Windows implementing accordingly …

    … a command line …


    play FtE3hoR_Nvo,W5IKT_xue4o,IfaGhyK78E8,BuN3yCmHb_U,TdiAwCPb_As,euZcUku9XiE,aMs0rNtBZJk

    … can loop and continuously play through that list of seven YouTube video IDs via a web browser use of our Shower Songs web application.


    Previous relevant YouTube API Caller Radio Play Doctype Meta Tutorial is shown below.

    YouTube API Caller Radio Play Doctype Meta Tutorial

    YouTube API Caller Radio Play Doctype Meta Tutorial

    It took a session on this MacBook Air’s macOS Firefox web browser trying the Tabular Single Row Media Gallery web application to emphasise the importance of more consistency checking on …

    • doctype HTML tagdeclaration …

      <!DOCTYPE html>

      … and …
    • meta HTML display tagcharset attribute …

      <meta charset="UTF-8">

    … existence in web applications we create, to the point that not having the second one defined was stopping proper webpage display on Firefox. Was this a portent of what is to come soon on more web browsers?!

    Let’s look at the purpose of these two HTML tagthingos …

    • doctype HTML tagdeclaration …

      All HTML documents must start with a declaration.

      The declaration is not an HTML tag. It is an “information” to the browser about what document type to expect.

      … and …

    • meta HTML display tagcharset attribute …

      The charset attribute specifies the character encoding for the HTML document.

      The HTML5 specification encourages web developers to use the UTF-8 character set, which covers almost all of the characters and symbols in the world!

    Regarding the same web application as yesterday’s YouTube API Caller Radio Play Playlist Windows Local System Tutorial talked about, why not revisit the tweaked swipe_media.html Tabular Single Row Media Gallery web application?


    Previous relevant YouTube API Caller Radio Play Playlist Windows Local System Tutorial is shown below.

    YouTube API Caller Radio Play Playlist Windows Local System Tutorial

    YouTube API Caller Radio Play Playlist Windows Local System Tutorial

    Further to the recent YouTube API Caller Radio Play Playlist Local System Tutorial macOS local system discussion, today, we code for …

    play

    … to mean something on the …

    Windows

    … “cmd” command accessible …

    command line

    What’s the scripting here? They are called batch files with extension *.bat we’re calling play.bat (going back to the DOS days of the ’70’s again). With *.bat you just need to plonk your play.bat anywhere within the Windows local system path, and the word (now command) “play” will do the rest anywhere in that user’s command line environment. And the batch file has …


    @echo off
    rem play.bat
    rem RJM Programming
    rem November, 2025

    set passed=
    set rest=

    if trick==trick%1 (
    set /p ans=Radio Play via comma separate YouTube 11 character IDs or search ideas for a playlist ... egs. Tragedy,Boogie Wonderland,Down Among the Dead Men ... random ... Tragedy ,Imagine*3,Breezin ... ordered 5 ... Tragedy ,Pina Colada Son,Fast Car ... audio ... Tragedy ,Galveston,Fix You ... audio ordered, and go.
    ) else (
    set ans="%1"
    set passed=yes
    if trick==trick%2 goto :loop
    set ans="%ans%,%2"
    if trick==trick%3 goto :loop
    set ans="%ans%,%3"
    if trick==trick%4 goto :loop
    set ans="%ans%,%4"
    if trick==trick%5 goto :loop
    set ans="%ans%,%5"
    if trick==trick%6 goto :loop
    set ans="%ans%,%6"
    if trick==trick%7 goto :loop
    set ans="%ans%,%7"
    if trick==trick%8 goto :loop
    set ans="%ans%,%8"
    if trick==trick%9 goto :loop
    set ans="%ans%,%9"
    explorer.exe "https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html %ans:"=%"
    :loop
    if "%9"=="" (
    @echo off
    ) else (
    shift
    set rest="%rest%,%9"
    goto :loop
    )
    set ans="%ans%%rest%"
    set ans=%ans:"=%
    explorer.exe "https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html %ans%"
    )
    if trick==trick%passed% (
    set ans=%ans:"=%
    if "%ans:,=%"=="%ans%" (
    echo "Nothing to do."
    ) else (
    explorer.exe "https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html %ans%"
    )
    )
    rem exit
    :end

    … as your starting gambit, here, where the equivalent of macOS’s “open” is “explorer.exe” on Windows (ie. the File Explorer) … almost as cute!


    Previous relevant YouTube API Caller Radio Play Playlist Local System Tutorial is shown below.

    YouTube API Caller Radio Play Playlist Local System Tutorial

    YouTube API Caller Radio Play Playlist Local System Tutorial

    The ..

    command line

    … of a laptop or notebook or personal computer can be an environment to relax from the GUI aspects of your modern operating systems and think about …

    • processes
    • batch driven tasks
    • task simplifications

    … and in the category of that last one, on our local macOS operating system we envisaged a day we could slip back to the “quiet world” of the “command line” and type a command like …


    play Tragedy,Imagine,Down Among the Dead Men PAN -

    … and get somewhere playing those songs through a web browser accessing the YouTube API and our interfacings to it in webpage software form, playing in a continuous Radio Play style.

    You see, with all the distractions, only having to remember …

    play

    … no matter where we were in “command line” woooorrrrllllddd seemed the ideal, and yes, it’s possible. However, we think explaining …


    bash /Applications/MAMP/htdocs/play.ksh Tragedy,Imagine,Down Among the Dead Men PAN -

    … is a necessary dividing line between two parts to the discussion. So what’s bash? It’s the shell we associate as your macOS default shell (we get to via the “out of the box” macOS desktop application called Terminal) … well, it used to be … anyway, the first line of (what started as play.ksh then play.sh and then eventually, just, play … as a filename that is) …


    #!/bin/bash
    rest=""
    if [ -z "$1" ]; then
    echo "Radio Play via comma separate YouTube 11 character IDs or search ideas for a playlist ... egs. Tragedy,Boogie Wonderland,Down Among the Dead Men ... random ... Tragedy ,Imagine*3,Breezin ... ordered 5 ... Tragedy ,Pina Colada Song,Fast Car ... audio ... Tragedy ,Galveston,Fix You ... audio ordered, and go."
    read ans
    else
    ans="$1 $2 $3 $4 $5 $6 $7 $8 $9"
    while [ ! -z "$9" ]; do
    shift
    rest="${rest} $9"
    done
    ans="$ans${rest}"
    fi
    if [ ! -z "$ans" ]; then
    open "https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html $ans"
    fi
    exit

    … tells the local system use the bash shell to interpret this what you might like to think of as an executable script (which we went chmod 777 play regarding to make it so).

    Okay, so we wrote this script in /Applications/MAMP/htdocs/ and that …


    bash /Applications/MAMP/htdocs/play Tragedy,Imagine,Down Among the Dead Men PAN -

    … could swing it at this stage, or even being in /Applications/MAMP/htdocs/ and going …


    ./play Tragedy,Imagine,Down Among the Dead Men PAN -

    … but (even in /Applications/MAMP/htdocs/) …


    play Tragedy,Imagine,Down Among the Dead Men PAN -

    … is most likely to reply something like …

    zsh: no such command

    As the programmer, perhaps you could leave it at that with your “insider knowledge”, or if “play” as a command already meant something (a test that would be good to do before any such proposed work), otherwise … do you really think you’ll remember next Wednesday? So …

    1. enter into the wooooorrrrllllddd of aliases (thanks to this great advice, thanks) … eg.

      alias play="/Applications/MAMP/htdocs/play"
    2. placed into …

      ~/.bashrc

      … via (in our case) …

      vi ~/.bashrc
    3. then …

      source ~/.bashrc

      … needs to be included into the login procedure of …

      ~/.profile

      …via (in our case) …

      vi ~/.profile
    4. to make …

      play

      … as the interactively asking alternative to the argumentative example of …

      play Tragedy,Imagine,Down Among the Dead Men PAN -

      … mean something … and anywhere

      … all of this possible because of the brilliantly useful macOS (not Linux nor unix) …


      open

      … opener of web browsers from the command line blowing of our tiny little rather still naive mind … mind you, VAX/VMS “phone” command from the ’70’s might have even been better?! And then there were those punch cards … in the hopper … and if you got a character wrong … back to the end of the queue.

      Sorry … we got a bit hot and bothered there!

      Anyway, as a layer of thought on top of the recent YouTube API Caller Radio Play Playlist Songname Search List Repeats Tutorial‘s mildly changed swipe_media.html Tabular Single Row Media Gallery web application work it might be a thing you want to pursue yourself?

      By the way, this brought into play for us what your default web browser is. Ours is Safari yet we develop more on Google Chrome. Safari, for us, does more Popup Blocking, and it is a thing to look out for should a window not open when expected (and these command line methodologies don’t get past you still having to unmute and/or click/tap once before the Radio Play mode of play kicks off). To undo the Popup Block there will probably be a means to do this to the right of the web browser address bar.


      Previous relevant YouTube API Caller Radio Play Playlist Songname Search List Repeats Tutorial is shown below.

      YouTube API Caller Radio Play Playlist Songname Search List Repeats Tutorial

      YouTube API Caller Radio Play Playlist Songname Search List Repeats Tutorial

      Burp …

      Sorry to open with a quote, and sorry to repeat myself, like.

      And sorry to repeat myself, like, again.

      But there is a point. Today represents an improvement on yesterday’s arrangements for dynamic playlist creation regarding our Tabular Single Row Media Gallery web application via the playlist emoji button 🔀 click/tap or on the web browser command line. With yesterday’s scenario, had you entered as your internal playlist comma separated string …

      Born to Run,Born to Run,Born to Run,Born to Run

      … without the …

      Burp …

      … that is you’d have ended up with the top find off a YouTube search repeated 4 times. Is this ideal? We asked Nala and Luna but, unfortunately they were busy, so they left me with the decision, and we came up with …

      That’s kind of silly.

      For these few reasons …

      • variety
      • album style Radio Play listening possibilities
      • perhaps getting around that …

        This video requires payment to watch YouTube

        … issue we talked about before … because you could uncheck it’s checkbox if the error appears

      • giving non-top search items a go

      … we decided to “mix it up” regarding entries like …

      Born to Run,Born to Run,Born to Run,Born to Run

      … as well as the simpler …

      Born to Run*4

      … so that repeats don’t cause users indigestion … chortle, chortle.

      Here’s the Javascript turning Born to Run*4 into Born to Run,Born to Run,Born to Run,Born to Run …


      function expandrepeats(ocsl) {
      var numnum=0, minone=-1, interesting='', ninteresting='', pinteresting='', superinteresting='', imn=1;
      var retocsl=ocsl;
      var acarr=ocsl.split(',');
      for (var iac=0; iac<acarr.length; iac++) {
      numnum=0;
      minone=-1;
      if (acarr[iac].trim() != '') {
      if (acarr[iac].trim().slice(-1) >= '0' && acarr[iac].trim().slice(-1) <= '9') {
      while (('S' + acarr[iac].trim()).slice(minone).substring(0,1) >= '0' && ('S' + acarr[iac].trim()).slice(minone).substring(0,1) <= '9') {
      numnum++;
      minone--;
      }
      }
      if (numnum > 0 && numnum < eval('' + acarr[iac].trim().length)) {
      ninteresting=acarr[iac].trim().slice(-numnum);
      interesting=acarr[iac].trim().substring(0, eval(-numnum + eval('' + acarr[iac].trim().length)));
      superinteresting='';
      pinteresting='';
      if (interesting.toLowerCase() != interesting.toLowerCase().replace(/\ x\ $/g,'')) {
      pinteresting=interesting.slice(-3) + ninteresting;
      superinteresting=interesting.replace(/\ x\ $/g,'').replace(/\ X\ $/g,'');
      } else if (interesting.toLowerCase() != interesting.toLowerCase().replace(/x\ $/g,'')) {
      pinteresting=interesting.slice(-2) + ninteresting;
      superinteresting=interesting.replace(/x\ $/g,'').replace(/X\ $/g,'');
      } else if (interesting.toLowerCase() != interesting.toLowerCase().replace(/\ x$/g,'')) {
      pinteresting=interesting.slice(-2) + ninteresting;
      superinteresting=interesting.replace(/\ x$/g,'').replace(/\ X$/g,'');
      } else if (interesting.toLowerCase() != interesting.toLowerCase().replace(/x$/g,'')) {
      pinteresting=interesting.slice(-1) + ninteresting;
      superinteresting=interesting.replace(/x$/g,'').replace(/X$/g,'');
      } else if (interesting.toLowerCase() != interesting.toLowerCase().replace(/\ \*\ $/g,'')) {
      pinteresting=interesting.slice(-3) + ninteresting;
      superinteresting=interesting.replace(/\ \*\ $/g,'');
      } else if (interesting.toLowerCase() != interesting.toLowerCase().replace(/\*\ $/g,'')) {
      pinteresting=interesting.slice(-2) + ninteresting;
      superinteresting=interesting.replace(/\*\ $/g,'');
      } else if (interesting.toLowerCase() != interesting.toLowerCase().replace(/\ \*$/g,'')) {
      pinteresting=interesting.slice(-2) + ninteresting;
      superinteresting=interesting.replace(/\ \*$/g,'');
      } else if (interesting.toLowerCase() != interesting.toLowerCase().replace(/\*$/g,'')) {
      pinteresting=interesting.slice(-1) + ninteresting;
      superinteresting=interesting.replace(/\*$/g,'');
      }
      if (superinteresting != '' && eval('' + ninteresting) >= 1) {
      for (imn=1; imn<=eval('' + ninteresting); imn++) {
      if (imn == 1) {
      retocsl=retocsl.replace(pinteresting, '');
      acarr[iac]=acarr[iac].replace(pinteresting, '');
      } else {
      retocsl=retocsl.replace(acarr[iac], acarr[iac] + ',' + superinteresting.trim());
      }
      }
      }
      }
      }
      }
      if (retocsl != ocsl) { outplist=retocsl; }
      return retocsl;
      }

      … in the changed swipe_media.html Tabular Single Row Media Gallery web application you can try for yourself (or try some more of The Boss), further to yesterday’s YouTube API Caller Radio Play Playlist Songname Search List Address Bar Tutorial.


      Previous relevant YouTube API Caller Radio Play Playlist Songname Search List Address Bar Tutorial is shown below.

      YouTube API Caller Radio Play Playlist Songname Search List Address Bar Tutorial

      YouTube API Caller Radio Play Playlist Songname Search List Address Bar Tutorial

      Don’t know if you are like me, but especially when on this MacBook Air we’re, forever, using a web browser address bar to type in, what we’ve set up as, a Google search engine webpage query. Rather than even going to Google webpage first, that is!

      Most people don’t want to know about arcane web application argument arrangements … though we’re very fond of the 5 minute ones?!

      What’s wrong with some of you? Who would not relish the thought of …

      • adding onto the address bar …

        https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html

        … with new arguments( eg. https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html Born to Run,Jungleland ) …
      • ?ask=y # will get you straight to the Javascript playlist prompt window
      • &or?thelist=[commaSeparatedList_encodeURIComponent_ized] # will supply that prompt window with the answer [commaSeparatedList_decodeURIComponent_ized]
      • &or?andgo=y # will click the Radio button after all above (unless notgo is mentioned in the list somewhere), as relevant, with the programmatically determined derived YouTube ID list via YouTube search(es)
      • 💬🦆 Come On!
      • … when, after a bit of thought and tweaks to our RJM Programming domain’s Apache Document Root residing 404.shtml webpage Javascript …

        if (document.URL.indexOf('rjmprogramming.com.au/HTMLCSS/swipe_media.htm') != -1) {
        if (decodeURIComponent(document.URL).indexOf(',') != -1) {
        if (decodeURIComponent(document.URL.split('rjmprogramming.com.au/HTMLCSS/swipe_media.htm')[1].replace(/^l/g,'')).toLowerCase().indexOf('notgo') != -1) {
        location.href='//www.rjmprogramming.com.au/HTMLCSS/swipe_media.html?thelist=' + encodeURIComponent(decodeURIComponent(document.URL.split('rjmprogramming.com.au/HTMLCSS/swipe_media.htm')[1].replace(/^l/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace('notgo','').replace('NOTGO','').replace('Notgo','')));
        } else {
        location.href='//www.rjmprogramming.com.au/HTMLCSS/swipe_media.html?andgo=y&thelist=' + encodeURIComponent(decodeURIComponent(document.URL.split('rjmprogramming.com.au/HTMLCSS/swipe_media.htm')[1].replace(/^l/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'').replace(/^\%20/g,'')));
        exit;
        }
        } else if (decodeURIComponent(document.URL.split('rjmprogramming.com.au/HTMLCSS/swipe_media.htm')[1].replace(/^l/g,'')).toLowerCase().indexOf('ask') != -1) {
        location.href='//www.rjmprogramming.com.au/HTMLCSS/swipe_media.html?ask=y';
        exit;
        }
        }

        … now all you need to add after that link above, on the web browser address bar is …

        [commaSeparatedList_decodeURIComponent_ized]

        … ie. just type a comma separated YouTube song search basis link after the link wording above
      • so 💬🦆 Come On down ye doubting Thomases!

      And so, further to yesterday’s YouTube API Caller Radio Play Playlist Songname Search List Dropdown Tutorial we have a changed swipe_media.html Tabular Single Row Media Gallery web application you can try for yourself.

      Stop Press

      On reflection, as well as …

      https://www.rjmprogramming.com.au/HTMLCSS/swipe_media.html Born to Run,Jungleland working up at the address bar, so, too, will https://www.rjmprogramming.com.au/ Born to Run,Jungleland


      Previous relevant YouTube API Caller Radio Play Playlist Songname Search List Dropdown Tutorial is shown below.

      YouTube API Caller Radio Play Playlist Songname Search List Dropdown Tutorial

      YouTube API Caller Radio Play Playlist Songname Search List Dropdown Tutorial

      Around here, regarding web application work, we really like dropdown (ie. HTML select element) work because a lot of information can be …

      • stored
      • displayed (often taking up minimal webpage space)
      • it’s option subelements can have an event life of their own, or be part of the select element event whole picture
      • dropdown multiple selection mode (as with today’s work) can …
        1. still support your single choice scenario
        2. we’ve coded today’s dropdown to support, as applicable, ordered single click choices … versus …
        3. can allow for control key (sets of choices not necessarily adjacent) and shift key (blocks of choices)
        4. can respond (as with today’s dropdown) to preset selections established at creation via dropdown (ie. select) innerHTML option subelement selected attribute setting
      • dropdown events onmousedown and ontouchdown (as for today’s dropdown) and onclick can be harnessed ahead of an onchange event … and in today’s case can help unset any preset option subelement selected attribute setting(s)

      Just so flexible! Subelement option CSS styling can be less friendly, but even so, often background colouring is possible, and we do a bit of that with the work from yesterday’s YouTube API Caller Radio Play Playlist Songname Search List Tutorial and today’s better “shored up” work you can see a bit of below (where your starting point might be that we “wrap” this particular Javascript prompt window through the Javascript overprompt function below) …


      var outplist='', kaconto=null, kacontoarr=[], rconeis=155, gconeis=255, bconeis=255;

      function overprompt(blb, defvl) {
      var tdsare=[], itdone=false, itds=0, baeis='', ivb=0, lastpassesmustard=true;
      var oklast=['A','E','I','M','Q','U','Y','c','g','k','o','s','w','0','4','8'];
      outplist=prompt(blb, defvl);
      if (outplist) {
      //alert(1);
      var outparrs=outplist.trim().split(',');
      //alert(11);
      if (eval('' + outparrs.length) > 1) {
      if (eval('' + outparrs[0].length) > 0) {
      if (oklast.indexOf(outparrs[0].slice(-1)) == -1) { lastpassesmustard=false; }
      }
      if ((outparrs[0] + baeis).replace(/\ \ \ $/g,'') != (outparrs[0] + baeis)) {
      baeis='&domatters=&20%20%20';
      outparrs[0]=outparrs[0].replace(/\ \ \ $/g,'');
      } else if ((outparrs[0] + baeis).replace(/\ \ $/g,'') != (outparrs[0] + baeis)) {
      baeis='&domatters=&20%20';
      outparrs[0]=outparrs[0].replace(/\ \ $/g,'');
      } else if ((outparrs[0] + baeis).replace(/\ $/g,'') != (outparrs[0] + baeis)) {
      baeis='&domatters=&20';
      outparrs[0]=outparrs[0].replace(/\ $/g,'');
      } else {
      baeis='';
      }
      //alert(111);
      if (eval('' + outparrs[0].length) != 11 || !lastpassesmustard || encodeURIComponent(outparrs[0]) != outparrs[0]) {
      //alert(1111);
      tdsare=document.getElementsByTagName('td');
      for (itds=0; itds<tdsare.length; itds++) {
      //alert(tdsare[itds].innerHTML);
      if (!itdone && tdsare[itds].innerHTML == '' && ('' + tdsare[itds].id) != 'td0001') {
      itdone=true;
      //alert('here ' + outplist.trim().replace(/\,/g,'|!!|'));
      //tdsare[itds].innerHTML='<iframe onload=karlook(this); style="width:100%;height:100%;" id=karsearch name=karsearch src="/HTMLCSS/karaoke_youtube_api.htm?youtubeid=++++++++++++' + encodeURIComponent(outplist.trim().replace(/\,/g,'|!!|')) + '&minimize=y&youtube_duration=&email=&emoji=on&clickcheck=y"></iframe>';
      tdsare[itds].innerHTML='<iframe onload=karlook(this); style="width:100%;height:80%;" id=karsearch name=karsearch src="/HTMLCSS/karaoke_youtube_api.htm?youtubeid=++++++++++++' + encodeURIComponent(outparrs[0]) + baeis + '&minimize=y&youtube_duration=&email=&emoji=on&clickcheck=y"></iframe>';
      tdsare[itds].scrollIntoView();
      //alert('there ' + outplist.trim().replace(/\,/g,'|!!|'));
      baeis='';
      kacontoarr=[];
      for (ivb=1; ivb<outparrs.length; ivb++) {
      kacontoarr.push(null);
      }
      for (ivb=1; ivb<outparrs.length; ivb++) {
      tdsare[eval(itds + ivb)].innerHTML='<iframe onload=karlookagain(this,' + eval(-1 + ivb) + '); style="width:100%;height:80%;visibility:hidden;" id=karsearch' + ivb + ' src="/HTMLCSS/karaoke_youtube_api.htm?youtubeid=++++++++++++' + encodeURIComponent(outparrs[ivb]) + '&minimize=y&youtube_duration=&email=&emoji=on&clickcheck=y"></iframe>';
      }
      return '';
      }
      }
      }
      }
      }
      return outplist;
      }

      function karlook(iois) {
      var aconto=null;
      aconto = (iois.contentWindow || iois.contentDocument);
      if (aconto != null) {
      if (aconto.document) { aconto = aconto.document; }
      if (aconto.body != null) {
      if (outplist.indexOf(',') != -1) {
      kaconto=aconto;
      setTimeout(function(){ kaconto.getElementById('ajaxs').style.cursor='progress'; }, 3000);
      setTimeout(postkarlook, 7000);
      } else if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
      kaconto=aconto;
      setTimeout(mpostkarlook, 7000);
      }
      }
      }
      }

      function karlookagain(iois,idxn) {
      var aconto=null;
      aconto = (iois.contentWindow || iois.contentDocument);
      if (aconto != null) {
      if (aconto.document) { aconto = aconto.document; }
      if (aconto.body != null) {
      if (eval('' + kacontoarr.length) > eval('' + idxn)) {
      kacontoarr[eval('' + idxn)]=aconto;
      } else {
      kacontoarr.push(aconto);
      }
      }
      }
      }

      function mpostkarlook() {
      if (kaconto.getElementById('ajaxs')) {
      var kbuts=kaconto.getElementsByTagName('input');
      for (var lbuts=0; lbuts<kbuts.length; lbuts++) {
      if (('' + kbuts[lbuts].type) == 'button') {
      if (('' + kbuts[lbuts].value).indexOf('Radio') == 0) {
      kbuts[lbuts].value=kbuts[lbuts].value.replace('Radio', String.fromCharCode(10) + 'Radio');
      }
      }
      }
      } else {
      setTimeout(mpostkarlook, 5000);
      }
      }

      function postkarlook() {
      var selectedones='', oktogo=true, hihi=0;
      if (kaconto.getElementById('ajaxs')) {
      //alert(kaconto.getElementById('ajaxs').innerHTML);
      for (hihi=0; hihi<kacontoarr.length; hihi++) {
      if (!kacontoarr[hihi]) {
      oktogo=false;
      //alert('hihi=' + hihi + ' NOT okay');
      } else if (!kacontoarr[hihi].getElementById('ajaxs')) {
      oktogo=false;
      //alert('hihi=' + hihi + ' not okay');
      }
      }
      if (!oktogo) {
      setTimeout(postkarlook, 5000);
      } else if (kaconto.getElementById('ajaxs').innerHTML.indexOf('... and then ...') == -1) {
      kaconto.getElementById('ajaxs').style.cursor='pointer';
      var otherps=baeisf();
      if (otherps != '' || navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
      var kbuts=kaconto.getElementsByTagName('input');
      for (var lbuts=0; lbuts<kbuts.length; lbuts++) {
      if (('' + kbuts[lbuts].type) == 'button') {
      if (('' + kbuts[lbuts].value).indexOf('Radio') == 0) {
      var wasvl=kbuts[lbuts].value;
      if (otherps == ' ') {
      kbuts[lbuts].value=kbuts[lbuts].value.replace('Radio', 'Ordered ' + String.fromCharCode(10) + 'Audio ' + String.fromCharCode(10) + 'Radio');
      } else if (otherps == ' ') {
      kbuts[lbuts].value=kbuts[lbuts].value.replace('Radio', 'Audio ' + String.fromCharCode(10) + 'Radio');
      } else if (otherps == ' ') {
      kbuts[lbuts].value=kbuts[lbuts].value.replace('Radio', 'Ordered ' + String.fromCharCode(10) + 'Radio');
      } else {
      kbuts[lbuts].value=kbuts[lbuts].value.replace('Radio', String.fromCharCode(10) + 'Radio');
      }
      }
      }
      }
      }
      selectedones=(kaconto.getElementById('ajaxs').innerHTML.split(kaconto.getElementById('ajaxs').innerHTML.split('</option>')[0] + '</option>')[1].split('</option>')[0] + '</option>').replace('>', ' class=uptop selected>');
      for (hihi=0; hihi<kacontoarr.length; hihi++) {
      if (rconeis == gconeis && rconeis == bconeis) {
      bconeis-=7;
      if (bconeis < 0) { bconeis+=255; }
      } else if (rconeis == gconeis) {
      gconeis-=7;
      if (gconeis < 0) { gconeis+=255; }
      } else {
      rconeis-=7;
      if (rconeis < 0) { rconeis+=255; }
      }
      selectedones+=((kacontoarr[hihi].getElementById('ajaxs').innerHTML.split(kacontoarr[hihi].getElementById('ajaxs').innerHTML.split('</option>')[0] + '</option>')[1].split('</option>')[0] + '</option>').replace('>', ' class=uptop selected>')).replace(/option\ onclick\=/g, 'option style=background-color:rgb(' + rconeis + ',' + gconeis + ',' + bconeis + '); onclick=');
      kaconto.getElementById('ajaxs').innerHTML+='<option value="">... and then ...</option>';
      kaconto.getElementById('ajaxs').innerHTML+=kacontoarr[hihi].getElementById('ajaxs').innerHTML.split(kacontoarr[hihi].getElementById('ajaxs').innerHTML.split('</option>')[0] + '</option>')[1].replace(/option\ onclick\=/g, 'option style=background-color:rgb(' + rconeis + ',' + gconeis + ',' + bconeis + '); onclick=');
      //alert(kacontoarr[hihi].getElementById('ajaxs').innerHTML);
      }
      //alert(selectedones);
      kaconto.getElementById('ajaxs').innerHTML=kaconto.getElementById('ajaxs').innerHTML.replace(kaconto.getElementById('ajaxs').innerHTML.split('</option>')[0] + '</option>', kaconto.getElementById('ajaxs').innerHTML.split('</option>')[0] + '</option>' + selectedones + (selectedones != '' ? '<option id=optclk value="">____ Selection above available (resettable via click here) as you click/tap button at right ____</option>' : ''));
      if (selectedones != '') {
      kaconto.getElementById('ajaxs').onmousedown=function(event){ if (event.target.parentNode.outerHTML.split('>')[0].indexOf(' data-flagged=') == -1) { event.target.parentNode.setAttribute('data-flagged','y'); event.target.parentNode.innerHTML=event.target.parentNode.innerHTML.replace(/\ selected/g, ' ').replace('____ Selection above available (resettable via click here) as you click/tap button at right ____','____ Please select choices in usual multiple choice dropdown ways ____'); } };
      kaconto.getElementById('ajaxs').ontouchdown=function(event){ if (event.target.parentNode.outerHTML.split('>')[0].indexOf(' data-flagged=') == -1) { event.target.parentNode.setAttribute('data-flagged','y'); event.target.parentNode.innerHTML=event.target.parentNode.innerHTML.replace(/\ selected/g, ' ').replace('____ Selection above available (resettable via click here) as you click/tap button at right ____','____ Please select choices in usual multiple choice dropdown ways ____'); } };
      }
      }
      }
      }

      function baeisf() {
      var outarrp=outplist.split(',');
      if (eval('' + outarrp.length) > 1) {
      return outarrp[0].replace(outarrp[0].trim(), '');
      }
      return '';
      }

      And so, today …

      • we add onto the default random ordering mode of Radio Play via YouTube search comma separated list, the further choices ordered or audio or audio ordered, as per the relevant Javascript prompt blurb that is now going …

        Enter YouTube 11 character code video (comma separated) or audio stream only of video (semicolon) list to Radio Play (and add ! to start in shuffle mode and/or # for the order you enter and/or & for whole list) … or a YouTube Search String basis for playlist via a Radio📻? button to activate, later. Comma separateds can be search ideas … egs. Tragedy,Boogie Wonderland,Down Among the Dead Men … random … Tragedy ,Imagine,Breezin … ordered … Tragedy  ,Pina Colada Song,Fast Car … audio … Tragedy   ,Galveston,Angel of the Morning … audio ordered. Double click on this cell for playlist redefinitions.

      • started allowing for dropdown events onmousedown and ontouchdown be able to reset the preset choices we programmatically select for the user should they be happy (but our motivation for this event work was the potential to run into a YouTube video that gives the error …

        This video requires payment to watch YouTube

        )

      Codewise, this involved …

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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

Posted in eLearning, Hardware, iOS, Software, Trips, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Swift Playgrounds for iOS Map Control Tutorial

Swift Playgrounds for iOS Map Control Tutorial

Swift Playgrounds for iOS Map Control Tutorial

We change yesterday’s Swift Playgrounds on macOS Map Control Tutorial‘s titling from …


to macOS

… to …


for iOS

… today, because as we were working on macOS Xcode Map Playgrounds, we were offered two “change of direction” offerings, they being …

  1. installation of iOS Simulator … which we jumped at to do …
  2. File -> New -> Playground… -> macOSiOS tab -> Map

… which has no affect on yesterday’s work, which picks out the most recent relevant Swift code, whether macOS or iOS.

Then we wondered about Xcode Playground (device) Targets and it appears very difficult to Simulate to a device using Xcode Playgrounds, while using Xcode Projects, it can happen, and so, any Simulators set up can be used down the line, perhaps?! The same applies to Apple white lead connected iPhones or iPads connected to your macOS. Please, here, try your own research on this, because we did come across conflicting thoughts here.


Previous relevant Swift Playgrounds on macOS Map Control Tutorial is shown below.

Swift Playgrounds on macOS Map Control Tutorial

Swift Playgrounds on macOS Map Control Tutorial

Going along with yesterday’s …

… featuring two command line (PHP exec) call types separated by an HTML form place for users to tailor their own maps, as per …


  1. find "/" -name "Contents.swift" -type f -exec grep -l "CLLocationCoordinate2DMake(" {} + 2> /dev/null
  2. HTML form place for users to tailor their own maps regarding, so far, latitude and longitude and pin titles

  3. open -a Xcode [xcodePlaygroundOfInterest.playground]

… using our first draft (we’d want you to download to the Document Root of your macOS MAMP local Apache/PHP/MySql web server and calling it map_playground.php) Xcode New -> Playground… -> Map integrator.


Previous relevant Swift Playgrounds on macOS Map Revisit Tutorial is shown below.

Swift Playgrounds on macOS Map Revisit Tutorial

Swift Playgrounds on macOS Map Revisit Tutorial

With a newer version of macOS Xcode Version 26.6 (17F113), we’re revisiting the …


New -> Playground... -> Map

… concepts developed upon with Swift Playgrounds on macOS Map Emoji Tutorial.

This time around the motivation is different, and that “basis in source workflow” will be …

  • developed (or integrated) onto from without …
  • and developed from within, as well, and that available to be developed onto as well

But for today, we took that “basis in source workflow” playground above and tweaked it’s …

  1. latitude and longitude geographicals basis
  2. map distance
  3. map pin label

… to be able to show, hereabouts …

Luna’s Den


Previous relevant Swift Playgrounds on macOS Map GeoJson Tutorial is shown below.

Swift Playgrounds on macOS Map GeoJson Tutorial

Swift Playgrounds on macOS Map GeoJson Tutorial

Before we leave the …

  • Xcode on macOS …
  • File -> New -> Playground…
  • Map
  • Next
  • Create

… “where of life” Google Maps or Apple Maps ideas of yesterday’s Swift Playgrounds on macOS Map Tutorial we wanted to further take in the excellence of the advice of MapKit Tutorial: Getting Started | Kodeco, the new raywenderlich.com and delve into the …

  • involvement of public GeoJson PublicArt examples (ours being Geelong … so if you zoom out to southern Victoria and back in on the colourful colour coded new pins representing Geelong PublicArt locations) … in conjunction with …
  • MKGeoJSONDecoder (to decode GeoJSON data)

… is a great approach to Customising Annotations on your Swift Playground Map desktop application, via Xcode as you can see with our changed MyPlayground.swift Swift source code macOS Swift desktop application code …


//: A MapKit based Playground

import PlaygroundSupport
import MapKit

private var artworks: [Artwork] = []

class ArtworkMarkerView: MKMarkerAnnotationView {
override var annotation: MKAnnotation? {
willSet {
// 1
guard let artwork = newValue as? Artwork else {
return
}
canShowCallout = true
calloutOffset = CGPoint(x: -5, y: 5)
//rightCalloutAccessoryView = UIButton(type:
// .detailDisclosure)

// 2
markerTintColor = artwork.markerTintColor
if let letter = artwork.art_type?.first {
glyphText = String(letter)
}
}
}
}

class Artwork: NSObject, MKAnnotation {
let title: String?
let locationName: String?
let art_type: String?
let coordinate: CLLocationCoordinate2D


var markerTintColor: NSColor {
switch art_type {
case "Monument":
return .red
case "Mural":
return .cyan
case "Plaque":
return .blue
case "Fountain":
return .yellow
case "Sculpture":
return .purple
case "Art":
return .magenta
default:
return .green
}
}


init(
title: String?,
locationName: String?,
art_type: String?,
coordinate: CLLocationCoordinate2D
) {
self.title = title
self.locationName = locationName
self.art_type = art_type
self.coordinate = coordinate

super.init()
}

init?(feature: MKGeoJSONFeature) {
// 1
guard
let point = feature.geometry.first as? MKPointAnnotation,
let propertiesData = feature.properties,
let json = try? JSONSerialization.jsonObject(with: propertiesData),
let properties = json as? [String: Any]
else {
return nil
}

// 3
title = properties["name"] as? String
locationName = properties["descriptio"] as? String
art_type = properties["art_type"] as? String
coordinate = point.coordinate
super.init()
}


var subtitle: String? {
return locationName
}
}

private func loadInitialData() {
// 1
guard
let fileName = Bundle.main.url(forResource: "PublicArt", withExtension: "geojson"),
let artworkData = try? Data(contentsOf: fileName)
else {
return
}

do {
// 2
let features = try MKGeoJSONDecoder()
.decode(artworkData)
.compactMap { $0 as? MKGeoJSONFeature }
// 3
let validWorks = features.compactMap(Artwork.init)
// 4
artworks.append(contentsOf: validWorks)
} catch {
// 5
print("Unexpected error: \(error).")
}
}

let chatswoodCoordinates = CLLocationCoordinate2DMake(-33.8009948,151.1664372)

// Now let's create a MKMapView
let mapView = MKMapView(frame: CGRect(x:0, y:0, width:800, height:800))

// Define a region for our map view
var mapRegion = MKCoordinateRegion()

let mapRegionSpan = 0.001
mapRegion.center = chatswoodCoordinates
mapRegion.span.latitudeDelta = mapRegionSpan
mapRegion.span.longitudeDelta = mapRegionSpan

mapView.setRegion(mapRegion, animated: true)

// Create a map annotation
let annotation = MKPointAnnotation()
annotation.coordinate = chatswoodCoordinates
annotation.title = "Chatswood"
annotation.subtitle = "Greville"

mapView.addAnnotation(annotation)

// Show artwork on map
let artwork = Artwork(
title: "The Cheesetree",
locationName: "Santa Clause Lane",
art_type: "Nature, like",
coordinate: CLLocationCoordinate2D(latitude: -33.8010376, longitude: 151.1663819))

mapView.addAnnotation(artwork)

loadInitialData()
mapView.addAnnotations(artworks)

mapView.register(
ArtworkMarkerView.self,
forAnnotationViewWithReuseIdentifier:
MKMapViewDefaultAnnotationViewReuseIdentifier)

// Add the created mapView to our Playground Live View
PlaygroundPage.current.liveView = mapView

… that goes along with our adding into our Playground project’s Resources a file called PublicArt.geojson downloaded via this webpage, thanks everybody!


Previous relevant Swift Playgrounds on macOS Map Tutorial is shown below.

Swift Playgrounds on macOS Map Tutorial

Swift Playgrounds on macOS Map Tutorial

Are you looking for …

  • informal … but …
  • IDE based compiling …
  • Swift … code based …
  • macOS or iOS … suiting …

… programming environment? How about, if you are into the “where of” in life …

  • Xcode on macOS …
  • File -> New -> Playground…
  • Map
  • Next
  • Create

Now, by informal, we mean you don’t have to worry about Development or Deployment certificates, and all that jazz. You just get to “play around”, make mistakes, take advice, and learn (more, on top of tutorials like Swift Playgrounds on iPad Primer Tutorial) about Swift programming language, in the process!

We had fun producing a macOS Swift playground desktop application that featured one local “Artwork” class (default) pinning map item, thanks to the great advice from MapKit Tutorial: Getting Started | Kodeco, the new raywenderlich.com … thanks. We ended up with …


//: A MapKit based Playground

import MapKit
import PlaygroundSupport

class Artwork: NSObject, MKAnnotation {
let title: String?
let locationName: String?
let discipline: String?
let coordinate: CLLocationCoordinate2D

init(
title: String?,
locationName: String?,
discipline: String?,
coordinate: CLLocationCoordinate2D
) {
self.title = title
self.locationName = locationName
self.discipline = discipline
self.coordinate = coordinate

super.init()
}

var subtitle: String? {
return locationName
}
}

let chatswoodCoordinates = CLLocationCoordinate2DMake(-33.8009948,151.1664372)

// Now let's create a MKMapView
let mapView = MKMapView(frame: CGRect(x:0, y:0, width:800, height:800))

// Define a region for our map view
var mapRegion = MKCoordinateRegion()

let mapRegionSpan = 0.001
mapRegion.center = chatswoodCoordinates
mapRegion.span.latitudeDelta = mapRegionSpan
mapRegion.span.longitudeDelta = mapRegionSpan

mapView.setRegion(mapRegion, animated: true)

// Create a map annotation
let annotation = MKPointAnnotation()
annotation.coordinate = chatswoodCoordinates
annotation.title = "Chatswood"
annotation.subtitle = "Greville"

mapView.addAnnotation(annotation)

// Show artwork on map
let artwork = Artwork(
title: "The Cheesetree",
locationName: "Santa Clause Lane",
discipline: "Nature, like",
coordinate: CLLocationCoordinate2D(latitude: -33.8010376, longitude: 151.1663819))

mapView.addAnnotation(artwork)

// Add the created mapView to our Playground Live View
PlaygroundPage.current.liveView = mapView

… in MyPlayground.swift Swift source code macOS Swift desktop application code.


Previous relevant Swift Playgrounds on iPad Primer Tutorial is shown below.

Swift Playgrounds on iPad Primer Tutorial

Swift Playgrounds on iPad Primer Tutorial

Generally speaking around here, we tend to think you need at least a laptop (eg. MacBook Pro) or desktop computer PC (macOS or Windows) or Linux operating system arrangement, to (computer) program (in other words, the iOS operating system is a missing part of the equation here). That has led us to assume more than we know, though looking into this topic via our Google search of …


ide for ipad

… had us first looking into Python via “pythonista”, but the $14.99 price tag was far too much for us to absorb so early in the morning, and a warning that exclusive “above the fold” reading can have you suffer from (FOMO) “fear of missing out” syndrome. Reading, then, below the fold, soon turned up the Xcode IDE (we have on macOS, here, and appears “above the fold” regarding blurb actions above) programming language of choice, Swift, with its Apple iPad place …


Swift Playgrounds

… as a great resource into programming and “robotics feeling” coding leading to “programming action”! And the presentation may well suit young’uns getting into programming early, if that’s why you are reading this blog posting. As Swift Playgrounds starts out intimating, to “follow a recipe” and perform “steps in order” is likely to lead to the happiest programming and coding experience (to put it mildly … or … just follow orders … initially … to put it more bluntly).

Curiosity is the big key here. Start this way, and invariably if it interests, it interests, and could lead to many other avenues of knowledge, and it involving the Swift computer language, that could be a lead in to iOS mobile app development via Xcode and (paying, or not) careers in Information Technology?!

Or perhaps you are on an iPad and wish to fork out the $14.99 and get into Python, then that would be interesting too, we have no doubt. Either way, see how we R&D‘ed this topic, on an iPad, with today’s PDF presentation (dare we say) following orders.

We’ve also heard, but have not researched this, that Apple is making changes with iPad products into the future, to improve their programming capacities. Stay tuned, with Apple, on that.

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

Swift Playgrounds on macOS Map Control Tutorial

Swift Playgrounds on macOS Map Control Tutorial

Swift Playgrounds on macOS Map Control Tutorial

Going along with yesterday’s …

… featuring two command line (PHP exec) call types separated by an HTML form place for users to tailor their own maps, as per …


  1. find "/" -name "Contents.swift" -type f -exec grep -l "CLLocationCoordinate2DMake(" {} + 2> /dev/null
  2. HTML form place for users to tailor their own maps regarding, so far, latitude and longitude and pin titles

  3. open -a Xcode [xcodePlaygroundOfInterest.playground]

… using our first draft (we’d want you to download to the Document Root of your macOS MAMP local Apache/PHP/MySql web server and calling it map_playground.php) Xcode New -> Playground… -> Map integrator.


Previous relevant Swift Playgrounds on macOS Map Revisit Tutorial is shown below.

Swift Playgrounds on macOS Map Revisit Tutorial

Swift Playgrounds on macOS Map Revisit Tutorial

With a newer version of macOS Xcode Version 26.6 (17F113), we’re revisiting the …


New -> Playground... -> Map

… concepts developed upon with Swift Playgrounds on macOS Map Emoji Tutorial.

This time around the motivation is different, and that “basis in source workflow” will be …

  • developed (or integrated) onto from without …
  • and developed from within, as well, and that available to be developed onto as well

But for today, we took that “basis in source workflow” playground above and tweaked it’s …

  1. latitude and longitude geographicals basis
  2. map distance
  3. map pin label

… to be able to show, hereabouts …

Luna’s Den


Previous relevant Swift Playgrounds on macOS Map GeoJson Tutorial is shown below.

Swift Playgrounds on macOS Map GeoJson Tutorial

Swift Playgrounds on macOS Map GeoJson Tutorial

Before we leave the …

  • Xcode on macOS …
  • File -> New -> Playground…
  • Map
  • Next
  • Create

… “where of life” Google Maps or Apple Maps ideas of yesterday’s Swift Playgrounds on macOS Map Tutorial we wanted to further take in the excellence of the advice of MapKit Tutorial: Getting Started | Kodeco, the new raywenderlich.com and delve into the …

  • involvement of public GeoJson PublicArt examples (ours being Geelong … so if you zoom out to southern Victoria and back in on the colourful colour coded new pins representing Geelong PublicArt locations) … in conjunction with …
  • MKGeoJSONDecoder (to decode GeoJSON data)

… is a great approach to Customising Annotations on your Swift Playground Map desktop application, via Xcode as you can see with our changed MyPlayground.swift Swift source code macOS Swift desktop application code …


//: A MapKit based Playground

import PlaygroundSupport
import MapKit

private var artworks: [Artwork] = []

class ArtworkMarkerView: MKMarkerAnnotationView {
override var annotation: MKAnnotation? {
willSet {
// 1
guard let artwork = newValue as? Artwork else {
return
}
canShowCallout = true
calloutOffset = CGPoint(x: -5, y: 5)
//rightCalloutAccessoryView = UIButton(type:
// .detailDisclosure)

// 2
markerTintColor = artwork.markerTintColor
if let letter = artwork.art_type?.first {
glyphText = String(letter)
}
}
}
}

class Artwork: NSObject, MKAnnotation {
let title: String?
let locationName: String?
let art_type: String?
let coordinate: CLLocationCoordinate2D


var markerTintColor: NSColor {
switch art_type {
case "Monument":
return .red
case "Mural":
return .cyan
case "Plaque":
return .blue
case "Fountain":
return .yellow
case "Sculpture":
return .purple
case "Art":
return .magenta
default:
return .green
}
}


init(
title: String?,
locationName: String?,
art_type: String?,
coordinate: CLLocationCoordinate2D
) {
self.title = title
self.locationName = locationName
self.art_type = art_type
self.coordinate = coordinate

super.init()
}

init?(feature: MKGeoJSONFeature) {
// 1
guard
let point = feature.geometry.first as? MKPointAnnotation,
let propertiesData = feature.properties,
let json = try? JSONSerialization.jsonObject(with: propertiesData),
let properties = json as? [String: Any]
else {
return nil
}

// 3
title = properties["name"] as? String
locationName = properties["descriptio"] as? String
art_type = properties["art_type"] as? String
coordinate = point.coordinate
super.init()
}


var subtitle: String? {
return locationName
}
}

private func loadInitialData() {
// 1
guard
let fileName = Bundle.main.url(forResource: "PublicArt", withExtension: "geojson"),
let artworkData = try? Data(contentsOf: fileName)
else {
return
}

do {
// 2
let features = try MKGeoJSONDecoder()
.decode(artworkData)
.compactMap { $0 as? MKGeoJSONFeature }
// 3
let validWorks = features.compactMap(Artwork.init)
// 4
artworks.append(contentsOf: validWorks)
} catch {
// 5
print("Unexpected error: \(error).")
}
}

let chatswoodCoordinates = CLLocationCoordinate2DMake(-33.8009948,151.1664372)

// Now let's create a MKMapView
let mapView = MKMapView(frame: CGRect(x:0, y:0, width:800, height:800))

// Define a region for our map view
var mapRegion = MKCoordinateRegion()

let mapRegionSpan = 0.001
mapRegion.center = chatswoodCoordinates
mapRegion.span.latitudeDelta = mapRegionSpan
mapRegion.span.longitudeDelta = mapRegionSpan

mapView.setRegion(mapRegion, animated: true)

// Create a map annotation
let annotation = MKPointAnnotation()
annotation.coordinate = chatswoodCoordinates
annotation.title = "Chatswood"
annotation.subtitle = "Greville"

mapView.addAnnotation(annotation)

// Show artwork on map
let artwork = Artwork(
title: "The Cheesetree",
locationName: "Santa Clause Lane",
art_type: "Nature, like",
coordinate: CLLocationCoordinate2D(latitude: -33.8010376, longitude: 151.1663819))

mapView.addAnnotation(artwork)

loadInitialData()
mapView.addAnnotations(artworks)

mapView.register(
ArtworkMarkerView.self,
forAnnotationViewWithReuseIdentifier:
MKMapViewDefaultAnnotationViewReuseIdentifier)

// Add the created mapView to our Playground Live View
PlaygroundPage.current.liveView = mapView

… that goes along with our adding into our Playground project’s Resources a file called PublicArt.geojson downloaded via this webpage, thanks everybody!


Previous relevant Swift Playgrounds on macOS Map Tutorial is shown below.

Swift Playgrounds on macOS Map Tutorial

Swift Playgrounds on macOS Map Tutorial

Are you looking for …

  • informal … but …
  • IDE based compiling …
  • Swift … code based …
  • macOS or iOS … suiting …

… programming environment? How about, if you are into the “where of” in life …

  • Xcode on macOS …
  • File -> New -> Playground…
  • Map
  • Next
  • Create

Now, by informal, we mean you don’t have to worry about Development or Deployment certificates, and all that jazz. You just get to “play around”, make mistakes, take advice, and learn (more, on top of tutorials like Swift Playgrounds on iPad Primer Tutorial) about Swift programming language, in the process!

We had fun producing a macOS Swift playground desktop application that featured one local “Artwork” class (default) pinning map item, thanks to the great advice from MapKit Tutorial: Getting Started | Kodeco, the new raywenderlich.com … thanks. We ended up with …


//: A MapKit based Playground

import MapKit
import PlaygroundSupport

class Artwork: NSObject, MKAnnotation {
let title: String?
let locationName: String?
let discipline: String?
let coordinate: CLLocationCoordinate2D

init(
title: String?,
locationName: String?,
discipline: String?,
coordinate: CLLocationCoordinate2D
) {
self.title = title
self.locationName = locationName
self.discipline = discipline
self.coordinate = coordinate

super.init()
}

var subtitle: String? {
return locationName
}
}

let chatswoodCoordinates = CLLocationCoordinate2DMake(-33.8009948,151.1664372)

// Now let's create a MKMapView
let mapView = MKMapView(frame: CGRect(x:0, y:0, width:800, height:800))

// Define a region for our map view
var mapRegion = MKCoordinateRegion()

let mapRegionSpan = 0.001
mapRegion.center = chatswoodCoordinates
mapRegion.span.latitudeDelta = mapRegionSpan
mapRegion.span.longitudeDelta = mapRegionSpan

mapView.setRegion(mapRegion, animated: true)

// Create a map annotation
let annotation = MKPointAnnotation()
annotation.coordinate = chatswoodCoordinates
annotation.title = "Chatswood"
annotation.subtitle = "Greville"

mapView.addAnnotation(annotation)

// Show artwork on map
let artwork = Artwork(
title: "The Cheesetree",
locationName: "Santa Clause Lane",
discipline: "Nature, like",
coordinate: CLLocationCoordinate2D(latitude: -33.8010376, longitude: 151.1663819))

mapView.addAnnotation(artwork)

// Add the created mapView to our Playground Live View
PlaygroundPage.current.liveView = mapView

… in MyPlayground.swift Swift source code macOS Swift desktop application code.


Previous relevant Swift Playgrounds on iPad Primer Tutorial is shown below.

Swift Playgrounds on iPad Primer Tutorial

Swift Playgrounds on iPad Primer Tutorial

Generally speaking around here, we tend to think you need at least a laptop (eg. MacBook Pro) or desktop computer PC (macOS or Windows) or Linux operating system arrangement, to (computer) program (in other words, the iOS operating system is a missing part of the equation here). That has led us to assume more than we know, though looking into this topic via our Google search of …


ide for ipad

… had us first looking into Python via “pythonista”, but the $14.99 price tag was far too much for us to absorb so early in the morning, and a warning that exclusive “above the fold” reading can have you suffer from (FOMO) “fear of missing out” syndrome. Reading, then, below the fold, soon turned up the Xcode IDE (we have on macOS, here, and appears “above the fold” regarding blurb actions above) programming language of choice, Swift, with its Apple iPad place …


Swift Playgrounds

… as a great resource into programming and “robotics feeling” coding leading to “programming action”! And the presentation may well suit young’uns getting into programming early, if that’s why you are reading this blog posting. As Swift Playgrounds starts out intimating, to “follow a recipe” and perform “steps in order” is likely to lead to the happiest programming and coding experience (to put it mildly … or … just follow orders … initially … to put it more bluntly).

Curiosity is the big key here. Start this way, and invariably if it interests, it interests, and could lead to many other avenues of knowledge, and it involving the Swift computer language, that could be a lead in to iOS mobile app development via Xcode and (paying, or not) careers in Information Technology?!

Or perhaps you are on an iPad and wish to fork out the $14.99 and get into Python, then that would be interesting too, we have no doubt. Either way, see how we R&D‘ed this topic, on an iPad, with today’s PDF presentation (dare we say) following orders.

We’ve also heard, but have not researched this, that Apple is making changes with iPad products into the future, to improve their programming capacities. Stay tuned, with Apple, on that.

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

Swift Playgrounds on macOS Map Revisit Tutorial

Swift Playgrounds on macOS Map Revisit Tutorial

Swift Playgrounds on macOS Map Revisit Tutorial

With a newer version of macOS Xcode Version 26.6 (17F113), we’re revisiting the …


New -> Playground... -> Map

… concepts developed upon with Swift Playgrounds on macOS Map Emoji Tutorial.

This time around the motivation is different, and that “basis in source workflow” will be …

  • developed (or integrated) onto from without …
  • and developed from within, as well, and that available to be developed onto as well

But for today, we took that “basis in source workflow” playground above and tweaked it’s …

  1. latitude and longitude geographicals basis
  2. map distance
  3. map pin label

… to be able to show, hereabouts …

Luna’s Den


Previous relevant Swift Playgrounds on macOS Map GeoJson Tutorial is shown below.

Swift Playgrounds on macOS Map GeoJson Tutorial

Swift Playgrounds on macOS Map GeoJson Tutorial

Before we leave the …

  • Xcode on macOS …
  • File -> New -> Playground…
  • Map
  • Next
  • Create

… “where of life” Google Maps or Apple Maps ideas of yesterday’s Swift Playgrounds on macOS Map Tutorial we wanted to further take in the excellence of the advice of MapKit Tutorial: Getting Started | Kodeco, the new raywenderlich.com and delve into the …

  • involvement of public GeoJson PublicArt examples (ours being Geelong … so if you zoom out to southern Victoria and back in on the colourful colour coded new pins representing Geelong PublicArt locations) … in conjunction with …
  • MKGeoJSONDecoder (to decode GeoJSON data)

… is a great approach to Customising Annotations on your Swift Playground Map desktop application, via Xcode as you can see with our changed MyPlayground.swift Swift source code macOS Swift desktop application code …


//: A MapKit based Playground

import PlaygroundSupport
import MapKit

private var artworks: [Artwork] = []

class ArtworkMarkerView: MKMarkerAnnotationView {
override var annotation: MKAnnotation? {
willSet {
// 1
guard let artwork = newValue as? Artwork else {
return
}
canShowCallout = true
calloutOffset = CGPoint(x: -5, y: 5)
//rightCalloutAccessoryView = UIButton(type:
// .detailDisclosure)

// 2
markerTintColor = artwork.markerTintColor
if let letter = artwork.art_type?.first {
glyphText = String(letter)
}
}
}
}

class Artwork: NSObject, MKAnnotation {
let title: String?
let locationName: String?
let art_type: String?
let coordinate: CLLocationCoordinate2D


var markerTintColor: NSColor {
switch art_type {
case "Monument":
return .red
case "Mural":
return .cyan
case "Plaque":
return .blue
case "Fountain":
return .yellow
case "Sculpture":
return .purple
case "Art":
return .magenta
default:
return .green
}
}


init(
title: String?,
locationName: String?,
art_type: String?,
coordinate: CLLocationCoordinate2D
) {
self.title = title
self.locationName = locationName
self.art_type = art_type
self.coordinate = coordinate

super.init()
}

init?(feature: MKGeoJSONFeature) {
// 1
guard
let point = feature.geometry.first as? MKPointAnnotation,
let propertiesData = feature.properties,
let json = try? JSONSerialization.jsonObject(with: propertiesData),
let properties = json as? [String: Any]
else {
return nil
}

// 3
title = properties["name"] as? String
locationName = properties["descriptio"] as? String
art_type = properties["art_type"] as? String
coordinate = point.coordinate
super.init()
}


var subtitle: String? {
return locationName
}
}

private func loadInitialData() {
// 1
guard
let fileName = Bundle.main.url(forResource: "PublicArt", withExtension: "geojson"),
let artworkData = try? Data(contentsOf: fileName)
else {
return
}

do {
// 2
let features = try MKGeoJSONDecoder()
.decode(artworkData)
.compactMap { $0 as? MKGeoJSONFeature }
// 3
let validWorks = features.compactMap(Artwork.init)
// 4
artworks.append(contentsOf: validWorks)
} catch {
// 5
print("Unexpected error: \(error).")
}
}

let chatswoodCoordinates = CLLocationCoordinate2DMake(-33.8009948,151.1664372)

// Now let's create a MKMapView
let mapView = MKMapView(frame: CGRect(x:0, y:0, width:800, height:800))

// Define a region for our map view
var mapRegion = MKCoordinateRegion()

let mapRegionSpan = 0.001
mapRegion.center = chatswoodCoordinates
mapRegion.span.latitudeDelta = mapRegionSpan
mapRegion.span.longitudeDelta = mapRegionSpan

mapView.setRegion(mapRegion, animated: true)

// Create a map annotation
let annotation = MKPointAnnotation()
annotation.coordinate = chatswoodCoordinates
annotation.title = "Chatswood"
annotation.subtitle = "Greville"

mapView.addAnnotation(annotation)

// Show artwork on map
let artwork = Artwork(
title: "The Cheesetree",
locationName: "Santa Clause Lane",
art_type: "Nature, like",
coordinate: CLLocationCoordinate2D(latitude: -33.8010376, longitude: 151.1663819))

mapView.addAnnotation(artwork)

loadInitialData()
mapView.addAnnotations(artworks)

mapView.register(
ArtworkMarkerView.self,
forAnnotationViewWithReuseIdentifier:
MKMapViewDefaultAnnotationViewReuseIdentifier)

// Add the created mapView to our Playground Live View
PlaygroundPage.current.liveView = mapView

… that goes along with our adding into our Playground project’s Resources a file called PublicArt.geojson downloaded via this webpage, thanks everybody!


Previous relevant Swift Playgrounds on macOS Map Tutorial is shown below.

Swift Playgrounds on macOS Map Tutorial

Swift Playgrounds on macOS Map Tutorial

Are you looking for …

  • informal … but …
  • IDE based compiling …
  • Swift … code based …
  • macOS or iOS … suiting …

… programming environment? How about, if you are into the “where of” in life …

  • Xcode on macOS …
  • File -> New -> Playground…
  • Map
  • Next
  • Create

Now, by informal, we mean you don’t have to worry about Development or Deployment certificates, and all that jazz. You just get to “play around”, make mistakes, take advice, and learn (more, on top of tutorials like Swift Playgrounds on iPad Primer Tutorial) about Swift programming language, in the process!

We had fun producing a macOS Swift playground desktop application that featured one local “Artwork” class (default) pinning map item, thanks to the great advice from MapKit Tutorial: Getting Started | Kodeco, the new raywenderlich.com … thanks. We ended up with …


//: A MapKit based Playground

import MapKit
import PlaygroundSupport

class Artwork: NSObject, MKAnnotation {
let title: String?
let locationName: String?
let discipline: String?
let coordinate: CLLocationCoordinate2D

init(
title: String?,
locationName: String?,
discipline: String?,
coordinate: CLLocationCoordinate2D
) {
self.title = title
self.locationName = locationName
self.discipline = discipline
self.coordinate = coordinate

super.init()
}

var subtitle: String? {
return locationName
}
}

let chatswoodCoordinates = CLLocationCoordinate2DMake(-33.8009948,151.1664372)

// Now let's create a MKMapView
let mapView = MKMapView(frame: CGRect(x:0, y:0, width:800, height:800))

// Define a region for our map view
var mapRegion = MKCoordinateRegion()

let mapRegionSpan = 0.001
mapRegion.center = chatswoodCoordinates
mapRegion.span.latitudeDelta = mapRegionSpan
mapRegion.span.longitudeDelta = mapRegionSpan

mapView.setRegion(mapRegion, animated: true)

// Create a map annotation
let annotation = MKPointAnnotation()
annotation.coordinate = chatswoodCoordinates
annotation.title = "Chatswood"
annotation.subtitle = "Greville"

mapView.addAnnotation(annotation)

// Show artwork on map
let artwork = Artwork(
title: "The Cheesetree",
locationName: "Santa Clause Lane",
discipline: "Nature, like",
coordinate: CLLocationCoordinate2D(latitude: -33.8010376, longitude: 151.1663819))

mapView.addAnnotation(artwork)

// Add the created mapView to our Playground Live View
PlaygroundPage.current.liveView = mapView

… in MyPlayground.swift Swift source code macOS Swift desktop application code.


Previous relevant Swift Playgrounds on iPad Primer Tutorial is shown below.

Swift Playgrounds on iPad Primer Tutorial

Swift Playgrounds on iPad Primer Tutorial

Generally speaking around here, we tend to think you need at least a laptop (eg. MacBook Pro) or desktop computer PC (macOS or Windows) or Linux operating system arrangement, to (computer) program (in other words, the iOS operating system is a missing part of the equation here). That has led us to assume more than we know, though looking into this topic via our Google search of …


ide for ipad

… had us first looking into Python via “pythonista”, but the $14.99 price tag was far too much for us to absorb so early in the morning, and a warning that exclusive “above the fold” reading can have you suffer from (FOMO) “fear of missing out” syndrome. Reading, then, below the fold, soon turned up the Xcode IDE (we have on macOS, here, and appears “above the fold” regarding blurb actions above) programming language of choice, Swift, with its Apple iPad place …


Swift Playgrounds

… as a great resource into programming and “robotics feeling” coding leading to “programming action”! And the presentation may well suit young’uns getting into programming early, if that’s why you are reading this blog posting. As Swift Playgrounds starts out intimating, to “follow a recipe” and perform “steps in order” is likely to lead to the happiest programming and coding experience (to put it mildly … or … just follow orders … initially … to put it more bluntly).

Curiosity is the big key here. Start this way, and invariably if it interests, it interests, and could lead to many other avenues of knowledge, and it involving the Swift computer language, that could be a lead in to iOS mobile app development via Xcode and (paying, or not) careers in Information Technology?!

Or perhaps you are on an iPad and wish to fork out the $14.99 and get into Python, then that would be interesting too, we have no doubt. Either way, see how we R&D‘ed this topic, on an iPad, with today’s PDF presentation (dare we say) following orders.

We’ve also heard, but have not researched this, that Apple is making changes with iPad products into the future, to improve their programming capacities. Stay tuned, with Apple, on that.

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

Tcl/Tk macOS and Xcode Revisit Tutorial

Tcl/Tk macOS and Xcode Revisit Tutorial

Tcl/Tk macOS and Xcode Revisit Tutorial

Rather than trying to get the GUI side of Tcl, called Tk, working on our AlmaLinux public web server, we settled for a Tcl only web application there when we presented Tcl and Javascript and PHP Calculator AlmaLinux Tutorial.

But here, on our local macOS, only using Mac Silicon chips, and this is important these days here in October 2026 with macOS Tahoe 26.6.1 Apple M1 chip, revisiting Tcl/Tk thoughts as we did yesterday, we wanted to reach at the end of our first day’s foray, as kilometermilestones …

  1. be able to go …

    clang --version

    … on command line (ie. in Terminal) as a C compiler … and associated with that are that Xcode projects with make become viable … as, then, after more installing, could …
  2. be able to go …

    tclsh

    … on command line with your ideal version of Tcl
  3. be able to go …

    wish

    … on command line with your ideal version of Tk (ie. GUI affect your local “DISPLAY defined” macOS is capable of) … another Tk test being …

    info patchlevel # coming back 8.6.14 for us ... but read on
    package require Tk # coming back 8.6.14 for us ... but read on
  4. be able to go …

    python3 -c "import tkinter; tkinter._test()"

    … on command line via going to Python website and installing via this installing link (ie. not using Homebrew and not using pip just installing off Python links)

For us, here, with our macOS Mac Silicon chip scenario, after online research, we settled for version …


8.6.14

… ie. tcl8.6.14 and tk8.6.14 to be the ones of interest (ie. our ideal version is 8.6.14), and to avoid Homebrew as your installer. Wish may work with open -a Wish ahead of any installs, out of the box, but if it is not using your ideal version, that is not going to cut it to go onto your own future development work. Perhaps, here, we should say, in all likelihood, along your install path to that first day’s mission statement achievement …

You’ll run into command line errors (and Xcode IDE errors, as applicable).

But what we’d say to that, as a general good idea, is to pick out whole relevant (don’t start with /) error message individual lines (from command line work and/or from Xcode Version 26.6 (17F113) IDE work) and feed all that relevant error line into a Google search box, accessing the advice of the great Open Source online community, thanks, to see what advice you get, and below, we’ve collected some of the ones we got to …

… on our quest highlighted by, getting right, commands …


  1. xcode-select --install

  2. sudo xcodebuild -runFirstLaunch

  3. cd ~/Downloads # having downloaded tcl8.66.14 and tk8.6.14 from SourceForge webpages
    # extracted in their ~/Downloads place both tcl8.6.14-src.tar.gz and tk8.6.14-src.tar.gz creating tcl8.6.14 and tk8.6.14 subfolders
    # mv tcl8.6.14 tcl
    # mv tk8.6.14 tk
    # extracted in their ~/Downloads place both tcl8.6.14-src.tar.gz and tk8.6.14-src.tar.gz again, creating tcl8.6.14 and tk8.6.14 subfolders to end up with four subfolders to work with
    make -C tcl8.6.14/macosx
    sudo make -C tcl8.6.14/macosx install
    make -C tk8.6.14/macosx
    sudo make -C tk8.6.14/macosx install

… and maybe there’ll be file permission issues and there may be reasons to create macosx subfolders off macosx subfolders that may happen involving Xcode IDE but we ended up with more joy back at Terminal command line work just using make, it seemed to us.

So, our own tailored Tcl/Tk development work? That awaits!


Previous relevant Tcl and Javascript and PHP Calculator AlmaLinux Tutorial is shown below.

Tcl and Javascript and PHP Calculator AlmaLinux Tutorial

Tcl and Javascript and PHP Calculator AlmaLinux Tutorial

We want to research the wonderful …

  • tcl … programming language often accessed via the “tclsh” shell … and accompanying …
  • tk … via “wish” and/or tkinter GUI side

… on the AlmaLinux environment of the Apache/PHP/MySql web server we’re using here to host the RJM Programming domain.

We’re just touching on tcl ideas today, revisiting Tcl and Javascript and PHP Calculator Tutorial‘s calculator web application. We had in there some code scouring any local web server systems you may have, and getting the localhost:8888 port arrangements wrong for our local MAMP Apache/PHP/MySql web server, and this was causing unnecessary issues, especially because “tclsh” works, for us, up at AlmaLinux. How can we tell? We took on the excellent advice of Installing Tcl/Tk, and tried …


tclsh

… on the command line (and “exit” gets you out of it) with success. Yayyyyy!!! That’s tcl installed already, else we’d have gone dnf install tcl

That’s enough installing for today’s purposes, as we do not call on the tk GUI side of things for our calculator. But, to check on the install part to this, try …


wish

… on the command line, and check that there is a wishful response whether that be erroneous (as we were, so far, with AlmaLinux command line) or not, else we’d have gone dnf install tk

All that sorted, and we’re “good to go” with the changed calculator.php Calculator web application calling on our unchanged calculator.tcl TCL source code, as below …

Another woooorrrrlllldddd, perhaps?!


Previous relevant Tcl and Javascript and PHP Calculator Tutorial is shown below.

Tcl and Javascript and PHP Calculator Tutorial

Tcl and Javascript and PHP Calculator Tutorial

It’s a “blown mind” that has led me to involve Javascript to make the incarnation of our calculator of Tcl and PHP Calculator Tutorial allow for some round bracket functionality around the TCL (expr) “kernel” (sorry, Unix … my apologies LinusLinux). The nexus between what a user may enter, versus the hierarchy needs of TCL’s expr command just blew my mind, manperson!

So what did we turn to? Modernizing one’s thinking? We’re onto it? But we digress. Well, well.

We turned to Javascript’s eval function, not PHP’s eval, nor TCL’s eval version, thanks, but no thanks. Nevertheless … and didn’t you just know that “but” would be insulted by the paragraph above?! … use of Javascript eval (for round bracketing scenarios or operator hierarchy scenarios) is not the “cakewalk” that you may imagine. That is because …


6 ** 2 // in TCL "to the power of" operator syntax (which remains our web application display choice for the user) has ...
Math.pow(6, 2) // Javascript equivalent (behind the scenes)

… so we need to cater for that possibility. The Javascript logic is called at the document.body onload event.

As we often do here, the “progression” of logic was to convert some “hardcoded” HTML text (specifically “First Number:” and “:Second Number”) into HTML select (dropdown) elements to the left and to the right (respectively) of the “TCL kernel”, with additional options for the round bracketing the user may want. These dropdowns move out to the edges of the webpage as they make room for user entered additions to the calculation complexity of what they want to calculate. The “Math.pow()” logic needed benefits from the event timing thoughts on the dropdown’s onchange event logic, otherwise you’d be doing that dreaded of all dreadeds, in many programmers’ worlds methinks, tracking back through entered “calculator equation” texts to discover when a numerical value becomes an operator, a horrible job when a minus sign can be either, for example. These same “horrible” programming tasks would have been at the fore to making a “TCL only backend solution” come to pass, we are sure, too.

Can you see from all this how well (clientside) Javascript works with (serverside) PHP? They are a very potent duo, because it is like two bites at the cherry, every time, with their different timings of the application of their logics.

The downloadable PHP source code calculator.php changed this way to achieve this extension of functionality still supervising an unchanged calculator.tcl TCL source code script, and here is a live run link for you to try this calculator for yourself.


Previous relevant Tcl and PHP Calculator Tutorial is shown below.

Tcl and PHP Calculator Tutorial

Tcl and PHP Calculator Tutorial

The Tcl and PHP Primer Tutorial was a foretaste to today’s calculator web application that …

  • uses PHP as a frontend and (HTML) form navigation destination …
  • connects to backend via PHP exec …
  • uses TCL as backend … via …

    exec("tclsh calculator.tcl < calculator.txt | tail -1 > calculator.out");

Crucial to the TCL’s backend role is TCL’s expr command, as a determinant regarding what today’s calculator is capable of.

Here is a link to some downloadable PHP source code calculator.php supervising calculator.tcl TCL source code, and here is a live run link.


Previous relevant Tcl and PHP Primer Tutorial … http://www.tcl.tk/software/tcltk/ is shown below.

Tcl and PHP Primer Tutorial ... http://www.tcl.tk/software/tcltk/

Tcl and PHP Primer Tutorial ... http://www.tcl.tk/software/tcltk/

Have you heard of Tcl/Tk? Think maybe you could introduce yourself to it with Tcl/Tk So Brilliant (but where do you start?) Primer Tutorial as shown below.

The Tcl in Tcl/Tk refers to the scripting side of things, while the Tk is a GUI framework. On some (maybe lots) of Linux or unix web servers, such as the one for this domain here at www.rjmprogramming.com.au Tcl scripting is available and that means Tcl could be used by PHP, as a server side language to use the exec method to ask something of Tcl and get something back, half of which is the arrangement we’d like to have when feeding our babies.

Today we write a webpage for finding the Country of Origin of a designated URL where PHP supervises Tcl:

  1. ask for a URL in PHP,
  2. send that to the same PHP with a different call …
  3. and use PHP exec method to send a Tcl commend line command to Tclsh and output this to a file known by the PHP,
  4. get the PHP to read the file of step 3. and send that information in a modified call of this same PHP,
  5. write out the Tcl based findings to the webpage in PHP,
  6. ask for a URL in PHP

Here is a link to some downloadable PHP source code domain.php supervising domain.tcl TCL source code, and here is a live run link.

Thanks to:


Previous relevant Tcl/Tk So Brilliant (but where do you start?) Primer Tutorial is shown below.

Tcl/Tk So Brilliant (but where do you start?) Primer Tutorial ... http://www.tcl.tk/software/tcltk/Tcl/Tk So Brilliant (but where do you start?) Primer Tutorial ... http://www.tcl.tk/software/tcltk/

Tcl/Tk So Brilliant (but where do you start?) Primer Tutorial ... http://www.tcl.tk/software/tcltk/

Have you heard of Tcl/Tk?

Tcl/Tk is open source (based on a BSD-style license), so you can use it and modify it virtually any way you want, including for commercial uses.

With Tcl/Tk have used in conjunction with C++ and Python (look out for Tkinter).

Use it for Games Programming (it makes pretty cute GUIs … you may disagree?!) and it used to work back at Mac OS X 10.5.8/XCode 3.0 (am going to try Mac OS X 10.7.5 … any advice anywhere?) and had it going on Windows XP with Visual Studio Express as well. It has a lot of cross-platform strengths.

Think Tcl/Tk is really really good.

In this primer tutorial you can see a Draw Poker game as an XCode project, see it Build and in action, then see how to arrange for *.dmg Package Distribution via Package Manager.

Link to Tcl/Tk website … Home of Tcl/Tk … where quote up the top resides
Link to Tcl/Tk jobs done … Tcl/Tk jobs done … personal experience

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

WordPress Mobile Ontouchmove Event Tutorial

WordPress Mobile Ontouchmove Event Tutorial

WordPress Mobile Ontouchmove Event Tutorial

For a while now we’ve been trying out, on rarefied occasions, for mobile device usage, an …


ontouchmove="alert(this.title);"

… pared down idea, in an …

  1. “easy does it, not wanting to cruel any real coded for ontouchmove event logic way” in the sense that we want to see it not adversely affecting other functionalities (and, of course, this is like a one by one scenario proposition) … because …
  2. if not interfering, it, with some more nuance we’ll talk about below, could be a bit of a way forward helping mobile device UX (ie. user experience) start to benefit from a kind of emulation of the first of two aspects non-mobile devices have over them, they being …
    • when hovering over an element with a defined title attribute, the user sees that title attribute like a tooltip
    • non-mobile users can access Web Inspectors (and/or View Page Source) to effectively know everything that is going on with a webpage if they have accessed it with most modern web browsers

And because the second idea above will probably never be possible for mobile users, we have introduced into our nuanced ontouchmove=”alert(this.title);” idea changes for a lot of this WordPress blog’s webpages you are reading, a bit of what we’d say is “hand holding” in the new Javascript code, (similarly to the ways of WordPress Javascript Coding Rearrangements Primer Tutorial), as per the changed hive_off_header_php.js‘s “at document.body onload event” intervening …


var lastelo=null;

// New mobile ontouchmove idea ... October, 2026
if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) || eval(String.fromCharCode(32).trim() + navigator.maxTouchPoints) > 0) {
var jhoare=0, khoare=0, ihoare=[], elthingos=['a','span', 'font', 'sup', 'sub', 'table', 'select', 'button', 'textarea', 'input', 'h1', 'h2', 'h3', 'h4', 'code', 'blockquote']; // 'p',
for (khoare=0; khoare<elthingos.length; khoare++) {
ihoare=document.getElementsByTagName(elthingos[khoare]);
for (jhoare=0; jhoare<ihoare.length; jhoare++) {
if (('' + ihoare[jhoare].outerHTML).indexOf(' ontouchmove=') == -1 && ('' + ihoare[jhoare].outerHTML.split('>')[0]).replace(' title=""', '').replace(" title=''", "").indexOf(' title=') != -1) {
ihoare[jhoare].ontouchmove=function(event){ otmalert(event); };
} else if (elthingos[khoare] == 'a' && ('' + ihoare[jhoare].outerHTML.split('>')[0]).replace(' title=""', '').replace(" title=''", "").indexOf(' title=') == -1 && ('' + ihoare[jhoare].outerHTML.split('>')[0]).replace(' href=""', '').replace(" href=''", "").indexOf(' href=') != -1) {
ihoare[jhoare].title='' + ihoare[jhoare].href;
ihoare[jhoare].ontouchmove=function(event){ otmalert(event); };
} else if (('' + ihoare[jhoare].outerHTML.split('>')[0]).replace(' title=""', '').replace(" title=''", "").indexOf(' title=') == -1 && ('' + ihoare[jhoare].outerHTML.split('>gt;')[0]).replace(' class=""', '').replace(" class=''", "").indexOf(' class=') != -1) {
ihoare[jhoare].title='Class ' + ihoare[jhoare].className;
ihoare[jhoare].ontouchmove=function(event){ otmalert(event); };
}
}
}
}

… where the mild “hand holding” occurs potentially creating “on the fly” title attributes occasionally to potentially provide more information to your more curious mobile user readers of this blog, who, behind the scenes, access the following new Javascript function …


function otmalert(eloev) {
eloev.stopPropagation();
if (eloev.target != lastelo) {
lastelo=eloev.target;
if (('' + lastelo.title) != '') {
alert(lastelo.title);
}
}
}

… in their travels.

Oh, by the way, mobile users out there reading this blog, now “exploratory wiggling” is advisory!


Previous relevant WordPress Javascript Coding Rearrangements Primer Tutorial is shown below.

WordPress Javascript Coding Rearrangements Primer Tutorial

WordPress Javascript Coding Rearrangements Primer Tutorial

If you are a regular reader here reading yesterday’s Window Object Function Equals Function Primer Tutorial‘s …

… using (from within the clientside realms of the coding of this WordPress.org blog’s) Javascript …

… what might have zipped through your mind could have been the connecting phrase …

… from within good ol’ TwentyTen theme’s header.php …

… or somesuch. Because that has been what we normally do. Don’t get me wrong though, with the rearrangement idea blurb below, we could persist arranging it that way (and if the Javascript relies on PHP, we still do), but that recent Performance Review we last referenced with PHP MySql WordPress Blog Apache Restart Watchdog Tutorial got us to “see the light” somewhat and reorganize a bit regarding how Javascript code within this WordPress.org blog is organized. And so, read on.

Did you feel let down with PHP MySql WordPress Blog Performance PHP-FPM Configuration Tutorial when we said …

Codex loop.php WordPress error 404 event PHP
Overuse of file_get_contents Rearrange use of file_get_contents …
passing more work to crontab/curl overnight run

… and did not go into more detail?! So were we, but we had to think on this a lot to flesh it out, and looked into the often used around here PHP function …


file_get_contents

To our reckoning, until recently, we’d never tried PHP file_get_contents with more than one parameter. But, perhaps, it helps website bandwidth to start using those other parametersarguments (you say either, but we say neither … let’s call the whole thing off!)?

Within the 404.php (HTTP Error 404 “Not Found”) PHP file_get_contents calls what was being asked content wise included all that webpage Javascript written into good ol’ TwentyTen theme’s header.php … ouch regarding bandwidth! And so it led us to rearrange as per …

  1. set aside Javascript that was interspersed with PHP as the Javascript we’d still keep in good ol’ TwentyTen theme’s header.php … but the rest, and it was considerable …
  2. as for the rest, it could be placed into a new external Javascript file called hive_off_header_php.js (first draft of several, at time of writing) … called via the less wordy …

    <script type='text/javascript' src='//www.rjmprogramming.com.au/ITblog/hive_off_header_php.js?rand=<?php echo rand(0,1986754); ?>'></script>

… to, we’re thinking …

  1. potentially save on file_get_contents call website load bandwidth …
  2. be able to design, in 404.php, parametersarguments (you say either, but we say neither … let’s call the whole thing off!) that are measurable and definitive hence the 150000 below) … to end up with the modified 404.php codeline …

    $thisbpc=file_get_contents('http://www.rjmprogramming.com.au/ITblog/?p=' . $pnumis, FALSE, NULL, 0, 150000);

However, that is part one of two, to this part of the Performance Review. Part two will be explained in days to come.


Previous relevant Window Object Function Equals Function Primer Tutorial is shown below.

Window Object Function Equals Function Primer Tutorial

Window Object Function Equals Function Primer Tutorial

In keeping with yesterday’s Web Browser Brand Roles Primer Tutorial‘s KISS lead in, there’s a subtle difference between what happens with the two tabulated links below …

KISS KISS

… using (from within the clientside realms of the coding of this WordPress.org blog’s) Javascript …


function scrollIntoViewExactly(inob) {
if (document.getElementById('nest' + inob.id) || 4 == 4) {
// var ninob=document.getElementById('nest' + inob.id);
// ninob.style.width='' + inob.width + 'px';
// ninob.style.height='' + inob.height + 'px';
//inob.style.display='inline-block';
// ninob.style.display='inline-block';
// forceVerticalOverflow(ninob);
//document.body.style.whiteSpace='nowrap';
// document.body.style.overflow='scroll';// Safely sets horizontal scroll across all modern browsers
var inobr=inob.getBoundingClientRect();
//alert('' + inobr.width + ',' + inobr.height);
//alert('' + document.body.scrollLeft);
//alert('' + eval('' + inobr.left) + ',' + eval('' + inobr.top));
//alert('{ left:' + Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)) + ', top:' + Math.floor(eval('' + inobr.top) + eval('' + document.body.scrollTop)) + ", behavior: 'smooth' }");
// ninob.style.overflowX='scroll';
// ninob.style.maxWidth='' + ninob.style.width;
//inob.innerHTML+=' ';
//ninob.style.maxHeight='200px';
// ninob.style.overflowY='scroll';
// alert(ninob.outerHTML);
//var innardsare='{ left:' + Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)) + ', top:' + Math.floor(eval('' + inobr.top) + eval('' + document.body.scrollTop)) + ", behavior: 'smooth' }";
// left: Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)),
var ioffis=eval(eval(screen.width - eval('' + document.getElementById('content').getBoundingClientRect().width)) / 2);
thenx=Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft) + eval('' + document.body.offsetLeft) + ioffis);
const innardsare = {
top: eval(120 + Math.floor(eval('' + inobr.top) + eval('' + document.body.scrollTop))),
behavior: 'smooth'
};
const xinnardsare = {
left: Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft) + eval('' + document.body.offsetLeft) + ioffis),
behavior: 'auto'
};
if (7 == 7) {
location.href='#' + inob.id;
} else {
// alert(isScrollable(ninob));
forceVerticalOverflow(document.body);
//alert(isScrollable(document.body));
//alert(innardsare);
window.scrollTo(innardsare);
//alert(Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)));
//setTimeout(function(){ document.body.style.overflowX = 'auto'; document.body.scrollBy(xinnardsare); }, 8000);
//setTimeout(function(){ alert(thenx); document.scrollingElement.scrollLeft='' + thenx + ''; }, 8000);
}
setTimeout(function(){
//document.body.overflowX='scroll';
document.body.style.cursor='progress';
document.body.style.marginLeft='-' + thenx + 'px'; //inob.scrollLeft=thenx;
inob.setAttribute('data-cb', '25');
setTimeout(countback, 1000);
setTimeout(function(){
document.body.style.cursor='pointer';
document.body.style.marginLeft='0px'; //inob.scrollLeft=thenx;
}, 25000);
}, 1000);
if (3 == 5) {
setTimeout(function(){
//document.body.style.whiteSpace='nowrap';
//document.body.style.overflow='scroll';// Safely sets horizontal scroll across all modern browsers
if (document.scrollingElement) {
document.scrollingElement.scrollLeft = thenx;
} else {
// Fallback for older browsers
document.documentElement.scrollLeft = thenx;
document.body.scrollLeft = thenx;
}
}, 5000);
}
} else {
window.scrollIntoView(inob);
}
}


Previous relevant Web Browser Brand Roles Primer Tutorial is shown below.

Web Browser Brand Roles Primer Tutorial

Web Browser Brand Roles Primer Tutorial

With a job, the day to day organization can be important, and is likely to be crucial to achieving goals.

We spend a lot of time around web browser applications, being into I.T. and creating web applications, in particular.

We’ve organized macOS MacBook Air usage mainly, around one major disk folder and four brands of web browser, the folder being, for us is …


/Applications/MAMP/htdocs

Huh?! Well, being into PHP as our “all things server” programming language, and having installed (many versions) of MAMP, as our Apache/PHP/MySql local web server brand of choice, and by default /Applications/MAMP/htdocs is MAMP’s Document Root (and defaulting to port 8888) corresponding to URL …


http://localhost:8888

Even with compiling language work, we’ll often use subfolders off /Applications/MAMP/htdocs … working to a KISS principle!

Turning to web browsers, the four we tabulate below are all very good products, and can all work well for you, especially on macOS, but a consideration to do with how you organize work, there is the consideration of what work life will be like if you have to, say, clear all web browser cookies and data, for instance. As such, in the list below, we’ve organized Google Chrome and/or Firefox as the two web browsers we can tolerate that with (but prefer to just clear Last Hour or Last 15 Minutes or Last 24 Hours usually), in our (web browser) Organization Table below …

Opera
  • RJM Programming website email … opened as this web browser’s home page
Safari
  • RJM Programming website WHM and cPanel login to domain related configurations and monitoring functionality
  • MAMP (opened when MacBook Air (re-)boots) based Animated GIF creation executions
  • Crazy Domains web hosting login to payments and Live Chat support
Firefox
  • Web application testing for tests that need to ignore Google Chrome
Google Chrome
  • RJM Programming *.php lately changed list report … opened as this web browser’s home page
  • Norton Safe Search of RJM Programming webpage … opened also when web browser loads up
  • Gmail via URL personal and work emails
  • WordPress.org blog Content Management System work
  • Web application Research and Development
  • Web application executions
  • Web application Web Inspector debugging

When there are jobs requiring command line needing to be seen next to a web browser rendition, macOS Terminal application windows can easily be arranged to not overlap any web browser brand window from the list above.

Screenshots on macOS have moved on from good ol’ Grab with the very easy keyboard shortcut …


control-command-shift-3

… working really well with good ol’ macOS version of PaintBrush‘s File->New from Clipboard functionality. Preview is good for PDF creation and compilation functionality. Gimp is good for blurring and other filtering requirements.

More and more we’ll use AirDrop to transfer from iPad or iPhone to the macOS MacBook Air, or use that iOS device’s Mail sharing option to download to the macOS MacBook Air Downloads folder usually, and then, usually, this will be copied to good ol’ /Applications/MAMP/htdocs (or a subfolder off this, especially if what is copied is a *.zip file (extracted)).

Crontab on the macOS MacBook Air has an “every minute” check of good ol’ /Applications/MAMP/htdocs changed (within last minute) *.png (primarily coming out of Paintbrush File->Save As… functionality) or *.[Hh][Ee][Ii][Cc] (off iPhone or iPad Camera app usage) ready for (PHP calling of) ImageMagick‘s convertion to versions of *.[Jj][Pp]*[Gg] images.

Uploads to (and downloads from) the RJM Programming domain are all conducted via sftp connections using the FileZilla macOS desktop application.

TextWrangler is our favourite text editor by a very large margin!

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

WordPress Javascript Coding Rearrangements Primer Tutorial

WordPress Javascript Coding Rearrangements Primer Tutorial

WordPress Javascript Coding Rearrangements Primer Tutorial

If you are a regular reader here reading yesterday’s Window Object Function Equals Function Primer Tutorial‘s …

… using (from within the clientside realms of the coding of this WordPress.org blog’s) Javascript …

… what might have zipped through your mind could have been the connecting phrase …

… from within good ol’ TwentyTen theme’s header.php …

… or somesuch. Because that has been what we normally do. Don’t get me wrong though, with the rearrangement idea blurb below, we could persist arranging it that way (and if the Javascript relies on PHP, we still do), but that recent Performance Review we last referenced with PHP MySql WordPress Blog Apache Restart Watchdog Tutorial got us to “see the light” somewhat and reorganize a bit regarding how Javascript code within this WordPress.org blog is organized. And so, read on.

Did you feel let down with PHP MySql WordPress Blog Performance PHP-FPM Configuration Tutorial when we said …

Codex loop.php WordPress error 404 event PHP
Overuse of file_get_contents Rearrange use of file_get_contents …
passing more work to crontab/curl overnight run

… and did not go into more detail?! So were we, but we had to think on this a lot to flesh it out, and looked into the often used around here PHP function …


file_get_contents

To our reckoning, until recently, we’d never tried PHP file_get_contents with more than one parameter. But, perhaps, it helps website bandwidth to start using those other parametersarguments (you say either, but we say neither … let’s call the whole thing off!)?

Within the 404.php (HTTP Error 404 “Not Found”) PHP file_get_contents calls what was being asked content wise included all that webpage Javascript written into good ol’ TwentyTen theme’s header.php … ouch regarding bandwidth! And so it led us to rearrange as per …

  1. set aside Javascript that was interspersed with PHP as the Javascript we’d still keep in good ol’ TwentyTen theme’s header.php … but the rest, and it was considerable …
  2. as for the rest, it could be placed into a new external Javascript file called hive_off_header_php.js (first draft of several, at time of writing) … called via the less wordy …

    <script type='text/javascript' src='//www.rjmprogramming.com.au/ITblog/hive_off_header_php.js?rand=<?php echo rand(0,1986754); ?>'></script>

… to, we’re thinking …

  1. potentially save on file_get_contents call website load bandwidth …
  2. be able to design, in 404.php, parametersarguments (you say either, but we say neither … let’s call the whole thing off!) that are measurable and definitive hence the 150000 below) … to end up with the modified 404.php codeline …

    $thisbpc=file_get_contents('http://www.rjmprogramming.com.au/ITblog/?p=' . $pnumis, FALSE, NULL, 0, 150000);

However, that is part one of two, to this part of the Performance Review. Part two will be explained in days to come.


Previous relevant Window Object Function Equals Function Primer Tutorial is shown below.

Window Object Function Equals Function Primer Tutorial

Window Object Function Equals Function Primer Tutorial

In keeping with yesterday’s Web Browser Brand Roles Primer Tutorial‘s KISS lead in, there’s a subtle difference between what happens with the two tabulated links below …

KISS KISS

… using (from within the clientside realms of the coding of this WordPress.org blog’s) Javascript …


function scrollIntoViewExactly(inob) {
if (document.getElementById('nest' + inob.id) || 4 == 4) {
// var ninob=document.getElementById('nest' + inob.id);
// ninob.style.width='' + inob.width + 'px';
// ninob.style.height='' + inob.height + 'px';
//inob.style.display='inline-block';
// ninob.style.display='inline-block';
// forceVerticalOverflow(ninob);
//document.body.style.whiteSpace='nowrap';
// document.body.style.overflow='scroll';// Safely sets horizontal scroll across all modern browsers
var inobr=inob.getBoundingClientRect();
//alert('' + inobr.width + ',' + inobr.height);
//alert('' + document.body.scrollLeft);
//alert('' + eval('' + inobr.left) + ',' + eval('' + inobr.top));
//alert('{ left:' + Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)) + ', top:' + Math.floor(eval('' + inobr.top) + eval('' + document.body.scrollTop)) + ", behavior: 'smooth' }");
// ninob.style.overflowX='scroll';
// ninob.style.maxWidth='' + ninob.style.width;
//inob.innerHTML+=' ';
//ninob.style.maxHeight='200px';
// ninob.style.overflowY='scroll';
// alert(ninob.outerHTML);
//var innardsare='{ left:' + Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)) + ', top:' + Math.floor(eval('' + inobr.top) + eval('' + document.body.scrollTop)) + ", behavior: 'smooth' }";
// left: Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)),
var ioffis=eval(eval(screen.width - eval('' + document.getElementById('content').getBoundingClientRect().width)) / 2);
thenx=Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft) + eval('' + document.body.offsetLeft) + ioffis);
const innardsare = {
top: eval(120 + Math.floor(eval('' + inobr.top) + eval('' + document.body.scrollTop))),
behavior: 'smooth'
};
const xinnardsare = {
left: Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft) + eval('' + document.body.offsetLeft) + ioffis),
behavior: 'auto'
};
if (7 == 7) {
location.href='#' + inob.id;
} else {
// alert(isScrollable(ninob));
forceVerticalOverflow(document.body);
//alert(isScrollable(document.body));
//alert(innardsare);
window.scrollTo(innardsare);
//alert(Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)));
//setTimeout(function(){ document.body.style.overflowX = 'auto'; document.body.scrollBy(xinnardsare); }, 8000);
//setTimeout(function(){ alert(thenx); document.scrollingElement.scrollLeft='' + thenx + ''; }, 8000);
}
setTimeout(function(){
//document.body.overflowX='scroll';
document.body.style.cursor='progress';
document.body.style.marginLeft='-' + thenx + 'px'; //inob.scrollLeft=thenx;
inob.setAttribute('data-cb', '25');
setTimeout(countback, 1000);
setTimeout(function(){
document.body.style.cursor='pointer';
document.body.style.marginLeft='0px'; //inob.scrollLeft=thenx;
}, 25000);
}, 1000);
if (3 == 5) {
setTimeout(function(){
//document.body.style.whiteSpace='nowrap';
//document.body.style.overflow='scroll';// Safely sets horizontal scroll across all modern browsers
if (document.scrollingElement) {
document.scrollingElement.scrollLeft = thenx;
} else {
// Fallback for older browsers
document.documentElement.scrollLeft = thenx;
document.body.scrollLeft = thenx;
}
}, 5000);
}
} else {
window.scrollIntoView(inob);
}
}


Previous relevant Web Browser Brand Roles Primer Tutorial is shown below.

Web Browser Brand Roles Primer Tutorial

Web Browser Brand Roles Primer Tutorial

With a job, the day to day organization can be important, and is likely to be crucial to achieving goals.

We spend a lot of time around web browser applications, being into I.T. and creating web applications, in particular.

We’ve organized macOS MacBook Air usage mainly, around one major disk folder and four brands of web browser, the folder being, for us is …


/Applications/MAMP/htdocs

Huh?! Well, being into PHP as our “all things server” programming language, and having installed (many versions) of MAMP, as our Apache/PHP/MySql local web server brand of choice, and by default /Applications/MAMP/htdocs is MAMP’s Document Root (and defaulting to port 8888) corresponding to URL …


http://localhost:8888

Even with compiling language work, we’ll often use subfolders off /Applications/MAMP/htdocs … working to a KISS principle!

Turning to web browsers, the four we tabulate below are all very good products, and can all work well for you, especially on macOS, but a consideration to do with how you organize work, there is the consideration of what work life will be like if you have to, say, clear all web browser cookies and data, for instance. As such, in the list below, we’ve organized Google Chrome and/or Firefox as the two web browsers we can tolerate that with (but prefer to just clear Last Hour or Last 15 Minutes or Last 24 Hours usually), in our (web browser) Organization Table below …

Opera
  • RJM Programming website email … opened as this web browser’s home page
Safari
  • RJM Programming website WHM and cPanel login to domain related configurations and monitoring functionality
  • MAMP (opened when MacBook Air (re-)boots) based Animated GIF creation executions
  • Crazy Domains web hosting login to payments and Live Chat support
Firefox
  • Web application testing for tests that need to ignore Google Chrome
Google Chrome
  • RJM Programming *.php lately changed list report … opened as this web browser’s home page
  • Norton Safe Search of RJM Programming webpage … opened also when web browser loads up
  • Gmail via URL personal and work emails
  • WordPress.org blog Content Management System work
  • Web application Research and Development
  • Web application executions
  • Web application Web Inspector debugging

When there are jobs requiring command line needing to be seen next to a web browser rendition, macOS Terminal application windows can easily be arranged to not overlap any web browser brand window from the list above.

Screenshots on macOS have moved on from good ol’ Grab with the very easy keyboard shortcut …


control-command-shift-3

… working really well with good ol’ macOS version of PaintBrush‘s File->New from Clipboard functionality. Preview is good for PDF creation and compilation functionality. Gimp is good for blurring and other filtering requirements.

More and more we’ll use AirDrop to transfer from iPad or iPhone to the macOS MacBook Air, or use that iOS device’s Mail sharing option to download to the macOS MacBook Air Downloads folder usually, and then, usually, this will be copied to good ol’ /Applications/MAMP/htdocs (or a subfolder off this, especially if what is copied is a *.zip file (extracted)).

Crontab on the macOS MacBook Air has an “every minute” check of good ol’ /Applications/MAMP/htdocs changed (within last minute) *.png (primarily coming out of Paintbrush File->Save As… functionality) or *.[Hh][Ee][Ii][Cc] (off iPhone or iPad Camera app usage) ready for (PHP calling of) ImageMagick‘s convertion to versions of *.[Jj][Pp]*[Gg] images.

Uploads to (and downloads from) the RJM Programming domain are all conducted via sftp connections using the FileZilla macOS desktop application.

TextWrangler is our favourite text editor by a very large margin!

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

Window Object Function Equals Function Primer Tutorial

Window Object Function Equals Function Primer Tutorial

Window Object Function Equals Function Primer Tutorial

In keeping with yesterday’s Web Browser Brand Roles Primer Tutorial‘s KISS lead in, there’s a subtle difference between what happens with the two tabulated links below …

KISS KISS

… using (from within the clientside realms of the coding of this WordPress.org blog’s) Javascript …


function scrollIntoViewExactly(inob) {
if (document.getElementById('nest' + inob.id) || 4 == 4) {
// var ninob=document.getElementById('nest' + inob.id);
// ninob.style.width='' + inob.width + 'px';
// ninob.style.height='' + inob.height + 'px';
//inob.style.display='inline-block';
// ninob.style.display='inline-block';
// forceVerticalOverflow(ninob);
//document.body.style.whiteSpace='nowrap';
// document.body.style.overflow='scroll';// Safely sets horizontal scroll across all modern browsers
var inobr=inob.getBoundingClientRect();
//alert('' + inobr.width + ',' + inobr.height);
//alert('' + document.body.scrollLeft);
//alert('' + eval('' + inobr.left) + ',' + eval('' + inobr.top));
//alert('{ left:' + Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)) + ', top:' + Math.floor(eval('' + inobr.top) + eval('' + document.body.scrollTop)) + ", behavior: 'smooth' }");
// ninob.style.overflowX='scroll';
// ninob.style.maxWidth='' + ninob.style.width;
//inob.innerHTML+=' ';
//ninob.style.maxHeight='200px';
// ninob.style.overflowY='scroll';
// alert(ninob.outerHTML);
//var innardsare='{ left:' + Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)) + ', top:' + Math.floor(eval('' + inobr.top) + eval('' + document.body.scrollTop)) + ", behavior: 'smooth' }";
// left: Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)),
var ioffis=eval(eval(screen.width - eval('' + document.getElementById('content').getBoundingClientRect().width)) / 2);
thenx=Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft) + eval('' + document.body.offsetLeft) + ioffis);
const innardsare = {
top: eval(120 + Math.floor(eval('' + inobr.top) + eval('' + document.body.scrollTop))),
behavior: 'smooth'
};
const xinnardsare = {
left: Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft) + eval('' + document.body.offsetLeft) + ioffis),
behavior: 'auto'
};
if (7 == 7) {
location.href='#' + inob.id;
} else {
// alert(isScrollable(ninob));
forceVerticalOverflow(document.body);
//alert(isScrollable(document.body));
//alert(innardsare);
window.scrollTo(innardsare);
//alert(Math.floor(eval('' + inobr.left) + eval('' + document.body.scrollLeft)));
//setTimeout(function(){ document.body.style.overflowX = 'auto'; document.body.scrollBy(xinnardsare); }, 8000);
//setTimeout(function(){ alert(thenx); document.scrollingElement.scrollLeft='' + thenx + ''; }, 8000);
}
setTimeout(function(){
//document.body.overflowX='scroll';
document.body.style.cursor='progress';
document.body.style.marginLeft='-' + thenx + 'px'; //inob.scrollLeft=thenx;
inob.setAttribute('data-cb', '25');
setTimeout(countback, 1000);
setTimeout(function(){
document.body.style.cursor='pointer';
document.body.style.marginLeft='0px'; //inob.scrollLeft=thenx;
}, 25000);
}, 1000);
if (3 == 5) {
setTimeout(function(){
//document.body.style.whiteSpace='nowrap';
//document.body.style.overflow='scroll';// Safely sets horizontal scroll across all modern browsers
if (document.scrollingElement) {
document.scrollingElement.scrollLeft = thenx;
} else {
// Fallback for older browsers
document.documentElement.scrollLeft = thenx;
document.body.scrollLeft = thenx;
}
}, 5000);
}
} else {
window.scrollIntoView(inob);
}
}


Previous relevant Web Browser Brand Roles Primer Tutorial is shown below.

Web Browser Brand Roles Primer Tutorial

Web Browser Brand Roles Primer Tutorial

With a job, the day to day organization can be important, and is likely to be crucial to achieving goals.

We spend a lot of time around web browser applications, being into I.T. and creating web applications, in particular.

We’ve organized macOS MacBook Air usage mainly, around one major disk folder and four brands of web browser, the folder being, for us is …


/Applications/MAMP/htdocs

Huh?! Well, being into PHP as our “all things server” programming language, and having installed (many versions) of MAMP, as our Apache/PHP/MySql local web server brand of choice, and by default /Applications/MAMP/htdocs is MAMP’s Document Root (and defaulting to port 8888) corresponding to URL …


http://localhost:8888

Even with compiling language work, we’ll often use subfolders off /Applications/MAMP/htdocs … working to a KISS principle!

Turning to web browsers, the four we tabulate below are all very good products, and can all work well for you, especially on macOS, but a consideration to do with how you organize work, there is the consideration of what work life will be like if you have to, say, clear all web browser cookies and data, for instance. As such, in the list below, we’ve organized Google Chrome and/or Firefox as the two web browsers we can tolerate that with (but prefer to just clear Last Hour or Last 15 Minutes or Last 24 Hours usually), in our (web browser) Organization Table below …

Opera
  • RJM Programming website email … opened as this web browser’s home page
Safari
  • RJM Programming website WHM and cPanel login to domain related configurations and monitoring functionality
  • MAMP (opened when MacBook Air (re-)boots) based Animated GIF creation executions
  • Crazy Domains web hosting login to payments and Live Chat support
Firefox
  • Web application testing for tests that need to ignore Google Chrome
Google Chrome
  • RJM Programming *.php lately changed list report … opened as this web browser’s home page
  • Norton Safe Search of RJM Programming webpage … opened also when web browser loads up
  • Gmail via URL personal and work emails
  • WordPress.org blog Content Management System work
  • Web application Research and Development
  • Web application executions
  • Web application Web Inspector debugging

When there are jobs requiring command line needing to be seen next to a web browser rendition, macOS Terminal application windows can easily be arranged to not overlap any web browser brand window from the list above.

Screenshots on macOS have moved on from good ol’ Grab with the very easy keyboard shortcut …


control-command-shift-3

… working really well with good ol’ macOS version of PaintBrush‘s File->New from Clipboard functionality. Preview is good for PDF creation and compilation functionality. Gimp is good for blurring and other filtering requirements.

More and more we’ll use AirDrop to transfer from iPad or iPhone to the macOS MacBook Air, or use that iOS device’s Mail sharing option to download to the macOS MacBook Air Downloads folder usually, and then, usually, this will be copied to good ol’ /Applications/MAMP/htdocs (or a subfolder off this, especially if what is copied is a *.zip file (extracted)).

Crontab on the macOS MacBook Air has an “every minute” check of good ol’ /Applications/MAMP/htdocs changed (within last minute) *.png (primarily coming out of Paintbrush File->Save As… functionality) or *.[Hh][Ee][Ii][Cc] (off iPhone or iPad Camera app usage) ready for (PHP calling of) ImageMagick‘s convertion to versions of *.[Jj][Pp]*[Gg] images.

Uploads to (and downloads from) the RJM Programming domain are all conducted via sftp connections using the FileZilla macOS desktop application.

TextWrangler is our favourite text editor by a very large margin!

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