Bluetooth Based Tethering of iPad to iPhone Tutorial

Bluetooth Based Tethering of iPad to iPhone Tutorial

Bluetooth Based Tethering of iPad to iPhone Tutorial

Today we have an outage regarding the WiFi to our office, and wanted to …

  • do some online work on an iPad with no SIM card … and …
  • we do have access to an iPhone with Mobile Data on and a connection to a Service Provider

What can be achieved with Bluetooth only (other than Spotify, which worked fine with our Bluetooth only Sonos speaker and the Spotify app)?

  • how about tethering iPad to iPhone …
  • via an iPhone HotSpot (like talked about with Making of Automated Tethering of iPhone to iPad Tutorial) …
  • Bluetooth based …
  • connection
  • ? Other than eating more into your Mobile Data quota, it sounds good to us … and was!


    Previous relevant Making of Automated Tethering of iPhone to iPad Tutorial is shown below.

    Making of Automated Tethering of iPhone to iPad Tutorial

    Making of Automated Tethering of iPhone to iPad Tutorial

    The animated GIF presentation featuring in yesterday’s Automated Tethering of iPhone to iPad Tutorial featured …

    • iPad control-command-shift-3 generated screenshot images making their way to Photos app … and …
    • iPhone control-command-shift-3 generated screenshot images making their way to Photos app … and …
    • coalescing back at Photos app so as to be able to Mail share in a zip file download (iPad ones getting named in the range IMG_1631.PNG to IMG_1639.PNG and iPhone ones in the range IMG_2777.PNG to IMG_2781.PNG) …
    • at this MacBook Air … so as to …
    • browse for these images as the source for that animated GIF’s contents …

    … but in order to tell the story of that blog posting well, what order (because we captured the “story’s images” involving interplay that had us jumping from one device to the other and back)?

    Well, at macOS operating systems you get (downloaded) image file …

    • datetime created
    • datetime added
    • datetime modified

    … but after downloading, these all end up indistinguishable. What we need is …


    datetime image captured

    … to make the job easier (albeit, and we did as well, you could load them all into a PDF and use application like macOS Preview to reorder them appropriately (hopefully soon after) from memory)? Oops! Or, is the image metadata going to help us here? These are PNG images and Exif is best with JPEG images, but still, we remember looking into this when we presented the PHP Exif Image Information Revisit Tutorial blog posting that resulted in the PHP (“first draft”) “Exif Information” web application (as the basis for better “Exif Information” web application later on).

    We ran this on our local MAMP Apache/PHP/MySql web server …

    … and there was enough there to go on to help out getting the order better (where you’ll see us using …

    • iPhone Notes app …

      … to write down image identifier and capture datetimes … marrying that up when …
    • choosing order of images when constructing animated GIF … and sanity checking via …
    • macOS Preview application approach that is so good at shaping to (or really) rearranging slide image orders

    ). Phew!


    Previous relevant Automated Tethering of iPhone to iPad Tutorial is shown below.

    Automated Tethering of iPhone to iPad Tutorial

    Automated Tethering of iPhone to iPad Tutorial

    Thinking on yesterday’s Automated Tethering of iPhone to Mac Tutorial, the next day …

    Was in the car doing a bit of work on the iPad (iOS (8th generation) Version 16.3.1), unconnected at the time, the other day, when we didn’t got get a surprise. Lo and behold, a To infinity and beyond, we looked, but no notification style dialog box came up.

    But we went looking in …


    Settings -> Wi-Fi -> Auto Join Hotspot

    … and discovered the setting was set to “Ask to Join” while we think a better setting to get the ball rolling, here, would be “Automatic” (rather than “Never”). And so it came to pass.

    And though we had to adjust Personal Hotspot settings on the iPhone to allow others to connect (automatically, now), Wi-Fi connections on the iPad became automated, and we did get connected to the big wide online connected wooooorrrrrllllldddd on the iPad via the iPhone’s Personal Hotspot this way! Yayyyyyy!


    Previous relevant Automated Tethering of iPhone to Mac Tutorial is shown below.

    Automated Tethering of iPhone to Mac Tutorial

    Automated Tethering of iPhone to Mac Tutorial

    Was in the car doing a bit of work on the MacBook Air (macOS Sonoma Version 14.5), unconnected at the time, the other day, when we got a surprise. Lo and behold, a notification style dialog box came up …

    Personal Hotspot Available
    Do you want to join “Robert’s iPhone”?

    … presumably because we had our iPhone in the car (and had invoked its Personal Hotspot functionality in the past, as you can read about with Troubleshooting Retethering Windows 10 to iPhone Tutorial) and then, on hovering over it (it took me a day to tweak to) came up with …

    Personal Hotspot Available
    Do you want to join “Robert’s iPhone”?     

    … that on clicking the Join button had us connected to the big wide online connected wooooorrrrrllllldddd without needing to do anything on the iPhone! Great integration!

    We looked up with Google’s Image search via …


    Personal Hotspot Available

    … in “full FOMO horror”, getting us to read this webpage, thanks, to see that some people even expect more?! Impressive enough, and stop there, we’d say.


    Previous relevant Troubleshooting Retethering Windows 10 to iPhone Tutorial is shown below.

    Troubleshooting Retethering Windows 10 to iPhone Tutorial

    Troubleshooting Retethering Windows 10 to iPhone Tutorial

    You might say today’s “Troubleshooting Retethering Windows 10 to iPhone Tutorial” is missing a “Tethering Windows 10 to iPhone Primer Tutorial” on top of the Tethering MacBook Pro to iPhone Primer Tutorial involving the macOS wooooooorrrrrrllllllddd, but sometimes we can intimate the positives during an explanation of the negatives (… and after all that’s what it’s all about).

    And yes, things go wrong in I.T.? Who’d believe it? And so, today, we had just such a disconnect re-rehearsing a way to have a Windows 10 laptop be connected to the Internet away from a WiFi router scenario offsite, but taking along the “lassooable” iPhone 6 (you guessed it … as had been done successfully in the past). Well, another whole consideration is “why would the iPhone 6 Personal Hotspot (turned on) not appear in the Windows 10 WiFi connection list” but today’s troubleshooting theme goes past that onto the practicalities of Forgetting the whY and adding the MCAand concentrating on the “how” of “how to fix this”, which via good ol’ Google


    windows 10 will not connect to iphone 6 personal hotspot

    … leading us to today’s star turn link (thanks) …

    1 Press Windows Key + I shortcut to quickly open the Settings app.
    2 When Settings app opens, navigate to Network & Internet section
    3 From the menu on the left select Wi-Fi. Now click on Manage known networks.
    4 List of memorized Wi-Fi networks will appear. Select your Wi-Fi network and click the Forget button.
    5 Then connect to your hotspot network again.

    … curiously precursored by a presumption we do not believe to have been true surmising that the hotspot password had changed. No worries, though, because the advice helped, that being to first …

    1. Forget the network (on Windows 10 laptop)
    2. Retry the reopened Personal Hotspot network (on iPhone 6)
    3. Back at same place you “Forgot”, suddenly “remember” via Properties set “Connect Automatically When in Range” on (on Windows 10 laptop) … perhaps needing the iPhone 6 Personal Hotspot password

    … that last step above an “addendum” to the great advice quoted above, and summarized via today’s animated GIF presentation.

    Voila! Connection for Windows 10 in a scenario where there is no WiFi router but an iPhone 6 Personal Hotspot is available. We have to say, though, two things …

    • the iPhone needs Mobile Data to be on, and to get a signal to its ISP here … and that …
    • this is likely to cost you more in cold hard cash than your home WiFi arrangements would, in all probability, for the time it takes to get the work done, in this Personal Hotspot way (and for people called “Personal Hotspot”My way)

    We hope you never have this issue, and thank the contributors to troubleshooting advice, who have, and by sharing online, thereby getting answers out of people we’d like to thank, too … Dzięki.


    Previous relevant Tethering MacBook Pro to iPhone Primer Tutorial is shown below.

    Tethering MacBook Pro to iPhone Primer Tutorial

    Tethering MacBook Pro to iPhone Primer Tutorial

    Today we talk about a networking topic, regarding the idea if you are out and about, out of reach of WiFi connections, with your laptop, notebook or MacBook Pro, but you have available to you a device such as an Android or iPhone or iPad or tablet with inbuilt SIM card network connector, that networks via a mobile network (eg. here in Australia a 4G (soon to go to 5G) network) you (and we) can, perhaps …

    • “tether” your laptop, notebook or MacBook Pro (Robert’s MacBook Pro) … to that …
    • Android or iPhone (Robert’s iPhone) or iPad or tablet with inbuilt SIM card network connector accessing its mobile network (such as, here in Australia, 4G (soon to become 5G))

    No, our MacBook Pro is not Mister Ed, but we do form a “stable” connection … chortle, chortle.

    The clue to all this is, for us, in the iPhone’s …


    Settings -> Personal Hotspot -> switch on

    … and there you will see three modes of “hotspotting” …

    1. WiFi
    2. Bluetooth … enable on both and “Pair” on both
    3. USB … we use in Xcode running and testing mobile applications on iPhone (or iPad)

    … the first of which is great with that scenario we talked about at the top of the article.

    1. be on iPhone and touch Settings icon
    2. touch Personal Hotspot
    3. touch to be On
    4. over at MacBook Pro and click Settings icon
    5. click WiFi
    6. pick Robert’s iPhone (or equivalent) in the list and it will have that “tethering” icon (two linked ellipses)
    7. voila! … you can surf the net, read your emails and do any of those other “online” activities … but be aware that this arrangement usually costs more in service charges

    You can take a look at our PDF slideshow presentation of some of these concepts.

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

YouTube Video API Event Playlist Generations Tutorial

YouTube Video API Event Playlist Generations Tutorial

YouTube Video API Event Playlist Generations Tutorial

Recently, on this current YouTube API interfacing Song Playing web application, further to the recent YouTube Video API Event Playlist User Settings Tutorial, we’ve been referring a lot to …


top.document.title

… as a place to store settings in which all three generational layers we’ve got going, can share information, and function calls like …


var a_js_var = top.getlasttitleclicked();

This has all worked okay until you consider, “iframe hereditary wise” …

What happens? Well …


top.document.title

… refers to this WordPress blog webpage, whereas we originally coded it with the intention that it would refer to the “grandparent” level webpage in the list above. For the “title” scenario this can be remedied by code at the grandparent level checking for this scenario and being agile (as per some example code below) …


function clit(lno, twhat) {
if (top.document.title.indexOf(twhat.split(' ...')[0]) > 0) {
document.title=top.document.title;
return top.document.title;
} else {
console.log('!' + origtitle + '! ... ' + lno + ': ' + ('' + (new Date())) + ' top.document.title=' + twhat);
return twhat;
}
}

if (window.top) { if (window.top != window.self) {
if (top.document.getElementById('phfloater') && !top.document.getElementById('listeleven')) {
top.document.getElementById('phfloater').innerHTML+="<div id=listeleven style='display:none;'></div>";
}
if (top.document.title.indexOf(' ...') == -1) {
tdtis=top.document.title;
dtis=document.title;
document.title=tdtis + ' ' + dtis;
origtitle='' + document.title.split(' ...')[0] + ' ...';
top.document.title=clit(401,document.title);
}
} }

But ideas like …


var a_js_var = top.getlasttitleclicked();

… are another matter entirely. We’re not going around shoving irrelevant Javascript functions into the makeup of our WordPress Blog webpages! And that is the situation that made us try, for the first time we can remember …


var a_js_var = parent.parent.getlasttitleclicked();

… huh?! Yes, you can go back through the generations to an exact generation of interest, that way, and the Javascript function called exists, and according to the codeline above, if the code is in the grandchild level the called Javascript function is in a grandparent level. Cute, huh?!


Previous relevant YouTube Video API Event Playlist User Settings Tutorial is shown below.

YouTube Video API Event Playlist User Settings Tutorial

YouTube Video API Event Playlist User Settings Tutorial

We’re happy to be talking about three new pieces of functionality to add to our recent YouTube API interfacing Song Playing web application last talked about with the recent YouTube Video API Event Playlist Background Image Tutorial, those being …

  1. 📹 ( &#128249; ) means by which a user can choose to suppress the video aspects (but not the controls) to the YouTube video “parent” level webpage(s) we display
  2. 📜 ( &#128220; ) scroll emoji allowing the Radio playing web application aspects push the relevant video playing parts to the top of the screen
  3. colour picker can allow user tailoring of the background colour to the “parent” level webpages supervising the “grandchild” players of the YouTube videos

These all rely on document.title settings …


function fixtitlecolour(inic) {
if (document.title.indexOf(origtitle) == -1) {
if (document.title.indexOf('Playlist playing ...') != -1) {
origtitle='Playlist playing ...';
}
}
if (('' + inic).toLowerCase().indexOf('ffff00') != -1) {
if (document.title.indexOf(' background:') != -1) {
document.title=document.title.replace(' ' + document.title.split(' background:')[1].replace(' !important; background','~ background').split(';')[0].replace('~',' !important;') + ';', ' ');
document.getElementById('karit').src=backiurl.replace('rand=', 'rand=' + Math.floor(Math.random() * 23));
}
} else {
if (document.title.indexOf(' background:') != -1) {
document.title=document.title.replace(' ' + document.title.split(' background:')[1].replace(' !important; background','~ background').split(';')[0].replace('~',' !important;') + ';', ' ');
}
document.title=document.title.replace(origtitle, origtitle + ' background:linear-gradient(180deg,#' + inic.value.replace('#','') + ',#' + inic.value.replace('#','') + ') !important; background-color:#' + inic.value.replace('#','') + ' !important; ');
document.getElementById('karit').src=backiurl.replace('rand=', 'rand=' + Math.floor(Math.random() * 23));
}
return true;
}

function togglesiv(aiois) {
var aih=aiois.innerHTML, bih='';
if (aih.indexOf('</strike>') == -1) {
aiois.innerHTML='<strike>' + aih + '</strike>';
} else {
aiois.innerHTML=aih.replace('<strike>','').replace('</strike>','');
}
}

function togglejustaudio(aiois) {
var aih=aiois.innerHTML, bih='';
if (aih.indexOf('</strike>') == -1) {
if (document.title.indexOf(' justaudio ') == -1) {
if (document.title.indexOf(origtitle) == -1) {
if (document.title.indexOf('Playlist playing ...') != -1) {
origtitle='Playlist playing ...';
}
}
if (document.title.indexOf(' background:') != -1) {
document.title=document.title.replace(' ' + document.title.split(' background:')[1].replace(' !important; background','~ background').split(';')[0].replace('~',' !important;') + ';', ' ');
}
document.title=document.title.replace(origtitle, origtitle + ' justaudio background:linear-gradient(180deg,transparent,transparent) !important; background-color:transparent !important; ');
document.getElementById('karit').src=backiurl.replace('rand=', 'rand=' + Math.floor(Math.random() * 23));
}
aiois.innerHTML='<strike>' + aih + '</strike>';
if (document.getElementById('bplay')) {
if (document.getElementById('bplay').innerHTML.indexOf('  ') != -1 && document.getElementById('bplay').innerHTML.indexOf('audio') == -1) {
bih=document.getElementById('bplay').innerHTML.split('  ')[1];
document.getElementById('bplay').innerHTML=document.getElementById('bplay').innerHTML.split('  ')[0] + '  just audio ' + bih;
}
}
} else {
document.title=document.title.replace(/\ justaudio\ /g,' ');
aiois.innerHTML=aih.replace('<strike>','').replace('</strike>','');
if (document.getElementById('bplay').innerHTML.indexOf('  ') != -1 && document.getElementById('bplay').innerHTML.indexOf('audio') != -1) {
bih=document.getElementById('bplay').innerHTML.indexOf('  ')[1];
document.getElementById('bplay').innerHTML=document.getElementById('bplay').innerHTML.replace('  just audio ','  ');
}
}
}

Codewise, it was all of the “the three amigos”, at it again …

… that got involved.


Previous relevant YouTube Video API Event Playlist Background Image Tutorial is shown below.

YouTube Video API Event Playlist Background Image Tutorial

YouTube Video API Event Playlist Background Image Tutorial

Our current project last talked about with YouTube Video API Event Playlist Shuffle and Loop Tutorial started as a …

  • “proof of concept” one to allow for user testing of event.stopPropagation() Javascript event bubbling control usage … and yet, is also a …
  • player of YouTube videos using the YouTube API inhouse interfacing here

… and it is the second functionality we want to emphasize. In such scenarios, we sometimes apply an apt Background Image (we’re applying to all document.body) via


<style>
td { vertical-align: top; }
select { background-color: lightblue; }
option:not(:checked) { background-color: yellow; opacity: 0.5; }
textarea { background-color: #f0f0f0; }
body {
background-image:linear-gradient(rgba(255,255,255,0.8),rgba(255,255,255,0.8)),URL('/retro-music-concept-with-headphones-space.jpg');
background-size:cover;
background-repeat:no-repeat;
}

* { border-radius:10px; border-color:magenta; }
</style>

… and regarding /retro-music-concept-with-headphones-space.jpg we have Freepik to thank for the free headphones background image we found there and downloaded then uploaded into place.

While we’re talking styling another CSS measure we often use to change the aesthetics of a webpage look is to soften some squared off borders via the application of a border-radius.

The meta viewport tag came in handy for this project, as another layer, for mobile platforms, of allowing mobile gestures to genuinely improve the video viewing, for the user …


<meta id='myviewport' name='viewport' content='width=device-width, initial-scale=1, minimum-scale=0.1, maximum-scale=8, user-scalable=yes' >

Another matter with mobile usage and a personalized playlist play scenario was that the use of the Mute and Unmute checkboxes at the “grandparent” level did not amount to a real click at the “grandchild” level, and so we started involving Javascript confirm box querying of users here, and this satisfied as a real user click for mobile platform media play purposes.

Codewise, all of the “the three amigos”, at it again …

… got involved.


Previous relevant YouTube Video API Event Playlist Shuffle and Loop Tutorial is shown below.

YouTube Video API Event Playlist Shuffle and Loop Tutorial

YouTube Video API Event Playlist Shuffle and Loop Tutorial

We left our Song Playing web application in YouTube Video API Event Playlist Save and Recall Tutorial

  • on mobile, needing a lot of “user tap maintenance” to keep the “personalized playlist” (consisting of YouTube ID video) music rolling … hence our …

    And yes, we want to try to get a mobile Radio scenario working for mobile, perhaps, by researching YouTube API (their) playlists … no guarantees, as you’d imagine!

    … from a preceeding tutorial … well … we still allow that mode of use, but add to that, the possibility of …

  • on mobile or non-mobile, we now offer the referencing of …
    1. YouTube Playlist IDs (34 characters) … or …
    2. Spotify Playlist IDs (22 characters)

    … so that shuffling and, in the case of YouTube Playlists using the YouTube App (if on mobile), looping can be part of the mix in your Song Plays (now appearing in the web application title … doh!! … yay!!!!)

The way to access this new functionality, above, is via the “now always appearing” 🍪 ( &#127850; Cookie button ) new prompt window arrangement


var xname='';
if (('' + location.hash).replace(/^\#/g,'') != '') {
xname=prompt('Recall name for this playlist. Understand that 34 character words will be seen as YouTube Playlist IDs or 22 character words will be seen as Spotify Playlist IDs for which we will start the ball rolling, and present them ready for you to play. Spaces at front results in a request to us at RJM Programming to host your proposed playlist on our YouTube channel and we will return a 34 character ID you can use yourself in the textbox presented. Add spaces at end also to just attend to that email off to RJM Programming.', '');
} else {
xname=prompt('Please optionally enter a recallable YouTube (34) or Spotify (22) playlist ID we will save for you from here on in optionally suffixed by # hashtag separated playlist title. Understand that 34 character words will be seen as YouTube Playlist IDs or 22 character words will be seen as Spotify Playlist IDs for which we will start the ball rolling, and present them ready for you to play. Our supplied YouTube playlist ID example is Nala and Luna (mainly) but please use Cancel to avoid remembering this playlist into the future.', 'PLjsR7WjAKSPU-6URvzZ552o5cvQ2p2GYE#Nala and Luna');
if (xname != null) { if (eval('' + xname.indexOf('#')) > 0) { btoaname=encodeURIComponent(xname.split('#')[1].replace(/\ /g,'_')); xname=xname.split('#')[0]; } usethisnotlh=xname; }
}

… that is possible when no personalized playlist hashtag data is in the mix. If it is, well, that opens another whole story all the way through to allowing the user to (email) request the creation of their personalized list of YouTube video IDs becoming a public facing YouTube Playlist hosted on the RJM Programming YouTube Channel, whereby we moderate, here, and if all passes muster, we return a 34 character YouTube Playlist ID the user can save from then on as a playlist on mobile or non-mobile capable of shuffling and looping (if the YouTube App is invoked, on mobile).

We’ve allowed those YouTube search results to “linger longer” too, by replicating them at the “grandparent level” at the point of time we wipe them from the “parent level”, the latest set appearing just below those top three options we now have going for both non-mobile and mobile platforms.

Codewise, two of the “the three amigos” were at it again …


Previous relevant YouTube Video API Event Playlist Save and Recall Tutorial is shown below.

YouTube Video API Event Playlist Save and Recall Tutorial

YouTube Video API Event Playlist Save and Recall Tutorial

Meanwhile, back at the wishlist, with our recent YouTube API interfacing web application project …

st*_st* way to set mute straight away via $_GET[‘mute’] and/or blanks in duration get and a hashtag way to temporarily mute
Save a playlist for later via window.localStorage
Share a playlist
Radio and Oneatatime with a straight hashtag URL
Mute and unmute dynamically
Turn “-” into a reset link

Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)

… it is the olive ideas we’ve made a start on today. We say “we’ve made a start on” only because, when it comes to programming, it doesn’t pay to close off alternate ideas as you go about looking for solutions. Take “Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)(for some reason we’re nicknaming “innerHTML” … who wrote this script)

… well, yes, that would be nice, but, more to the point, we started involving top.document.title in solution making but then, along the way, started incorporating just plain and simple Javascript get/set functionality


var ajaxs_ih='';


function get_ajaxs_ih() {
return ajaxs_ih;
}


function set_ajaxs_ih(wht) {
ajaxs_ih=wht;
}

parent.get_ajaxs_ih() and parent.set_ajaxs_ih(strIn) references from the “parent” level referencing the “grandparent” level (of code above) and being able to populate those YouTube search dropdowns more efficiently. This get/set paradigm is “a classic” methodology in a lot of OOP work, further to the recent YouTube Video API Event Radio Play Sharing Tutorial.

Codewise, again, “the three amigos” were at it again …


Previous relevant YouTube Video API Event Radio Play Sharing Tutorial is shown below.

YouTube Video API Event Radio Play Sharing Tutorial

YouTube Video API Event Radio Play Sharing Tutorial

Wishful thinking with today’s tasklist regarding our current YouTube Video API Event Radio Play Idea Tutorial YouTube API interfacing web application project, where the blue ideas were started …

st*_st* way to set mute straight away via $_GET[‘mute’] and/or blanks in duration get and a hashtag way to temporarily mute
Save a playlist for later via window.localStorage
Share a playlist
Radio and Oneatatime with a straight hashtag URL
Mute and unmute dynamically
Turn “-” into a reset link

Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)

… further to yesterday’s YouTube Video API Event Radio Play Idea Tutorial

And yes, we want to try to get a mobile Radio scenario working for mobile, perhaps, by researching YouTube API (their) playlists … no guarantees, as you’d imagine!

Of interest, here, might be the “emoji means” and top.document.title means by which we tackle the Mute and unmute dynamically issue. Why use top.document.title here? Well, a grandchild of the grandparent is best placed to …

  • tell the grandparent the non-muted volume (which seems to always be 100, as you control what 100 means with the actual volume you have for your speakers) … as well as …
  • obey a grandparent edict to either …
    1. mute
    2. unmute

    … the volume as our way to say “keep playing the radio but shush while I take this phone call” in certain scenarios that might happen

… meaning that all the grandparent has to do, effectively “broadcasting” to any “grandchildren YouTube video players”, is “the emoji flagging work” and adjusting (what it knows as) document.title to perform this functionality for the two new input type=checkboxes (appended by an empty span element and nested in a span id=smute element) we add into the HTML design mix via onchange event function Javascript …


function domute(thiscbo) {
if (thiscbo.checked) {
thiscbo.style.backgroundColor='yellow';
document.getElementById('cbunmute').style.backgroundColor='white';
document.getElementById('smute').innerHTML=document.getElementById('smute').innerHTML.replace('>Mute' + document.getElementById('smute').innerHTML.split('>Mute')[1].split('<')[0] + '<', '>Mute ' + '&#10004;<').replace('>Unmute' + document.getElementById('smute').innerHTML.split('>Unmute')[1].split('<')[0] + '<', '>Unmute<');
if (document.title.indexOf('volume:') != -1) {
var rest='volume:' + document.title.split('volume:')[1];
document.title=document.title.replace(rest, rest.replace(document.title.split('volume:')[1].toLowerCase().replace(/^\ /g,'').replace(/^\ /g,'').replace(/^\ /g,'').split(' ')[0].split(',')[0].split(';')[0].split('|')[0], 'mute'));
} else {
thiscbo.style.backgroundColor='white';
document.title+=' volume:mute';
}
thiscbo.checked=false;
}
}

function dounmute(thiscbo) {
if (thiscbo.checked) {
thiscbo.style.backgroundColor='yellow';
document.getElementById('cbmute').style.backgroundColor='white';
document.getElementById('smute').innerHTML=document.getElementById('smute').innerHTML.replace('>Unmute' + document.getElementById('smute').innerHTML.split('>Unmute')[1].split('<')[0] + '<', '>Unmute ' + '&#10004;<').replace('>Mute' + document.getElementById('smute').innerHTML.split('>Mute')[1].split('<')[0] + '<', '>Mute<');
if (document.title.indexOf('volume:') != -1) {
var rest='volume:' + document.title.split('volume:')[1];
document.title=document.title.replace(rest, rest.replace(document.title.split('volume:')[1].toLowerCase().replace(/^\ /g,'').replace(/^\ /g,'').replace(/^\ /g,'').split(' ')[0].split(',')[0].split(';')[0].split('|')[0], 'unmute'));
} else {
thiscbo.style.backgroundColor='white';
document.title+=' volume:unmute';
}
thiscbo.checked=false;
}
}

It is this complex because (we found out) input type=checkbox CSS styling, as a subject, is a “bit of a closed book” matter!

Codewise, also regarding email and SMS (radio) playlist sharing functionality, amongst other changes, involved …


Previous relevant YouTube Video API Event Stop Propagation Idea Tutorial is shown below.

YouTube Video API Event Stop Propagation Idea Tutorial

YouTube Video API Event Stop Propagation Idea Tutorial

We’re back using the YouTube API video playing themes of YouTube Video API Interfacer Audio Play Tutorial as a means to setting up a web application that may help explain …


event.stopPropagation();

… Javascript event control of it’s “bubbling” (up through an element hierarchy), in other words, depending where you place this, stopping it’s “bubbling up” at that element concerned …

The stopPropagation() method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases. It does not, however, prevent any default behaviors from occurring; for instance, clicks on links are still processed. If you want to stop those behaviors, see the preventDefault() method. It also does not prevent propagation to other event-handlers of the current element. If you want to stop those, see stopImmediatePropagation().

We find, around here, we don’t know we’ve created a need for event.stopPropagation() usage until we’ve stumbled onto it, most of the time, so trying to get in ahead of it with today’s proof of concept to event.stopPropagation() or not to event.stopPropagation() web application feels a bit novel to us, in a good way.

This means by which to toggle that mode of use was more straightforward than “data control” with our musical YouTube API video functionality allowing a user to choose and slot in their own video ideas via either …

  • YouTube video ID … 11 characters long … or …
  • search string to try to select a video, via a programmatically populated dropdown, with an 11 character long YouTube video ID

… asking us to do a fair bit of tweaking to our inhouse interfacing …

… you might want to try out, yourself, to see what we’re getting at here, below …


Previous relevant YouTube Video API Interfacer Audio Play Tutorial is shown below.

YouTube Video API Interfacer Audio Play Tutorial

YouTube Video API Interfacer Audio Play Tutorial

The recent Making Of Earth Scanner Legs Tutorial set us to thinking about how to offer a toggling arrangement between our inhouse YouTube Embedded Iframe API playing of …

  • video … with an incarnation of this that plays …
  • audio … “sort of” only (but able to be toggled back to video playing)

… and it got us wondering how to “dull out” a video. We chose the CSS …

<style>

iframe { filter: invert(45%); }

</style>

If you want a “complete dull out” try filter: invert(50%); … but we wanted to see controls down the bottom, still useful for audio only playing.

You can try this all out in the changed karaoke_youtube_api.htm inhouse YouTube video interfacer.

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


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


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


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


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


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


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


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


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

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

WebGL Google Chrome Configuration Issue Tutorial

WebGL Google Chrome Configuration Issue Tutorial

WebGL Google Chrome Configuration Issue Tutorial

On our macOS 14.5 (23F79) Google Chrome web browser Version 130.0.6723.70 (Official Build) (arm64) we had an issue revisiting the WebGL API using inhouse web application we last talked about with WebGL Prism Canvas Email Tutorial. Other web browsers such as Safari or Firefox or Opera do not have the issue for us.

Perhaps, on your Google Chrome web browser, clicking that “inhouse web application” link above, you too, get the error message …

It doesn’t appear your computer can support WebGL.

? Well, we were able to turn that around for our AlmaLinux adjusted webgl_test.html WebGL using inhouse web application via …

  1. stumbled upon great advice from this useful link, thanks … to … type into Google Chrome address bar …

  2. chrome:gpu

    … where …
  3. the ensuing report showed …

    * OpenGL: Disabled

    … so we …

  4. got to …

    chrome://settings/system

    … in our case, via Chrome -> Settings… -> System
  5. to find … Use graphics acceleration when available … set to Off (as the default) … so …
  6. we set … Use graphics acceleration when available … to On
  7. and clicked Relaunch button

… to make this web application “start talking” on Google Chrome.


Previous relevant WebGL Prism Canvas Email Tutorial is shown below.

WebGL Prism Canvas Email Tutorial

WebGL Prism Canvas Email Tutorial

Today we’re revisiting our “Convex Polygon shape with an added dimension by displaying its 3D prism equivalent via the WebGL API scenario”, we last talked about with PHP and Javascript and CSS WebGL Prism Tutorial as shown below. We revisit with a view to …

  • make it more aesthetically pleasing, we hope
  • centre the main graphical elements of the web application when unsupervised and avoid our old “sinful” align=’center’ “habit” usage we talked about at W3C XHTML Nu Checker Validation Primer Tutorial going on, which we diligently changed to style=” width:100%;text-align:center; “ here today … when unsupervised, but …
  • left justify the main graphical elements of the web application when supervised, so this involved detecting “supervision” and Javascript DOM changes at …

    window.onload = function init() {
    if (document.URL.indexOf('huh=') != -1 || parent.document.getElementById('glcanvas') != null || (document.referrer.indexOf('/HTMLCSS/ShapeDraw') != -1 && document.referrer.indexOf('.htm') == -1)) {
    document.getElementById('myform').innerHTML+='<input type=hidden name=huh value=></input>';
    document.getElementById('mydiv').style.position='absolute';
    document.getElementById('mydiv').style.top='0px';
    document.getElementById('mydiv').style.left='0px';
    document.getElementById('mydiv').style.width='300px';
    document.getElementById('mydiv').style.textAlign='left';
    document.getElementById('mydiv').innerHTML='<canvas id="gl-canvas" width="300" height="300"></canvas>';
    document.getElementById('mydiv2').style.position='absolute';
    document.getElementById('mydiv2').style.top='310px';
    document.getElementById('mydiv2').style.left='0px';
    document.getElementById('mydiv2').style.textAlign='left';
    document.getElementById('mydiv3').style.position='absolute';
    document.getElementById('mydiv3').style.top='330px';
    document.getElementById('mydiv3').style.left='0px';
    document.getElementById('mydiv3').style.textAlign='left';
    } else {
    document.getElementById('mydiv').innerHTML='<canvas id="gl-canvas" width="400" height="400"></canvas>';
    }

    canvas = document.getElementById( "gl-canvas" );
    // more follows ...
  • adding new Email functionality via mailto: tags linking to the user’s default Email client program, featuring the ability to …
  • have the body section of that email be able to have a clipboard image pasted into it, for which we can utilize HTML5 canvas element’s toDataURL() method, teamed up with a window.open popup window of the toDataURL image data, which can be selected and copied, optionally, by the user themselves, should they wish this to make their email more self explanatory … and that canvas element’s “meeting of minds” with WebGL changing as per …

  • gl = WebGLUtils.setupWebGL( canvas, {preserveDrawingBuffer:true} );

    … the help for which we got great ideas from this useful link, thanks, and which allows the canvas element content to be retained long enough to be available for the toDataURL() call of it

As we’ve said before about email, as a communication tool, its use can add a lot of accountability to your web applications, as well as being a great “sharing” method.

So please feel free to try …

When will we see you … again … da, da da, da da?


Previous relevant PHP and Javascript and CSS WebGL Prism Tutorial is shown below.

PHP and Javascript and CSS WebGL Prism Tutorial

PHP and Javascript and CSS WebGL Prism Tutorial

To infinity and beyond!! … well, at least to the 3rd dimension … yes, we’re rejoining our Geometry and Land Surveying theme today, rejoining the discussion of PHP and Javascript and CSS Shape Rotation Tutorial as shown below, but giving some additional functionality to show the Convex Polygon shape with an added dimension by displaying its 3D prism equivalent via the WebGL API, modelling the additional code via the public generosity and wonderful resources from the University of New Mexico … our heartfelt thanks.

If you have been a recent reader you’ll have seen that we have been discussing OpenGL. OpenGL has a OpenGL.org landing page which will talk about all the platforms supported, and let’s just remind you about the purpose, with a quote from the webpage …

The Industry’s Foundation for High Performance Graphics
from games to virtual reality, mobile phones to supercomputers

… well, today, we use some of that knowledge … some being the operative word, and we’ll talk more on this tomorrow, but … with the sequence of blog posts culminating in C++ OpenGL in Xcode Generic Regular Prism Drawing Tutorial we learnt some things about graphics software and the concepts of …

  • object vertices definition
  • object colour
  • lighting … direction, type, angle, numbers of sources etcetera
  • perspective … field of view, aspect ratio, Z position

… and the Land Surveying use of thinking about Survey Traverses as an idea to genericize the vertex definition phase, as this is the major difference between drawing a “cube” or a “hexagonal prism” or a “butterfly in Brazil” (just kidding … that’s for tomorrow (in Klingon time)).

So the wonderful code from the University of New Mexico (via StackOverflow) was to show a cube, and the use of buttons to display animation and rendering “smarts” … so am really really really keen for you to examine this additional HTML code of today you could call webgl_test.html … we change it to add some Land Surveying feeling to the creation of vertices for our Convex Polygon extended into a Prism arrangement as per the Javascript code …


var numsides = location.search.split('numsides=')[1] ? location.search.split('numsides=')[1].split('&')[0] : 4;
var NumVertices = eval((numsides * 2) * 3);
var evalc="", evalcol="";
var delim="[";
var sidelen=eval((1.0 * 3.0) / numsides);
var x=eval(0.0 - (sidelen / 2.0) * (numsides / 3)), y=eval(0.0 - (sidelen / 2.0) * (numsides / 3)), z=1.5, otherz=0.5, thisis=1;
var bearing=0.0;
var prevbearing;
var nextx, nexty, nextis=2;
var prevx, prevy, previs=numsides, downis=eval(numsides);
downis++;
evalc="";
for (ij=0; ij<eval(numsides * 2); ij++) {
if (ij == numsides) {
z=0.5;
otherz=1.5;
}
nextx=eval(x + sidelen * Math.sin(bearing / 57.2957795));
if (Math.abs(nextx) < 0.00001) nextx = 0.0;
nexty=eval(y + sidelen * Math.cos(bearing / 57.2957795));
if (Math.abs(nexty) < 0.00001) nexty = 0.0;
prevbearing = ((bearing + 540 - (360.0 / numsides)) % 360.0);
prevx=eval(x + sidelen * Math.sin(prevbearing / 57.2957795));
if (Math.abs(prevx) < 0.00001) prevx = 0.0;
prevy=eval(y + sidelen * Math.cos(prevbearing / 57.2957795));
if (Math.abs(prevy) < 0.00001) prevy = 0.0;
if (eval((ij + 1) % numsides) != 0) {
evalc += (delim + "vec4(" + x + "," + y + "," + z + ",1.0) /" + "/" + thisis + "\n");
evalcol += (delim + "vec4( 1.0, 0.0, 0.0, 1.0 ) /" + "/red \n");
delim=",";
evalc += (delim + "vec4(" + nextx + "," + nexty + "," + z + ",1.0) /" + "/" + nextis + "\n");
evalcol += (delim + "vec4( 1.0, 0.0, 0.0, 1.0 ) /" + "/red \n");
}
if ((ij % numsides) == 0) {
evalc += (delim + "vec4(" + x + "," + y + "," + z + ",1.0) /" + "/" + thisis + "\n");
evalcol += (delim + "vec4( 1.0, 0.0, 0.0, 1.0 ) /" + "/red \n");
evalc += (delim + "vec4(" + prevx + "," + prevy + "," + z + ",1.0) /" + "/" + previs + "\n");
evalcol += (delim + "vec4( 1.0, 0.0, 0.0, 1.0 ) /" + "/red \n");
previs = eval(previs * 2);
}
if (ij < numsides) {
evalc += (delim + "vec4(" + x + "," + y + "," + z + ",1.0) /" + "/" + thisis + "\n");
evalcol += (delim + "vec4( 1.0, 0.0, 0.0, 1.0 ) /" + "/red \n");
evalc += (delim + "vec4(" + x + "," + y + "," + otherz + ",1.0) /" + "/" + downis + "\n");
evalcol += (delim + "vec4( 1.0, 0.0, 0.0, 1.0 ) /" + "/red \n");
}
x = nextx;
y = nexty;
thisis++;
nextis++;
downis++;
bearing += (360.0 / numsides);
}
evalc += "];";
evalcol += "];";
var vertices;
vertices = eval(evalc);

WebGL API performs its graphics via the use of the HTML5 canvas element. We’ll be discussing more on this topic, no doubt, as time goes on.

Here is a link to Shape Draw live run (with Google Line Chart and HTML svg and WebGL 3D Prism drawing and University of New Mexico inspired animation functionality) here.
Here is a link to Shape Draw PHP source code ShapeDraw.php with changes from previous code as per this link.

Try it out, and get into web based 3D graphics via the WebGL API … you’ll be drawing prism animals before the sun goes down!


Previous relevant PHP and Javascript and CSS Shape Rotation Tutorial is shown below.

PHP and Javascript and CSS Shape Rotation Tutorial

PHP and Javascript and CSS Shape Rotation Tutorial

We’re continuing on with our Geometry and Land Surveying theme today, following on from yesterday’s PHP and Javascript and CSS Shape Drawing Tutorial as shown below. When there are only small distances we talk about Plane Geometry because the curvature of the earth doesn’t come into the equation. When Earth curvature matters, over longer distances, in Land Surveying the term Geodetic Surveying is often used. Here, the equations used need to model the Earth as close as possible to known measurements.

If you read yesterday’s posting you’ll see that we added some popup window functionality to display the Convex Polygon created by the web application in a relative sense, and to do this we called on (where variable “opop” is global in scope) …


  • opop = window.open("", "Polygon " + numlegs, "left=400,top=250,height=" + parseFloat(50 + maxy) + ",width=" + parseFloat(50 + maxx));

  • opop.document.write([someDerivedHTML]);

We’re here, today, to remind you, that that popup doesn’t have to be like a dead fish, just displaying information. It can be interactive itself, and is known to the “parent” window, so can have its own “hidden input” HTML element (for example) as per …


<input id="myunload" type="hidden" value=""></input>

… that is updated when a button as per (this function, that is used to create this button and a related dropdown) …


function buttonideas() {
var crotate1 = "<input type='button' onclick=' if (document.getElementById(\"myunload\") != null) { document.getElementById(\"myunload\").value=\"" + initiallength + "," + numlegs + "," + "\" + document.getElementById(\"myselect\").value; }' value='Rotate Clockwise'></input> <select id='myselect'><option value='" + eval(180.0 / numlegs) + "'>By " + eval(180.0 / numlegs) + "° ... vs ...</option></select>";
for (var steps=0; steps<=360; steps++) {
crotate1=crotate1.replace("</option></select>", "</option><option value='" + steps + "'>By " + steps + "°</option></select>");
}
return crotate1;
}

… then our “parent” window can swing into action via a setInterval() scenario (where variable sipos is global) …


sipos = setInterval(takealook, 5000);

… with code like …


function takealook() {
var things;
if (opop != null) {
if (opop.document.getElementById('myunload').value.indexOf(",") != -1) {
things = opop.document.getElementById('myunload').value.split(",");
opop.close();
opop = null;
if (things.length >= 3) {
if (sipos != null) { clearInterval(sipos); sipos = null; }
var bis = 0.0;
bis += parseFloat(initialbearing);
bis += parseFloat(things[2]);
window.location = "./ShapeDraw.php?sides=" + things[1] + ",0&length=" + things[0] + "&bearing=" + posval(bis);
}
}
}
}

… to allow for some HTML “svg” element rotation functionality, if the button is pressed, that is. One last nicety is to use the Window Event “onunload” to clear the setInterval handler with a web browser close or a user closing the parent webpage as per …


<body onunload=" if (sipos != null) { clearInterval(sipos); sipos = null; }" style="background-color: #fffff0;">

Link to Shape Draw live run (with Google Line Chart and HTML svg functionality) here.
Link to Shape Draw PHP source code ShapeDraw.php with changes from code yesterday as per this link.

You may be interested in CSS3 ways to rotate HTML elements as well, so we’ll leave you with this link to point you in the direction of where we have discussed this previously.


Previous relevant PHP and Javascript and CSS Shape Drawing Tutorial is shown below.

PHP and Javascript and CSS Shape Drawing Tutorial

PHP and Javascript and CSS Shape Drawing Tutorial

It is no coincidence that Geometry and Land Surveying have a lot in common. When there are only small distances we talk about Plane Geometry because the curvature of the earth doesn’t come into the equation. When Earth curvature matters, over longer distances, in Land Surveying the term Geodetic Surveying is often used. Here, the equations used need to model the Earth as close as possible to known measurements.

So today, with our Plane Geometry web application, we start with our previous Survey Traverse web application, and add to its functionality with ability for it to fill out more for the user to describe a regular polygon of their choosing, defined by …

  1. number of polygon sides
  2. length of each polygon side

We also add to the Google Charts Line Graph of the Drawn Shape a popup window showing the polygon as an HTML svg element. Part of the reason for this is that the Google Chart Line Graph can exaggerate the x or y co-ordinate of its plots, but with the HTML svg element, you avoid this issue, as we are just showing you a “relative” view of the shape (ie. as distinct from an “absolute” view with distinct co-ordinates).

The thinking here started with a look at New Century Maths stages 5.2/5.3 “Exterior angle sum of a convex polygon”. Did you know?

The sum of the exterior angles of a convex polygon is 360°.

What we found to be the case, practically speaking, to imagine the drawing of a regular even-sided convex polygon (with “numsides” sides) was …

  • look north …
  • turn clockwise (360° / numsides) for first line to draw (NB. there is more symmetry if this number is then divided by 2) … then from then on …
  • off this previous line, turn clockwise (180° + (360° / numsides)) for subsequent lines

Link to Shape Draw live run (with Google Line Chart and HTML svg functionality) here.
Link to Shape Draw PHP source code ShapeDraw.php with changes from code below as per this link.

Hope you enjoy the geometry ideas, and will leave you with a very useful link that helped with the Convex Polygon method to calculate the Surface Area here.


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

HTML and Javascript and CSS Survey Traverse Tutorial

HTML and Javascript and CSS Survey Traverse Tutorial

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

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

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

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

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

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

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


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


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


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


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


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

Posted in Event-Driven Programming, GUI, Operating System, Software, Tutorials | Tagged , , , , , , , , , , , , , , , , , , , , , , , , | Leave a comment

YouTube Video API Event Playlist User Settings Tutorial

YouTube Video API Event Playlist User Settings Tutorial

YouTube Video API Event Playlist User Settings Tutorial

We’re happy to be talking about three new pieces of functionality to add to our recent YouTube API interfacing Song Playing web application last talked about with the recent YouTube Video API Event Playlist Background Image Tutorial, those being …

  1. 📹 ( &#128249; ) means by which a user can choose to suppress the video aspects (but not the controls) to the YouTube video “parent” level webpage(s) we display
  2. 📜 ( &#128220; ) scroll emoji allowing the Radio playing web application aspects push the relevant video playing parts to the top of the screen
  3. colour picker can allow user tailoring of the background colour to the “parent” level webpages supervising the “grandchild” players of the YouTube videos

These all rely on document.title settings …


function fixtitlecolour(inic) {
if (document.title.indexOf(origtitle) == -1) {
if (document.title.indexOf('Playlist playing ...') != -1) {
origtitle='Playlist playing ...';
}
}
if (('' + inic).toLowerCase().indexOf('ffff00') != -1) {
if (document.title.indexOf(' background:') != -1) {
document.title=document.title.replace(' ' + document.title.split(' background:')[1].replace(' !important; background','~ background').split(';')[0].replace('~',' !important;') + ';', ' ');
document.getElementById('karit').src=backiurl.replace('rand=', 'rand=' + Math.floor(Math.random() * 23));
}
} else {
if (document.title.indexOf(' background:') != -1) {
document.title=document.title.replace(' ' + document.title.split(' background:')[1].replace(' !important; background','~ background').split(';')[0].replace('~',' !important;') + ';', ' ');
}
document.title=document.title.replace(origtitle, origtitle + ' background:linear-gradient(180deg,#' + inic.value.replace('#','') + ',#' + inic.value.replace('#','') + ') !important; background-color:#' + inic.value.replace('#','') + ' !important; ');
document.getElementById('karit').src=backiurl.replace('rand=', 'rand=' + Math.floor(Math.random() * 23));
}
return true;
}

function togglesiv(aiois) {
var aih=aiois.innerHTML, bih='';
if (aih.indexOf('</strike>') == -1) {
aiois.innerHTML='<strike>' + aih + '</strike>';
} else {
aiois.innerHTML=aih.replace('<strike>','').replace('</strike>','');
}
}

function togglejustaudio(aiois) {
var aih=aiois.innerHTML, bih='';
if (aih.indexOf('</strike>') == -1) {
if (document.title.indexOf(' justaudio ') == -1) {
if (document.title.indexOf(origtitle) == -1) {
if (document.title.indexOf('Playlist playing ...') != -1) {
origtitle='Playlist playing ...';
}
}
if (document.title.indexOf(' background:') != -1) {
document.title=document.title.replace(' ' + document.title.split(' background:')[1].replace(' !important; background','~ background').split(';')[0].replace('~',' !important;') + ';', ' ');
}
document.title=document.title.replace(origtitle, origtitle + ' justaudio background:linear-gradient(180deg,transparent,transparent) !important; background-color:transparent !important; ');
document.getElementById('karit').src=backiurl.replace('rand=', 'rand=' + Math.floor(Math.random() * 23));
}
aiois.innerHTML='<strike>' + aih + '</strike>';
if (document.getElementById('bplay')) {
if (document.getElementById('bplay').innerHTML.indexOf('  ') != -1 && document.getElementById('bplay').innerHTML.indexOf('audio') == -1) {
bih=document.getElementById('bplay').innerHTML.split('  ')[1];
document.getElementById('bplay').innerHTML=document.getElementById('bplay').innerHTML.split('  ')[0] + '  just audio ' + bih;
}
}
} else {
document.title=document.title.replace(/\ justaudio\ /g,' ');
aiois.innerHTML=aih.replace('<strike>','').replace('</strike>','');
if (document.getElementById('bplay').innerHTML.indexOf('  ') != -1 && document.getElementById('bplay').innerHTML.indexOf('audio') != -1) {
bih=document.getElementById('bplay').innerHTML.indexOf('  ')[1];
document.getElementById('bplay').innerHTML=document.getElementById('bplay').innerHTML.replace('  just audio ','  ');
}
}
}

Codewise, it was all of the “the three amigos”, at it again …

… that got involved.


Previous relevant YouTube Video API Event Playlist Background Image Tutorial is shown below.

YouTube Video API Event Playlist Background Image Tutorial

YouTube Video API Event Playlist Background Image Tutorial

Our current project last talked about with YouTube Video API Event Playlist Shuffle and Loop Tutorial started as a …

  • “proof of concept” one to allow for user testing of event.stopPropagation() Javascript event bubbling control usage … and yet, is also a …
  • player of YouTube videos using the YouTube API inhouse interfacing here

… and it is the second functionality we want to emphasize. In such scenarios, we sometimes apply an apt Background Image (we’re applying to all document.body) via


<style>
td { vertical-align: top; }
select { background-color: lightblue; }
option:not(:checked) { background-color: yellow; opacity: 0.5; }
textarea { background-color: #f0f0f0; }
body {
background-image:linear-gradient(rgba(255,255,255,0.8),rgba(255,255,255,0.8)),URL('/retro-music-concept-with-headphones-space.jpg');
background-size:cover;
background-repeat:no-repeat;
}

* { border-radius:10px; border-color:magenta; }
</style>

… and regarding /retro-music-concept-with-headphones-space.jpg we have Freepik to thank for the free headphones background image we found there and downloaded then uploaded into place.

While we’re talking styling another CSS measure we often use to change the aesthetics of a webpage look is to soften some squared off borders via the application of a border-radius.

The meta viewport tag came in handy for this project, as another layer, for mobile platforms, of allowing mobile gestures to genuinely improve the video viewing, for the user …


<meta id='myviewport' name='viewport' content='width=device-width, initial-scale=1, minimum-scale=0.1, maximum-scale=8, user-scalable=yes' >

Another matter with mobile usage and a personalized playlist play scenario was that the use of the Mute and Unmute checkboxes at the “grandparent” level did not amount to a real click at the “grandchild” level, and so we started involving Javascript confirm box querying of users here, and this satisfied as a real user click for mobile platform media play purposes.

Codewise, all of the “the three amigos”, at it again …

… got involved.


Previous relevant YouTube Video API Event Playlist Shuffle and Loop Tutorial is shown below.

YouTube Video API Event Playlist Shuffle and Loop Tutorial

YouTube Video API Event Playlist Shuffle and Loop Tutorial

We left our Song Playing web application in YouTube Video API Event Playlist Save and Recall Tutorial

  • on mobile, needing a lot of “user tap maintenance” to keep the “personalized playlist” (consisting of YouTube ID video) music rolling … hence our …

    And yes, we want to try to get a mobile Radio scenario working for mobile, perhaps, by researching YouTube API (their) playlists … no guarantees, as you’d imagine!

    … from a preceeding tutorial … well … we still allow that mode of use, but add to that, the possibility of …

  • on mobile or non-mobile, we now offer the referencing of …
    1. YouTube Playlist IDs (34 characters) … or …
    2. Spotify Playlist IDs (22 characters)

    … so that shuffling and, in the case of YouTube Playlists using the YouTube App (if on mobile), looping can be part of the mix in your Song Plays (now appearing in the web application title … doh!! … yay!!!!)

The way to access this new functionality, above, is via the “now always appearing” 🍪 ( &#127850; Cookie button ) new prompt window arrangement


var xname='';
if (('' + location.hash).replace(/^\#/g,'') != '') {
xname=prompt('Recall name for this playlist. Understand that 34 character words will be seen as YouTube Playlist IDs or 22 character words will be seen as Spotify Playlist IDs for which we will start the ball rolling, and present them ready for you to play. Spaces at front results in a request to us at RJM Programming to host your proposed playlist on our YouTube channel and we will return a 34 character ID you can use yourself in the textbox presented. Add spaces at end also to just attend to that email off to RJM Programming.', '');
} else {
xname=prompt('Please optionally enter a recallable YouTube (34) or Spotify (22) playlist ID we will save for you from here on in optionally suffixed by # hashtag separated playlist title. Understand that 34 character words will be seen as YouTube Playlist IDs or 22 character words will be seen as Spotify Playlist IDs for which we will start the ball rolling, and present them ready for you to play. Our supplied YouTube playlist ID example is Nala and Luna (mainly) but please use Cancel to avoid remembering this playlist into the future.', 'PLjsR7WjAKSPU-6URvzZ552o5cvQ2p2GYE#Nala and Luna');
if (xname != null) { if (eval('' + xname.indexOf('#')) > 0) { btoaname=encodeURIComponent(xname.split('#')[1].replace(/\ /g,'_')); xname=xname.split('#')[0]; } usethisnotlh=xname; }
}

… that is possible when no personalized playlist hashtag data is in the mix. If it is, well, that opens another whole story all the way through to allowing the user to (email) request the creation of their personalized list of YouTube video IDs becoming a public facing YouTube Playlist hosted on the RJM Programming YouTube Channel, whereby we moderate, here, and if all passes muster, we return a 34 character YouTube Playlist ID the user can save from then on as a playlist on mobile or non-mobile capable of shuffling and looping (if the YouTube App is invoked, on mobile).

We’ve allowed those YouTube search results to “linger longer” too, by replicating them at the “grandparent level” at the point of time we wipe them from the “parent level”, the latest set appearing just below those top three options we now have going for both non-mobile and mobile platforms.

Codewise, two of the “the three amigos” were at it again …


Previous relevant YouTube Video API Event Playlist Save and Recall Tutorial is shown below.

YouTube Video API Event Playlist Save and Recall Tutorial

YouTube Video API Event Playlist Save and Recall Tutorial

Meanwhile, back at the wishlist, with our recent YouTube API interfacing web application project …

st*_st* way to set mute straight away via $_GET[‘mute’] and/or blanks in duration get and a hashtag way to temporarily mute
Save a playlist for later via window.localStorage
Share a playlist
Radio and Oneatatime with a straight hashtag URL
Mute and unmute dynamically
Turn “-” into a reset link

Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)

… it is the olive ideas we’ve made a start on today. We say “we’ve made a start on” only because, when it comes to programming, it doesn’t pay to close off alternate ideas as you go about looking for solutions. Take “Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)(for some reason we’re nicknaming “innerHTML” … who wrote this script)

… well, yes, that would be nice, but, more to the point, we started involving top.document.title in solution making but then, along the way, started incorporating just plain and simple Javascript get/set functionality


var ajaxs_ih='';


function get_ajaxs_ih() {
return ajaxs_ih;
}


function set_ajaxs_ih(wht) {
ajaxs_ih=wht;
}

parent.get_ajaxs_ih() and parent.set_ajaxs_ih(strIn) references from the “parent” level referencing the “grandparent” level (of code above) and being able to populate those YouTube search dropdowns more efficiently. This get/set paradigm is “a classic” methodology in a lot of OOP work, further to the recent YouTube Video API Event Radio Play Sharing Tutorial.

Codewise, again, “the three amigos” were at it again …


Previous relevant YouTube Video API Event Radio Play Sharing Tutorial is shown below.

YouTube Video API Event Radio Play Sharing Tutorial

YouTube Video API Event Radio Play Sharing Tutorial

Wishful thinking with today’s tasklist regarding our current YouTube Video API Event Radio Play Idea Tutorial YouTube API interfacing web application project, where the blue ideas were started …

st*_st* way to set mute straight away via $_GET[‘mute’] and/or blanks in duration get and a hashtag way to temporarily mute
Save a playlist for later via window.localStorage
Share a playlist
Radio and Oneatatime with a straight hashtag URL
Mute and unmute dynamically
Turn “-” into a reset link

Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)

… further to yesterday’s YouTube Video API Event Radio Play Idea Tutorial

And yes, we want to try to get a mobile Radio scenario working for mobile, perhaps, by researching YouTube API (their) playlists … no guarantees, as you’d imagine!

Of interest, here, might be the “emoji means” and top.document.title means by which we tackle the Mute and unmute dynamically issue. Why use top.document.title here? Well, a grandchild of the grandparent is best placed to …

  • tell the grandparent the non-muted volume (which seems to always be 100, as you control what 100 means with the actual volume you have for your speakers) … as well as …
  • obey a grandparent edict to either …
    1. mute
    2. unmute

    … the volume as our way to say “keep playing the radio but shush while I take this phone call” in certain scenarios that might happen

… meaning that all the grandparent has to do, effectively “broadcasting” to any “grandchildren YouTube video players”, is “the emoji flagging work” and adjusting (what it knows as) document.title to perform this functionality for the two new input type=checkboxes (appended by an empty span element and nested in a span id=smute element) we add into the HTML design mix via onchange event function Javascript …


function domute(thiscbo) {
if (thiscbo.checked) {
thiscbo.style.backgroundColor='yellow';
document.getElementById('cbunmute').style.backgroundColor='white';
document.getElementById('smute').innerHTML=document.getElementById('smute').innerHTML.replace('>Mute' + document.getElementById('smute').innerHTML.split('>Mute')[1].split('<')[0] + '<', '>Mute ' + '&#10004;<').replace('>Unmute' + document.getElementById('smute').innerHTML.split('>Unmute')[1].split('<')[0] + '<', '>Unmute<');
if (document.title.indexOf('volume:') != -1) {
var rest='volume:' + document.title.split('volume:')[1];
document.title=document.title.replace(rest, rest.replace(document.title.split('volume:')[1].toLowerCase().replace(/^\ /g,'').replace(/^\ /g,'').replace(/^\ /g,'').split(' ')[0].split(',')[0].split(';')[0].split('|')[0], 'mute'));
} else {
thiscbo.style.backgroundColor='white';
document.title+=' volume:mute';
}
thiscbo.checked=false;
}
}

function dounmute(thiscbo) {
if (thiscbo.checked) {
thiscbo.style.backgroundColor='yellow';
document.getElementById('cbmute').style.backgroundColor='white';
document.getElementById('smute').innerHTML=document.getElementById('smute').innerHTML.replace('>Unmute' + document.getElementById('smute').innerHTML.split('>Unmute')[1].split('<')[0] + '<', '>Unmute ' + '&#10004;<').replace('>Mute' + document.getElementById('smute').innerHTML.split('>Mute')[1].split('<')[0] + '<', '>Mute<');
if (document.title.indexOf('volume:') != -1) {
var rest='volume:' + document.title.split('volume:')[1];
document.title=document.title.replace(rest, rest.replace(document.title.split('volume:')[1].toLowerCase().replace(/^\ /g,'').replace(/^\ /g,'').replace(/^\ /g,'').split(' ')[0].split(',')[0].split(';')[0].split('|')[0], 'unmute'));
} else {
thiscbo.style.backgroundColor='white';
document.title+=' volume:unmute';
}
thiscbo.checked=false;
}
}

It is this complex because (we found out) input type=checkbox CSS styling, as a subject, is a “bit of a closed book” matter!

Codewise, also regarding email and SMS (radio) playlist sharing functionality, amongst other changes, involved …


Previous relevant YouTube Video API Event Stop Propagation Idea Tutorial is shown below.

YouTube Video API Event Stop Propagation Idea Tutorial

YouTube Video API Event Stop Propagation Idea Tutorial

We’re back using the YouTube API video playing themes of YouTube Video API Interfacer Audio Play Tutorial as a means to setting up a web application that may help explain …


event.stopPropagation();

… Javascript event control of it’s “bubbling” (up through an element hierarchy), in other words, depending where you place this, stopping it’s “bubbling up” at that element concerned …

The stopPropagation() method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases. It does not, however, prevent any default behaviors from occurring; for instance, clicks on links are still processed. If you want to stop those behaviors, see the preventDefault() method. It also does not prevent propagation to other event-handlers of the current element. If you want to stop those, see stopImmediatePropagation().

We find, around here, we don’t know we’ve created a need for event.stopPropagation() usage until we’ve stumbled onto it, most of the time, so trying to get in ahead of it with today’s proof of concept to event.stopPropagation() or not to event.stopPropagation() web application feels a bit novel to us, in a good way.

This means by which to toggle that mode of use was more straightforward than “data control” with our musical YouTube API video functionality allowing a user to choose and slot in their own video ideas via either …

  • YouTube video ID … 11 characters long … or …
  • search string to try to select a video, via a programmatically populated dropdown, with an 11 character long YouTube video ID

… asking us to do a fair bit of tweaking to our inhouse interfacing …

… you might want to try out, yourself, to see what we’re getting at here, below …


Previous relevant YouTube Video API Interfacer Audio Play Tutorial is shown below.

YouTube Video API Interfacer Audio Play Tutorial

YouTube Video API Interfacer Audio Play Tutorial

The recent Making Of Earth Scanner Legs Tutorial set us to thinking about how to offer a toggling arrangement between our inhouse YouTube Embedded Iframe API playing of …

  • video … with an incarnation of this that plays …
  • audio … “sort of” only (but able to be toggled back to video playing)

… and it got us wondering how to “dull out” a video. We chose the CSS …

<style>

iframe { filter: invert(45%); }

</style>

If you want a “complete dull out” try filter: invert(50%); … but we wanted to see controls down the bottom, still useful for audio only playing.

You can try this all out in the changed karaoke_youtube_api.htm inhouse YouTube video interfacer.

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


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


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


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


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


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


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


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

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

Javascript Object New Method Creator Primer Tutorial

Javascript Object New Method Creator Primer Tutorial

Javascript Object New Method Creator Primer Tutorial

As with Javascript Microtask Primer Tutorial

  • HTML textarea elements … hosting …
  • Javascript code … we want to pass across via …
  • HTML form method=GET … featuring …
  • onsubmit event function logic (and from here on the two have logic differences) …

    function quickbtoa() {
    document.getElementById('newcode').value='' + window.btoa(document.getElementById('newcode').value);
    document.getElementById('usingcode').value='' + window.btoa(document.getElementById('usingcode').value);
    setTimeout(function(){
    document.getElementById('newcode').value='' + window.atob(document.getElementById('newcode').value);
    document.getElementById('usingcode').value='' + window.atob(document.getElementById('usingcode').value);
    }, 2000);
    document.getElementById('ifresults').style.display='block';
    return true;
    }

    … and …
  • received via …

    var newcodeinbtoaed=location.search.split('newcode=')[1] ? decodeURIComponent(location.search.split('newcode=')[1].split('&')[0]) : '';
    var usingcodeinbtoaed=location.search.split('usingcode=')[1] ? decodeURIComponent(location.search.split('usingcode=')[1].split('&')[0]) : '';
    var tag=null;


    function execute() {

    if (newcodeinbtoaed != '') {
    document.getElementById('newcode').value=window.atob(newcodeinbtoaed);
    }

    if (usingcodeinbtoaed != '') {
    document.getElementById('usingcode').value=window.atob(usingcodeinbtoaed);
    }

    if (newcodeinbtoaed != '') {
    tag = document.createElement('script');
    tag.setAttribute("type", "text/javascript");
    tag.innerHTML = window.atob(newcodeinbtoaed);
    document.body.appendChild(tag);
    document.getElementById('footer').innerHTML+='<hr>New Javascript Code</hr>';
    }

    if (usingcodeinbtoaed != '') {
    tag = document.createElement('script');
    tag.setAttribute("type", "text/javascript");
    tag.innerHTML = window.atob(usingcodeinbtoaed);
    document.body.appendChild(tag);
    document.getElementById('footer').innerHTML+='<hr>Using Javascript Code</hr>';
    }
    }

… same, same but different … we want to facilitate a user driven discovery modus operandi towards exploring Javascript object method usage, with a mind to the user creating …

  • overridden methods … and/or …
  • new methods

… and the example we supply as a default, with thanks to this great webpage whose reworking of …


String.fromCodePoint

… fallback has been used by us for years now.

But, Javascript being that incredibly flexible coding language that it is, based on Object Oriented Programming ( ie. OOP ) as required (think DOM, think OOPs) you can create new methods on the fly very easily (as you do so much with OOP).

Pardon our eternal naivety here, but we always think on this with wonder, because of the “verb” functional way we also think of, when we think of Javascript. To us, it’s like you can be inventing coding language on the fly, rather than just “obeying syntax rules”, if you see what we are getting at here. Javascript has this way of satisfying your needs, no matter how those needs roll! Amazing!

Anyway, we thought you might want to enter …

  • Javascript object method … whether that be new or overriding … along with optional …
  • Javascript using that new or overriding Javascript object method

… to try out our new “proof of concept” new Javascript method creator you might want to try below …


Previous relevant Javascript Microtask Primer Tutorial is shown below.

Javascript Microtask Primer Tutorial

Javascript Microtask Primer Tutorial

Javascript, in “clientside mode”, has many more asynchronous ideas than it used to, say, a decade ago, where it was mainly setTimeout and setInterval timer functions we turned to, in this regard. It used to be that any idea of “waiting for JS” was not on, but that does not have to be the case with the modern web browsers using “modern Javascript”. Today, for example, we’ve written a “proof of concept” web application making use of …


queueMicrotask

… with accompanying description …

A microtask is a short function which is executed after the function or program which created it exits and only if the JavaScript execution stack is empty, but before returning control to the event loop being used by the user agent to drive the script’s execution environment.

… which, as you may surmise, allows for a “jumping order of execution” paradigm with your Javascript.

The example code of the queueMicrotask informational webpage made us happy, thanks, and so we wrapped that into a “shell of user usage” by …

  • writing code in PHP … huh?! … so that …
  • we can use navigation via an HTML form method=POST … allowing for large amounts of user written Javascript code they want to dynamically execute … and …
  • as we mentioned with the recent PHP Tokeniser Primer Tutorial talking about “code as content, teamed with navigation using this code data” …
    1. we leave using Javascript window.btoa
      <?php echo ”

      function doit(tdiho) {
      document.getElementById('jcode').value=window.btoa(tdiho.innerText);
      document.getElementById('mysub').click();
      }

      “; ?>
      … hanging off an HTML td contenteditable=true onblur event logic idea … and …
    2. arrive back using PHP base64_decode
      <?php

      if (isset($_POST['jcode'])) {
      $thejcode=base64_decode($_POST['jcode']);
      }

      ?>

    … so as …

  • to better handle the transference of real “+” characters in your data (as code is apt to have)

… as you can see using today’s proof of concept queueMicrotask using web application you can also try below …

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


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

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

YouTube Video API Event Playlist Background Image Tutorial

YouTube Video API Event Playlist Background Image Tutorial

YouTube Video API Event Playlist Background Image Tutorial

Our current project last talked about with YouTube Video API Event Playlist Shuffle and Loop Tutorial started as a …

  • “proof of concept” one to allow for user testing of event.stopPropagation() Javascript event bubbling control usage … and yet, is also a …
  • player of YouTube videos using the YouTube API inhouse interfacing here

… and it is the second functionality we want to emphasize. In such scenarios, we sometimes apply an apt Background Image (we’re applying to all document.body) via


<style>
td { vertical-align: top; }
select { background-color: lightblue; }
option:not(:checked) { background-color: yellow; opacity: 0.5; }
textarea { background-color: #f0f0f0; }
body {
background-image:linear-gradient(rgba(255,255,255,0.8),rgba(255,255,255,0.8)),URL('/retro-music-concept-with-headphones-space.jpg');
background-size:cover;
background-repeat:no-repeat;
}

* { border-radius:10px; border-color:magenta; }
</style>

… and regarding /retro-music-concept-with-headphones-space.jpg we have Freepik to thank for the free headphones background image we found there and downloaded then uploaded into place.

While we’re talking styling another CSS measure we often use to change the aesthetics of a webpage look is to soften some squared off borders via the application of a border-radius.

The meta viewport tag came in handy for this project, as another layer, for mobile platforms, of allowing mobile gestures to genuinely improve the video viewing, for the user …


<meta id='myviewport' name='viewport' content='width=device-width, initial-scale=1, minimum-scale=0.1, maximum-scale=8, user-scalable=yes' >

Another matter with mobile usage and a personalized playlist play scenario was that the use of the Mute and Unmute checkboxes at the “grandparent” level did not amount to a real click at the “grandchild” level, and so we started involving Javascript confirm box querying of users here, and this satisfied as a real user click for mobile platform media play purposes.

Codewise, all of the “the three amigos”, at it again …

… got involved.


Previous relevant YouTube Video API Event Playlist Shuffle and Loop Tutorial is shown below.

YouTube Video API Event Playlist Shuffle and Loop Tutorial

YouTube Video API Event Playlist Shuffle and Loop Tutorial

We left our Song Playing web application in YouTube Video API Event Playlist Save and Recall Tutorial

  • on mobile, needing a lot of “user tap maintenance” to keep the “personalized playlist” (consisting of YouTube ID video) music rolling … hence our …

    And yes, we want to try to get a mobile Radio scenario working for mobile, perhaps, by researching YouTube API (their) playlists … no guarantees, as you’d imagine!

    … from a preceeding tutorial … well … we still allow that mode of use, but add to that, the possibility of …

  • on mobile or non-mobile, we now offer the referencing of …
    1. YouTube Playlist IDs (34 characters) … or …
    2. Spotify Playlist IDs (22 characters)

    … so that shuffling and, in the case of YouTube Playlists using the YouTube App (if on mobile), looping can be part of the mix in your Song Plays (now appearing in the web application title … doh!! … yay!!!!)

The way to access this new functionality, above, is via the “now always appearing” 🍪 ( &#127850; Cookie button ) new prompt window arrangement


var xname='';
if (('' + location.hash).replace(/^\#/g,'') != '') {
xname=prompt('Recall name for this playlist. Understand that 34 character words will be seen as YouTube Playlist IDs or 22 character words will be seen as Spotify Playlist IDs for which we will start the ball rolling, and present them ready for you to play. Spaces at front results in a request to us at RJM Programming to host your proposed playlist on our YouTube channel and we will return a 34 character ID you can use yourself in the textbox presented. Add spaces at end also to just attend to that email off to RJM Programming.', '');
} else {
xname=prompt('Please optionally enter a recallable YouTube (34) or Spotify (22) playlist ID we will save for you from here on in optionally suffixed by # hashtag separated playlist title. Understand that 34 character words will be seen as YouTube Playlist IDs or 22 character words will be seen as Spotify Playlist IDs for which we will start the ball rolling, and present them ready for you to play. Our supplied YouTube playlist ID example is Nala and Luna (mainly) but please use Cancel to avoid remembering this playlist into the future.', 'PLjsR7WjAKSPU-6URvzZ552o5cvQ2p2GYE#Nala and Luna');
if (xname != null) { if (eval('' + xname.indexOf('#')) > 0) { btoaname=encodeURIComponent(xname.split('#')[1].replace(/\ /g,'_')); xname=xname.split('#')[0]; } usethisnotlh=xname; }
}

… that is possible when no personalized playlist hashtag data is in the mix. If it is, well, that opens another whole story all the way through to allowing the user to (email) request the creation of their personalized list of YouTube video IDs becoming a public facing YouTube Playlist hosted on the RJM Programming YouTube Channel, whereby we moderate, here, and if all passes muster, we return a 34 character YouTube Playlist ID the user can save from then on as a playlist on mobile or non-mobile capable of shuffling and looping (if the YouTube App is invoked, on mobile).

We’ve allowed those YouTube search results to “linger longer” too, by replicating them at the “grandparent level” at the point of time we wipe them from the “parent level”, the latest set appearing just below those top three options we now have going for both non-mobile and mobile platforms.

Codewise, two of the “the three amigos” were at it again …


Previous relevant YouTube Video API Event Playlist Save and Recall Tutorial is shown below.

YouTube Video API Event Playlist Save and Recall Tutorial

YouTube Video API Event Playlist Save and Recall Tutorial

Meanwhile, back at the wishlist, with our recent YouTube API interfacing web application project …

st*_st* way to set mute straight away via $_GET[‘mute’] and/or blanks in duration get and a hashtag way to temporarily mute
Save a playlist for later via window.localStorage
Share a playlist
Radio and Oneatatime with a straight hashtag URL
Mute and unmute dynamically
Turn “-” into a reset link

Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)

… it is the olive ideas we’ve made a start on today. We say “we’ve made a start on” only because, when it comes to programming, it doesn’t pay to close off alternate ideas as you go about looking for solutions. Take “Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)(for some reason we’re nicknaming “innerHTML” … who wrote this script)

… well, yes, that would be nice, but, more to the point, we started involving top.document.title in solution making but then, along the way, started incorporating just plain and simple Javascript get/set functionality


var ajaxs_ih='';


function get_ajaxs_ih() {
return ajaxs_ih;
}


function set_ajaxs_ih(wht) {
ajaxs_ih=wht;
}

parent.get_ajaxs_ih() and parent.set_ajaxs_ih(strIn) references from the “parent” level referencing the “grandparent” level (of code above) and being able to populate those YouTube search dropdowns more efficiently. This get/set paradigm is “a classic” methodology in a lot of OOP work, further to the recent YouTube Video API Event Radio Play Sharing Tutorial.

Codewise, again, “the three amigos” were at it again …


Previous relevant YouTube Video API Event Radio Play Sharing Tutorial is shown below.

YouTube Video API Event Radio Play Sharing Tutorial

YouTube Video API Event Radio Play Sharing Tutorial

Wishful thinking with today’s tasklist regarding our current YouTube Video API Event Radio Play Idea Tutorial YouTube API interfacing web application project, where the blue ideas were started …

st*_st* way to set mute straight away via $_GET[‘mute’] and/or blanks in duration get and a hashtag way to temporarily mute
Save a playlist for later via window.localStorage
Share a playlist
Radio and Oneatatime with a straight hashtag URL
Mute and unmute dynamically
Turn “-” into a reset link

Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)

… further to yesterday’s YouTube Video API Event Radio Play Idea Tutorial

And yes, we want to try to get a mobile Radio scenario working for mobile, perhaps, by researching YouTube API (their) playlists … no guarantees, as you’d imagine!

Of interest, here, might be the “emoji means” and top.document.title means by which we tackle the Mute and unmute dynamically issue. Why use top.document.title here? Well, a grandchild of the grandparent is best placed to …

  • tell the grandparent the non-muted volume (which seems to always be 100, as you control what 100 means with the actual volume you have for your speakers) … as well as …
  • obey a grandparent edict to either …
    1. mute
    2. unmute

    … the volume as our way to say “keep playing the radio but shush while I take this phone call” in certain scenarios that might happen

… meaning that all the grandparent has to do, effectively “broadcasting” to any “grandchildren YouTube video players”, is “the emoji flagging work” and adjusting (what it knows as) document.title to perform this functionality for the two new input type=checkboxes (appended by an empty span element and nested in a span id=smute element) we add into the HTML design mix via onchange event function Javascript …


function domute(thiscbo) {
if (thiscbo.checked) {
thiscbo.style.backgroundColor='yellow';
document.getElementById('cbunmute').style.backgroundColor='white';
document.getElementById('smute').innerHTML=document.getElementById('smute').innerHTML.replace('>Mute' + document.getElementById('smute').innerHTML.split('>Mute')[1].split('<')[0] + '<', '>Mute ' + '&#10004;<').replace('>Unmute' + document.getElementById('smute').innerHTML.split('>Unmute')[1].split('<')[0] + '<', '>Unmute<');
if (document.title.indexOf('volume:') != -1) {
var rest='volume:' + document.title.split('volume:')[1];
document.title=document.title.replace(rest, rest.replace(document.title.split('volume:')[1].toLowerCase().replace(/^\ /g,'').replace(/^\ /g,'').replace(/^\ /g,'').split(' ')[0].split(',')[0].split(';')[0].split('|')[0], 'mute'));
} else {
thiscbo.style.backgroundColor='white';
document.title+=' volume:mute';
}
thiscbo.checked=false;
}
}

function dounmute(thiscbo) {
if (thiscbo.checked) {
thiscbo.style.backgroundColor='yellow';
document.getElementById('cbmute').style.backgroundColor='white';
document.getElementById('smute').innerHTML=document.getElementById('smute').innerHTML.replace('>Unmute' + document.getElementById('smute').innerHTML.split('>Unmute')[1].split('<')[0] + '<', '>Unmute ' + '&#10004;<').replace('>Mute' + document.getElementById('smute').innerHTML.split('>Mute')[1].split('<')[0] + '<', '>Mute<');
if (document.title.indexOf('volume:') != -1) {
var rest='volume:' + document.title.split('volume:')[1];
document.title=document.title.replace(rest, rest.replace(document.title.split('volume:')[1].toLowerCase().replace(/^\ /g,'').replace(/^\ /g,'').replace(/^\ /g,'').split(' ')[0].split(',')[0].split(';')[0].split('|')[0], 'unmute'));
} else {
thiscbo.style.backgroundColor='white';
document.title+=' volume:unmute';
}
thiscbo.checked=false;
}
}

It is this complex because (we found out) input type=checkbox CSS styling, as a subject, is a “bit of a closed book” matter!

Codewise, also regarding email and SMS (radio) playlist sharing functionality, amongst other changes, involved …


Previous relevant YouTube Video API Event Stop Propagation Idea Tutorial is shown below.

YouTube Video API Event Stop Propagation Idea Tutorial

YouTube Video API Event Stop Propagation Idea Tutorial

We’re back using the YouTube API video playing themes of YouTube Video API Interfacer Audio Play Tutorial as a means to setting up a web application that may help explain …


event.stopPropagation();

… Javascript event control of it’s “bubbling” (up through an element hierarchy), in other words, depending where you place this, stopping it’s “bubbling up” at that element concerned …

The stopPropagation() method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases. It does not, however, prevent any default behaviors from occurring; for instance, clicks on links are still processed. If you want to stop those behaviors, see the preventDefault() method. It also does not prevent propagation to other event-handlers of the current element. If you want to stop those, see stopImmediatePropagation().

We find, around here, we don’t know we’ve created a need for event.stopPropagation() usage until we’ve stumbled onto it, most of the time, so trying to get in ahead of it with today’s proof of concept to event.stopPropagation() or not to event.stopPropagation() web application feels a bit novel to us, in a good way.

This means by which to toggle that mode of use was more straightforward than “data control” with our musical YouTube API video functionality allowing a user to choose and slot in their own video ideas via either …

  • YouTube video ID … 11 characters long … or …
  • search string to try to select a video, via a programmatically populated dropdown, with an 11 character long YouTube video ID

… asking us to do a fair bit of tweaking to our inhouse interfacing …

… you might want to try out, yourself, to see what we’re getting at here, below …


Previous relevant YouTube Video API Interfacer Audio Play Tutorial is shown below.

YouTube Video API Interfacer Audio Play Tutorial

YouTube Video API Interfacer Audio Play Tutorial

The recent Making Of Earth Scanner Legs Tutorial set us to thinking about how to offer a toggling arrangement between our inhouse YouTube Embedded Iframe API playing of …

  • video … with an incarnation of this that plays …
  • audio … “sort of” only (but able to be toggled back to video playing)

… and it got us wondering how to “dull out” a video. We chose the CSS …

<style>

iframe { filter: invert(45%); }

</style>

If you want a “complete dull out” try filter: invert(50%); … but we wanted to see controls down the bottom, still useful for audio only playing.

You can try this all out in the changed karaoke_youtube_api.htm inhouse YouTube video interfacer.

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


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


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


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


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


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


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

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

YouTube Video API Event Playlist Shuffle and Loop Tutorial

YouTube Video API Event Playlist Shuffle and Loop Tutorial

YouTube Video API Event Playlist Shuffle and Loop Tutorial

We left our Song Playing web application in YouTube Video API Event Playlist Save and Recall Tutorial

  • on mobile, needing a lot of “user tap maintenance” to keep the “personalized playlist” (consisting of YouTube ID video) music rolling … hence our …

    And yes, we want to try to get a mobile Radio scenario working for mobile, perhaps, by researching YouTube API (their) playlists … no guarantees, as you’d imagine!

    … from a preceeding tutorial … well … we still allow that mode of use, but add to that, the possibility of …

  • on mobile or non-mobile, we now offer the referencing of …
    1. YouTube Playlist IDs (34 characters) … or …
    2. Spotify Playlist IDs (22 characters)

    … so that shuffling and, in the case of YouTube Playlists using the YouTube App (if on mobile), looping can be part of the mix in your Song Plays (now appearing in the web application title … doh!! … yay!!!!)

The way to access this new functionality, above, is via the “now always appearing” 🍪 ( &#127850; Cookie button ) new prompt window arrangement


var xname='';
if (('' + location.hash).replace(/^\#/g,'') != '') {
xname=prompt('Recall name for this playlist. Understand that 34 character words will be seen as YouTube Playlist IDs or 22 character words will be seen as Spotify Playlist IDs for which we will start the ball rolling, and present them ready for you to play. Spaces at front results in a request to us at RJM Programming to host your proposed playlist on our YouTube channel and we will return a 34 character ID you can use yourself in the textbox presented. Add spaces at end also to just attend to that email off to RJM Programming.', '');
} else {
xname=prompt('Please optionally enter a recallable YouTube (34) or Spotify (22) playlist ID we will save for you from here on in optionally suffixed by # hashtag separated playlist title. Understand that 34 character words will be seen as YouTube Playlist IDs or 22 character words will be seen as Spotify Playlist IDs for which we will start the ball rolling, and present them ready for you to play. Our supplied YouTube playlist ID example is Nala and Luna (mainly) but please use Cancel to avoid remembering this playlist into the future.', 'PLjsR7WjAKSPU-6URvzZ552o5cvQ2p2GYE#Nala and Luna');
if (xname != null) { if (eval('' + xname.indexOf('#')) > 0) { btoaname=encodeURIComponent(xname.split('#')[1].replace(/\ /g,'_')); xname=xname.split('#')[0]; } usethisnotlh=xname; }
}

… that is possible when no personalized playlist hashtag data is in the mix. If it is, well, that opens another whole story all the way through to allowing the user to (email) request the creation of their personalized list of YouTube video IDs becoming a public facing YouTube Playlist hosted on the RJM Programming YouTube Channel, whereby we moderate, here, and if all passes muster, we return a 34 character YouTube Playlist ID the user can save from then on as a playlist on mobile or non-mobile capable of shuffling and looping (if the YouTube App is invoked, on mobile).

We’ve allowed those YouTube search results to “linger longer” too, by replicating them at the “grandparent level” at the point of time we wipe them from the “parent level”, the latest set appearing just below those top three options we now have going for both non-mobile and mobile platforms.

Codewise, two of the “the three amigos” were at it again …


Previous relevant YouTube Video API Event Playlist Save and Recall Tutorial is shown below.

YouTube Video API Event Playlist Save and Recall Tutorial

YouTube Video API Event Playlist Save and Recall Tutorial

Meanwhile, back at the wishlist, with our recent YouTube API interfacing web application project …

st*_st* way to set mute straight away via $_GET[‘mute’] and/or blanks in duration get and a hashtag way to temporarily mute
Save a playlist for later via window.localStorage
Share a playlist
Radio and Oneatatime with a straight hashtag URL
Mute and unmute dynamically
Turn “-” into a reset link

Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)

… it is the olive ideas we’ve made a start on today. We say “we’ve made a start on” only because, when it comes to programming, it doesn’t pay to close off alternate ideas as you go about looking for solutions. Take “Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)(for some reason we’re nicknaming “innerHTML” … who wrote this script)

… well, yes, that would be nice, but, more to the point, we started involving top.document.title in solution making but then, along the way, started incorporating just plain and simple Javascript get/set functionality


var ajaxs_ih='';


function get_ajaxs_ih() {
return ajaxs_ih;
}


function set_ajaxs_ih(wht) {
ajaxs_ih=wht;
}

parent.get_ajaxs_ih() and parent.set_ajaxs_ih(strIn) references from the “parent” level referencing the “grandparent” level (of code above) and being able to populate those YouTube search dropdowns more efficiently. This get/set paradigm is “a classic” methodology in a lot of OOP work, further to the recent YouTube Video API Event Radio Play Sharing Tutorial.

Codewise, again, “the three amigos” were at it again …


Previous relevant YouTube Video API Event Radio Play Sharing Tutorial is shown below.

YouTube Video API Event Radio Play Sharing Tutorial

YouTube Video API Event Radio Play Sharing Tutorial

Wishful thinking with today’s tasklist regarding our current YouTube Video API Event Radio Play Idea Tutorial YouTube API interfacing web application project, where the blue ideas were started …

st*_st* way to set mute straight away via $_GET[‘mute’] and/or blanks in duration get and a hashtag way to temporarily mute
Save a playlist for later via window.localStorage
Share a playlist
Radio and Oneatatime with a straight hashtag URL
Mute and unmute dynamically
Turn “-” into a reset link

Amalgamate entries searched for into IP address and raw character sets (perhaps collected in top.document.title)

… further to yesterday’s YouTube Video API Event Radio Play Idea Tutorial

And yes, we want to try to get a mobile Radio scenario working for mobile, perhaps, by researching YouTube API (their) playlists … no guarantees, as you’d imagine!

Of interest, here, might be the “emoji means” and top.document.title means by which we tackle the Mute and unmute dynamically issue. Why use top.document.title here? Well, a grandchild of the grandparent is best placed to …

  • tell the grandparent the non-muted volume (which seems to always be 100, as you control what 100 means with the actual volume you have for your speakers) … as well as …
  • obey a grandparent edict to either …
    1. mute
    2. unmute

    … the volume as our way to say “keep playing the radio but shush while I take this phone call” in certain scenarios that might happen

… meaning that all the grandparent has to do, effectively “broadcasting” to any “grandchildren YouTube video players”, is “the emoji flagging work” and adjusting (what it knows as) document.title to perform this functionality for the two new input type=checkboxes (appended by an empty span element and nested in a span id=smute element) we add into the HTML design mix via onchange event function Javascript …


function domute(thiscbo) {
if (thiscbo.checked) {
thiscbo.style.backgroundColor='yellow';
document.getElementById('cbunmute').style.backgroundColor='white';
document.getElementById('smute').innerHTML=document.getElementById('smute').innerHTML.replace('>Mute' + document.getElementById('smute').innerHTML.split('>Mute')[1].split('<')[0] + '<', '>Mute ' + '&#10004;<').replace('>Unmute' + document.getElementById('smute').innerHTML.split('>Unmute')[1].split('<')[0] + '<', '>Unmute<');
if (document.title.indexOf('volume:') != -1) {
var rest='volume:' + document.title.split('volume:')[1];
document.title=document.title.replace(rest, rest.replace(document.title.split('volume:')[1].toLowerCase().replace(/^\ /g,'').replace(/^\ /g,'').replace(/^\ /g,'').split(' ')[0].split(',')[0].split(';')[0].split('|')[0], 'mute'));
} else {
thiscbo.style.backgroundColor='white';
document.title+=' volume:mute';
}
thiscbo.checked=false;
}
}

function dounmute(thiscbo) {
if (thiscbo.checked) {
thiscbo.style.backgroundColor='yellow';
document.getElementById('cbmute').style.backgroundColor='white';
document.getElementById('smute').innerHTML=document.getElementById('smute').innerHTML.replace('>Unmute' + document.getElementById('smute').innerHTML.split('>Unmute')[1].split('<')[0] + '<', '>Unmute ' + '&#10004;<').replace('>Mute' + document.getElementById('smute').innerHTML.split('>Mute')[1].split('<')[0] + '<', '>Mute<');
if (document.title.indexOf('volume:') != -1) {
var rest='volume:' + document.title.split('volume:')[1];
document.title=document.title.replace(rest, rest.replace(document.title.split('volume:')[1].toLowerCase().replace(/^\ /g,'').replace(/^\ /g,'').replace(/^\ /g,'').split(' ')[0].split(',')[0].split(';')[0].split('|')[0], 'unmute'));
} else {
thiscbo.style.backgroundColor='white';
document.title+=' volume:unmute';
}
thiscbo.checked=false;
}
}

It is this complex because (we found out) input type=checkbox CSS styling, as a subject, is a “bit of a closed book” matter!

Codewise, also regarding email and SMS (radio) playlist sharing functionality, amongst other changes, involved …


Previous relevant YouTube Video API Event Stop Propagation Idea Tutorial is shown below.

YouTube Video API Event Stop Propagation Idea Tutorial

YouTube Video API Event Stop Propagation Idea Tutorial

We’re back using the YouTube API video playing themes of YouTube Video API Interfacer Audio Play Tutorial as a means to setting up a web application that may help explain …


event.stopPropagation();

… Javascript event control of it’s “bubbling” (up through an element hierarchy), in other words, depending where you place this, stopping it’s “bubbling up” at that element concerned …

The stopPropagation() method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases. It does not, however, prevent any default behaviors from occurring; for instance, clicks on links are still processed. If you want to stop those behaviors, see the preventDefault() method. It also does not prevent propagation to other event-handlers of the current element. If you want to stop those, see stopImmediatePropagation().

We find, around here, we don’t know we’ve created a need for event.stopPropagation() usage until we’ve stumbled onto it, most of the time, so trying to get in ahead of it with today’s proof of concept to event.stopPropagation() or not to event.stopPropagation() web application feels a bit novel to us, in a good way.

This means by which to toggle that mode of use was more straightforward than “data control” with our musical YouTube API video functionality allowing a user to choose and slot in their own video ideas via either …

  • YouTube video ID … 11 characters long … or …
  • search string to try to select a video, via a programmatically populated dropdown, with an 11 character long YouTube video ID

… asking us to do a fair bit of tweaking to our inhouse interfacing …

… you might want to try out, yourself, to see what we’re getting at here, below …


Previous relevant YouTube Video API Interfacer Audio Play Tutorial is shown below.

YouTube Video API Interfacer Audio Play Tutorial

YouTube Video API Interfacer Audio Play Tutorial

The recent Making Of Earth Scanner Legs Tutorial set us to thinking about how to offer a toggling arrangement between our inhouse YouTube Embedded Iframe API playing of …

  • video … with an incarnation of this that plays …
  • audio … “sort of” only (but able to be toggled back to video playing)

… and it got us wondering how to “dull out” a video. We chose the CSS …

<style>

iframe { filter: invert(45%); }

</style>

If you want a “complete dull out” try filter: invert(50%); … but we wanted to see controls down the bottom, still useful for audio only playing.

You can try this all out in the changed karaoke_youtube_api.htm inhouse YouTube video interfacer.

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

ImageMagick Postscript Primer Tutorial

ImageMagick Postscript Primer Tutorial

ImageMagick Postscript Primer Tutorial

We could spend a lifetime telling you about the functionality of various ImageMagick guises and usages, further to the recent Imagick PHP Class Primer Tutorial. We’ve decided to live a little separated from ImageMagick, or we just know we would have dreams about command line switches that turn into snakes or command lines turning into congo lines or command lines telling me about ten things I was never meant to do.

The other day, though, we stumbled upon a webpage rekindling interest, which is far easier these days, with ImageMagick installed on our AlmaLinux web server here at RJM Programming. Mind you, we also had it installed on the old CentOS web server, but it was as if, on CentOS, we had never …

Released the Kraken

… with the lack of diskspace there on CentOS, also causing us unrest?! No such problems on AlmaLinux, we give thanks for.

Anyway, that webpage link got us thinking about where …

  • Ghostscript … a PDF conversion specialist suite of software, you’ll often associate with “hardcode” printout functionality … interplays with …
  • ImageMagick

… and the command line had us hooked again. So, we wrote a way you can get hooked too, effectively parsing a favoured ImageMagick “convert” (verb) command into switches, a bit like parsing a language sentence, using PHP.

What?!!!!

Yes, it looks bad, as far as security goes, but we do some checks for malicious usage, in our “proof of concept” ImageMagick command line, via PHP, channeller of Ghostscript ideas image creator web application.


Previous relevant Imagick PHP Class Primer Tutorial is shown below.

Form Target Self Primer Tutorial

Imagick PHP Class Primer Tutorial

We’re talking “class” today. Up until now, regarding the great ImageMagick suite of software, and it’s interactions with PHP, we’ve …

… in a first draft not installed here on CentOS but okay here with AlmaLinux. Am sure most people would concur that this is much more integrated approach for PHP …


<?php
// oil_painting_thumbnail.php
// RJM Programming - August, 2024
// Start using PHP Imagick class
$image=null;
if (!isset($_GET['image']) && !isset($_POST['image'])) {
echo "<html><head><scr" . "ipt type=text/javascript> function ask() { var bsh=prompt('See the default brightness, saturation, hue settings, black point %, white point % and change as desired ... 100,0,100,90,95 is grayscale ... darkest 90% of pixels are turned black, the brightest 5% are made white, and those between 90% and 95% are grey-scaled', document.getElementById('brightness').value + ',' + document.getElementById('saturation').value + ',' + document.getElementById('hue').value + ',' + document.getElementById('blackpoint').value + ',' + document.getElementById('whitepoint').value); if (bsh != null) { if (eval('' + bsh.split(',').length) == 5) { document.getElementById('brightness').value=bsh.split(',')[0]; document.getElementById('saturation').value=bsh.split(',')[1]; document.getElementById('hue').value=bsh.split(',')[2]; document.getElementById('blackpoint').value=bsh.split(',')[3]; document.getElementById('whitepoint').value=bsh.split(',')[4]; } } return true; } </scr" . "ipt></head><body><h1>Imagick Ideas</h1><h3>RJM Programming - August, 2024 ... thanks to https://www.php.net/manual/en/book.imagick.php and https://www.php.net/manual/en/imagick.contraststretchimage.php</h3><br><br><form action='./oil_painting_thumbnail.php' id=myform method=GET><input type=hidden name=brightness value=100 id=brightness></input><input type=hidden name=saturation value=0 id=saturation></input><input type=hidden name=hue value=100 id=hue></input><input type=hidden name=blackpoint value=90 id=blackpoint></input><input type=hidden name=whitepoint value=95 id=whitepoint></input><input style='width:70%;' type=text placeholder='Image to process ...' name=image id=image value=''></input><br><br><input onclick=\" document.getElementById('myform').method='GET'; \" type=submit style=background-color:orange; value=Negate></input> <input style=background-color:yellow; onclick=\" if (ask()) { document.getElementById('myform').method='POST'; } \" type=submit value='Contrast Stretch'></input></form></body></html>";
} else {
if (isset($_GET['image'])) {

header('Content-type: image/jpeg');

//Instantiate a new Imagick object
$image = new Imagick(realpath(urldecode($_GET['image'])));
$image->negateImage(false);

// If 0 is provided as a width or height parameter,
// aspect ratio is maintained
$image->thumbnailImage(100, 0);

echo $image;
exit;

} else {
//Instantiate a new Imagick object
$image = new Imagick(realpath(urldecode($_POST['image'])));
list($width, $height) = array_values ($image->getImageGeometry());
$b=(isset($_POST['brightness']) ? $_POST['brightness'] : '100');
$s=(isset($_POST['saturation']) ? $_POST['saturation'] : '0');
$h=(isset($_POST['hue']) ? $_POST['hue'] : '100');
$bp=(isset($_POST['blackpoint']) ? $_POST['blackpoint'] : '90');
$wp=(isset($_POST['whitepoint']) ? $_POST['whitepoint'] : '95');
$image->modulateImage($b, $s, $h);
$image->contrastStretchImage($width * $height * ($bp / 100.0), $width * $height * ($wp / 100.0));
$image->writeImage('example_thumbnail.jpg');
echo "<html><body><p>My Changed Image " . urldecode($_POST['image']) . " ... brightness " . $b . ", saturation " . $s . ", hue " . $h . ", black point % " . $bp . "%, white point % " . $wp . "%</p><br><img src='./example_thumbnail.jpg'></img></body></html>";
exit;

}
}
?>

… to interface to the great ImageMagick image manipulation software.

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