Pdfimages PDF Image Extraction PHP Browsing Tutorial

Pdfimages PDF Image Extraction PHP Tutorial

Pdfimages PDF Image Extraction PHP Browsing Tutorial

Yesterday’s Pdfimages PDF Image Extraction PHP Tutorial

  • asked a lot of the user as far as interactive entry goes having to specify …
    1. input PDF file path
    2. input PDF file name
  • when, in this day and age with the HTML5 and the File API we can browse for that PDF file using a look like those dialogue boxes from the early Windows and Mac OS X desktop application days

We don’t reinvent the wheel here, but tweak our oft-changed inhouse client_browsing.htm (which we’d like you to download to your MAMP local Apache/PHP/MySql web server HTMLCSS folder, you create, off its document root) interfacing to the File API, allowing the interface, within the parent window nested in an iframe element, return …

  1. file base name
  2. file size

… not pushing any barrows chasing the non-generic file path data members available on a rare platform (to fill in our input PDF file path), instead, writing some PHP to try to glean that input PDF file path ourselves, knowing the two pieces of information above …

<?php

function rsearch($folder, $pattern, $size) { // thanks, anyway, to https://stackoverflow.com/questions/17160696/php-glob-scan-in-subfolders-for-a-file
$didea='';
if (PHP_OS == "Darwin") {
//file_put_contents("x.ksh", "find " . $folder . " -type f -name \"" . $pattern . "\" 2> /dev/null -exec wc -c {} + | egrep '^ " . $size . " ' | sed '/ " . $size . " /s///g'");
if ($folder == DIRECTORY_SEPARATOR) {
$didea=shell_exec("find \$HOME/Downloads -type f -name \"" . $pattern . "\" 2> /dev/null -exec wc -c {} + | egrep '^ " . $size . " ' | sed '/ " . $size . " /s///g'");
//file_put_contents("xx.ksh", $didea);
if ($didea != '') { return $didea; }
$didea=shell_exec("find " . dirname(__FILE__) . DIRECTORY_SEPARATOR . " -type f -name \"" . $pattern . "\" 2> /dev/null -exec wc -c {} + | egrep '^ " . $size . " ' | sed '/ " . $size . " /s///g'");
//file_put_contents("xxx.ksh", $didea);
if ($didea != '') { return $didea; }
}
return shell_exec("find " . $folder . " -type f -name \"" . $pattern . "\" 2> /dev/null -exec wc -c {} + | egrep '^ " . $size . " ' | sed '/ " . $size . " /s///g'");
}
//$iti = new RecursiveDirectoryIterator($folder);
//foreach (new RecursiveIteratorIterator($iti) as $file) {
//foreach (glob($folder . $pattern) as $file) {
// if (strpos($file , $pattern) !== false && filesize($file) == $size) {
// return $file;
// }
//}
return '';
}

?>

… so far just for Mac OS X or macOS … sorrrryyyyy!

Along the way, we now offer, as far as image displays go, the choices of …

  • images from left to right (as with yesterday) … and now …
  • images from top to bottom
  • images that fill screen width, as far as they can fit

The images can be clicked to open individually in new web browser tabs, should that interest.

So, why not download the changed php_calls_pdfimages.php MAMP local Apache/PHP/MySql web server’s document root ( ie. using a MAMP macOS URL HTTP://localhost:8888/php_calls_pdfimages.php and may take you there with this public domain RJM Programming link if all of above holds ).


Previous relevant Pdfimages PDF Image Extraction PHP Tutorial is shown below.

Pdfimages PDF Image Extraction PHP Tutorial

Pdfimages PDF Image Extraction PHP Tutorial

Today we’re building on yesterday’s Pdfimages PDF Image Extraction Primer Tutorial‘s …

  • macOS command line use of thanks, that the great Pdfimages suite of software works in to extract the images contained within a PDF … by allowing …
  • a combination of …

    … can present a form a MAMP webpage user uses to find the input PDF and suggest a prefixing part to the filenames, which will end up creating images from that PDF file as per … [userPrefix]-0.jpg [userPrefix]-1.jpg [userPrefix]-2.jpg etcetera etcetera etcetera

So here’s our source code for php_calls_pdfimages.php as it sits for this first incarnation ( ie. using a MAMP macOS URL HTTP://localhost:8888/php_calls_pdfimages.php and may take you there with this public domain RJM Programming link if all of above holds ).


Previous relevant Pdfimages PDF Image Extraction Primer Tutorial is shown below.

Pdfimages PDF Image Extraction Primer Tutorial

Pdfimages PDF Image Extraction Primer Tutorial

When we presented PDF via Slide Images and Back Again via ImageMagick Primer Tutorial we referenced …

  • the great ImageMagick suite of software capable of extracting PDF pages as an image … as distinct from our curiosity today …
  • we discovered, thanks, that the great Pdfimages suite of software can extract the images contained within a PDF

And so, today, we show with today’s animated GIF presentation …

  • installing Pdfimages on macOS via …

    brew install poppler
  • using a macOS command line (via Terminal application) issued command …

    pdfimages -j "September 22 record.pdf" ideas -png

    … to extract the 242 images (curiously, as jpeg images) contained within our input PDF.

Interesting, huh?


Previous relevant PDF via Slide Images and Back Again via ImageMagick Primer Tutorial is shown below.

PDF via Slide Images and Back Again via ImageMagick Primer Tutorial

PDF via Slide Images and Back Again via ImageMagick Primer Tutorial

Does today’s blog posting title sound familiar to you? If so, I’m impressed. If not, get the whole picture, in context (we hope), today of …

  • today’s “PDF via Slide Images and Back Again via ImageMagick Primer Tutorial” … gets its cues from a …
  • previous “Video via Slide Images and Back Again via ffmpeg Primer Tutorial” … so that …
    1. PDF is the output file format as distinct from a Video Format such as *.mov or *.mp4
    2. ImageMagick is the conduit to that work as distinct from ffmpeg

… and that what is a common denominator here to be able to convert between Video and PDF and vice versa, is a set of image slides (or frames) of the animation concerned, today’s being, again, that Ant Video we took on our iPhone (that became the “Star Ant Video”), and that today takes as its starting point

  1. image slides (or frames) from Video via Slide Images and Back Again via ffmpeg Primer Tutorial our MacBook Pro (via an email attachment download) … a listing of which looks like …

    $ ls -l image-000*.jpeg
    -rw-r--r-- 1 user admin 170993 26 Jul 11:20 image-0001.jpeg
    -rw-r--r-- 1 user admin 205565 26 Jul 11:20 image-0002.jpeg
    -rw-r--r-- 1 user admin 218950 26 Jul 11:20 image-0003.jpeg
    -rw-r--r-- 1 user admin 164271 26 Jul 11:20 image-0004.jpeg
    -rw-r--r-- 1 user admin 171662 26 Jul 11:20 image-0005.jpeg
    -rw-r--r-- 1 user admin 155528 26 Jul 11:20 image-0006.jpeg
    -rw-r--r-- 1 user admin 53193 26 Jul 11:20 image-0007.jpeg
  2. gets converted to an original (input) PDF (antsoriginal.pdf) (with slideshow capabilities via applications like Mac OS X’s Preview or Adobe Acrobat Reader) via Mac OS X Terminal application command line’s ImageMagick executable convert command …

    convert image-000*.jpeg -density 4096 antsoriginal.pdf

    … and then we act as though this PDF was our original source of data and decide to …
  3. break that PDF into its constituent image slides (or frames) via …

    convert -density 900 antsoriginal.pdf image_pdf.jpeg

    … and then use ImageMagick convert commands again to …
  4. crop those image slides via Mac OS X Terminal application command line’s ImageMagick executable convert commands (thanks to this great advice) …

    $ convert image_pdf-0.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-0.jpg
    $ convert image_pdf-1.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-1.jpg
    $ convert image_pdf-2.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-2.jpg
    $ convert image_pdf-3.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-3.jpg
    $ convert image_pdf-4.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-4.jpg
    $ convert image_pdf-5.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-5.jpg
    $ convert image_pdf-6.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-6.jpg

    … into new PDF slide images (or frames) that can be converted to (output) PDF (antscentral.pdf) via ImageMagick executable convert command …

    convert image_pdf*.jpg antscentral.pdf

    … to see …
  5. we end up with the (relevant) file listing …

    $ ls -l image-000*.jpeg image_pdf*.jp*g ants*l.pdf
    -rw-r--r--@ 1 user admin 17405330 15 Aug 12:00 antscentral.pdf
    -rw-r--r--@ 1 user admin 1350686 15 Aug 11:53 antsoriginal.pdf
    -rw-r--r-- 1 user admin 170993 26 Jul 11:20 image-0001.jpeg
    -rw-r--r-- 1 user admin 205565 26 Jul 11:20 image-0002.jpeg
    -rw-r--r-- 1 user admin 218950 26 Jul 11:20 image-0003.jpeg
    -rw-r--r-- 1 user admin 164271 26 Jul 11:20 image-0004.jpeg
    -rw-r--r-- 1 user admin 171662 26 Jul 11:20 image-0005.jpeg
    -rw-r--r-- 1 user admin 155528 26 Jul 11:20 image-0006.jpeg
    -rw-r--r-- 1 user admin 53193 26 Jul 11:20 image-0007.jpeg
    -rw-r--r-- 1 user admin 17643304 15 Aug 11:18 image_pdf-0.jpeg
    -rw-r--r-- 1 user admin 2906716 15 Aug 11:56 image_pdf-0.jpg
    -rw-r--r-- 1 user admin 18521373 15 Aug 11:18 image_pdf-1.jpeg
    -rw-r--r-- 1 user admin 3022841 15 Aug 11:58 image_pdf-1.jpg
    -rw-r--r-- 1 user admin 17394312 15 Aug 11:18 image_pdf-2.jpeg
    -rw-r--r-- 1 user admin 2762837 15 Aug 11:58 image_pdf-2.jpg
    -rw-r--r-- 1 user admin 13963420 15 Aug 11:19 image_pdf-3.jpeg
    -rw-r--r-- 1 user admin 2215533 15 Aug 11:58 image_pdf-3.jpg
    -rw-r--r-- 1 user admin 16076730 15 Aug 11:19 image_pdf-4.jpeg
    -rw-r--r-- 1 user admin 2597147 15 Aug 11:59 image_pdf-4.jpg
    -rw-r--r-- 1 user admin 16544272 15 Aug 11:19 image_pdf-5.jpeg
    -rw-r--r-- 1 user admin 2840288 15 Aug 11:59 image_pdf-5.jpg
    -rw-r--r-- 1 user admin 6870989 15 Aug 11:19 image_pdf-6.jpeg
    -rw-r--r-- 1 user admin 1030314 15 Aug 11:59 image_pdf-6.jpg
  6. Just as we decided to reinstall ffmpeg due to that disk crash, we decided to reinstall ImageMagick to this MacBook Pro here, and found, thanks to great advice, we found that we needed to …

    1. install ImageMagick via that previous link’s relevant download link … then at Terminal application command line …

      sudo -k ln -s /opt/ImageMagick/bin/convert /usr/bin/convert
    2. install GhostScript via that previous link’s relevant download link … then at Terminal application command line …

      sudo -k ln -s /opt/Ghostscript/bin/gs /usr/local/bin/gs

    3. install XQuartz via via XQuartz download page, thanks

    All animations, different forms (or formats), all presentation facilitators, is the message here today.


    Previous relevant Video via Slide Images and Back Again via ffmpeg Primer Tutorial is shown below.

    Video via Slide Images and Back Again via ffmpeg Primer Tutorial

    Video via Slide Images and Back Again via ffmpeg Primer Tutorial

    Reading yesterday’s LibreOffice Spreadsheet via dBase Primer Tutorial you can’t say I didn’t warn you about my interest in ants (and bees)? Glad you asked?

    Did you know?

    • the queen ant (often just one per ant colony) is not a leader as such in thinking out strategies … believe it or not …
    • it is believed ant colony strategies are worked by what we might call “groupthink”
    • ants march in line often and the scent that the ants leave behind is pheromone, that non-leader ants follow off that left behind by the “leader ant” … ie. “leader” of position, rather than “leader” of hierarchy

    So seeing some ants walking in line up a power pole, used an iPhone to capture a very short video (short enough to use the iPhone’s Photo app’s Share via Mail (attachment) method of emailing to the MacBook Pro, and then (Gmail website) downloading) of this, and later, buck the “ant” trend, and “anthropomorphise” a “star ant”, by honing in on an ant in this video and ring it (and its movement) before creating another “Star Ant Video”.

    There are video editing approaches you could use, but what got us interested was the thought of …

    • break the video into its component parts … just like animations like “Bugs Bunny” … a series of (slide, or frame) images
    • edit those (slide) images to add the (we’ve decided should be) red ringing of our “Star Ant” … who we’ve decided you, the user can call whatever you so desire … aaaaaaarrrrrrr
    • reconstitute a new video from some new (slide) image components

    That’s where one of our favourite Mac Os X friendly media players, which is also a command line “player” (yayyyyyy!) comes to the fore, for us. It’s the wonderful ffmpeg which we’ve had for a long time now on this MacBook Pro until a disk crash mentioned some weeks back. Could get it back off restore, but decided to reconsitute …

    … as a fairly straightforward exercise (given you have Xcode installed already) via a How to install FFmpeg on Mac OS X webpage by René Calles, thanks, heaps, we discovered the commands that worked well for us that go …


    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    brew install ffmpeg --with-fdk-aac --with-ffplay --with-freetype --with-frei0r --with-libass --with-libvo-aacenc --with-libvorbis --with-libvpx --with-opencore-amr --with-openjpeg --with-opus --with-rtmpdump --with-schroedinger --with-speex --with-theora --with-tools

    … to (re)install ffmpeg so that, then …


    ffmpeg -i IMG_0738.MOV -r 1 image-%04d.jpeg

    … could create those original 7 (slide) images, though the use of a value bigger than 1 frames per second for the “-r” switch could be on the cards for your usages.

    How to edit those images? We just used the Mac OS X version of PaintBrush and lined a lot of these images side by side across the screen to try to track our “Star Ant” and award it the “Red Ellipse PaintBrush Order of Merit” (for individualism … tee hee).

    Reconstituting the new slides into a new video we remember was another talent of ffmpeg and found this useful webpage, thanks, on the topic of taking raw (slide) images to create a video via ffmpeg. Actually, though, we also had our previous very useful Animated GIF and Video via PHP Writing PHP Data URI Tutorial (presented below) to turn to to end up with the Mac OS X (Terminal session command line command …


    ffmpeg -r 1 -i image-%04d.jpg ants.mp4

    There are no worries with video file “workings” to do with uppercase and lowercase and names, so we …


    cp IMG_0738.MOV ants.mov

    … just for some consistency purposes (and could use “mv” to rename instead) so that we can show you …

    Before … After … “Star Ant Video”

    See a lot of all these goings on at today’s PDF slideshow.


    Previous relevant Animated GIF and Video via PHP Writing PHP Data URI Tutorial is shown below.

    Animated GIF and Video via PHP Writing PHP Data URI Tutorial

    Animated GIF and Video via PHP Writing PHP Data URI Tutorial

    There is a great open source command line application called “FFmpeg” that can create video (or convert video) from image slides (for instance), and so, if we merge functionality for this into yesterday’s Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial some “presentation” styles that our web application can process are now …

    • animated GIF
    • slideshow
    • video

    As useful as “FFmpeg” is, it is not necessarily a default application existing on web server operating systems like our rjmprogramming.com.au’s CentOS server. But we do have it on our Mac OS X (MacBook Pro) operating system’s command line, so we write our PHP determining whether to …

    • create the video data there and then via “FFmpeg” and PHP’s exec method … or …
    • provide instructions to be able to create the video back at your client computer (that has “FFmpeg” perhaps) … to suit the …

      ffmpeg -r 1 -i %03d.jpg video.mp4

      … to create a video called video.mp4 with 1 second delays between (input) slides named 001.jpg then 002.jpg then 003.jpg etcetera … thanks useful webpage for the help … that in the command line can sometimes be played via …

      open video.mp4

      … or used in some HTML as per …

      <video controls id=ivideo type='video/mp4'><source src='video.mp4'></source></video>

      … that we show you, below, the Mac OS X local MAMP (Apache/PHP/MySql) web server running of today’s PHP to create …

    If you are a regular at this blog and “FFmpeg” sounds a bit familiar to you, that’s probably because you’ve read FFmpeg Image Optimization Primer Tutorial on an earlier occasion … by candlelight … with the lights dimmed?!

    See this in the context of how this PHP tutorial_to_animated_gif.php code changed for videos in this way or try it as a live run.


    Previous relevant Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial is shown below.

    Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial

    Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial

    To us, there are great similarities between animated GIFs and slideshows, as two forms of “presentation”, and so to extend yesterday’s Animated GIF via PHP Writing PHP Data URI Tutorial animated GIF creator “PHP Writes PHP” web application that now has the option for data URI “exports” we add the functionality for …

    • slideshow creation (using our inhouse methods) which defaults to a horizontal (hashtag type of) navigation … as well as adding a …
    • slideshow creation, with Data URI image data, using functionality as if CSS z-index (ie. slides stacked on top of each other in “overlay” style) was being used, but actually isn’t …

    … that little bit different to another “stacked” (or z-index feeling) approach we talked about with Multiple Class Slideshow Details Tutorial, where HTML element “class” properties were changed so that the last class defined reflects the look of the slideshow slide desired at any given time. We just use an array, and a setTimeout timer to achieve the same ends today, with our work (or “presentation”). If this “horizontal versus stack” navigation choice interests you, also take a read of HTML Input Element Types Randomized History Tutorial.

    Again, with all this added functionality, because it is “hosted” in an HTML iframe element all the existant web browser (Windows right click or Mac OS X two finger gesture) functionality can come into play, and make life quite interesting for your non-mobile users “collecting” data URIs … there are worse hobbies!

    You can see this in the context of how this PHP tutorial_to_animated_gif.php code changed for slideshows in this way or try it as a live run.


    Previous relevant Animated GIF via PHP Writing PHP Data URI Tutorial is shown below.

    Animated GIF via PHP Writing PHP Data URI Tutorial

    Animated GIF via PHP Writing PHP Data URI Tutorial

    The previous relevant “PHP writes PHP” methodology animated GIF creator we talked about, first, with Animated GIF via PHP Writing PHP Primer Tutorial came back to mind yesterday with our Missing Javascript Audio on Unmute Tutorial, where we pondered on whether an animated GIF could be represented on a webpage by a data URI. Why take an interest in this? Data URIs are very important to do with …

    • future mobile development web form navigation benefits from their usage
    • the use of data URIs make your web pages independent of web server location issues, so make your web data more portable, and flexible

    … and ideally, animated GIFs are also not just a decorative part of all this web application usage (as they can be a very efficient representation of an animation that could not be a more succinct way to show that animation or presentation), and if they can be made to be like any other GIF or image data file in the ways they can be represented (and used), then that is all for the good.

    So we changed the Jeroen van Wissen’s inspired PHP (“PHP writes PHP” methodology) code tutorial_to_animated_gif.php code allow for this extra animated GIF data URI representation in a new additional HTML iframe (containing the animegif.html of code below) that when harnessing existant web browser (Windows right click or Mac OS X two finger gesture) functionality can glean for us, as required, that animated GIF’s data URI representation. But don’t get too excited about this being rocket science, in that with a bit of effort, and PHP, it could have been gleaned from what we already produced, in that (in PHP “land”) …


    $lastbitto="\$fp = fopen('animegif.gif', 'w');
    \$data = \$gif->GetAnimation();
    \$dataUri = 'data:image/gif;base64,' . base64_encode(\$data);
    fwrite(\$fp, \$data);
    fclose(\$fp);
    \$fp = fopen('animegif.html', 'w');
    fwrite(\$fp, '<!doctype html><html><body><h1>Data URI version below<h1><br><h4> ... via web browser (Windows right click, Mac OS X two finger gesture ...</h4><br><img src=' . \"\\n\" . \$dataUri . \"\\n\" . ' title=DataURI></img></body></html>');
    fclose(\$fp);";

    You can see this in the context of how this PHP code changed in this way or try it as a live run.


    Previous relevant Animated GIF via PHP Writing PHP Primer Tutorial is shown below.

    Animated GIF via PHP Writing PHP Primer Tutorial

    Animated GIF via PHP Writing PHP Primer Tutorial

    We find another very useful reason for PHP to write PHP. Today we establish a PHP web application to dynamically create Animated GIF images via some still images, like Gifpal would do.

    We have some great open source PHP code to thank for the basis of the functionality we found at Jeroen van Wissen’s very useful link, thanks.

    Then we added a more user friendly interface to get the information off the user we need. We present this in an HTML form, which navigates to the same PHP to do the actual assembly of the Animated GIF via techniques where PHP writes PHP … and really needs to, to be useful.

    Do you remember, last, when we did some PHP writing PHP functionality … PHP Writes PHP Vertical TextBoxes Primer Tutorial?

    And inside the PHP it makes big use of the GD and Image Functions to read and write the image data we assemble via the user information.

    This Animated GIF form of animation is the easiest to implement, as it consists of just the one GIF image file, but the user has very little control over the animation settings, such as the delay between stills, one of the settings we ask about in our web application.

    Our PHP source code today you could call tutorial_to_animated_gif.php and we redirect you to some live run ideas …

    • normal run with HTML form which posts back to itself … live run
    • example GET parameters run (like our tutorial picture)

    Hope you find this tutorial useful.

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

Pdfimages PDF Image Extraction PHP Tutorial

Pdfimages PDF Image Extraction PHP Tutorial

Pdfimages PDF Image Extraction PHP Tutorial

Today we’re building on yesterday’s Pdfimages PDF Image Extraction Primer Tutorial‘s …

  • macOS command line use of thanks, that the great Pdfimages suite of software works in to extract the images contained within a PDF … by allowing …
  • a combination of …

    … can present a form a MAMP webpage user uses to find the input PDF and suggest a prefixing part to the filenames, which will end up creating images from that PDF file as per … [userPrefix]-0.jpg [userPrefix]-1.jpg [userPrefix]-2.jpg etcetera etcetera etcetera

So here’s our source code for php_calls_pdfimages.php as it sits for this first incarnation ( ie. using a MAMP macOS URL HTTP://localhost:8888/php_calls_pdfimages.php and may take you there with this public domain RJM Programming link if all of above holds ).


Previous relevant Pdfimages PDF Image Extraction Primer Tutorial is shown below.

Pdfimages PDF Image Extraction Primer Tutorial

Pdfimages PDF Image Extraction Primer Tutorial

When we presented PDF via Slide Images and Back Again via ImageMagick Primer Tutorial we referenced …

  • the great ImageMagick suite of software capable of extracting PDF pages as an image … as distinct from our curiosity today …
  • we discovered, thanks, that the great Pdfimages suite of software can extract the images contained within a PDF

And so, today, we show with today’s animated GIF presentation …

  • installing Pdfimages on macOS via …

    brew install poppler
  • using a macOS command line (via Terminal application) issued command …

    pdfimages -j "September 22 record.pdf" ideas -png

    … to extract the 242 images (curiously, as jpeg images) contained within our input PDF.

Interesting, huh?


Previous relevant PDF via Slide Images and Back Again via ImageMagick Primer Tutorial is shown below.

PDF via Slide Images and Back Again via ImageMagick Primer Tutorial

PDF via Slide Images and Back Again via ImageMagick Primer Tutorial

Does today’s blog posting title sound familiar to you? If so, I’m impressed. If not, get the whole picture, in context (we hope), today of …

  • today’s “PDF via Slide Images and Back Again via ImageMagick Primer Tutorial” … gets its cues from a …
  • previous “Video via Slide Images and Back Again via ffmpeg Primer Tutorial” … so that …
    1. PDF is the output file format as distinct from a Video Format such as *.mov or *.mp4
    2. ImageMagick is the conduit to that work as distinct from ffmpeg

… and that what is a common denominator here to be able to convert between Video and PDF and vice versa, is a set of image slides (or frames) of the animation concerned, today’s being, again, that Ant Video we took on our iPhone (that became the “Star Ant Video”), and that today takes as its starting point

  1. image slides (or frames) from Video via Slide Images and Back Again via ffmpeg Primer Tutorial our MacBook Pro (via an email attachment download) … a listing of which looks like …

    $ ls -l image-000*.jpeg
    -rw-r--r-- 1 user admin 170993 26 Jul 11:20 image-0001.jpeg
    -rw-r--r-- 1 user admin 205565 26 Jul 11:20 image-0002.jpeg
    -rw-r--r-- 1 user admin 218950 26 Jul 11:20 image-0003.jpeg
    -rw-r--r-- 1 user admin 164271 26 Jul 11:20 image-0004.jpeg
    -rw-r--r-- 1 user admin 171662 26 Jul 11:20 image-0005.jpeg
    -rw-r--r-- 1 user admin 155528 26 Jul 11:20 image-0006.jpeg
    -rw-r--r-- 1 user admin 53193 26 Jul 11:20 image-0007.jpeg
  2. gets converted to an original (input) PDF (antsoriginal.pdf) (with slideshow capabilities via applications like Mac OS X’s Preview or Adobe Acrobat Reader) via Mac OS X Terminal application command line’s ImageMagick executable convert command …

    convert image-000*.jpeg -density 4096 antsoriginal.pdf

    … and then we act as though this PDF was our original source of data and decide to …
  3. break that PDF into its constituent image slides (or frames) via …

    convert -density 900 antsoriginal.pdf image_pdf.jpeg

    … and then use ImageMagick convert commands again to …
  4. crop those image slides via Mac OS X Terminal application command line’s ImageMagick executable convert commands (thanks to this great advice) …

    $ convert image_pdf-0.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-0.jpg
    $ convert image_pdf-1.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-1.jpg
    $ convert image_pdf-2.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-2.jpg
    $ convert image_pdf-3.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-3.jpg
    $ convert image_pdf-4.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-4.jpg
    $ convert image_pdf-5.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-5.jpg
    $ convert image_pdf-6.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-6.jpg

    … into new PDF slide images (or frames) that can be converted to (output) PDF (antscentral.pdf) via ImageMagick executable convert command …

    convert image_pdf*.jpg antscentral.pdf

    … to see …
  5. we end up with the (relevant) file listing …

    $ ls -l image-000*.jpeg image_pdf*.jp*g ants*l.pdf
    -rw-r--r--@ 1 user admin 17405330 15 Aug 12:00 antscentral.pdf
    -rw-r--r--@ 1 user admin 1350686 15 Aug 11:53 antsoriginal.pdf
    -rw-r--r-- 1 user admin 170993 26 Jul 11:20 image-0001.jpeg
    -rw-r--r-- 1 user admin 205565 26 Jul 11:20 image-0002.jpeg
    -rw-r--r-- 1 user admin 218950 26 Jul 11:20 image-0003.jpeg
    -rw-r--r-- 1 user admin 164271 26 Jul 11:20 image-0004.jpeg
    -rw-r--r-- 1 user admin 171662 26 Jul 11:20 image-0005.jpeg
    -rw-r--r-- 1 user admin 155528 26 Jul 11:20 image-0006.jpeg
    -rw-r--r-- 1 user admin 53193 26 Jul 11:20 image-0007.jpeg
    -rw-r--r-- 1 user admin 17643304 15 Aug 11:18 image_pdf-0.jpeg
    -rw-r--r-- 1 user admin 2906716 15 Aug 11:56 image_pdf-0.jpg
    -rw-r--r-- 1 user admin 18521373 15 Aug 11:18 image_pdf-1.jpeg
    -rw-r--r-- 1 user admin 3022841 15 Aug 11:58 image_pdf-1.jpg
    -rw-r--r-- 1 user admin 17394312 15 Aug 11:18 image_pdf-2.jpeg
    -rw-r--r-- 1 user admin 2762837 15 Aug 11:58 image_pdf-2.jpg
    -rw-r--r-- 1 user admin 13963420 15 Aug 11:19 image_pdf-3.jpeg
    -rw-r--r-- 1 user admin 2215533 15 Aug 11:58 image_pdf-3.jpg
    -rw-r--r-- 1 user admin 16076730 15 Aug 11:19 image_pdf-4.jpeg
    -rw-r--r-- 1 user admin 2597147 15 Aug 11:59 image_pdf-4.jpg
    -rw-r--r-- 1 user admin 16544272 15 Aug 11:19 image_pdf-5.jpeg
    -rw-r--r-- 1 user admin 2840288 15 Aug 11:59 image_pdf-5.jpg
    -rw-r--r-- 1 user admin 6870989 15 Aug 11:19 image_pdf-6.jpeg
    -rw-r--r-- 1 user admin 1030314 15 Aug 11:59 image_pdf-6.jpg
  6. Just as we decided to reinstall ffmpeg due to that disk crash, we decided to reinstall ImageMagick to this MacBook Pro here, and found, thanks to great advice, we found that we needed to …

    1. install ImageMagick via that previous link’s relevant download link … then at Terminal application command line …

      sudo -k ln -s /opt/ImageMagick/bin/convert /usr/bin/convert
    2. install GhostScript via that previous link’s relevant download link … then at Terminal application command line …

      sudo -k ln -s /opt/Ghostscript/bin/gs /usr/local/bin/gs

    3. install XQuartz via via XQuartz download page, thanks

    All animations, different forms (or formats), all presentation facilitators, is the message here today.


    Previous relevant Video via Slide Images and Back Again via ffmpeg Primer Tutorial is shown below.

    Video via Slide Images and Back Again via ffmpeg Primer Tutorial

    Video via Slide Images and Back Again via ffmpeg Primer Tutorial

    Reading yesterday’s LibreOffice Spreadsheet via dBase Primer Tutorial you can’t say I didn’t warn you about my interest in ants (and bees)? Glad you asked?

    Did you know?

    • the queen ant (often just one per ant colony) is not a leader as such in thinking out strategies … believe it or not …
    • it is believed ant colony strategies are worked by what we might call “groupthink”
    • ants march in line often and the scent that the ants leave behind is pheromone, that non-leader ants follow off that left behind by the “leader ant” … ie. “leader” of position, rather than “leader” of hierarchy

    So seeing some ants walking in line up a power pole, used an iPhone to capture a very short video (short enough to use the iPhone’s Photo app’s Share via Mail (attachment) method of emailing to the MacBook Pro, and then (Gmail website) downloading) of this, and later, buck the “ant” trend, and “anthropomorphise” a “star ant”, by honing in on an ant in this video and ring it (and its movement) before creating another “Star Ant Video”.

    There are video editing approaches you could use, but what got us interested was the thought of …

    • break the video into its component parts … just like animations like “Bugs Bunny” … a series of (slide, or frame) images
    • edit those (slide) images to add the (we’ve decided should be) red ringing of our “Star Ant” … who we’ve decided you, the user can call whatever you so desire … aaaaaaarrrrrrr
    • reconstitute a new video from some new (slide) image components

    That’s where one of our favourite Mac Os X friendly media players, which is also a command line “player” (yayyyyyy!) comes to the fore, for us. It’s the wonderful ffmpeg which we’ve had for a long time now on this MacBook Pro until a disk crash mentioned some weeks back. Could get it back off restore, but decided to reconsitute …

    … as a fairly straightforward exercise (given you have Xcode installed already) via a How to install FFmpeg on Mac OS X webpage by René Calles, thanks, heaps, we discovered the commands that worked well for us that go …


    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    brew install ffmpeg --with-fdk-aac --with-ffplay --with-freetype --with-frei0r --with-libass --with-libvo-aacenc --with-libvorbis --with-libvpx --with-opencore-amr --with-openjpeg --with-opus --with-rtmpdump --with-schroedinger --with-speex --with-theora --with-tools

    … to (re)install ffmpeg so that, then …


    ffmpeg -i IMG_0738.MOV -r 1 image-%04d.jpeg

    … could create those original 7 (slide) images, though the use of a value bigger than 1 frames per second for the “-r” switch could be on the cards for your usages.

    How to edit those images? We just used the Mac OS X version of PaintBrush and lined a lot of these images side by side across the screen to try to track our “Star Ant” and award it the “Red Ellipse PaintBrush Order of Merit” (for individualism … tee hee).

    Reconstituting the new slides into a new video we remember was another talent of ffmpeg and found this useful webpage, thanks, on the topic of taking raw (slide) images to create a video via ffmpeg. Actually, though, we also had our previous very useful Animated GIF and Video via PHP Writing PHP Data URI Tutorial (presented below) to turn to to end up with the Mac OS X (Terminal session command line command …


    ffmpeg -r 1 -i image-%04d.jpg ants.mp4

    There are no worries with video file “workings” to do with uppercase and lowercase and names, so we …


    cp IMG_0738.MOV ants.mov

    … just for some consistency purposes (and could use “mv” to rename instead) so that we can show you …

    Before … After … “Star Ant Video”

    See a lot of all these goings on at today’s PDF slideshow.


    Previous relevant Animated GIF and Video via PHP Writing PHP Data URI Tutorial is shown below.

    Animated GIF and Video via PHP Writing PHP Data URI Tutorial

    Animated GIF and Video via PHP Writing PHP Data URI Tutorial

    There is a great open source command line application called “FFmpeg” that can create video (or convert video) from image slides (for instance), and so, if we merge functionality for this into yesterday’s Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial some “presentation” styles that our web application can process are now …

    • animated GIF
    • slideshow
    • video

    As useful as “FFmpeg” is, it is not necessarily a default application existing on web server operating systems like our rjmprogramming.com.au’s CentOS server. But we do have it on our Mac OS X (MacBook Pro) operating system’s command line, so we write our PHP determining whether to …

    • create the video data there and then via “FFmpeg” and PHP’s exec method … or …
    • provide instructions to be able to create the video back at your client computer (that has “FFmpeg” perhaps) … to suit the …

      ffmpeg -r 1 -i %03d.jpg video.mp4

      … to create a video called video.mp4 with 1 second delays between (input) slides named 001.jpg then 002.jpg then 003.jpg etcetera … thanks useful webpage for the help … that in the command line can sometimes be played via …

      open video.mp4

      … or used in some HTML as per …

      <video controls id=ivideo type='video/mp4'><source src='video.mp4'></source></video>

      … that we show you, below, the Mac OS X local MAMP (Apache/PHP/MySql) web server running of today’s PHP to create …

    If you are a regular at this blog and “FFmpeg” sounds a bit familiar to you, that’s probably because you’ve read FFmpeg Image Optimization Primer Tutorial on an earlier occasion … by candlelight … with the lights dimmed?!

    See this in the context of how this PHP tutorial_to_animated_gif.php code changed for videos in this way or try it as a live run.


    Previous relevant Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial is shown below.

    Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial

    Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial

    To us, there are great similarities between animated GIFs and slideshows, as two forms of “presentation”, and so to extend yesterday’s Animated GIF via PHP Writing PHP Data URI Tutorial animated GIF creator “PHP Writes PHP” web application that now has the option for data URI “exports” we add the functionality for …

    • slideshow creation (using our inhouse methods) which defaults to a horizontal (hashtag type of) navigation … as well as adding a …
    • slideshow creation, with Data URI image data, using functionality as if CSS z-index (ie. slides stacked on top of each other in “overlay” style) was being used, but actually isn’t …

    … that little bit different to another “stacked” (or z-index feeling) approach we talked about with Multiple Class Slideshow Details Tutorial, where HTML element “class” properties were changed so that the last class defined reflects the look of the slideshow slide desired at any given time. We just use an array, and a setTimeout timer to achieve the same ends today, with our work (or “presentation”). If this “horizontal versus stack” navigation choice interests you, also take a read of HTML Input Element Types Randomized History Tutorial.

    Again, with all this added functionality, because it is “hosted” in an HTML iframe element all the existant web browser (Windows right click or Mac OS X two finger gesture) functionality can come into play, and make life quite interesting for your non-mobile users “collecting” data URIs … there are worse hobbies!

    You can see this in the context of how this PHP tutorial_to_animated_gif.php code changed for slideshows in this way or try it as a live run.


    Previous relevant Animated GIF via PHP Writing PHP Data URI Tutorial is shown below.

    Animated GIF via PHP Writing PHP Data URI Tutorial

    Animated GIF via PHP Writing PHP Data URI Tutorial

    The previous relevant “PHP writes PHP” methodology animated GIF creator we talked about, first, with Animated GIF via PHP Writing PHP Primer Tutorial came back to mind yesterday with our Missing Javascript Audio on Unmute Tutorial, where we pondered on whether an animated GIF could be represented on a webpage by a data URI. Why take an interest in this? Data URIs are very important to do with …

    • future mobile development web form navigation benefits from their usage
    • the use of data URIs make your web pages independent of web server location issues, so make your web data more portable, and flexible

    … and ideally, animated GIFs are also not just a decorative part of all this web application usage (as they can be a very efficient representation of an animation that could not be a more succinct way to show that animation or presentation), and if they can be made to be like any other GIF or image data file in the ways they can be represented (and used), then that is all for the good.

    So we changed the Jeroen van Wissen’s inspired PHP (“PHP writes PHP” methodology) code tutorial_to_animated_gif.php code allow for this extra animated GIF data URI representation in a new additional HTML iframe (containing the animegif.html of code below) that when harnessing existant web browser (Windows right click or Mac OS X two finger gesture) functionality can glean for us, as required, that animated GIF’s data URI representation. But don’t get too excited about this being rocket science, in that with a bit of effort, and PHP, it could have been gleaned from what we already produced, in that (in PHP “land”) …


    $lastbitto="\$fp = fopen('animegif.gif', 'w');
    \$data = \$gif->GetAnimation();
    \$dataUri = 'data:image/gif;base64,' . base64_encode(\$data);
    fwrite(\$fp, \$data);
    fclose(\$fp);
    \$fp = fopen('animegif.html', 'w');
    fwrite(\$fp, '<!doctype html><html><body><h1>Data URI version below<h1><br><h4> ... via web browser (Windows right click, Mac OS X two finger gesture ...</h4><br><img src=' . \"\\n\" . \$dataUri . \"\\n\" . ' title=DataURI></img></body></html>');
    fclose(\$fp);";

    You can see this in the context of how this PHP code changed in this way or try it as a live run.


    Previous relevant Animated GIF via PHP Writing PHP Primer Tutorial is shown below.

    Animated GIF via PHP Writing PHP Primer Tutorial

    Animated GIF via PHP Writing PHP Primer Tutorial

    We find another very useful reason for PHP to write PHP. Today we establish a PHP web application to dynamically create Animated GIF images via some still images, like Gifpal would do.

    We have some great open source PHP code to thank for the basis of the functionality we found at Jeroen van Wissen’s very useful link, thanks.

    Then we added a more user friendly interface to get the information off the user we need. We present this in an HTML form, which navigates to the same PHP to do the actual assembly of the Animated GIF via techniques where PHP writes PHP … and really needs to, to be useful.

    Do you remember, last, when we did some PHP writing PHP functionality … PHP Writes PHP Vertical TextBoxes Primer Tutorial?

    And inside the PHP it makes big use of the GD and Image Functions to read and write the image data we assemble via the user information.

    This Animated GIF form of animation is the easiest to implement, as it consists of just the one GIF image file, but the user has very little control over the animation settings, such as the delay between stills, one of the settings we ask about in our web application.

    Our PHP source code today you could call tutorial_to_animated_gif.php and we redirect you to some live run ideas …

    • normal run with HTML form which posts back to itself … live run
    • example GET parameters run (like our tutorial picture)

    Hope you find this tutorial useful.

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

Pdfimages PDF Image Extraction Primer Tutorial

Pdfimages PDF Image Extraction Primer Tutorial

Pdfimages PDF Image Extraction Primer Tutorial

When we presented PDF via Slide Images and Back Again via ImageMagick Primer Tutorial we referenced …

  • the great ImageMagick suite of software capable of extracting PDF pages as an image … as distinct from our curiosity today …
  • we discovered, thanks, that the great Pdfimages suite of software can extract the images contained within a PDF

And so, today, we show with today’s animated GIF presentation …

  • installing Pdfimages on macOS via …

    brew install poppler
  • using a macOS command line (via Terminal application) issued command …

    pdfimages -j "September 22 record.pdf" ideas -png

    … to extract the 242 images (curiously, as jpeg images) contained within our input PDF.

Interesting, huh?


Previous relevant PDF via Slide Images and Back Again via ImageMagick Primer Tutorial is shown below.

PDF via Slide Images and Back Again via ImageMagick Primer Tutorial

PDF via Slide Images and Back Again via ImageMagick Primer Tutorial

Does today’s blog posting title sound familiar to you? If so, I’m impressed. If not, get the whole picture, in context (we hope), today of …

  • today’s “PDF via Slide Images and Back Again via ImageMagick Primer Tutorial” … gets its cues from a …
  • previous “Video via Slide Images and Back Again via ffmpeg Primer Tutorial” … so that …
    1. PDF is the output file format as distinct from a Video Format such as *.mov or *.mp4
    2. ImageMagick is the conduit to that work as distinct from ffmpeg

… and that what is a common denominator here to be able to convert between Video and PDF and vice versa, is a set of image slides (or frames) of the animation concerned, today’s being, again, that Ant Video we took on our iPhone (that became the “Star Ant Video”), and that today takes as its starting point

  1. image slides (or frames) from Video via Slide Images and Back Again via ffmpeg Primer Tutorial our MacBook Pro (via an email attachment download) … a listing of which looks like …

    $ ls -l image-000*.jpeg
    -rw-r--r-- 1 user admin 170993 26 Jul 11:20 image-0001.jpeg
    -rw-r--r-- 1 user admin 205565 26 Jul 11:20 image-0002.jpeg
    -rw-r--r-- 1 user admin 218950 26 Jul 11:20 image-0003.jpeg
    -rw-r--r-- 1 user admin 164271 26 Jul 11:20 image-0004.jpeg
    -rw-r--r-- 1 user admin 171662 26 Jul 11:20 image-0005.jpeg
    -rw-r--r-- 1 user admin 155528 26 Jul 11:20 image-0006.jpeg
    -rw-r--r-- 1 user admin 53193 26 Jul 11:20 image-0007.jpeg
  2. gets converted to an original (input) PDF (antsoriginal.pdf) (with slideshow capabilities via applications like Mac OS X’s Preview or Adobe Acrobat Reader) via Mac OS X Terminal application command line’s ImageMagick executable convert command …

    convert image-000*.jpeg -density 4096 antsoriginal.pdf

    … and then we act as though this PDF was our original source of data and decide to …
  3. break that PDF into its constituent image slides (or frames) via …

    convert -density 900 antsoriginal.pdf image_pdf.jpeg

    … and then use ImageMagick convert commands again to …
  4. crop those image slides via Mac OS X Terminal application command line’s ImageMagick executable convert commands (thanks to this great advice) …

    $ convert image_pdf-0.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-0.jpg
    $ convert image_pdf-1.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-1.jpg
    $ convert image_pdf-2.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-2.jpg
    $ convert image_pdf-3.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-3.jpg
    $ convert image_pdf-4.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-4.jpg
    $ convert image_pdf-5.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-5.jpg
    $ convert image_pdf-6.jpeg -crop 3000x6000+4000+4000 -gravity center image_pdf-6.jpg

    … into new PDF slide images (or frames) that can be converted to (output) PDF (antscentral.pdf) via ImageMagick executable convert command …

    convert image_pdf*.jpg antscentral.pdf

    … to see …
  5. we end up with the (relevant) file listing …

    $ ls -l image-000*.jpeg image_pdf*.jp*g ants*l.pdf
    -rw-r--r--@ 1 user admin 17405330 15 Aug 12:00 antscentral.pdf
    -rw-r--r--@ 1 user admin 1350686 15 Aug 11:53 antsoriginal.pdf
    -rw-r--r-- 1 user admin 170993 26 Jul 11:20 image-0001.jpeg
    -rw-r--r-- 1 user admin 205565 26 Jul 11:20 image-0002.jpeg
    -rw-r--r-- 1 user admin 218950 26 Jul 11:20 image-0003.jpeg
    -rw-r--r-- 1 user admin 164271 26 Jul 11:20 image-0004.jpeg
    -rw-r--r-- 1 user admin 171662 26 Jul 11:20 image-0005.jpeg
    -rw-r--r-- 1 user admin 155528 26 Jul 11:20 image-0006.jpeg
    -rw-r--r-- 1 user admin 53193 26 Jul 11:20 image-0007.jpeg
    -rw-r--r-- 1 user admin 17643304 15 Aug 11:18 image_pdf-0.jpeg
    -rw-r--r-- 1 user admin 2906716 15 Aug 11:56 image_pdf-0.jpg
    -rw-r--r-- 1 user admin 18521373 15 Aug 11:18 image_pdf-1.jpeg
    -rw-r--r-- 1 user admin 3022841 15 Aug 11:58 image_pdf-1.jpg
    -rw-r--r-- 1 user admin 17394312 15 Aug 11:18 image_pdf-2.jpeg
    -rw-r--r-- 1 user admin 2762837 15 Aug 11:58 image_pdf-2.jpg
    -rw-r--r-- 1 user admin 13963420 15 Aug 11:19 image_pdf-3.jpeg
    -rw-r--r-- 1 user admin 2215533 15 Aug 11:58 image_pdf-3.jpg
    -rw-r--r-- 1 user admin 16076730 15 Aug 11:19 image_pdf-4.jpeg
    -rw-r--r-- 1 user admin 2597147 15 Aug 11:59 image_pdf-4.jpg
    -rw-r--r-- 1 user admin 16544272 15 Aug 11:19 image_pdf-5.jpeg
    -rw-r--r-- 1 user admin 2840288 15 Aug 11:59 image_pdf-5.jpg
    -rw-r--r-- 1 user admin 6870989 15 Aug 11:19 image_pdf-6.jpeg
    -rw-r--r-- 1 user admin 1030314 15 Aug 11:59 image_pdf-6.jpg
  6. Just as we decided to reinstall ffmpeg due to that disk crash, we decided to reinstall ImageMagick to this MacBook Pro here, and found, thanks to great advice, we found that we needed to …

    1. install ImageMagick via that previous link’s relevant download link … then at Terminal application command line …

      sudo -k ln -s /opt/ImageMagick/bin/convert /usr/bin/convert
    2. install GhostScript via that previous link’s relevant download link … then at Terminal application command line …

      sudo -k ln -s /opt/Ghostscript/bin/gs /usr/local/bin/gs

    3. install XQuartz via via XQuartz download page, thanks

    All animations, different forms (or formats), all presentation facilitators, is the message here today.


    Previous relevant Video via Slide Images and Back Again via ffmpeg Primer Tutorial is shown below.

    Video via Slide Images and Back Again via ffmpeg Primer Tutorial

    Video via Slide Images and Back Again via ffmpeg Primer Tutorial

    Reading yesterday’s LibreOffice Spreadsheet via dBase Primer Tutorial you can’t say I didn’t warn you about my interest in ants (and bees)? Glad you asked?

    Did you know?

    • the queen ant (often just one per ant colony) is not a leader as such in thinking out strategies … believe it or not …
    • it is believed ant colony strategies are worked by what we might call “groupthink”
    • ants march in line often and the scent that the ants leave behind is pheromone, that non-leader ants follow off that left behind by the “leader ant” … ie. “leader” of position, rather than “leader” of hierarchy

    So seeing some ants walking in line up a power pole, used an iPhone to capture a very short video (short enough to use the iPhone’s Photo app’s Share via Mail (attachment) method of emailing to the MacBook Pro, and then (Gmail website) downloading) of this, and later, buck the “ant” trend, and “anthropomorphise” a “star ant”, by honing in on an ant in this video and ring it (and its movement) before creating another “Star Ant Video”.

    There are video editing approaches you could use, but what got us interested was the thought of …

    • break the video into its component parts … just like animations like “Bugs Bunny” … a series of (slide, or frame) images
    • edit those (slide) images to add the (we’ve decided should be) red ringing of our “Star Ant” … who we’ve decided you, the user can call whatever you so desire … aaaaaaarrrrrrr
    • reconstitute a new video from some new (slide) image components

    That’s where one of our favourite Mac Os X friendly media players, which is also a command line “player” (yayyyyyy!) comes to the fore, for us. It’s the wonderful ffmpeg which we’ve had for a long time now on this MacBook Pro until a disk crash mentioned some weeks back. Could get it back off restore, but decided to reconsitute …

    … as a fairly straightforward exercise (given you have Xcode installed already) via a How to install FFmpeg on Mac OS X webpage by René Calles, thanks, heaps, we discovered the commands that worked well for us that go …


    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    brew install ffmpeg --with-fdk-aac --with-ffplay --with-freetype --with-frei0r --with-libass --with-libvo-aacenc --with-libvorbis --with-libvpx --with-opencore-amr --with-openjpeg --with-opus --with-rtmpdump --with-schroedinger --with-speex --with-theora --with-tools

    … to (re)install ffmpeg so that, then …


    ffmpeg -i IMG_0738.MOV -r 1 image-%04d.jpeg

    … could create those original 7 (slide) images, though the use of a value bigger than 1 frames per second for the “-r” switch could be on the cards for your usages.

    How to edit those images? We just used the Mac OS X version of PaintBrush and lined a lot of these images side by side across the screen to try to track our “Star Ant” and award it the “Red Ellipse PaintBrush Order of Merit” (for individualism … tee hee).

    Reconstituting the new slides into a new video we remember was another talent of ffmpeg and found this useful webpage, thanks, on the topic of taking raw (slide) images to create a video via ffmpeg. Actually, though, we also had our previous very useful Animated GIF and Video via PHP Writing PHP Data URI Tutorial (presented below) to turn to to end up with the Mac OS X (Terminal session command line command …


    ffmpeg -r 1 -i image-%04d.jpg ants.mp4

    There are no worries with video file “workings” to do with uppercase and lowercase and names, so we …


    cp IMG_0738.MOV ants.mov

    … just for some consistency purposes (and could use “mv” to rename instead) so that we can show you …

    Before … After … “Star Ant Video”

    See a lot of all these goings on at today’s PDF slideshow.


    Previous relevant Animated GIF and Video via PHP Writing PHP Data URI Tutorial is shown below.

    Animated GIF and Video via PHP Writing PHP Data URI Tutorial

    Animated GIF and Video via PHP Writing PHP Data URI Tutorial

    There is a great open source command line application called “FFmpeg” that can create video (or convert video) from image slides (for instance), and so, if we merge functionality for this into yesterday’s Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial some “presentation” styles that our web application can process are now …

    • animated GIF
    • slideshow
    • video

    As useful as “FFmpeg” is, it is not necessarily a default application existing on web server operating systems like our rjmprogramming.com.au’s CentOS server. But we do have it on our Mac OS X (MacBook Pro) operating system’s command line, so we write our PHP determining whether to …

    • create the video data there and then via “FFmpeg” and PHP’s exec method … or …
    • provide instructions to be able to create the video back at your client computer (that has “FFmpeg” perhaps) … to suit the …

      ffmpeg -r 1 -i %03d.jpg video.mp4

      … to create a video called video.mp4 with 1 second delays between (input) slides named 001.jpg then 002.jpg then 003.jpg etcetera … thanks useful webpage for the help … that in the command line can sometimes be played via …

      open video.mp4

      … or used in some HTML as per …

      <video controls id=ivideo type='video/mp4'><source src='video.mp4'></source></video>

      … that we show you, below, the Mac OS X local MAMP (Apache/PHP/MySql) web server running of today’s PHP to create …

    If you are a regular at this blog and “FFmpeg” sounds a bit familiar to you, that’s probably because you’ve read FFmpeg Image Optimization Primer Tutorial on an earlier occasion … by candlelight … with the lights dimmed?!

    See this in the context of how this PHP tutorial_to_animated_gif.php code changed for videos in this way or try it as a live run.


    Previous relevant Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial is shown below.

    Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial

    Animated GIF and Slideshow via PHP Writing PHP Data URI Tutorial

    To us, there are great similarities between animated GIFs and slideshows, as two forms of “presentation”, and so to extend yesterday’s Animated GIF via PHP Writing PHP Data URI Tutorial animated GIF creator “PHP Writes PHP” web application that now has the option for data URI “exports” we add the functionality for …

    • slideshow creation (using our inhouse methods) which defaults to a horizontal (hashtag type of) navigation … as well as adding a …
    • slideshow creation, with Data URI image data, using functionality as if CSS z-index (ie. slides stacked on top of each other in “overlay” style) was being used, but actually isn’t …

    … that little bit different to another “stacked” (or z-index feeling) approach we talked about with Multiple Class Slideshow Details Tutorial, where HTML element “class” properties were changed so that the last class defined reflects the look of the slideshow slide desired at any given time. We just use an array, and a setTimeout timer to achieve the same ends today, with our work (or “presentation”). If this “horizontal versus stack” navigation choice interests you, also take a read of HTML Input Element Types Randomized History Tutorial.

    Again, with all this added functionality, because it is “hosted” in an HTML iframe element all the existant web browser (Windows right click or Mac OS X two finger gesture) functionality can come into play, and make life quite interesting for your non-mobile users “collecting” data URIs … there are worse hobbies!

    You can see this in the context of how this PHP tutorial_to_animated_gif.php code changed for slideshows in this way or try it as a live run.


    Previous relevant Animated GIF via PHP Writing PHP Data URI Tutorial is shown below.

    Animated GIF via PHP Writing PHP Data URI Tutorial

    Animated GIF via PHP Writing PHP Data URI Tutorial

    The previous relevant “PHP writes PHP” methodology animated GIF creator we talked about, first, with Animated GIF via PHP Writing PHP Primer Tutorial came back to mind yesterday with our Missing Javascript Audio on Unmute Tutorial, where we pondered on whether an animated GIF could be represented on a webpage by a data URI. Why take an interest in this? Data URIs are very important to do with …

    • future mobile development web form navigation benefits from their usage
    • the use of data URIs make your web pages independent of web server location issues, so make your web data more portable, and flexible

    … and ideally, animated GIFs are also not just a decorative part of all this web application usage (as they can be a very efficient representation of an animation that could not be a more succinct way to show that animation or presentation), and if they can be made to be like any other GIF or image data file in the ways they can be represented (and used), then that is all for the good.

    So we changed the Jeroen van Wissen’s inspired PHP (“PHP writes PHP” methodology) code tutorial_to_animated_gif.php code allow for this extra animated GIF data URI representation in a new additional HTML iframe (containing the animegif.html of code below) that when harnessing existant web browser (Windows right click or Mac OS X two finger gesture) functionality can glean for us, as required, that animated GIF’s data URI representation. But don’t get too excited about this being rocket science, in that with a bit of effort, and PHP, it could have been gleaned from what we already produced, in that (in PHP “land”) …


    $lastbitto="\$fp = fopen('animegif.gif', 'w');
    \$data = \$gif->GetAnimation();
    \$dataUri = 'data:image/gif;base64,' . base64_encode(\$data);
    fwrite(\$fp, \$data);
    fclose(\$fp);
    \$fp = fopen('animegif.html', 'w');
    fwrite(\$fp, '<!doctype html><html><body><h1>Data URI version below<h1><br><h4> ... via web browser (Windows right click, Mac OS X two finger gesture ...</h4><br><img src=' . \"\\n\" . \$dataUri . \"\\n\" . ' title=DataURI></img></body></html>');
    fclose(\$fp);";

    You can see this in the context of how this PHP code changed in this way or try it as a live run.


    Previous relevant Animated GIF via PHP Writing PHP Primer Tutorial is shown below.

    Animated GIF via PHP Writing PHP Primer Tutorial

    Animated GIF via PHP Writing PHP Primer Tutorial

    We find another very useful reason for PHP to write PHP. Today we establish a PHP web application to dynamically create Animated GIF images via some still images, like Gifpal would do.

    We have some great open source PHP code to thank for the basis of the functionality we found at Jeroen van Wissen’s very useful link, thanks.

    Then we added a more user friendly interface to get the information off the user we need. We present this in an HTML form, which navigates to the same PHP to do the actual assembly of the Animated GIF via techniques where PHP writes PHP … and really needs to, to be useful.

    Do you remember, last, when we did some PHP writing PHP functionality … PHP Writes PHP Vertical TextBoxes Primer Tutorial?

    And inside the PHP it makes big use of the GD and Image Functions to read and write the image data we assemble via the user information.

    This Animated GIF form of animation is the easiest to implement, as it consists of just the one GIF image file, but the user has very little control over the animation settings, such as the delay between stills, one of the settings we ask about in our web application.

    Our PHP source code today you could call tutorial_to_animated_gif.php and we redirect you to some live run ideas …

    • normal run with HTML form which posts back to itself … live run
    • example GET parameters run (like our tutorial picture)

    Hope you find this tutorial useful.

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

SVG and Gradient Fraction Game Operators Tutorial

SVG and Gradient Fraction Game Operators Tutorial

SVG and Gradient Fraction Game Operators Tutorial

Onto the SVG “cake” display functionality added with yesterday’s SVG and Gradient Fraction Game Tutorial into our Fractions Game web application, we’re adding …

  • SVG circle “cakes” that can be rotated … but not in the SVG … rather in the nesting HTML div … as per

    rotdeg=eval(Math.floor(eval(360.0 * numerator / denominator)) % 360);
    rotdegr=eval(Math.floor(eval(360.0 * numeratortwo / denominatortwo)) % 360);

    document.getElementById('dstyle').innerHTML+='<style>' + ' #atend { background-image: none !important; transform: rotate(' + rotdeg + 'deg); } </style>';
    document.getElementById('dstyle').innerHTML+='<style>' + ' #atright { background-image: none !important; transform: rotate(' + rotdegr + 'deg); } </style>';

    … as a “distinguisher” (of SVG as distinct from conic-gradient) and “for user interest, and challenge, sake”
  • two new mathematics operators to offer on that “operator dropdown” … in addition to + – x / …
    •  % (ie. modulo eg. in Javascript eval(3/4 % 1/2) is 1/4 is 0.25)
    •  ^ (ie. “left fraction base” to the power of “right fraction power” eg. (1/4 ^ 1/2) ( we can internally express as Math.pow(1/4, 1/2) ) is 1/2 is 0.5)

    … today, again “for user interest, and challenge, sake” … naturally, as far as answers go, we’ve always accepted decimal answers

… in the changed circular_sectors.html Fractions Game.


Previous relevant SVG and Gradient Fraction Game Tutorial is shown below.

SVG and Gradient Fraction Game Tutorial

SVG and Gradient Fraction Game Tutorial

To add onto yesterday’s Gradient Fraction Game Mobile Tutorial

  • exclusively gradient
    • conic
    • linear
    • radial

    … “cake” displays in our Fractions Game … and add in …

  • SVG circle and rectangle alternative displays

… it is not hard coding work, only really involving the rearrangement of the “stop colour” element …


function stopit(incsv) {
//alert(incsv);
// <stop offset='0%' stop-color='#f00'/><stop offset='100%' stop-color='#0ff'/>
var incsvs=incsv.split('%, ');
var outstops="<stop offset='0%' stop-color='" + incsvs[0].split(' ')[0] + "'/>";
for (var iis=1; iis<incsvs.length; iis++) {
outstops+="<stop offset='" + (incsvs[iis].split(' ')[1].trim() + "%").replace('%%','%') + "' stop-color='" + incsvs[iis].split(' ')[0] + "'/>";
}
//alert(outstops);
//document.getElementById('atend').title=outstops.replace(/255/g, '127');
return outstops.replace(/255/g, '127');
}

… code syntax.

But before that we went down a garden path thinking we could have all 5 “cake” display options be …

  • as the CSS property background-image to a table cell nesting HTML div element … sort of like this webpage‘s (thanks all the same) …

    #atright {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='%23F00'/><stop offset='90%' stop-color='%23fcc'/> </linearGradient><rect fill='url(%23gradient)' x='0' y='0' width='100%' height='100%'/></svg>");
    }
    // ... or ...
    #atend {
    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PGxpbmVhckdyYWRpZW50IGlkPSdncmFkaWVudCc+PHN0b3Agb2Zmc2V0PScxMCUnIHN0b3AtY29sb3I9JyNGMDAnLz48c3RvcCBvZmZzZXQ9JzkwJScgc3RvcC1jb2xvcj0nI2ZjYycvPiA8L2xpbmVhckdyYWRpZW50PjxyZWN0IGZpbGw9J3VybCgjZ3JhZGllbnQpJyB4PScwJyB5PScwJyB3aWR0aD0nMTAwJScgaGVpZ2h0PScxMDAlJy8+PC9zdmc+");
    }

    … and though we had lots of success with work of this ilk with our “Just Javascript” series of blog posts, we found the technique flaky today, so opted to, instead …

    1. fill HTML div element’s innerHTML (ie. content) with “raw” SVG
    2. set that HTML div element’s CSS style property background-image to “none”

… as the approach we landed upon, allowing for SVG


if (issvg > 0) {
var mySVG = "<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='#F00'/><stop offset='90%' stop-color='#fcc'/> </linearGradient><rect fill='url(#gradient)' x='0' y='0' width='100%' height='100%'/></svg>";
if (issvg == 1) {
mySVG="<svg xmlns='http://www.w3.org/2000/svg' width='" + pwidth + "' height='" + pheight + "' viewport='0 0 100 100'><linearGradient id='test'>" + stopit(newlist) + " </linearGradient><circle fill='url(#test)' cx='" + eval(pwidth / 2) + "' cy='" + eval(pheight / 2) + "' r='" + eval(pwidth / 2) + "' stroke='none' stroke-width='12'/></svg>"; //.replace(/\~/g, String.fromCharCode(10));
} else if (issvg == 2) {
mySVG="<svg xmlns='http://www.w3.org/2000/svg' width='" + pwidth + "' height='" + pheight + "' viewport='0 0 100 100'><linearGradient id='test'>" + stopit(newlist) + " </linearGradient><rect fill='url(#test)' width='" + eval(pwidth / 1) + "' height='" + eval(pheight / 1) + "' stroke='none' stroke-width='12'/></svg>"; //.replace(/\~/g, String.fromCharCode(10));
}
document.getElementById('atend').innerHTML=mySVG;
if (issvg == 1) {
mySVG="<svg xmlns='http://www.w3.org/2000/svg' width='" + pwidth + "' height='" + pheight + "' viewport='0 0 100 100'><linearGradient id='testr'>" + stopit(newlistr) + " </linearGradient><circle fill='url(#testr)' cx='" + eval(pwidth / 2) + "' cy='" + eval(pheight / 2) + "' r='" + eval(pwidth / 2) + "' stroke='none' stroke-width='12'/></svg>"; //.replace(/\~/g, String.fromCharCode(10));
} else if (issvg == 2) {
mySVG="<svg xmlns='http://www.w3.org/2000/svg' width='" + pwidth + "' height='" + pheight + "' viewport='0 0 100 100'><linearGradient id='testr'>" + stopit(newlistr) + " </linearGradient><rect fill='url(#testr)' width='" + eval(pwidth / 1) + "' height='" + eval(pheight / 1) + "' stroke='none' stroke-width='12'/></svg>"; //.replace(/\~/g, String.fromCharCode(10));
}
document.getElementById('atright').innerHTML=mySVG;
document.getElementById('dstyle').innerHTML+='<style>' + ' #atend { background-image: none !important; } </style>';
document.getElementById('dstyle').innerHTML+='<style>' + ' #atright { background-image: none !important; } </style>';
} else {
document.getElementById('atend').innerHTML='';
document.getElementById('atright').innerHTML='';

document.getElementById('dstyle').innerHTML+='<style>' + ' #atend { background-image: ' + gprefix.toLowerCase() + '-gradient(' + newlist + ') !important; } </style>';
document.getElementById('dstyle').innerHTML+='<style>' + ' #atright { background-image: ' + gprefix.toLowerCase() + '-gradient(' + newlistr + ') !important; } </style>';
}

… in the changed circular_sectors.html Fractions Game.


Previous relevant Gradient Fraction Game Mobile Tutorial is shown below.

Gradient Fraction Game Mobile Tutorial

Gradient Fraction Game Mobile Tutorial

Many responsive web design purists will push the web developers out there to never …

  • express HTML element dimensions in “static” “px” types of units … but rather …
  • express HTML element dimensions in “%” or “vx” or “vh” proportional style of units … and, of course, their advice has a lot of merit, but, sometimes, like today, we want to be a bit pragmatic here and say …
  • a third way, particularly suiting an initial development phase that suited a display on a laptop (and deploying “static” “px” types of units that look okay on a laptop), for instance, but then wanting to look more apt on your smaller mobile devices, you could …
    1. ensure you have within the webpage head element a “meta” viewport element such as (our) …

      <meta id='myviewport' name='viewport' content='width=device-width, initial-scale=1, minimum-scale=0.1, maximum-scale=8, user-scalable=yes' >
    2. stay with “static” “px” types of units but if analysis (which can be before document.body “onload” event (and, you couldn’t possibly have heard it from me, cough cough, but dovetail findings within Javascript document.write statements within the document.body static HTML)) of either/both screen.width and/or screen.height indicates lack of suitablility …

      var fromprefix='border-radius: 612px;', toprefix="margin-top: 0px;";
      var pwidth=602, pheight=602, pbr=612, ptop=17.3594, pleft=386.5, thirtytwo=32, ocbit='';
      var worry=false;

      if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && btoas.trim() == '' && denominator == '0' && numerator == '0') {
      ocbit=' onclick=" viadb=true; ask(); " ';
      }
      if (eval(eval('' + screen.width) - eval(eval('' + pbr) * 2)) < 0 && (btoas.trim() != '' || denominator != '0' || numerator != '0')) {
      thirtytwo=Math.floor(eval(eval('' + thirtytwo) * Math.floor(eval(eval('' + screen.width) / 2.1)) / eval('' + pbr)));
      ptop=eval(eval('' + ptop) * Math.floor(eval(eval('' + screen.width) / 2.1)) / eval('' + pbr));
      pleft=eval(eval('' + pleft) * Math.floor(eval(eval('' + screen.width) / 2.1)) / eval('' + pbr));
      pbr=Math.floor(eval(eval('' + screen.width) / 2.1));
      fromprefix='border-radius: ' + pbr + 'px;'
      pwidth=eval(-10 + pbr);
      pheight=eval(-10 + pbr);
      worry=true;
      //alert('width,height,br,top,left=' + pwidth + ',' + pheight + ',' + pbr + ',' + ptop + ',' + pleft);
      }

      … Javascript “head” code affecting the “body” …

      <body>
      <script type='text/javascript'>
      document.write('<table id=mytable><tbody id=mytbody><tr id=mytr><td id=mytd>');
      if (denominator == '0' && btoas == '') {
      if (worry) {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="position: absolute; left: ' + pleft + 'px; top: ' + ptop + 'px; width: ' + pwidth + 'px; height: ' + pheight + 'px; border-radius: ' + pbr + 'px; ">');
      } else {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="position: absolute; left: 386.5px; top: 17.3594px; width: 602px; height: 602px; border-radius: 612px; ">');
      }
      document.write('<iframe scrolling="no" frameborder="0" style="z-index:23;margin-left:127px;margin-top:130px;height:400px;" src="analogue_clock.htm?backcol=transparent&x=7654#xbody"></iframe>');
      } else {
      if (worry) {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="width: ' + pwidth + 'px; height: ' + pheight + 'px; border-radius: ' + pbr + 'px; ">');
      } else {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="width: 602px; height: 602px; border-radius: 612px; ">');
      }
      }
      if (worry) {
      document.write('</div></td><td id=mymtd style=display:none;vertical-align:middle;>  <select id=ssign style=font-size:' + thirtytwo + 'px;background-color:yellow; readonly disable><option value="+">➕</option><option value="-">➖</option><option value="x">✖</option><option value="/">➗</option></select></td><td id=myrtd style=display:none;>  <div ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atright" style="width: ' + pwidth + 'px; height: ' + pheight + 'px; border-radius: ' + pbr + 'px; "></div></td></tr></tbody></table>');
      } else {
      document.write('</div></td><td id=mymtd style=display:none;vertical-align:middle;>  <select id=ssign style=font-size:' + thirtytwo + 'px;background-color:yellow; readonly disable><option value="+">➕</option><option value="-">➖</option><option value="x">✖</option><option value="/">➗</option></select></td><td id=myrtd style=display:none;>  <div ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atright" style="width: 602px; height: 602px; border-radius: 612px; "></div></td></tr></tbody></table>');
      }
      </script>
      <div id=dstyle></div>
      </body>

      … element, to lean on “hardcodings become parameter” types of thinking to proceed with a more apt dimensional display (that is all sorted out ahead of document.body “onload” event, still not associated with any Javascript code, above)

Yes, you can develop web applications on mobile. There are ways. But we find it much more natural and easy to develop web applications on a laptop, here it being a MacBook Air at the moment. One reason we’d give, is that the quality of laptop web browser web inspectors is sky high, and all the modern browsers seem to have a (laptop) version now.

And as such, improving mobile usage of yesterday’s Gradient Fraction Game Equations Tutorial we have in a changed circular_sectors.html Fractions Game.


Previous relevant Gradient Fraction Game Equations Tutorial is shown below.

Gradient Fraction Game Equations Tutorial

Gradient Fraction Game Equations Tutorial

There are three styles of CSS gradient …

  • conic
  • linear
  • radial

… and “different folks may learn via diff’rent CSS strokes”, so we incorporate a way for the user, when using the Fractions Game component of our latest web application, so that they can toggle the “cake” display among these three styles of gradient display.

Also, extending yesterday’s Conic Gradient Fraction Game Equations Tutorial, we …

  • allow, during the Fractions Game mode usage, have a window.prompt Cancel click send the user back to the Analogue Clock, so that unnecessary and errant window.prompt popup windows are avoided … and …
  • we incorporate “lowest common denominator” …

    function lcdextra(varn, vard) {
    var retv='', iv=0;
    for (iv=Math.min(Math.abs(varn),Math.abs(vard)); iv>=2; iv--) {
    if (eval(Math.abs(varn) % iv) == 0 && eval(Math.abs(vard) % iv) == 0) {
    varn /= iv;
    vard /= iv;
    retv+=' = ' + varn + ' / ' + vard + String.fromCharCode(10);
    }
    }
    return retv;
    }

    … calculations into our “show workings” section as Ms Trimpole would have wanted
  • involve emoji operators in that same “show workings” section to better mimic how we were taught at school in Mathematics class

… in the changed circular_sectors.html Fractions Game.


Previous relevant Conic Gradient Fraction Game Equations Tutorial is shown below.

Conic Gradient Fraction Game Equations Tutorial

Conic Gradient Fraction Game Equations Tutorial

We’re extending the functionality started with yesterday’s Dual Purpose Conic Gradient Primer Tutorial‘s second “dual purpose” …

  • Fractions Game piece of functionality …
  • Adding to its possibility the optional user job of solving operator …
    •  +
    •  –
    •  x
    •  /

    … types of fraction based equations

Simply put, changes to allow for this involved …

  • forsaking position:absolute “cakes” for your usual default position:relative positioning … within …
  • single row, three cell (cake, sign, cake) display … prior to …
  • hardly changed window.prompt user interaction, to answer … but …
  • more complex analysis for equation based scenarios …

    function showworking(instr, realans) {
    var outstr=instr;
    var xnumerator=numerator, xnumeratortwo=numeratortwo, xdenominatortwo=denominatortwo;
    var varw='';
    if (document.getElementById('ssign').value == '+') {
    if (denominatortwo == denominator.slice(-1)) {
    varw+=' = (' + numerator + ' + ' + numeratortwo + ') / ' + denominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) + eval('' + numeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    } else {
    varw+=' = (' + numerator + ' x ' + denominatortwo + ' + ' + numeratortwo + ' x ' + denominator.slice(-1) + ') / (' + denominator.slice(-1) + ' x ' + denominatortwo + ')' + String.fromCharCode(10);
    xnumerator*=denominatortwo;
    xnumeratortwo*=eval('' + denominator.slice(-1));
    xdenominatortwo*=eval('' + denominator.slice(-1));
    varw+=' = (' + xnumerator + ' + ' + xnumeratortwo + ') / ' + xdenominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + xnumerator) + eval('' + xnumeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    }
    } else if (document.getElementById('ssign').value == '-') {
    if (denominatortwo == denominator.slice(-1)) {
    varw+=' = (' + numerator + ' - ' + numeratortwo + ') / ' + denominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(numerator - numeratortwo) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    } else {
    varw+=' = (' + numerator + ' x ' + denominatortwo + ' - ' + numeratortwo + ' x ' + denominator.slice(-1) + ') / (' + denominator.slice(-1) + ' x ' + denominatortwo + ')' + String.fromCharCode(10);
    xnumerator*=denominatortwo;
    xnumeratortwo*=eval('' + denominator.slice(-1));
    xdenominatortwo*=eval('' + denominator.slice(-1));
    varw+=' = (' + xnumerator + ' - ' + xnumeratortwo + ') / ' + xdenominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + xnumerator) - eval('' + xnumeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    }
    } else if (document.getElementById('ssign').value == '/') {
    varw+=' = (' + numerator + ' / ' + denominator.slice(-1) + ') x (' + denominatortwo + ' / ' + numeratortwo + ')' + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) * eval('' + denominatortwo)) + ' / ' + eval(eval('' + denominator.slice(-1)) * eval('' + numeratortwo)) + String.fromCharCode(10);
    } else if (document.getElementById('ssign').value == 'x' || document.getElementById('ssign').value == '*') {
    varw+=' = (' + numerator + ' / ' + denominator.slice(-1) + ') x (' + numeratortwo + ' / ' + denominatortwo + ')' + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) * eval('' + numeratortwo)) + ' / ' + eval(eval('' + denominator.slice(-1)) * eval('' + denominatortwo)) + String.fromCharCode(10);
    }
    return outstr + String.fromCharCode(10) + varw + ' = ' + realans + ' ' + String.fromCharCode(10);
    }

… in the changed circular_sectors.html Fractions Game.


Previous relevant Dual Purpose Conic Gradient Primer Tutorial is shown below.

Dual Purpose Conic Gradient Primer Tutorial

Dual Purpose Conic Gradient Primer Tutorial

Yes, today, we have a “proof of concept” circular_sectors.html

  • dual purpose … as a …
    1. local time analogue clock (also, below) … calling on a changed analogue_clock.html … or …
    2. Fractions Game
  • ondblclick (double click) event … ondblclick=” viadb=true; ask(); “ … toggling …

    var viadb=false;

    function ask() {
    var ans='';
    if (!viadb) {
    while (('' + ans).indexOf('/') == -1 && ('' + ans.replace(/^1$/g, '1.0')).indexOf('.') == -1) {
    ans=prompt('What fraction of the "cake" is coloured? (eg. 2/3)', '');
    }
    if (ans == '' + numerator + '/' + denominator.substring(1) || Math.abs(eval('' + numerator + '/' + denominator.substring(1)) - eval('' + ans)) < 0.005) {
    score++;
    goes++;
    alert('Well done! This makes your Fractions Game score to be ' + score + ' of ' + goes);
    } else {
    goes++;
    alert('Sorry ... the fraction you wanted is ' + numerator + '/' + denominator.substring(1) + ' leaving your Fractions Game score as ' + score + ' of ' + goes);
    }
    }
    numerator='' + eval(1 + Math.floor(Math.random() * 7));
    denominator='0';
    while (eval('' + denominator) < eval('' + numerator)) {
    denominator='' + eval(0 + Math.floor(Math.random() * 9));
    }
    if (viadb) {
    if (btoas == '') {
    location.href=document.URL.split('?')[0].split('#')[0] + '?btis=' + encodeURIComponent(btoa('' + numerator + '/' + denominator));
    } else {
    location.href=document.URL.split('?')[0].split('#')[0]; // + '?btis=' + encodeURIComponent(btoa('' + numerator + '/' + denominator));
    }
    }
    viadb=false;
    }

    … control … using …
  • CSS conic-gradient background …

    <style>
    #atend {
    background: conic-gradient(rgba(255,0,0,0.5) 0deg, rgba(0,0,255,0.5) 30deg, rgba(0,255,0,0.5) 60deg, rgba(255,192,203,0.5) 90deg, rgba(0,0,139,0.5) 120deg, rgba(144,238,144,0.5) 150deg, rgba(255,165,0,0.5) 180deg, rgba(173,216,230,0.5) 210deg, rgba(2,48,32,0.5) 240deg, rgba(255,0,255,0.5) 270deg, rgba(0,100,100,0.5) 300deg, rgba(128,128,0,0.5) 330deg);
    }
    </style>

… scenario, building on what we learnt when we presented CSS Gradient Creations Conic Tutorial a little while back.


Previous relevant CSS Gradient Creations Conic Tutorial is shown below.

CSS Gradient Creations Conic Tutorial

CSS Gradient Creations Conic Tutorial

Yesterday’s CSS Conic Gradient Primer Tutorial set us to thinking about integrating these Conic Gradients into our “Gradient Central” web application where you can create your own gradients which we last talked about with CSS Gradient Creations Mobile Width Tutorial.

These gradients …

  • linear-gradient
  • radial-gradient
  • conic-gradient

… are helping our webpage designs allow for colour gradation and subtlety we appreciate around here. They can often effectively fill in for that “graphic flair” not all of us possess, in our webpage designs.

What came up that was a bit new to us with this Conic Gradient integration? And yes, most tutorials bring up something new! Input element textboxes can be made inoperable by the setting of the Javascript DOM readOnly attribute, as with (Javascript code like) …


document.getElementById('mytextbox').readOnly=true; // and to make readable again use false instead

… but we found we couldn’t do that with select (ie. dropdown) elements. This useful link, thanks, put us right in our thinking to do this when conic-gradient selected …


document.getElementById('sdirection').disabled=true; // and to make enabled again use false instead

… because a conic-gradient direction value is much less nuanced than a linear-gradient direction value.

Feel free to try this changed gradient_creations.htm “Gradient Creations” live run link, or try below …

Stop Press

Today’s CSS Gradient Creations Conic Tutorial‘s integration of yesterday’s CSS Conic Gradient Primer Tutorial‘s work was missing some of the features of that latter web application, involving its textarea flexibility to add user additional dynamic CSS into the mix. No problems any longer, as we make use of the work we’ll talk about tomorrow, integrating into CSS Gradient Creations Conic Tutorial‘s web application one new line of code …


<script type='text/javascript' src='/divceditin.js?todowith=tdlook&after=tdcss&blurb=%2F*%20More%20gradient%20CSS%20styling%20can%20go%20here%20via%20a%20click%20...%20eg.%20border-radius%3A%2050%25%3B%20%20*%2F'></script>

… to offer that possibility. That will outline our use of element type div contenteditable=true with an input type=text value=”” placeholder=[Some Blurb] readonly prototype tool enabling users to add in their own dynamic CSS in the tweaked gradient_creations.htm “Gradient Creations” live run link, as also shown above this …


Previous relevant CSS Gradient Creations Mobile Width Tutorial is shown below.

CSS Gradient Creations Mobile Width Tutorial

CSS Gradient Creations Mobile Width Tutorial

When it comes to “width” (CSS styling) considerations with webpage design on mobile platforms where you are not prepared to “de-complex-ify” (if you know what I mean) the webpage contents you can run into the dual issues …

  • you want to show HTML elements legibly … and …
  • you also want to show the big picture

You see, with yesterday’s CSS Gradient Creations Width Makeover Tutorial we did hint when we said …

… we saw that it overshot the right hand border on the MacBook Air webpage screen.

… that the work yesterday was suited more towards your laptop usage rather than mobile phone (and to a less extent mobile tablet) usage.

There is a CSS styling “tool” to hand just for this scenario, though, the meta name=viewport (within <head> … </head> header element, usually) element, ours being, initially, for today’s work …


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

… the “red rag to a bull” signs that Javascript might come into it (to allow initially become eventually) being …

  1. the id=”myviewport” unusual attribute for a header element
  2. the big range difference between minimum-scale and maximum-scale but initial-scale being so conventionally valued

… in other words, today …

  • we start mobile platform web application “first few seconds” of display in “you want to show HTML elements legibly” mode … and that “first few seconds” of display tells us … anyone, anyone? … yes, Arielwe use setTimeout to delay

    <body onload="setTimeout(fixmobilewidth,5000); sdih=document.getElementById('sdirection').innerHTML; osdih=document.getElementById('rdirection').innerHTML; checkol();">

    … five seconds before …
  • we use Javascript DOM to adjust the meta name=viewport element as per …

    function fixmobilewidth() {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    var rectt=document.getElementsByTagName('table')[0].getBoundingClientRect();
    document.getElementById("myviewport").setAttribute("content", "width=device-width, initial-scale=" + eval(-0.35 + eval('' + (window.orientation == 0 ? window.innerHeight: window.innerWidth)) / eval('' + rectt.width)) + ", minimum-scale=0.1, maximum-scale=8, user-scalable=yes");
    }
    }

    … “to show the big picture” (of what’s available to the user to work the web application’s full functionality)

The control of whitespace came into the picture too. We replace in a lot of the table cells the non-breaking spaces (ie. &nbsp;) as per …


<td><input onblur="changeit();" onchange="changeit();" type=color id=c1 value='#ff0000'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs1 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc1 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o1 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c2 value='#0000ff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs2 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc2 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o2 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c3 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs3 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc3 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o3 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c4 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs4 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc4 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o4 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c5 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs5 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc5 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o5 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c6 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs6 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc6 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o6 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c7 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs7 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc7 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o7 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c8 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs8 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc8 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o8 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>

… with line breaks (ie. <br>) as per …


<td><input onblur="changeit();" onchange="changeit();" type=color id=c1 value='#ff0000'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs1 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc1 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o1 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c2 value='#0000ff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs2 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc2 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o2 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c3 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs3 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc3 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o3 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c4 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs4 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc4 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o4 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c5 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs5 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc5 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o5 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c6 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs6 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc6 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o6 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c7 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs7 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc7 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o7 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c8 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs8 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc8 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o8 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>

… to lessen the table cell width innards (at the expense, perhaps, of the table cell innard heights) that might become involved in our changed gradient_creations.htm “Gradient Creations” live run link.

Is the 5 seconds enough on your thinner mobile platform widths? That’s debatable, but the “spreading” gesture awaits those more accepting mobile phone users!


Previous relevant CSS Gradient Creations Width Makeover Tutorial is shown below.

CSS Gradient Creations Width Makeover Tutorial

CSS Gradient Creations Width Makeover Tutorial

Revisits to a web application, after some time, can bring “adverse” categories of reaction to me …

  • UX (user experience) Javascript criticism …
  • styling CSS annoyance

… and today’s work, on our “Gradient Creations” web application, is as a result of that second “styling CSS annoyance”.

Possibly the second is “less serious” in our mind, but, nonetheless, invariably we learn (or remember) quite a bit, researching them.

Maybe you can see from today’s tutorial animated GIF picture we categorized the slides into …

Slide … … with our commentary regarding our changed gradient_creations.htm “Gradient Creations” live run link
The problem … At 100% zoom level with the Google Chrome browser pointing at the previous “Gradient Creations” web application incarnation we saw that it overshot the right hand border on the MacBook Air webpage screen.
The culprit … Looking at the web page in Crome’s web inspector we identify the “Colour Name” textboxes (whose “id” starts with “sc” (as we mention later, to our advantage)) as being too wide and to lessen that width could improve the aesthetics.
The pathway …
  1. This search, thanks, got us to html – How to get CSS to select ID that begins with a string (not in Javascript)? – Stack Overflow, thanks, which taught us that, yes, “regex” is a friend to CSS selectors … as well as …
  2. This search, thanks, got us to css – sizing div based on window width – Stack Overflow which taught us (and reminded us) that the CSS width unit “vw” could be used like a percentage of screen width, our preferred expression of width, since we knew how many cells we wanted to cater for across the webpage, ahead of time, and so we picked “the conservative” “8vw” as this improved [id^=sc] selector improvement.
The intervention … Within the webpage’s <head> … </head> section we add …
<style>
[id^=sc] {
width: 8vw;
}
</style>
The improvement … The test shows improved aesthetics. Yay!

By the way, further reading on this topic (and web application) is available with CSS Gradient Creations Sharing Tutorial below.


Previous relevant CSS Gradient Creations Sharing Tutorial is shown below.

CSS Gradient Creations Sharing Tutorial

CSS Gradient Creations Sharing Tutorial

Turning a web application like yesterday’s CSS Gradient Creations Tutorial “Gradient Creations” one into a web application where you can share your discoveries is an exercise in both …

  • sharing and collaboration … as well as …
  • accountability

… opening up something that used to be just for private use only, to being one that is open to the rest of the online wooooorrrrllllddd.

As well as this new email and SMS sharing capability we add another contenteditable=true incursion into the mix as another selling product for our web application. Just quietly, perhaps you can use it as a “digital card” creator, as we offer to augment …

  • the table cell with a gradient background … with the idea that the user …
  • can write their wording (of say, a card) in the foreground of that same table cell

… and then allow the user to append a space to their Javascript prompt window answering of the emailee address to indicate to the web application that the email should just be that table cell content. On the way a collaboration phase is possible by tweaking the HTML …


xform.append('body',(document.body.outerHTML.split('</form>')[0] + '</form></body>').replace(/NONE\;/g, 'inline-block;').replace('<div ','<input type=text style=width:50%; ').replace('>background:', ' value="').replace('</div>', '"></input>').replace('"></textarea>', '">' + document.getElementById('tdlook').innerHTML.replace(/\<br\>/g,String.fromCharCode(10)) + '</textarea>'));

… to work with a form method=GET way for the emailee to adjust the gradient CSS to send off a return email (or one to a third party) in response to that first email. No collaboration here, but we also allow for SMS communications too.

Also, along the way, we allow for a colour to be defined by its name, if it makes the web application’s colour array list.

You can try our our changed gradient_creations.htm live run link, to see what we mean.


Previous relevant CSS Gradient Creations Tutorial is shown below.

CSS Gradient Creations Tutorial

CSS Gradient Creations Tutorial

The great CSS background “gradient” functionalities can come in four forms, those being …

  • linear gradient (and repeating linear gradient)
  • radial gradient (and repeating radial gradient)

… as a means to add background interest, even to the point where the background can have some (different) transparency (level) compared to the foreground, as per example CSS like …


<style>
html::before {
background: linear-gradient(rgba(255,255,255,0.8),rgba(255,255,255,0.8)),URL('//www.rjmprogramming.com.au/MyBusinessUnidad/Welcome_files/logo.jpg') repeat;
}
</style>

With tutorials like CSS Repeating Radial Gradients Primer Tutorial we allowed you to create some gradients, but we wanted a more detailed approach that was generic in its approach and left you with some CSS of use, which is often not the go with many other (albeit useful and inspiring) websites on the net.

There are a whole range of what you might call “directional” nuances you can apply to your gradients. There is opacity to allow for. There are “hard colour stops” you can apply. For linear gradients you can apply a variable angle. For radial gradients there are positional nuances that can be applied.

And then there are the colours. We are not sure of the limits, but we allow for up to eight colours. Enough to simulate the seven colours of the rainbow we go for with today’s tutorial picture arrangement whereby it tweaked with us that the HTML input type=color elements are all well and good but we needed to allow our CSS be editable by nesting into an HTML div contenteditable=true elements that can be tweaked for exact rgb or rgba colour definitions (thanks, Wikipedia), as we could look up for the purposes of displaying a rainbow coloured gradient background (we hope you like)!

Or see a repeating radial gradient example below …

So feel free to try our gradient_creations.html live run link, to see what we mean.


Previous relevant “CSS Gradient Creations Tutorial is shown below.

CSS Radial Gradients Primer Tutorial

CSS Repeating Radial Gradients Primer Tutorial

Way back when with HTML/Javascript Canvas Rainbow Primer Tutorial we talked about CSS linear gradients and radial gradients in the one blog posting, but ever since then, it has so much more that linear gradients have been useful to us here at this blog.

Today, though, we turn a bit of attention to radial gradients, specifically repeated radial gradients.

We’ve got a simple web application to play around with them in terms of …

  • ellipse versus circle
  • coloured versus black and white
  • extent keyword (closest-corner, closest-side, farthest-corner, farthest-side)

Below is one example of the CSS …


.circlefarthest-corner {
background: repeating-radial-gradient(circle farthest-corner,
red, black 5%, blue 5%, green 10%);
}

Feel free to play away at this live run that has this radial_gradients.html downloadable underlying HTML and CSS (and event logic Javascript that changes the HTML div element className property, to suit).


Previous relevant HTML/Javascript Canvas Rainbow Primer Tutorial is shown below.

HTML/Javascript Canvas Rainbow Primer Tutorial

HTML/Javascript Canvas Rainbow Primer Tutorial

The Canvas HTML element tag can be used as the container to draw graphics on the fly usually via the use of Javascript functions for rendering and event management.

In today’s tutorial we touch on a couple of the two dimensional Javascript functions to draw a rectangle or arc, but in the two dimensional context, canvas HTML elements can be used to draw text, lines, boxes and circles as well. We also touch on two functions to create a linear or radial gradient to the fillStyle and/or strokeStyle of your HTML element placed onto the canvas.

You may want to read more at HTML Canvas Reference as a generic reference, or here, at the tutorial javascript – How do I add a simple onClick event handler to a canvas element? – Stack Overflow.

As you can imagine, this HTML canvas element, new to HTML5, can be very useful for some practical client-side web functionality.

Link to some downloadable HTML programming code … rename to canvasrainbow.html

Here is a new link to some downloadable HTML programming source code explaining changes made (from HTML/Javascript Canvas Primer Tutorial) here.

You’ll notice heavy use of the Javascript Math.random() function.

We hope you enjoy this tutorial as a rainbow coloured live run.

Yes … you’ve reached the end … have a top supportive rainbow coloured day!

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


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


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


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


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


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


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


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


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


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


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


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


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

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

SVG and Gradient Fraction Game Tutorial

SVG and Gradient Fraction Game Tutorial

SVG and Gradient Fraction Game Tutorial

To add onto yesterday’s Gradient Fraction Game Mobile Tutorial

  • exclusively gradient
    • conic
    • linear
    • radial

    … “cake” displays in our Fractions Game … and add in …

  • SVG circle and rectangle alternative displays

… it is not hard coding work, only really involving the rearrangement of the “stop colour” element …


function stopit(incsv) {
//alert(incsv);
// <stop offset='0%' stop-color='#f00'/><stop offset='100%' stop-color='#0ff'/>
var incsvs=incsv.split('%, ');
var outstops="<stop offset='0%' stop-color='" + incsvs[0].split(' ')[0] + "'/>";
for (var iis=1; iis<incsvs.length; iis++) {
outstops+="<stop offset='" + (incsvs[iis].split(' ')[1].trim() + "%").replace('%%','%') + "' stop-color='" + incsvs[iis].split(' ')[0] + "'/>";
}
//alert(outstops);
//document.getElementById('atend').title=outstops.replace(/255/g, '127');
return outstops.replace(/255/g, '127');
}

… code syntax.

But before that we went down a garden path thinking we could have all 5 “cake” display options be …

  • as the CSS property background-image to a table cell nesting HTML div element … sort of like this webpage‘s (thanks all the same) …

    #atright {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='%23F00'/><stop offset='90%' stop-color='%23fcc'/> </linearGradient><rect fill='url(%23gradient)' x='0' y='0' width='100%' height='100%'/></svg>");
    }
    // ... or ...
    #atend {
    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PGxpbmVhckdyYWRpZW50IGlkPSdncmFkaWVudCc+PHN0b3Agb2Zmc2V0PScxMCUnIHN0b3AtY29sb3I9JyNGMDAnLz48c3RvcCBvZmZzZXQ9JzkwJScgc3RvcC1jb2xvcj0nI2ZjYycvPiA8L2xpbmVhckdyYWRpZW50PjxyZWN0IGZpbGw9J3VybCgjZ3JhZGllbnQpJyB4PScwJyB5PScwJyB3aWR0aD0nMTAwJScgaGVpZ2h0PScxMDAlJy8+PC9zdmc+");
    }

    … and though we had lots of success with work of this ilk with our “Just Javascript” series of blog posts, we found the technique flaky today, so opted to, instead …

    1. fill HTML div element’s innerHTML (ie. content) with “raw” SVG
    2. set that HTML div element’s CSS style property background-image to “none”

… as the approach we landed upon, allowing for SVG


if (issvg > 0) {
var mySVG = "<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='#F00'/><stop offset='90%' stop-color='#fcc'/> </linearGradient><rect fill='url(#gradient)' x='0' y='0' width='100%' height='100%'/></svg>";
if (issvg == 1) {
mySVG="<svg xmlns='http://www.w3.org/2000/svg' width='" + pwidth + "' height='" + pheight + "' viewport='0 0 100 100'><linearGradient id='test'>" + stopit(newlist) + " </linearGradient><circle fill='url(#test)' cx='" + eval(pwidth / 2) + "' cy='" + eval(pheight / 2) + "' r='" + eval(pwidth / 2) + "' stroke='none' stroke-width='12'/></svg>"; //.replace(/\~/g, String.fromCharCode(10));
} else if (issvg == 2) {
mySVG="<svg xmlns='http://www.w3.org/2000/svg' width='" + pwidth + "' height='" + pheight + "' viewport='0 0 100 100'><linearGradient id='test'>" + stopit(newlist) + " </linearGradient><rect fill='url(#test)' width='" + eval(pwidth / 1) + "' height='" + eval(pheight / 1) + "' stroke='none' stroke-width='12'/></svg>"; //.replace(/\~/g, String.fromCharCode(10));
}
document.getElementById('atend').innerHTML=mySVG;
if (issvg == 1) {
mySVG="<svg xmlns='http://www.w3.org/2000/svg' width='" + pwidth + "' height='" + pheight + "' viewport='0 0 100 100'><linearGradient id='testr'>" + stopit(newlistr) + " </linearGradient><circle fill='url(#testr)' cx='" + eval(pwidth / 2) + "' cy='" + eval(pheight / 2) + "' r='" + eval(pwidth / 2) + "' stroke='none' stroke-width='12'/></svg>"; //.replace(/\~/g, String.fromCharCode(10));
} else if (issvg == 2) {
mySVG="<svg xmlns='http://www.w3.org/2000/svg' width='" + pwidth + "' height='" + pheight + "' viewport='0 0 100 100'><linearGradient id='testr'>" + stopit(newlistr) + " </linearGradient><rect fill='url(#testr)' width='" + eval(pwidth / 1) + "' height='" + eval(pheight / 1) + "' stroke='none' stroke-width='12'/></svg>"; //.replace(/\~/g, String.fromCharCode(10));
}
document.getElementById('atright').innerHTML=mySVG;
document.getElementById('dstyle').innerHTML+='<style>' + ' #atend { background-image: none !important; } </style>';
document.getElementById('dstyle').innerHTML+='<style>' + ' #atright { background-image: none !important; } </style>';
} else {
document.getElementById('atend').innerHTML='';
document.getElementById('atright').innerHTML='';

document.getElementById('dstyle').innerHTML+='<style>' + ' #atend { background-image: ' + gprefix.toLowerCase() + '-gradient(' + newlist + ') !important; } </style>';
document.getElementById('dstyle').innerHTML+='<style>' + ' #atright { background-image: ' + gprefix.toLowerCase() + '-gradient(' + newlistr + ') !important; } </style>';
}

… in the changed circular_sectors.html Fractions Game.


Previous relevant Gradient Fraction Game Mobile Tutorial is shown below.

Gradient Fraction Game Mobile Tutorial

Gradient Fraction Game Mobile Tutorial

Many responsive web design purists will push the web developers out there to never …

  • express HTML element dimensions in “static” “px” types of units … but rather …
  • express HTML element dimensions in “%” or “vx” or “vh” proportional style of units … and, of course, their advice has a lot of merit, but, sometimes, like today, we want to be a bit pragmatic here and say …
  • a third way, particularly suiting an initial development phase that suited a display on a laptop (and deploying “static” “px” types of units that look okay on a laptop), for instance, but then wanting to look more apt on your smaller mobile devices, you could …
    1. ensure you have within the webpage head element a “meta” viewport element such as (our) …

      <meta id='myviewport' name='viewport' content='width=device-width, initial-scale=1, minimum-scale=0.1, maximum-scale=8, user-scalable=yes' >
    2. stay with “static” “px” types of units but if analysis (which can be before document.body “onload” event (and, you couldn’t possibly have heard it from me, cough cough, but dovetail findings within Javascript document.write statements within the document.body static HTML)) of either/both screen.width and/or screen.height indicates lack of suitablility …

      var fromprefix='border-radius: 612px;', toprefix="margin-top: 0px;";
      var pwidth=602, pheight=602, pbr=612, ptop=17.3594, pleft=386.5, thirtytwo=32, ocbit='';
      var worry=false;

      if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && btoas.trim() == '' && denominator == '0' && numerator == '0') {
      ocbit=' onclick=" viadb=true; ask(); " ';
      }
      if (eval(eval('' + screen.width) - eval(eval('' + pbr) * 2)) < 0 && (btoas.trim() != '' || denominator != '0' || numerator != '0')) {
      thirtytwo=Math.floor(eval(eval('' + thirtytwo) * Math.floor(eval(eval('' + screen.width) / 2.1)) / eval('' + pbr)));
      ptop=eval(eval('' + ptop) * Math.floor(eval(eval('' + screen.width) / 2.1)) / eval('' + pbr));
      pleft=eval(eval('' + pleft) * Math.floor(eval(eval('' + screen.width) / 2.1)) / eval('' + pbr));
      pbr=Math.floor(eval(eval('' + screen.width) / 2.1));
      fromprefix='border-radius: ' + pbr + 'px;'
      pwidth=eval(-10 + pbr);
      pheight=eval(-10 + pbr);
      worry=true;
      //alert('width,height,br,top,left=' + pwidth + ',' + pheight + ',' + pbr + ',' + ptop + ',' + pleft);
      }

      … Javascript “head” code affecting the “body” …

      <body>
      <script type='text/javascript'>
      document.write('<table id=mytable><tbody id=mytbody><tr id=mytr><td id=mytd>');
      if (denominator == '0' && btoas == '') {
      if (worry) {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="position: absolute; left: ' + pleft + 'px; top: ' + ptop + 'px; width: ' + pwidth + 'px; height: ' + pheight + 'px; border-radius: ' + pbr + 'px; ">');
      } else {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="position: absolute; left: 386.5px; top: 17.3594px; width: 602px; height: 602px; border-radius: 612px; ">');
      }
      document.write('<iframe scrolling="no" frameborder="0" style="z-index:23;margin-left:127px;margin-top:130px;height:400px;" src="analogue_clock.htm?backcol=transparent&x=7654#xbody"></iframe>');
      } else {
      if (worry) {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="width: ' + pwidth + 'px; height: ' + pheight + 'px; border-radius: ' + pbr + 'px; ">');
      } else {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="width: 602px; height: 602px; border-radius: 612px; ">');
      }
      }
      if (worry) {
      document.write('</div></td><td id=mymtd style=display:none;vertical-align:middle;>  <select id=ssign style=font-size:' + thirtytwo + 'px;background-color:yellow; readonly disable><option value="+">➕</option><option value="-">➖</option><option value="x">✖</option><option value="/">➗</option></select></td><td id=myrtd style=display:none;>  <div ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atright" style="width: ' + pwidth + 'px; height: ' + pheight + 'px; border-radius: ' + pbr + 'px; "></div></td></tr></tbody></table>');
      } else {
      document.write('</div></td><td id=mymtd style=display:none;vertical-align:middle;>  <select id=ssign style=font-size:' + thirtytwo + 'px;background-color:yellow; readonly disable><option value="+">➕</option><option value="-">➖</option><option value="x">✖</option><option value="/">➗</option></select></td><td id=myrtd style=display:none;>  <div ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atright" style="width: 602px; height: 602px; border-radius: 612px; "></div></td></tr></tbody></table>');
      }
      </script>
      <div id=dstyle></div>
      </body>

      … element, to lean on “hardcodings become parameter” types of thinking to proceed with a more apt dimensional display (that is all sorted out ahead of document.body “onload” event, still not associated with any Javascript code, above)

Yes, you can develop web applications on mobile. There are ways. But we find it much more natural and easy to develop web applications on a laptop, here it being a MacBook Air at the moment. One reason we’d give, is that the quality of laptop web browser web inspectors is sky high, and all the modern browsers seem to have a (laptop) version now.

And as such, improving mobile usage of yesterday’s Gradient Fraction Game Equations Tutorial we have in a changed circular_sectors.html Fractions Game.


Previous relevant Gradient Fraction Game Equations Tutorial is shown below.

Gradient Fraction Game Equations Tutorial

Gradient Fraction Game Equations Tutorial

There are three styles of CSS gradient …

  • conic
  • linear
  • radial

… and “different folks may learn via diff’rent CSS strokes”, so we incorporate a way for the user, when using the Fractions Game component of our latest web application, so that they can toggle the “cake” display among these three styles of gradient display.

Also, extending yesterday’s Conic Gradient Fraction Game Equations Tutorial, we …

  • allow, during the Fractions Game mode usage, have a window.prompt Cancel click send the user back to the Analogue Clock, so that unnecessary and errant window.prompt popup windows are avoided … and …
  • we incorporate “lowest common denominator” …

    function lcdextra(varn, vard) {
    var retv='', iv=0;
    for (iv=Math.min(Math.abs(varn),Math.abs(vard)); iv>=2; iv--) {
    if (eval(Math.abs(varn) % iv) == 0 && eval(Math.abs(vard) % iv) == 0) {
    varn /= iv;
    vard /= iv;
    retv+=' = ' + varn + ' / ' + vard + String.fromCharCode(10);
    }
    }
    return retv;
    }

    … calculations into our “show workings” section as Ms Trimpole would have wanted
  • involve emoji operators in that same “show workings” section to better mimic how we were taught at school in Mathematics class

… in the changed circular_sectors.html Fractions Game.


Previous relevant Conic Gradient Fraction Game Equations Tutorial is shown below.

Conic Gradient Fraction Game Equations Tutorial

Conic Gradient Fraction Game Equations Tutorial

We’re extending the functionality started with yesterday’s Dual Purpose Conic Gradient Primer Tutorial‘s second “dual purpose” …

  • Fractions Game piece of functionality …
  • Adding to its possibility the optional user job of solving operator …
    •  +
    •  –
    •  x
    •  /

    … types of fraction based equations

Simply put, changes to allow for this involved …

  • forsaking position:absolute “cakes” for your usual default position:relative positioning … within …
  • single row, three cell (cake, sign, cake) display … prior to …
  • hardly changed window.prompt user interaction, to answer … but …
  • more complex analysis for equation based scenarios …

    function showworking(instr, realans) {
    var outstr=instr;
    var xnumerator=numerator, xnumeratortwo=numeratortwo, xdenominatortwo=denominatortwo;
    var varw='';
    if (document.getElementById('ssign').value == '+') {
    if (denominatortwo == denominator.slice(-1)) {
    varw+=' = (' + numerator + ' + ' + numeratortwo + ') / ' + denominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) + eval('' + numeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    } else {
    varw+=' = (' + numerator + ' x ' + denominatortwo + ' + ' + numeratortwo + ' x ' + denominator.slice(-1) + ') / (' + denominator.slice(-1) + ' x ' + denominatortwo + ')' + String.fromCharCode(10);
    xnumerator*=denominatortwo;
    xnumeratortwo*=eval('' + denominator.slice(-1));
    xdenominatortwo*=eval('' + denominator.slice(-1));
    varw+=' = (' + xnumerator + ' + ' + xnumeratortwo + ') / ' + xdenominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + xnumerator) + eval('' + xnumeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    }
    } else if (document.getElementById('ssign').value == '-') {
    if (denominatortwo == denominator.slice(-1)) {
    varw+=' = (' + numerator + ' - ' + numeratortwo + ') / ' + denominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(numerator - numeratortwo) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    } else {
    varw+=' = (' + numerator + ' x ' + denominatortwo + ' - ' + numeratortwo + ' x ' + denominator.slice(-1) + ') / (' + denominator.slice(-1) + ' x ' + denominatortwo + ')' + String.fromCharCode(10);
    xnumerator*=denominatortwo;
    xnumeratortwo*=eval('' + denominator.slice(-1));
    xdenominatortwo*=eval('' + denominator.slice(-1));
    varw+=' = (' + xnumerator + ' - ' + xnumeratortwo + ') / ' + xdenominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + xnumerator) - eval('' + xnumeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    }
    } else if (document.getElementById('ssign').value == '/') {
    varw+=' = (' + numerator + ' / ' + denominator.slice(-1) + ') x (' + denominatortwo + ' / ' + numeratortwo + ')' + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) * eval('' + denominatortwo)) + ' / ' + eval(eval('' + denominator.slice(-1)) * eval('' + numeratortwo)) + String.fromCharCode(10);
    } else if (document.getElementById('ssign').value == 'x' || document.getElementById('ssign').value == '*') {
    varw+=' = (' + numerator + ' / ' + denominator.slice(-1) + ') x (' + numeratortwo + ' / ' + denominatortwo + ')' + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) * eval('' + numeratortwo)) + ' / ' + eval(eval('' + denominator.slice(-1)) * eval('' + denominatortwo)) + String.fromCharCode(10);
    }
    return outstr + String.fromCharCode(10) + varw + ' = ' + realans + ' ' + String.fromCharCode(10);
    }

… in the changed circular_sectors.html Fractions Game.


Previous relevant Dual Purpose Conic Gradient Primer Tutorial is shown below.

Dual Purpose Conic Gradient Primer Tutorial

Dual Purpose Conic Gradient Primer Tutorial

Yes, today, we have a “proof of concept” circular_sectors.html

  • dual purpose … as a …
    1. local time analogue clock (also, below) … calling on a changed analogue_clock.html … or …
    2. Fractions Game
  • ondblclick (double click) event … ondblclick=” viadb=true; ask(); “ … toggling …

    var viadb=false;

    function ask() {
    var ans='';
    if (!viadb) {
    while (('' + ans).indexOf('/') == -1 && ('' + ans.replace(/^1$/g, '1.0')).indexOf('.') == -1) {
    ans=prompt('What fraction of the "cake" is coloured? (eg. 2/3)', '');
    }
    if (ans == '' + numerator + '/' + denominator.substring(1) || Math.abs(eval('' + numerator + '/' + denominator.substring(1)) - eval('' + ans)) < 0.005) {
    score++;
    goes++;
    alert('Well done! This makes your Fractions Game score to be ' + score + ' of ' + goes);
    } else {
    goes++;
    alert('Sorry ... the fraction you wanted is ' + numerator + '/' + denominator.substring(1) + ' leaving your Fractions Game score as ' + score + ' of ' + goes);
    }
    }
    numerator='' + eval(1 + Math.floor(Math.random() * 7));
    denominator='0';
    while (eval('' + denominator) < eval('' + numerator)) {
    denominator='' + eval(0 + Math.floor(Math.random() * 9));
    }
    if (viadb) {
    if (btoas == '') {
    location.href=document.URL.split('?')[0].split('#')[0] + '?btis=' + encodeURIComponent(btoa('' + numerator + '/' + denominator));
    } else {
    location.href=document.URL.split('?')[0].split('#')[0]; // + '?btis=' + encodeURIComponent(btoa('' + numerator + '/' + denominator));
    }
    }
    viadb=false;
    }

    … control … using …
  • CSS conic-gradient background …

    <style>
    #atend {
    background: conic-gradient(rgba(255,0,0,0.5) 0deg, rgba(0,0,255,0.5) 30deg, rgba(0,255,0,0.5) 60deg, rgba(255,192,203,0.5) 90deg, rgba(0,0,139,0.5) 120deg, rgba(144,238,144,0.5) 150deg, rgba(255,165,0,0.5) 180deg, rgba(173,216,230,0.5) 210deg, rgba(2,48,32,0.5) 240deg, rgba(255,0,255,0.5) 270deg, rgba(0,100,100,0.5) 300deg, rgba(128,128,0,0.5) 330deg);
    }
    </style>

… scenario, building on what we learnt when we presented CSS Gradient Creations Conic Tutorial a little while back.


Previous relevant CSS Gradient Creations Conic Tutorial is shown below.

CSS Gradient Creations Conic Tutorial

CSS Gradient Creations Conic Tutorial

Yesterday’s CSS Conic Gradient Primer Tutorial set us to thinking about integrating these Conic Gradients into our “Gradient Central” web application where you can create your own gradients which we last talked about with CSS Gradient Creations Mobile Width Tutorial.

These gradients …

  • linear-gradient
  • radial-gradient
  • conic-gradient

… are helping our webpage designs allow for colour gradation and subtlety we appreciate around here. They can often effectively fill in for that “graphic flair” not all of us possess, in our webpage designs.

What came up that was a bit new to us with this Conic Gradient integration? And yes, most tutorials bring up something new! Input element textboxes can be made inoperable by the setting of the Javascript DOM readOnly attribute, as with (Javascript code like) …


document.getElementById('mytextbox').readOnly=true; // and to make readable again use false instead

… but we found we couldn’t do that with select (ie. dropdown) elements. This useful link, thanks, put us right in our thinking to do this when conic-gradient selected …


document.getElementById('sdirection').disabled=true; // and to make enabled again use false instead

… because a conic-gradient direction value is much less nuanced than a linear-gradient direction value.

Feel free to try this changed gradient_creations.htm “Gradient Creations” live run link, or try below …

Stop Press

Today’s CSS Gradient Creations Conic Tutorial‘s integration of yesterday’s CSS Conic Gradient Primer Tutorial‘s work was missing some of the features of that latter web application, involving its textarea flexibility to add user additional dynamic CSS into the mix. No problems any longer, as we make use of the work we’ll talk about tomorrow, integrating into CSS Gradient Creations Conic Tutorial‘s web application one new line of code …


<script type='text/javascript' src='/divceditin.js?todowith=tdlook&after=tdcss&blurb=%2F*%20More%20gradient%20CSS%20styling%20can%20go%20here%20via%20a%20click%20...%20eg.%20border-radius%3A%2050%25%3B%20%20*%2F'></script>

… to offer that possibility. That will outline our use of element type div contenteditable=true with an input type=text value=”” placeholder=[Some Blurb] readonly prototype tool enabling users to add in their own dynamic CSS in the tweaked gradient_creations.htm “Gradient Creations” live run link, as also shown above this …


Previous relevant CSS Gradient Creations Mobile Width Tutorial is shown below.

CSS Gradient Creations Mobile Width Tutorial

CSS Gradient Creations Mobile Width Tutorial

When it comes to “width” (CSS styling) considerations with webpage design on mobile platforms where you are not prepared to “de-complex-ify” (if you know what I mean) the webpage contents you can run into the dual issues …

  • you want to show HTML elements legibly … and …
  • you also want to show the big picture

You see, with yesterday’s CSS Gradient Creations Width Makeover Tutorial we did hint when we said …

… we saw that it overshot the right hand border on the MacBook Air webpage screen.

… that the work yesterday was suited more towards your laptop usage rather than mobile phone (and to a less extent mobile tablet) usage.

There is a CSS styling “tool” to hand just for this scenario, though, the meta name=viewport (within <head> … </head> header element, usually) element, ours being, initially, for today’s work …


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

… the “red rag to a bull” signs that Javascript might come into it (to allow initially become eventually) being …

  1. the id=”myviewport” unusual attribute for a header element
  2. the big range difference between minimum-scale and maximum-scale but initial-scale being so conventionally valued

… in other words, today …

  • we start mobile platform web application “first few seconds” of display in “you want to show HTML elements legibly” mode … and that “first few seconds” of display tells us … anyone, anyone? … yes, Arielwe use setTimeout to delay

    <body onload="setTimeout(fixmobilewidth,5000); sdih=document.getElementById('sdirection').innerHTML; osdih=document.getElementById('rdirection').innerHTML; checkol();">

    … five seconds before …
  • we use Javascript DOM to adjust the meta name=viewport element as per …

    function fixmobilewidth() {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    var rectt=document.getElementsByTagName('table')[0].getBoundingClientRect();
    document.getElementById("myviewport").setAttribute("content", "width=device-width, initial-scale=" + eval(-0.35 + eval('' + (window.orientation == 0 ? window.innerHeight: window.innerWidth)) / eval('' + rectt.width)) + ", minimum-scale=0.1, maximum-scale=8, user-scalable=yes");
    }
    }

    … “to show the big picture” (of what’s available to the user to work the web application’s full functionality)

The control of whitespace came into the picture too. We replace in a lot of the table cells the non-breaking spaces (ie. &nbsp;) as per …


<td><input onblur="changeit();" onchange="changeit();" type=color id=c1 value='#ff0000'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs1 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc1 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o1 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c2 value='#0000ff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs2 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc2 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o2 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c3 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs3 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc3 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o3 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c4 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs4 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc4 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o4 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c5 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs5 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc5 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o5 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c6 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs6 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc6 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o6 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c7 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs7 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc7 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o7 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c8 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs8 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc8 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o8 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>

… with line breaks (ie. <br>) as per …


<td><input onblur="changeit();" onchange="changeit();" type=color id=c1 value='#ff0000'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs1 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc1 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o1 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c2 value='#0000ff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs2 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc2 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o2 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c3 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs3 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc3 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o3 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c4 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs4 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc4 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o4 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c5 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs5 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc5 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o5 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c6 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs6 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc6 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o6 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c7 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs7 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc7 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o7 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c8 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs8 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc8 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o8 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>

… to lessen the table cell width innards (at the expense, perhaps, of the table cell innard heights) that might become involved in our changed gradient_creations.htm “Gradient Creations” live run link.

Is the 5 seconds enough on your thinner mobile platform widths? That’s debatable, but the “spreading” gesture awaits those more accepting mobile phone users!


Previous relevant CSS Gradient Creations Width Makeover Tutorial is shown below.

CSS Gradient Creations Width Makeover Tutorial

CSS Gradient Creations Width Makeover Tutorial

Revisits to a web application, after some time, can bring “adverse” categories of reaction to me …

  • UX (user experience) Javascript criticism …
  • styling CSS annoyance

… and today’s work, on our “Gradient Creations” web application, is as a result of that second “styling CSS annoyance”.

Possibly the second is “less serious” in our mind, but, nonetheless, invariably we learn (or remember) quite a bit, researching them.

Maybe you can see from today’s tutorial animated GIF picture we categorized the slides into …

Slide … … with our commentary regarding our changed gradient_creations.htm “Gradient Creations” live run link
The problem … At 100% zoom level with the Google Chrome browser pointing at the previous “Gradient Creations” web application incarnation we saw that it overshot the right hand border on the MacBook Air webpage screen.
The culprit … Looking at the web page in Crome’s web inspector we identify the “Colour Name” textboxes (whose “id” starts with “sc” (as we mention later, to our advantage)) as being too wide and to lessen that width could improve the aesthetics.
The pathway …
  1. This search, thanks, got us to html – How to get CSS to select ID that begins with a string (not in Javascript)? – Stack Overflow, thanks, which taught us that, yes, “regex” is a friend to CSS selectors … as well as …
  2. This search, thanks, got us to css – sizing div based on window width – Stack Overflow which taught us (and reminded us) that the CSS width unit “vw” could be used like a percentage of screen width, our preferred expression of width, since we knew how many cells we wanted to cater for across the webpage, ahead of time, and so we picked “the conservative” “8vw” as this improved [id^=sc] selector improvement.
The intervention … Within the webpage’s <head> … </head> section we add …
<style>
[id^=sc] {
width: 8vw;
}
</style>
The improvement … The test shows improved aesthetics. Yay!

By the way, further reading on this topic (and web application) is available with CSS Gradient Creations Sharing Tutorial below.


Previous relevant CSS Gradient Creations Sharing Tutorial is shown below.

CSS Gradient Creations Sharing Tutorial

CSS Gradient Creations Sharing Tutorial

Turning a web application like yesterday’s CSS Gradient Creations Tutorial “Gradient Creations” one into a web application where you can share your discoveries is an exercise in both …

  • sharing and collaboration … as well as …
  • accountability

… opening up something that used to be just for private use only, to being one that is open to the rest of the online wooooorrrrllllddd.

As well as this new email and SMS sharing capability we add another contenteditable=true incursion into the mix as another selling product for our web application. Just quietly, perhaps you can use it as a “digital card” creator, as we offer to augment …

  • the table cell with a gradient background … with the idea that the user …
  • can write their wording (of say, a card) in the foreground of that same table cell

… and then allow the user to append a space to their Javascript prompt window answering of the emailee address to indicate to the web application that the email should just be that table cell content. On the way a collaboration phase is possible by tweaking the HTML …


xform.append('body',(document.body.outerHTML.split('</form>')[0] + '</form></body>').replace(/NONE\;/g, 'inline-block;').replace('<div ','<input type=text style=width:50%; ').replace('>background:', ' value="').replace('</div>', '"></input>').replace('"></textarea>', '">' + document.getElementById('tdlook').innerHTML.replace(/\<br\>/g,String.fromCharCode(10)) + '</textarea>'));

… to work with a form method=GET way for the emailee to adjust the gradient CSS to send off a return email (or one to a third party) in response to that first email. No collaboration here, but we also allow for SMS communications too.

Also, along the way, we allow for a colour to be defined by its name, if it makes the web application’s colour array list.

You can try our our changed gradient_creations.htm live run link, to see what we mean.


Previous relevant CSS Gradient Creations Tutorial is shown below.

CSS Gradient Creations Tutorial

CSS Gradient Creations Tutorial

The great CSS background “gradient” functionalities can come in four forms, those being …

  • linear gradient (and repeating linear gradient)
  • radial gradient (and repeating radial gradient)

… as a means to add background interest, even to the point where the background can have some (different) transparency (level) compared to the foreground, as per example CSS like …


<style>
html::before {
background: linear-gradient(rgba(255,255,255,0.8),rgba(255,255,255,0.8)),URL('//www.rjmprogramming.com.au/MyBusinessUnidad/Welcome_files/logo.jpg') repeat;
}
</style>

With tutorials like CSS Repeating Radial Gradients Primer Tutorial we allowed you to create some gradients, but we wanted a more detailed approach that was generic in its approach and left you with some CSS of use, which is often not the go with many other (albeit useful and inspiring) websites on the net.

There are a whole range of what you might call “directional” nuances you can apply to your gradients. There is opacity to allow for. There are “hard colour stops” you can apply. For linear gradients you can apply a variable angle. For radial gradients there are positional nuances that can be applied.

And then there are the colours. We are not sure of the limits, but we allow for up to eight colours. Enough to simulate the seven colours of the rainbow we go for with today’s tutorial picture arrangement whereby it tweaked with us that the HTML input type=color elements are all well and good but we needed to allow our CSS be editable by nesting into an HTML div contenteditable=true elements that can be tweaked for exact rgb or rgba colour definitions (thanks, Wikipedia), as we could look up for the purposes of displaying a rainbow coloured gradient background (we hope you like)!

Or see a repeating radial gradient example below …

So feel free to try our gradient_creations.html live run link, to see what we mean.


Previous relevant “CSS Gradient Creations Tutorial is shown below.

CSS Radial Gradients Primer Tutorial

CSS Repeating Radial Gradients Primer Tutorial

Way back when with HTML/Javascript Canvas Rainbow Primer Tutorial we talked about CSS linear gradients and radial gradients in the one blog posting, but ever since then, it has so much more that linear gradients have been useful to us here at this blog.

Today, though, we turn a bit of attention to radial gradients, specifically repeated radial gradients.

We’ve got a simple web application to play around with them in terms of …

  • ellipse versus circle
  • coloured versus black and white
  • extent keyword (closest-corner, closest-side, farthest-corner, farthest-side)

Below is one example of the CSS …


.circlefarthest-corner {
background: repeating-radial-gradient(circle farthest-corner,
red, black 5%, blue 5%, green 10%);
}

Feel free to play away at this live run that has this radial_gradients.html downloadable underlying HTML and CSS (and event logic Javascript that changes the HTML div element className property, to suit).


Previous relevant HTML/Javascript Canvas Rainbow Primer Tutorial is shown below.

HTML/Javascript Canvas Rainbow Primer Tutorial

HTML/Javascript Canvas Rainbow Primer Tutorial

The Canvas HTML element tag can be used as the container to draw graphics on the fly usually via the use of Javascript functions for rendering and event management.

In today’s tutorial we touch on a couple of the two dimensional Javascript functions to draw a rectangle or arc, but in the two dimensional context, canvas HTML elements can be used to draw text, lines, boxes and circles as well. We also touch on two functions to create a linear or radial gradient to the fillStyle and/or strokeStyle of your HTML element placed onto the canvas.

You may want to read more at HTML Canvas Reference as a generic reference, or here, at the tutorial javascript – How do I add a simple onClick event handler to a canvas element? – Stack Overflow.

As you can imagine, this HTML canvas element, new to HTML5, can be very useful for some practical client-side web functionality.

Link to some downloadable HTML programming code … rename to canvasrainbow.html

Here is a new link to some downloadable HTML programming source code explaining changes made (from HTML/Javascript Canvas Primer Tutorial) here.

You’ll notice heavy use of the Javascript Math.random() function.

We hope you enjoy this tutorial as a rainbow coloured live run.

Yes … you’ve reached the end … have a top supportive rainbow coloured day!

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


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


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


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


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


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


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


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


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


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


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


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

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

Gradient Fraction Game Mobile Tutorial

Gradient Fraction Game Mobile Tutorial

Gradient Fraction Game Mobile Tutorial

Many responsive web design purists will push the web developers out there to never …

  • express HTML element dimensions in “static” “px” types of units … but rather …
  • express HTML element dimensions in “%” or “vx” or “vh” proportional style of units … and, of course, their advice has a lot of merit, but, sometimes, like today, we want to be a bit pragmatic here and say …
  • a third way, particularly suiting an initial development phase that suited a display on a laptop (and deploying “static” “px” types of units that look okay on a laptop), for instance, but then wanting to look more apt on your smaller mobile devices, you could …
    1. ensure you have within the webpage head element a “meta” viewport element such as (our) …

      <meta id='myviewport' name='viewport' content='width=device-width, initial-scale=1, minimum-scale=0.1, maximum-scale=8, user-scalable=yes' >
    2. stay with “static” “px” types of units but if analysis (which can be before document.body “onload” event (and, you couldn’t possibly have heard it from me, cough cough, but dovetail findings within Javascript document.write statements within the document.body static HTML)) of either/both screen.width and/or screen.height indicates lack of suitablility …

      var fromprefix='border-radius: 612px;', toprefix="margin-top: 0px;";
      var pwidth=602, pheight=602, pbr=612, ptop=17.3594, pleft=386.5, thirtytwo=32, ocbit='';
      var worry=false;

      if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i) && btoas.trim() == '' && denominator == '0' && numerator == '0') {
      ocbit=' onclick=" viadb=true; ask(); " ';
      }
      if (eval(eval('' + screen.width) - eval(eval('' + pbr) * 2)) < 0 && (btoas.trim() != '' || denominator != '0' || numerator != '0')) {
      thirtytwo=Math.floor(eval(eval('' + thirtytwo) * Math.floor(eval(eval('' + screen.width) / 2.1)) / eval('' + pbr)));
      ptop=eval(eval('' + ptop) * Math.floor(eval(eval('' + screen.width) / 2.1)) / eval('' + pbr));
      pleft=eval(eval('' + pleft) * Math.floor(eval(eval('' + screen.width) / 2.1)) / eval('' + pbr));
      pbr=Math.floor(eval(eval('' + screen.width) / 2.1));
      fromprefix='border-radius: ' + pbr + 'px;'
      pwidth=eval(-10 + pbr);
      pheight=eval(-10 + pbr);
      worry=true;
      //alert('width,height,br,top,left=' + pwidth + ',' + pheight + ',' + pbr + ',' + ptop + ',' + pleft);
      }

      … Javascript “head” code affecting the “body” …

      <body>
      <script type='text/javascript'>
      document.write('<table id=mytable><tbody id=mytbody><tr id=mytr><td id=mytd>');
      if (denominator == '0' && btoas == '') {
      if (worry) {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="position: absolute; left: ' + pleft + 'px; top: ' + ptop + 'px; width: ' + pwidth + 'px; height: ' + pheight + 'px; border-radius: ' + pbr + 'px; ">');
      } else {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="position: absolute; left: 386.5px; top: 17.3594px; width: 602px; height: 602px; border-radius: 612px; ">');
      }
      document.write('<iframe scrolling="no" frameborder="0" style="z-index:23;margin-left:127px;margin-top:130px;height:400px;" src="analogue_clock.htm?backcol=transparent&x=7654#xbody"></iframe>');
      } else {
      if (worry) {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="width: ' + pwidth + 'px; height: ' + pheight + 'px; border-radius: ' + pbr + 'px; ">');
      } else {
      document.write('<div' + ocbit + ' ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atend" style="width: 602px; height: 602px; border-radius: 612px; ">');
      }
      }
      if (worry) {
      document.write('</div></td><td id=mymtd style=display:none;vertical-align:middle;>  <select id=ssign style=font-size:' + thirtytwo + 'px;background-color:yellow; readonly disable><option value="+">➕</option><option value="-">➖</option><option value="x">✖</option><option value="/">➗</option></select></td><td id=myrtd style=display:none;>  <div ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atright" style="width: ' + pwidth + 'px; height: ' + pheight + 'px; border-radius: ' + pbr + 'px; "></div></td></tr></tbody></table>');
      } else {
      document.write('</div></td><td id=mymtd style=display:none;vertical-align:middle;>  <select id=ssign style=font-size:' + thirtytwo + 'px;background-color:yellow; readonly disable><option value="+">➕</option><option value="-">➖</option><option value="x">✖</option><option value="/">➗</option></select></td><td id=myrtd style=display:none;>  <div ondblclick=" viadb=true; ask(); " title="Analogue Clock via Conic Gradient or Double Click for Fractions Game toggle - RJM Programming - March, 2023" id="atright" style="width: 602px; height: 602px; border-radius: 612px; "></div></td></tr></tbody></table>');
      }
      </script>
      <div id=dstyle></div>
      </body>

      … element, to lean on “hardcodings become parameter” types of thinking to proceed with a more apt dimensional display (that is all sorted out ahead of document.body “onload” event, still not associated with any Javascript code, above)

Yes, you can develop web applications on mobile. There are ways. But we find it much more natural and easy to develop web applications on a laptop, here it being a MacBook Air at the moment. One reason we’d give, is that the quality of laptop web browser web inspectors is sky high, and all the modern browsers seem to have a (laptop) version now.

And as such, improving mobile usage of yesterday’s Gradient Fraction Game Equations Tutorial we have in a changed circular_sectors.html Fractions Game.


Previous relevant Gradient Fraction Game Equations Tutorial is shown below.

Gradient Fraction Game Equations Tutorial

Gradient Fraction Game Equations Tutorial

There are three styles of CSS gradient …

  • conic
  • linear
  • radial

… and “different folks may learn via diff’rent CSS strokes”, so we incorporate a way for the user, when using the Fractions Game component of our latest web application, so that they can toggle the “cake” display among these three styles of gradient display.

Also, extending yesterday’s Conic Gradient Fraction Game Equations Tutorial, we …

  • allow, during the Fractions Game mode usage, have a window.prompt Cancel click send the user back to the Analogue Clock, so that unnecessary and errant window.prompt popup windows are avoided … and …
  • we incorporate “lowest common denominator” …

    function lcdextra(varn, vard) {
    var retv='', iv=0;
    for (iv=Math.min(Math.abs(varn),Math.abs(vard)); iv>=2; iv--) {
    if (eval(Math.abs(varn) % iv) == 0 && eval(Math.abs(vard) % iv) == 0) {
    varn /= iv;
    vard /= iv;
    retv+=' = ' + varn + ' / ' + vard + String.fromCharCode(10);
    }
    }
    return retv;
    }

    … calculations into our “show workings” section as Ms Trimpole would have wanted
  • involve emoji operators in that same “show workings” section to better mimic how we were taught at school in Mathematics class

… in the changed circular_sectors.html Fractions Game.


Previous relevant Conic Gradient Fraction Game Equations Tutorial is shown below.

Conic Gradient Fraction Game Equations Tutorial

Conic Gradient Fraction Game Equations Tutorial

We’re extending the functionality started with yesterday’s Dual Purpose Conic Gradient Primer Tutorial‘s second “dual purpose” …

  • Fractions Game piece of functionality …
  • Adding to its possibility the optional user job of solving operator …
    •  +
    •  –
    •  x
    •  /

    … types of fraction based equations

Simply put, changes to allow for this involved …

  • forsaking position:absolute “cakes” for your usual default position:relative positioning … within …
  • single row, three cell (cake, sign, cake) display … prior to …
  • hardly changed window.prompt user interaction, to answer … but …
  • more complex analysis for equation based scenarios …

    function showworking(instr, realans) {
    var outstr=instr;
    var xnumerator=numerator, xnumeratortwo=numeratortwo, xdenominatortwo=denominatortwo;
    var varw='';
    if (document.getElementById('ssign').value == '+') {
    if (denominatortwo == denominator.slice(-1)) {
    varw+=' = (' + numerator + ' + ' + numeratortwo + ') / ' + denominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) + eval('' + numeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    } else {
    varw+=' = (' + numerator + ' x ' + denominatortwo + ' + ' + numeratortwo + ' x ' + denominator.slice(-1) + ') / (' + denominator.slice(-1) + ' x ' + denominatortwo + ')' + String.fromCharCode(10);
    xnumerator*=denominatortwo;
    xnumeratortwo*=eval('' + denominator.slice(-1));
    xdenominatortwo*=eval('' + denominator.slice(-1));
    varw+=' = (' + xnumerator + ' + ' + xnumeratortwo + ') / ' + xdenominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + xnumerator) + eval('' + xnumeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    }
    } else if (document.getElementById('ssign').value == '-') {
    if (denominatortwo == denominator.slice(-1)) {
    varw+=' = (' + numerator + ' - ' + numeratortwo + ') / ' + denominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(numerator - numeratortwo) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    } else {
    varw+=' = (' + numerator + ' x ' + denominatortwo + ' - ' + numeratortwo + ' x ' + denominator.slice(-1) + ') / (' + denominator.slice(-1) + ' x ' + denominatortwo + ')' + String.fromCharCode(10);
    xnumerator*=denominatortwo;
    xnumeratortwo*=eval('' + denominator.slice(-1));
    xdenominatortwo*=eval('' + denominator.slice(-1));
    varw+=' = (' + xnumerator + ' - ' + xnumeratortwo + ') / ' + xdenominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + xnumerator) - eval('' + xnumeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    }
    } else if (document.getElementById('ssign').value == '/') {
    varw+=' = (' + numerator + ' / ' + denominator.slice(-1) + ') x (' + denominatortwo + ' / ' + numeratortwo + ')' + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) * eval('' + denominatortwo)) + ' / ' + eval(eval('' + denominator.slice(-1)) * eval('' + numeratortwo)) + String.fromCharCode(10);
    } else if (document.getElementById('ssign').value == 'x' || document.getElementById('ssign').value == '*') {
    varw+=' = (' + numerator + ' / ' + denominator.slice(-1) + ') x (' + numeratortwo + ' / ' + denominatortwo + ')' + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) * eval('' + numeratortwo)) + ' / ' + eval(eval('' + denominator.slice(-1)) * eval('' + denominatortwo)) + String.fromCharCode(10);
    }
    return outstr + String.fromCharCode(10) + varw + ' = ' + realans + ' ' + String.fromCharCode(10);
    }

… in the changed circular_sectors.html Fractions Game.


Previous relevant Dual Purpose Conic Gradient Primer Tutorial is shown below.

Dual Purpose Conic Gradient Primer Tutorial

Dual Purpose Conic Gradient Primer Tutorial

Yes, today, we have a “proof of concept” circular_sectors.html

  • dual purpose … as a …
    1. local time analogue clock (also, below) … calling on a changed analogue_clock.html … or …
    2. Fractions Game
  • ondblclick (double click) event … ondblclick=” viadb=true; ask(); “ … toggling …

    var viadb=false;

    function ask() {
    var ans='';
    if (!viadb) {
    while (('' + ans).indexOf('/') == -1 && ('' + ans.replace(/^1$/g, '1.0')).indexOf('.') == -1) {
    ans=prompt('What fraction of the "cake" is coloured? (eg. 2/3)', '');
    }
    if (ans == '' + numerator + '/' + denominator.substring(1) || Math.abs(eval('' + numerator + '/' + denominator.substring(1)) - eval('' + ans)) < 0.005) {
    score++;
    goes++;
    alert('Well done! This makes your Fractions Game score to be ' + score + ' of ' + goes);
    } else {
    goes++;
    alert('Sorry ... the fraction you wanted is ' + numerator + '/' + denominator.substring(1) + ' leaving your Fractions Game score as ' + score + ' of ' + goes);
    }
    }
    numerator='' + eval(1 + Math.floor(Math.random() * 7));
    denominator='0';
    while (eval('' + denominator) < eval('' + numerator)) {
    denominator='' + eval(0 + Math.floor(Math.random() * 9));
    }
    if (viadb) {
    if (btoas == '') {
    location.href=document.URL.split('?')[0].split('#')[0] + '?btis=' + encodeURIComponent(btoa('' + numerator + '/' + denominator));
    } else {
    location.href=document.URL.split('?')[0].split('#')[0]; // + '?btis=' + encodeURIComponent(btoa('' + numerator + '/' + denominator));
    }
    }
    viadb=false;
    }

    … control … using …
  • CSS conic-gradient background …

    <style>
    #atend {
    background: conic-gradient(rgba(255,0,0,0.5) 0deg, rgba(0,0,255,0.5) 30deg, rgba(0,255,0,0.5) 60deg, rgba(255,192,203,0.5) 90deg, rgba(0,0,139,0.5) 120deg, rgba(144,238,144,0.5) 150deg, rgba(255,165,0,0.5) 180deg, rgba(173,216,230,0.5) 210deg, rgba(2,48,32,0.5) 240deg, rgba(255,0,255,0.5) 270deg, rgba(0,100,100,0.5) 300deg, rgba(128,128,0,0.5) 330deg);
    }
    </style>

… scenario, building on what we learnt when we presented CSS Gradient Creations Conic Tutorial a little while back.


Previous relevant CSS Gradient Creations Conic Tutorial is shown below.

CSS Gradient Creations Conic Tutorial

CSS Gradient Creations Conic Tutorial

Yesterday’s CSS Conic Gradient Primer Tutorial set us to thinking about integrating these Conic Gradients into our “Gradient Central” web application where you can create your own gradients which we last talked about with CSS Gradient Creations Mobile Width Tutorial.

These gradients …

  • linear-gradient
  • radial-gradient
  • conic-gradient

… are helping our webpage designs allow for colour gradation and subtlety we appreciate around here. They can often effectively fill in for that “graphic flair” not all of us possess, in our webpage designs.

What came up that was a bit new to us with this Conic Gradient integration? And yes, most tutorials bring up something new! Input element textboxes can be made inoperable by the setting of the Javascript DOM readOnly attribute, as with (Javascript code like) …


document.getElementById('mytextbox').readOnly=true; // and to make readable again use false instead

… but we found we couldn’t do that with select (ie. dropdown) elements. This useful link, thanks, put us right in our thinking to do this when conic-gradient selected …


document.getElementById('sdirection').disabled=true; // and to make enabled again use false instead

… because a conic-gradient direction value is much less nuanced than a linear-gradient direction value.

Feel free to try this changed gradient_creations.htm “Gradient Creations” live run link, or try below …

Stop Press

Today’s CSS Gradient Creations Conic Tutorial‘s integration of yesterday’s CSS Conic Gradient Primer Tutorial‘s work was missing some of the features of that latter web application, involving its textarea flexibility to add user additional dynamic CSS into the mix. No problems any longer, as we make use of the work we’ll talk about tomorrow, integrating into CSS Gradient Creations Conic Tutorial‘s web application one new line of code …


<script type='text/javascript' src='/divceditin.js?todowith=tdlook&after=tdcss&blurb=%2F*%20More%20gradient%20CSS%20styling%20can%20go%20here%20via%20a%20click%20...%20eg.%20border-radius%3A%2050%25%3B%20%20*%2F'></script>

… to offer that possibility. That will outline our use of element type div contenteditable=true with an input type=text value=”” placeholder=[Some Blurb] readonly prototype tool enabling users to add in their own dynamic CSS in the tweaked gradient_creations.htm “Gradient Creations” live run link, as also shown above this …


Previous relevant CSS Gradient Creations Mobile Width Tutorial is shown below.

CSS Gradient Creations Mobile Width Tutorial

CSS Gradient Creations Mobile Width Tutorial

When it comes to “width” (CSS styling) considerations with webpage design on mobile platforms where you are not prepared to “de-complex-ify” (if you know what I mean) the webpage contents you can run into the dual issues …

  • you want to show HTML elements legibly … and …
  • you also want to show the big picture

You see, with yesterday’s CSS Gradient Creations Width Makeover Tutorial we did hint when we said …

… we saw that it overshot the right hand border on the MacBook Air webpage screen.

… that the work yesterday was suited more towards your laptop usage rather than mobile phone (and to a less extent mobile tablet) usage.

There is a CSS styling “tool” to hand just for this scenario, though, the meta name=viewport (within <head> … </head> header element, usually) element, ours being, initially, for today’s work …


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

… the “red rag to a bull” signs that Javascript might come into it (to allow initially become eventually) being …

  1. the id=”myviewport” unusual attribute for a header element
  2. the big range difference between minimum-scale and maximum-scale but initial-scale being so conventionally valued

… in other words, today …

  • we start mobile platform web application “first few seconds” of display in “you want to show HTML elements legibly” mode … and that “first few seconds” of display tells us … anyone, anyone? … yes, Arielwe use setTimeout to delay

    <body onload="setTimeout(fixmobilewidth,5000); sdih=document.getElementById('sdirection').innerHTML; osdih=document.getElementById('rdirection').innerHTML; checkol();">

    … five seconds before …
  • we use Javascript DOM to adjust the meta name=viewport element as per …

    function fixmobilewidth() {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    var rectt=document.getElementsByTagName('table')[0].getBoundingClientRect();
    document.getElementById("myviewport").setAttribute("content", "width=device-width, initial-scale=" + eval(-0.35 + eval('' + (window.orientation == 0 ? window.innerHeight: window.innerWidth)) / eval('' + rectt.width)) + ", minimum-scale=0.1, maximum-scale=8, user-scalable=yes");
    }
    }

    … “to show the big picture” (of what’s available to the user to work the web application’s full functionality)

The control of whitespace came into the picture too. We replace in a lot of the table cells the non-breaking spaces (ie. &nbsp;) as per …


<td><input onblur="changeit();" onchange="changeit();" type=color id=c1 value='#ff0000'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs1 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc1 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o1 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c2 value='#0000ff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs2 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc2 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o2 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c3 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs3 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc3 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o3 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c4 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs4 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc4 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o4 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c5 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs5 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc5 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o5 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c6 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs6 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc6 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o6 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c7 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs7 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc7 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o7 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c8 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs8 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc8 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o8 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>

… with line breaks (ie. <br>) as per …


<td><input onblur="changeit();" onchange="changeit();" type=color id=c1 value='#ff0000'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs1 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc1 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o1 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c2 value='#0000ff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs2 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc2 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o2 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c3 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs3 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc3 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o3 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c4 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs4 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc4 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o4 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c5 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs5 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc5 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o5 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c6 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs6 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc6 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o6 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c7 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs7 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc7 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o7 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c8 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs8 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc8 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o8 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>

… to lessen the table cell width innards (at the expense, perhaps, of the table cell innard heights) that might become involved in our changed gradient_creations.htm “Gradient Creations” live run link.

Is the 5 seconds enough on your thinner mobile platform widths? That’s debatable, but the “spreading” gesture awaits those more accepting mobile phone users!


Previous relevant CSS Gradient Creations Width Makeover Tutorial is shown below.

CSS Gradient Creations Width Makeover Tutorial

CSS Gradient Creations Width Makeover Tutorial

Revisits to a web application, after some time, can bring “adverse” categories of reaction to me …

  • UX (user experience) Javascript criticism …
  • styling CSS annoyance

… and today’s work, on our “Gradient Creations” web application, is as a result of that second “styling CSS annoyance”.

Possibly the second is “less serious” in our mind, but, nonetheless, invariably we learn (or remember) quite a bit, researching them.

Maybe you can see from today’s tutorial animated GIF picture we categorized the slides into …

Slide … … with our commentary regarding our changed gradient_creations.htm “Gradient Creations” live run link
The problem … At 100% zoom level with the Google Chrome browser pointing at the previous “Gradient Creations” web application incarnation we saw that it overshot the right hand border on the MacBook Air webpage screen.
The culprit … Looking at the web page in Crome’s web inspector we identify the “Colour Name” textboxes (whose “id” starts with “sc” (as we mention later, to our advantage)) as being too wide and to lessen that width could improve the aesthetics.
The pathway …
  1. This search, thanks, got us to html – How to get CSS to select ID that begins with a string (not in Javascript)? – Stack Overflow, thanks, which taught us that, yes, “regex” is a friend to CSS selectors … as well as …
  2. This search, thanks, got us to css – sizing div based on window width – Stack Overflow which taught us (and reminded us) that the CSS width unit “vw” could be used like a percentage of screen width, our preferred expression of width, since we knew how many cells we wanted to cater for across the webpage, ahead of time, and so we picked “the conservative” “8vw” as this improved [id^=sc] selector improvement.
The intervention … Within the webpage’s <head> … </head> section we add …
<style>
[id^=sc] {
width: 8vw;
}
</style>
The improvement … The test shows improved aesthetics. Yay!

By the way, further reading on this topic (and web application) is available with CSS Gradient Creations Sharing Tutorial below.


Previous relevant CSS Gradient Creations Sharing Tutorial is shown below.

CSS Gradient Creations Sharing Tutorial

CSS Gradient Creations Sharing Tutorial

Turning a web application like yesterday’s CSS Gradient Creations Tutorial “Gradient Creations” one into a web application where you can share your discoveries is an exercise in both …

  • sharing and collaboration … as well as …
  • accountability

… opening up something that used to be just for private use only, to being one that is open to the rest of the online wooooorrrrllllddd.

As well as this new email and SMS sharing capability we add another contenteditable=true incursion into the mix as another selling product for our web application. Just quietly, perhaps you can use it as a “digital card” creator, as we offer to augment …

  • the table cell with a gradient background … with the idea that the user …
  • can write their wording (of say, a card) in the foreground of that same table cell

… and then allow the user to append a space to their Javascript prompt window answering of the emailee address to indicate to the web application that the email should just be that table cell content. On the way a collaboration phase is possible by tweaking the HTML …


xform.append('body',(document.body.outerHTML.split('</form>')[0] + '</form></body>').replace(/NONE\;/g, 'inline-block;').replace('<div ','<input type=text style=width:50%; ').replace('>background:', ' value="').replace('</div>', '"></input>').replace('"></textarea>', '">' + document.getElementById('tdlook').innerHTML.replace(/\<br\>/g,String.fromCharCode(10)) + '</textarea>'));

… to work with a form method=GET way for the emailee to adjust the gradient CSS to send off a return email (or one to a third party) in response to that first email. No collaboration here, but we also allow for SMS communications too.

Also, along the way, we allow for a colour to be defined by its name, if it makes the web application’s colour array list.

You can try our our changed gradient_creations.htm live run link, to see what we mean.


Previous relevant CSS Gradient Creations Tutorial is shown below.

CSS Gradient Creations Tutorial

CSS Gradient Creations Tutorial

The great CSS background “gradient” functionalities can come in four forms, those being …

  • linear gradient (and repeating linear gradient)
  • radial gradient (and repeating radial gradient)

… as a means to add background interest, even to the point where the background can have some (different) transparency (level) compared to the foreground, as per example CSS like …


<style>
html::before {
background: linear-gradient(rgba(255,255,255,0.8),rgba(255,255,255,0.8)),URL('//www.rjmprogramming.com.au/MyBusinessUnidad/Welcome_files/logo.jpg') repeat;
}
</style>

With tutorials like CSS Repeating Radial Gradients Primer Tutorial we allowed you to create some gradients, but we wanted a more detailed approach that was generic in its approach and left you with some CSS of use, which is often not the go with many other (albeit useful and inspiring) websites on the net.

There are a whole range of what you might call “directional” nuances you can apply to your gradients. There is opacity to allow for. There are “hard colour stops” you can apply. For linear gradients you can apply a variable angle. For radial gradients there are positional nuances that can be applied.

And then there are the colours. We are not sure of the limits, but we allow for up to eight colours. Enough to simulate the seven colours of the rainbow we go for with today’s tutorial picture arrangement whereby it tweaked with us that the HTML input type=color elements are all well and good but we needed to allow our CSS be editable by nesting into an HTML div contenteditable=true elements that can be tweaked for exact rgb or rgba colour definitions (thanks, Wikipedia), as we could look up for the purposes of displaying a rainbow coloured gradient background (we hope you like)!

Or see a repeating radial gradient example below …

So feel free to try our gradient_creations.html live run link, to see what we mean.


Previous relevant “CSS Gradient Creations Tutorial is shown below.

CSS Radial Gradients Primer Tutorial

CSS Repeating Radial Gradients Primer Tutorial

Way back when with HTML/Javascript Canvas Rainbow Primer Tutorial we talked about CSS linear gradients and radial gradients in the one blog posting, but ever since then, it has so much more that linear gradients have been useful to us here at this blog.

Today, though, we turn a bit of attention to radial gradients, specifically repeated radial gradients.

We’ve got a simple web application to play around with them in terms of …

  • ellipse versus circle
  • coloured versus black and white
  • extent keyword (closest-corner, closest-side, farthest-corner, farthest-side)

Below is one example of the CSS …


.circlefarthest-corner {
background: repeating-radial-gradient(circle farthest-corner,
red, black 5%, blue 5%, green 10%);
}

Feel free to play away at this live run that has this radial_gradients.html downloadable underlying HTML and CSS (and event logic Javascript that changes the HTML div element className property, to suit).


Previous relevant HTML/Javascript Canvas Rainbow Primer Tutorial is shown below.

HTML/Javascript Canvas Rainbow Primer Tutorial

HTML/Javascript Canvas Rainbow Primer Tutorial

The Canvas HTML element tag can be used as the container to draw graphics on the fly usually via the use of Javascript functions for rendering and event management.

In today’s tutorial we touch on a couple of the two dimensional Javascript functions to draw a rectangle or arc, but in the two dimensional context, canvas HTML elements can be used to draw text, lines, boxes and circles as well. We also touch on two functions to create a linear or radial gradient to the fillStyle and/or strokeStyle of your HTML element placed onto the canvas.

You may want to read more at HTML Canvas Reference as a generic reference, or here, at the tutorial javascript – How do I add a simple onClick event handler to a canvas element? – Stack Overflow.

As you can imagine, this HTML canvas element, new to HTML5, can be very useful for some practical client-side web functionality.

Link to some downloadable HTML programming code … rename to canvasrainbow.html

Here is a new link to some downloadable HTML programming source code explaining changes made (from HTML/Javascript Canvas Primer Tutorial) here.

You’ll notice heavy use of the Javascript Math.random() function.

We hope you enjoy this tutorial as a rainbow coloured live run.

Yes … you’ve reached the end … have a top supportive rainbow coloured day!

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


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


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


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


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


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


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


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


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


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


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

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

Gradient Fraction Game Equations Tutorial

Gradient Fraction Game Equations Tutorial

Gradient Fraction Game Equations Tutorial

There are three styles of CSS gradient …

  • conic
  • linear
  • radial

… and “different folks may learn via diff’rent CSS strokes”, so we incorporate a way for the user, when using the Fractions Game component of our latest web application, so that they can toggle the “cake” display among these three styles of gradient display.

Also, extending yesterday’s Conic Gradient Fraction Game Equations Tutorial, we …

  • allow, during the Fractions Game mode usage, have a window.prompt Cancel click send the user back to the Analogue Clock, so that unnecessary and errant window.prompt popup windows are avoided … and …
  • we incorporate “lowest common denominator” …

    function lcdextra(varn, vard) {
    var retv='', iv=0;
    for (iv=Math.min(Math.abs(varn),Math.abs(vard)); iv>=2; iv--) {
    if (eval(Math.abs(varn) % iv) == 0 && eval(Math.abs(vard) % iv) == 0) {
    varn /= iv;
    vard /= iv;
    retv+=' = ' + varn + ' / ' + vard + String.fromCharCode(10);
    }
    }
    return retv;
    }

    … calculations into our “show workings” section as Ms Trimpole would have wanted
  • involve emoji operators in that same “show workings” section to better mimic how we were taught at school in Mathematics class

… in the changed circular_sectors.html Fractions Game.


Previous relevant Conic Gradient Fraction Game Equations Tutorial is shown below.

Conic Gradient Fraction Game Equations Tutorial

Conic Gradient Fraction Game Equations Tutorial

We’re extending the functionality started with yesterday’s Dual Purpose Conic Gradient Primer Tutorial‘s second “dual purpose” …

  • Fractions Game piece of functionality …
  • Adding to its possibility the optional user job of solving operator …
    •  +
    •  –
    •  x
    •  /

    … types of fraction based equations

Simply put, changes to allow for this involved …

  • forsaking position:absolute “cakes” for your usual default position:relative positioning … within …
  • single row, three cell (cake, sign, cake) display … prior to …
  • hardly changed window.prompt user interaction, to answer … but …
  • more complex analysis for equation based scenarios …

    function showworking(instr, realans) {
    var outstr=instr;
    var xnumerator=numerator, xnumeratortwo=numeratortwo, xdenominatortwo=denominatortwo;
    var varw='';
    if (document.getElementById('ssign').value == '+') {
    if (denominatortwo == denominator.slice(-1)) {
    varw+=' = (' + numerator + ' + ' + numeratortwo + ') / ' + denominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) + eval('' + numeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    } else {
    varw+=' = (' + numerator + ' x ' + denominatortwo + ' + ' + numeratortwo + ' x ' + denominator.slice(-1) + ') / (' + denominator.slice(-1) + ' x ' + denominatortwo + ')' + String.fromCharCode(10);
    xnumerator*=denominatortwo;
    xnumeratortwo*=eval('' + denominator.slice(-1));
    xdenominatortwo*=eval('' + denominator.slice(-1));
    varw+=' = (' + xnumerator + ' + ' + xnumeratortwo + ') / ' + xdenominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + xnumerator) + eval('' + xnumeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    }
    } else if (document.getElementById('ssign').value == '-') {
    if (denominatortwo == denominator.slice(-1)) {
    varw+=' = (' + numerator + ' - ' + numeratortwo + ') / ' + denominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(numerator - numeratortwo) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    } else {
    varw+=' = (' + numerator + ' x ' + denominatortwo + ' - ' + numeratortwo + ' x ' + denominator.slice(-1) + ') / (' + denominator.slice(-1) + ' x ' + denominatortwo + ')' + String.fromCharCode(10);
    xnumerator*=denominatortwo;
    xnumeratortwo*=eval('' + denominator.slice(-1));
    xdenominatortwo*=eval('' + denominator.slice(-1));
    varw+=' = (' + xnumerator + ' - ' + xnumeratortwo + ') / ' + xdenominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + xnumerator) - eval('' + xnumeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    }
    } else if (document.getElementById('ssign').value == '/') {
    varw+=' = (' + numerator + ' / ' + denominator.slice(-1) + ') x (' + denominatortwo + ' / ' + numeratortwo + ')' + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) * eval('' + denominatortwo)) + ' / ' + eval(eval('' + denominator.slice(-1)) * eval('' + numeratortwo)) + String.fromCharCode(10);
    } else if (document.getElementById('ssign').value == 'x' || document.getElementById('ssign').value == '*') {
    varw+=' = (' + numerator + ' / ' + denominator.slice(-1) + ') x (' + numeratortwo + ' / ' + denominatortwo + ')' + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) * eval('' + numeratortwo)) + ' / ' + eval(eval('' + denominator.slice(-1)) * eval('' + denominatortwo)) + String.fromCharCode(10);
    }
    return outstr + String.fromCharCode(10) + varw + ' = ' + realans + ' ' + String.fromCharCode(10);
    }

… in the changed circular_sectors.html Fractions Game.


Previous relevant Dual Purpose Conic Gradient Primer Tutorial is shown below.

Dual Purpose Conic Gradient Primer Tutorial

Dual Purpose Conic Gradient Primer Tutorial

Yes, today, we have a “proof of concept” circular_sectors.html

  • dual purpose … as a …
    1. local time analogue clock (also, below) … calling on a changed analogue_clock.html … or …
    2. Fractions Game
  • ondblclick (double click) event … ondblclick=” viadb=true; ask(); “ … toggling …

    var viadb=false;

    function ask() {
    var ans='';
    if (!viadb) {
    while (('' + ans).indexOf('/') == -1 && ('' + ans.replace(/^1$/g, '1.0')).indexOf('.') == -1) {
    ans=prompt('What fraction of the "cake" is coloured? (eg. 2/3)', '');
    }
    if (ans == '' + numerator + '/' + denominator.substring(1) || Math.abs(eval('' + numerator + '/' + denominator.substring(1)) - eval('' + ans)) < 0.005) {
    score++;
    goes++;
    alert('Well done! This makes your Fractions Game score to be ' + score + ' of ' + goes);
    } else {
    goes++;
    alert('Sorry ... the fraction you wanted is ' + numerator + '/' + denominator.substring(1) + ' leaving your Fractions Game score as ' + score + ' of ' + goes);
    }
    }
    numerator='' + eval(1 + Math.floor(Math.random() * 7));
    denominator='0';
    while (eval('' + denominator) < eval('' + numerator)) {
    denominator='' + eval(0 + Math.floor(Math.random() * 9));
    }
    if (viadb) {
    if (btoas == '') {
    location.href=document.URL.split('?')[0].split('#')[0] + '?btis=' + encodeURIComponent(btoa('' + numerator + '/' + denominator));
    } else {
    location.href=document.URL.split('?')[0].split('#')[0]; // + '?btis=' + encodeURIComponent(btoa('' + numerator + '/' + denominator));
    }
    }
    viadb=false;
    }

    … control … using …
  • CSS conic-gradient background …

    <style>
    #atend {
    background: conic-gradient(rgba(255,0,0,0.5) 0deg, rgba(0,0,255,0.5) 30deg, rgba(0,255,0,0.5) 60deg, rgba(255,192,203,0.5) 90deg, rgba(0,0,139,0.5) 120deg, rgba(144,238,144,0.5) 150deg, rgba(255,165,0,0.5) 180deg, rgba(173,216,230,0.5) 210deg, rgba(2,48,32,0.5) 240deg, rgba(255,0,255,0.5) 270deg, rgba(0,100,100,0.5) 300deg, rgba(128,128,0,0.5) 330deg);
    }
    </style>

… scenario, building on what we learnt when we presented CSS Gradient Creations Conic Tutorial a little while back.


Previous relevant CSS Gradient Creations Conic Tutorial is shown below.

CSS Gradient Creations Conic Tutorial

CSS Gradient Creations Conic Tutorial

Yesterday’s CSS Conic Gradient Primer Tutorial set us to thinking about integrating these Conic Gradients into our “Gradient Central” web application where you can create your own gradients which we last talked about with CSS Gradient Creations Mobile Width Tutorial.

These gradients …

  • linear-gradient
  • radial-gradient
  • conic-gradient

… are helping our webpage designs allow for colour gradation and subtlety we appreciate around here. They can often effectively fill in for that “graphic flair” not all of us possess, in our webpage designs.

What came up that was a bit new to us with this Conic Gradient integration? And yes, most tutorials bring up something new! Input element textboxes can be made inoperable by the setting of the Javascript DOM readOnly attribute, as with (Javascript code like) …


document.getElementById('mytextbox').readOnly=true; // and to make readable again use false instead

… but we found we couldn’t do that with select (ie. dropdown) elements. This useful link, thanks, put us right in our thinking to do this when conic-gradient selected …


document.getElementById('sdirection').disabled=true; // and to make enabled again use false instead

… because a conic-gradient direction value is much less nuanced than a linear-gradient direction value.

Feel free to try this changed gradient_creations.htm “Gradient Creations” live run link, or try below …

Stop Press

Today’s CSS Gradient Creations Conic Tutorial‘s integration of yesterday’s CSS Conic Gradient Primer Tutorial‘s work was missing some of the features of that latter web application, involving its textarea flexibility to add user additional dynamic CSS into the mix. No problems any longer, as we make use of the work we’ll talk about tomorrow, integrating into CSS Gradient Creations Conic Tutorial‘s web application one new line of code …


<script type='text/javascript' src='/divceditin.js?todowith=tdlook&after=tdcss&blurb=%2F*%20More%20gradient%20CSS%20styling%20can%20go%20here%20via%20a%20click%20...%20eg.%20border-radius%3A%2050%25%3B%20%20*%2F'></script>

… to offer that possibility. That will outline our use of element type div contenteditable=true with an input type=text value=”” placeholder=[Some Blurb] readonly prototype tool enabling users to add in their own dynamic CSS in the tweaked gradient_creations.htm “Gradient Creations” live run link, as also shown above this …


Previous relevant CSS Gradient Creations Mobile Width Tutorial is shown below.

CSS Gradient Creations Mobile Width Tutorial

CSS Gradient Creations Mobile Width Tutorial

When it comes to “width” (CSS styling) considerations with webpage design on mobile platforms where you are not prepared to “de-complex-ify” (if you know what I mean) the webpage contents you can run into the dual issues …

  • you want to show HTML elements legibly … and …
  • you also want to show the big picture

You see, with yesterday’s CSS Gradient Creations Width Makeover Tutorial we did hint when we said …

… we saw that it overshot the right hand border on the MacBook Air webpage screen.

… that the work yesterday was suited more towards your laptop usage rather than mobile phone (and to a less extent mobile tablet) usage.

There is a CSS styling “tool” to hand just for this scenario, though, the meta name=viewport (within <head> … </head> header element, usually) element, ours being, initially, for today’s work …


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

… the “red rag to a bull” signs that Javascript might come into it (to allow initially become eventually) being …

  1. the id=”myviewport” unusual attribute for a header element
  2. the big range difference between minimum-scale and maximum-scale but initial-scale being so conventionally valued

… in other words, today …

  • we start mobile platform web application “first few seconds” of display in “you want to show HTML elements legibly” mode … and that “first few seconds” of display tells us … anyone, anyone? … yes, Arielwe use setTimeout to delay

    <body onload="setTimeout(fixmobilewidth,5000); sdih=document.getElementById('sdirection').innerHTML; osdih=document.getElementById('rdirection').innerHTML; checkol();">

    … five seconds before …
  • we use Javascript DOM to adjust the meta name=viewport element as per …

    function fixmobilewidth() {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    var rectt=document.getElementsByTagName('table')[0].getBoundingClientRect();
    document.getElementById("myviewport").setAttribute("content", "width=device-width, initial-scale=" + eval(-0.35 + eval('' + (window.orientation == 0 ? window.innerHeight: window.innerWidth)) / eval('' + rectt.width)) + ", minimum-scale=0.1, maximum-scale=8, user-scalable=yes");
    }
    }

    … “to show the big picture” (of what’s available to the user to work the web application’s full functionality)

The control of whitespace came into the picture too. We replace in a lot of the table cells the non-breaking spaces (ie. &nbsp;) as per …


<td><input onblur="changeit();" onchange="changeit();" type=color id=c1 value='#ff0000'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs1 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc1 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o1 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c2 value='#0000ff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs2 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc2 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o2 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c3 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs3 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc3 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o3 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c4 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs4 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc4 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o4 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c5 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs5 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc5 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o5 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c6 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs6 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc6 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o6 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c7 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs7 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc7 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o7 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c8 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs8 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc8 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o8 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>

… with line breaks (ie. <br>) as per …


<td><input onblur="changeit();" onchange="changeit();" type=color id=c1 value='#ff0000'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs1 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc1 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o1 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c2 value='#0000ff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs2 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc2 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o2 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c3 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs3 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc3 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o3 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c4 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs4 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc4 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o4 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c5 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs5 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc5 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o5 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c6 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs6 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc6 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o6 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c7 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs7 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc7 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o7 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c8 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs8 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc8 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o8 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>

… to lessen the table cell width innards (at the expense, perhaps, of the table cell innard heights) that might become involved in our changed gradient_creations.htm “Gradient Creations” live run link.

Is the 5 seconds enough on your thinner mobile platform widths? That’s debatable, but the “spreading” gesture awaits those more accepting mobile phone users!


Previous relevant CSS Gradient Creations Width Makeover Tutorial is shown below.

CSS Gradient Creations Width Makeover Tutorial

CSS Gradient Creations Width Makeover Tutorial

Revisits to a web application, after some time, can bring “adverse” categories of reaction to me …

  • UX (user experience) Javascript criticism …
  • styling CSS annoyance

… and today’s work, on our “Gradient Creations” web application, is as a result of that second “styling CSS annoyance”.

Possibly the second is “less serious” in our mind, but, nonetheless, invariably we learn (or remember) quite a bit, researching them.

Maybe you can see from today’s tutorial animated GIF picture we categorized the slides into …

Slide … … with our commentary regarding our changed gradient_creations.htm “Gradient Creations” live run link
The problem … At 100% zoom level with the Google Chrome browser pointing at the previous “Gradient Creations” web application incarnation we saw that it overshot the right hand border on the MacBook Air webpage screen.
The culprit … Looking at the web page in Crome’s web inspector we identify the “Colour Name” textboxes (whose “id” starts with “sc” (as we mention later, to our advantage)) as being too wide and to lessen that width could improve the aesthetics.
The pathway …
  1. This search, thanks, got us to html – How to get CSS to select ID that begins with a string (not in Javascript)? – Stack Overflow, thanks, which taught us that, yes, “regex” is a friend to CSS selectors … as well as …
  2. This search, thanks, got us to css – sizing div based on window width – Stack Overflow which taught us (and reminded us) that the CSS width unit “vw” could be used like a percentage of screen width, our preferred expression of width, since we knew how many cells we wanted to cater for across the webpage, ahead of time, and so we picked “the conservative” “8vw” as this improved [id^=sc] selector improvement.
The intervention … Within the webpage’s <head> … </head> section we add …
<style>
[id^=sc] {
width: 8vw;
}
</style>
The improvement … The test shows improved aesthetics. Yay!

By the way, further reading on this topic (and web application) is available with CSS Gradient Creations Sharing Tutorial below.


Previous relevant CSS Gradient Creations Sharing Tutorial is shown below.

CSS Gradient Creations Sharing Tutorial

CSS Gradient Creations Sharing Tutorial

Turning a web application like yesterday’s CSS Gradient Creations Tutorial “Gradient Creations” one into a web application where you can share your discoveries is an exercise in both …

  • sharing and collaboration … as well as …
  • accountability

… opening up something that used to be just for private use only, to being one that is open to the rest of the online wooooorrrrllllddd.

As well as this new email and SMS sharing capability we add another contenteditable=true incursion into the mix as another selling product for our web application. Just quietly, perhaps you can use it as a “digital card” creator, as we offer to augment …

  • the table cell with a gradient background … with the idea that the user …
  • can write their wording (of say, a card) in the foreground of that same table cell

… and then allow the user to append a space to their Javascript prompt window answering of the emailee address to indicate to the web application that the email should just be that table cell content. On the way a collaboration phase is possible by tweaking the HTML …


xform.append('body',(document.body.outerHTML.split('</form>')[0] + '</form></body>').replace(/NONE\;/g, 'inline-block;').replace('<div ','<input type=text style=width:50%; ').replace('>background:', ' value="').replace('</div>', '"></input>').replace('"></textarea>', '">' + document.getElementById('tdlook').innerHTML.replace(/\<br\>/g,String.fromCharCode(10)) + '</textarea>'));

… to work with a form method=GET way for the emailee to adjust the gradient CSS to send off a return email (or one to a third party) in response to that first email. No collaboration here, but we also allow for SMS communications too.

Also, along the way, we allow for a colour to be defined by its name, if it makes the web application’s colour array list.

You can try our our changed gradient_creations.htm live run link, to see what we mean.


Previous relevant CSS Gradient Creations Tutorial is shown below.

CSS Gradient Creations Tutorial

CSS Gradient Creations Tutorial

The great CSS background “gradient” functionalities can come in four forms, those being …

  • linear gradient (and repeating linear gradient)
  • radial gradient (and repeating radial gradient)

… as a means to add background interest, even to the point where the background can have some (different) transparency (level) compared to the foreground, as per example CSS like …


<style>
html::before {
background: linear-gradient(rgba(255,255,255,0.8),rgba(255,255,255,0.8)),URL('//www.rjmprogramming.com.au/MyBusinessUnidad/Welcome_files/logo.jpg') repeat;
}
</style>

With tutorials like CSS Repeating Radial Gradients Primer Tutorial we allowed you to create some gradients, but we wanted a more detailed approach that was generic in its approach and left you with some CSS of use, which is often not the go with many other (albeit useful and inspiring) websites on the net.

There are a whole range of what you might call “directional” nuances you can apply to your gradients. There is opacity to allow for. There are “hard colour stops” you can apply. For linear gradients you can apply a variable angle. For radial gradients there are positional nuances that can be applied.

And then there are the colours. We are not sure of the limits, but we allow for up to eight colours. Enough to simulate the seven colours of the rainbow we go for with today’s tutorial picture arrangement whereby it tweaked with us that the HTML input type=color elements are all well and good but we needed to allow our CSS be editable by nesting into an HTML div contenteditable=true elements that can be tweaked for exact rgb or rgba colour definitions (thanks, Wikipedia), as we could look up for the purposes of displaying a rainbow coloured gradient background (we hope you like)!

Or see a repeating radial gradient example below …

So feel free to try our gradient_creations.html live run link, to see what we mean.


Previous relevant “CSS Gradient Creations Tutorial is shown below.

CSS Radial Gradients Primer Tutorial

CSS Repeating Radial Gradients Primer Tutorial

Way back when with HTML/Javascript Canvas Rainbow Primer Tutorial we talked about CSS linear gradients and radial gradients in the one blog posting, but ever since then, it has so much more that linear gradients have been useful to us here at this blog.

Today, though, we turn a bit of attention to radial gradients, specifically repeated radial gradients.

We’ve got a simple web application to play around with them in terms of …

  • ellipse versus circle
  • coloured versus black and white
  • extent keyword (closest-corner, closest-side, farthest-corner, farthest-side)

Below is one example of the CSS …


.circlefarthest-corner {
background: repeating-radial-gradient(circle farthest-corner,
red, black 5%, blue 5%, green 10%);
}

Feel free to play away at this live run that has this radial_gradients.html downloadable underlying HTML and CSS (and event logic Javascript that changes the HTML div element className property, to suit).


Previous relevant HTML/Javascript Canvas Rainbow Primer Tutorial is shown below.

HTML/Javascript Canvas Rainbow Primer Tutorial

HTML/Javascript Canvas Rainbow Primer Tutorial

The Canvas HTML element tag can be used as the container to draw graphics on the fly usually via the use of Javascript functions for rendering and event management.

In today’s tutorial we touch on a couple of the two dimensional Javascript functions to draw a rectangle or arc, but in the two dimensional context, canvas HTML elements can be used to draw text, lines, boxes and circles as well. We also touch on two functions to create a linear or radial gradient to the fillStyle and/or strokeStyle of your HTML element placed onto the canvas.

You may want to read more at HTML Canvas Reference as a generic reference, or here, at the tutorial javascript – How do I add a simple onClick event handler to a canvas element? – Stack Overflow.

As you can imagine, this HTML canvas element, new to HTML5, can be very useful for some practical client-side web functionality.

Link to some downloadable HTML programming code … rename to canvasrainbow.html

Here is a new link to some downloadable HTML programming source code explaining changes made (from HTML/Javascript Canvas Primer Tutorial) here.

You’ll notice heavy use of the Javascript Math.random() function.

We hope you enjoy this tutorial as a rainbow coloured live run.

Yes … you’ve reached the end … have a top supportive rainbow coloured day!

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


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


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


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


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


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


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


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


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


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

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

Conic Gradient Fraction Game Equations Tutorial

Conic Gradient Fraction Game Equations Tutorial

Conic Gradient Fraction Game Equations Tutorial

We’re extending the functionality started with yesterday’s Dual Purpose Conic Gradient Primer Tutorial‘s second “dual purpose” …

  • Fractions Game piece of functionality …
  • Adding to its possibility the optional user job of solving operator …
    •  +
    •  –
    •  x
    •  /

    … types of fraction based equations

Simply put, changes to allow for this involved …

  • forsaking position:absolute “cakes” for your usual default position:relative positioning … within …
  • single row, three cell (cake, sign, cake) display … prior to …
  • hardly changed window.prompt user interaction, to answer … but …
  • more complex analysis for equation based scenarios …

    function showworking(instr, realans) {
    var outstr=instr;
    var xnumerator=numerator, xnumeratortwo=numeratortwo, xdenominatortwo=denominatortwo;
    var varw='';
    if (document.getElementById('ssign').value == '+') {
    if (denominatortwo == denominator.slice(-1)) {
    varw+=' = (' + numerator + ' + ' + numeratortwo + ') / ' + denominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) + eval('' + numeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    } else {
    varw+=' = (' + numerator + ' x ' + denominatortwo + ' + ' + numeratortwo + ' x ' + denominator.slice(-1) + ') / (' + denominator.slice(-1) + ' x ' + denominatortwo + ')' + String.fromCharCode(10);
    xnumerator*=denominatortwo;
    xnumeratortwo*=eval('' + denominator.slice(-1));
    xdenominatortwo*=eval('' + denominator.slice(-1));
    varw+=' = (' + xnumerator + ' + ' + xnumeratortwo + ') / ' + xdenominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + xnumerator) + eval('' + xnumeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    }
    } else if (document.getElementById('ssign').value == '-') {
    if (denominatortwo == denominator.slice(-1)) {
    varw+=' = (' + numerator + ' - ' + numeratortwo + ') / ' + denominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(numerator - numeratortwo) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    } else {
    varw+=' = (' + numerator + ' x ' + denominatortwo + ' - ' + numeratortwo + ' x ' + denominator.slice(-1) + ') / (' + denominator.slice(-1) + ' x ' + denominatortwo + ')' + String.fromCharCode(10);
    xnumerator*=denominatortwo;
    xnumeratortwo*=eval('' + denominator.slice(-1));
    xdenominatortwo*=eval('' + denominator.slice(-1));
    varw+=' = (' + xnumerator + ' - ' + xnumeratortwo + ') / ' + xdenominatortwo + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + xnumerator) - eval('' + xnumeratortwo)) + ' / ' + xdenominatortwo + String.fromCharCode(10);
    }
    } else if (document.getElementById('ssign').value == '/') {
    varw+=' = (' + numerator + ' / ' + denominator.slice(-1) + ') x (' + denominatortwo + ' / ' + numeratortwo + ')' + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) * eval('' + denominatortwo)) + ' / ' + eval(eval('' + denominator.slice(-1)) * eval('' + numeratortwo)) + String.fromCharCode(10);
    } else if (document.getElementById('ssign').value == 'x' || document.getElementById('ssign').value == '*') {
    varw+=' = (' + numerator + ' / ' + denominator.slice(-1) + ') x (' + numeratortwo + ' / ' + denominatortwo + ')' + String.fromCharCode(10);
    varw+=' = ' + eval(eval('' + numerator) * eval('' + numeratortwo)) + ' / ' + eval(eval('' + denominator.slice(-1)) * eval('' + denominatortwo)) + String.fromCharCode(10);
    }
    return outstr + String.fromCharCode(10) + varw + ' = ' + realans + ' ' + String.fromCharCode(10);
    }

… in the changed circular_sectors.html Fractions Game.


Previous relevant Dual Purpose Conic Gradient Primer Tutorial is shown below.

Dual Purpose Conic Gradient Primer Tutorial

Dual Purpose Conic Gradient Primer Tutorial

Yes, today, we have a “proof of concept” circular_sectors.html

  • dual purpose … as a …
    1. local time analogue clock (also, below) … calling on a changed analogue_clock.html … or …
    2. Fractions Game
  • ondblclick (double click) event … ondblclick=” viadb=true; ask(); “ … toggling …

    var viadb=false;

    function ask() {
    var ans='';
    if (!viadb) {
    while (('' + ans).indexOf('/') == -1 && ('' + ans.replace(/^1$/g, '1.0')).indexOf('.') == -1) {
    ans=prompt('What fraction of the "cake" is coloured? (eg. 2/3)', '');
    }
    if (ans == '' + numerator + '/' + denominator.substring(1) || Math.abs(eval('' + numerator + '/' + denominator.substring(1)) - eval('' + ans)) < 0.005) {
    score++;
    goes++;
    alert('Well done! This makes your Fractions Game score to be ' + score + ' of ' + goes);
    } else {
    goes++;
    alert('Sorry ... the fraction you wanted is ' + numerator + '/' + denominator.substring(1) + ' leaving your Fractions Game score as ' + score + ' of ' + goes);
    }
    }
    numerator='' + eval(1 + Math.floor(Math.random() * 7));
    denominator='0';
    while (eval('' + denominator) < eval('' + numerator)) {
    denominator='' + eval(0 + Math.floor(Math.random() * 9));
    }
    if (viadb) {
    if (btoas == '') {
    location.href=document.URL.split('?')[0].split('#')[0] + '?btis=' + encodeURIComponent(btoa('' + numerator + '/' + denominator));
    } else {
    location.href=document.URL.split('?')[0].split('#')[0]; // + '?btis=' + encodeURIComponent(btoa('' + numerator + '/' + denominator));
    }
    }
    viadb=false;
    }

    … control … using …
  • CSS conic-gradient background …

    <style>
    #atend {
    background: conic-gradient(rgba(255,0,0,0.5) 0deg, rgba(0,0,255,0.5) 30deg, rgba(0,255,0,0.5) 60deg, rgba(255,192,203,0.5) 90deg, rgba(0,0,139,0.5) 120deg, rgba(144,238,144,0.5) 150deg, rgba(255,165,0,0.5) 180deg, rgba(173,216,230,0.5) 210deg, rgba(2,48,32,0.5) 240deg, rgba(255,0,255,0.5) 270deg, rgba(0,100,100,0.5) 300deg, rgba(128,128,0,0.5) 330deg);
    }
    </style>

… scenario, building on what we learnt when we presented CSS Gradient Creations Conic Tutorial a little while back.


Previous relevant CSS Gradient Creations Conic Tutorial is shown below.

CSS Gradient Creations Conic Tutorial

CSS Gradient Creations Conic Tutorial

Yesterday’s CSS Conic Gradient Primer Tutorial set us to thinking about integrating these Conic Gradients into our “Gradient Central” web application where you can create your own gradients which we last talked about with CSS Gradient Creations Mobile Width Tutorial.

These gradients …

  • linear-gradient
  • radial-gradient
  • conic-gradient

… are helping our webpage designs allow for colour gradation and subtlety we appreciate around here. They can often effectively fill in for that “graphic flair” not all of us possess, in our webpage designs.

What came up that was a bit new to us with this Conic Gradient integration? And yes, most tutorials bring up something new! Input element textboxes can be made inoperable by the setting of the Javascript DOM readOnly attribute, as with (Javascript code like) …


document.getElementById('mytextbox').readOnly=true; // and to make readable again use false instead

… but we found we couldn’t do that with select (ie. dropdown) elements. This useful link, thanks, put us right in our thinking to do this when conic-gradient selected …


document.getElementById('sdirection').disabled=true; // and to make enabled again use false instead

… because a conic-gradient direction value is much less nuanced than a linear-gradient direction value.

Feel free to try this changed gradient_creations.htm “Gradient Creations” live run link, or try below …

Stop Press

Today’s CSS Gradient Creations Conic Tutorial‘s integration of yesterday’s CSS Conic Gradient Primer Tutorial‘s work was missing some of the features of that latter web application, involving its textarea flexibility to add user additional dynamic CSS into the mix. No problems any longer, as we make use of the work we’ll talk about tomorrow, integrating into CSS Gradient Creations Conic Tutorial‘s web application one new line of code …


<script type='text/javascript' src='/divceditin.js?todowith=tdlook&after=tdcss&blurb=%2F*%20More%20gradient%20CSS%20styling%20can%20go%20here%20via%20a%20click%20...%20eg.%20border-radius%3A%2050%25%3B%20%20*%2F'></script>

… to offer that possibility. That will outline our use of element type div contenteditable=true with an input type=text value=”” placeholder=[Some Blurb] readonly prototype tool enabling users to add in their own dynamic CSS in the tweaked gradient_creations.htm “Gradient Creations” live run link, as also shown above this …


Previous relevant CSS Gradient Creations Mobile Width Tutorial is shown below.

CSS Gradient Creations Mobile Width Tutorial

CSS Gradient Creations Mobile Width Tutorial

When it comes to “width” (CSS styling) considerations with webpage design on mobile platforms where you are not prepared to “de-complex-ify” (if you know what I mean) the webpage contents you can run into the dual issues …

  • you want to show HTML elements legibly … and …
  • you also want to show the big picture

You see, with yesterday’s CSS Gradient Creations Width Makeover Tutorial we did hint when we said …

… we saw that it overshot the right hand border on the MacBook Air webpage screen.

… that the work yesterday was suited more towards your laptop usage rather than mobile phone (and to a less extent mobile tablet) usage.

There is a CSS styling “tool” to hand just for this scenario, though, the meta name=viewport (within <head> … </head> header element, usually) element, ours being, initially, for today’s work …


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

… the “red rag to a bull” signs that Javascript might come into it (to allow initially become eventually) being …

  1. the id=”myviewport” unusual attribute for a header element
  2. the big range difference between minimum-scale and maximum-scale but initial-scale being so conventionally valued

… in other words, today …

  • we start mobile platform web application “first few seconds” of display in “you want to show HTML elements legibly” mode … and that “first few seconds” of display tells us … anyone, anyone? … yes, Arielwe use setTimeout to delay

    <body onload="setTimeout(fixmobilewidth,5000); sdih=document.getElementById('sdirection').innerHTML; osdih=document.getElementById('rdirection').innerHTML; checkol();">

    … five seconds before …
  • we use Javascript DOM to adjust the meta name=viewport element as per …

    function fixmobilewidth() {
    if (navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i)) {
    var rectt=document.getElementsByTagName('table')[0].getBoundingClientRect();
    document.getElementById("myviewport").setAttribute("content", "width=device-width, initial-scale=" + eval(-0.35 + eval('' + (window.orientation == 0 ? window.innerHeight: window.innerWidth)) / eval('' + rectt.width)) + ", minimum-scale=0.1, maximum-scale=8, user-scalable=yes");
    }
    }

    … “to show the big picture” (of what’s available to the user to work the web application’s full functionality)

The control of whitespace came into the picture too. We replace in a lot of the table cells the non-breaking spaces (ie. &nbsp;) as per …


<td><input onblur="changeit();" onchange="changeit();" type=color id=c1 value='#ff0000'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs1 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc1 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o1 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c2 value='#0000ff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs2 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc2 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o2 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c3 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs3 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc3 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o3 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c4 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs4 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc4 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o4 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c5 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs5 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc5 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o5 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c6 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs6 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc6 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o6 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c7 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs7 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc7 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o7 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c8 value='#ffffff'></input>&nbsp;<input onblur="changeit();" onchange="changeit();" type=text id=hcs8 value='' placeholder='Colour Stop %' style=width:120px;></input>&nbsp;<input onblur='lookup(this.value,this);' type=text id=sc8 placeholder='Colour by name'></input>&nbsp;Opacity:&nbsp;<input onblur="changeit();" onchange="changeit();" type=number id=o8 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>

… with line breaks (ie. <br>) as per …


<td><input onblur="changeit();" onchange="changeit();" type=color id=c1 value='#ff0000'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs1 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc1 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o1 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c2 value='#0000ff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs2 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc2 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o2 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c3 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs3 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc3 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o3 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c4 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs4 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc4 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o4 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c5 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs5 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc5 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o5 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c6 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs6 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc6 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o6 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c7 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs7 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc7 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o7 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>
<td><input onblur="changeit();" onchange="changeit();" type=color id=c8 value='#ffffff'></input><br><input onblur="changeit();" onchange="changeit();" type=text id=hcs8 value='' placeholder='Colour Stop %' style=width:120px;></input><br><input onblur='lookup(this.value,this);' type=text id=sc8 placeholder='Colour by name'></input><br>Opacity: <input onblur="changeit();" onchange="changeit();" type=number id=o8 min=0.0 max=1.0 step=0.1 value='1.0'></input></td>

… to lessen the table cell width innards (at the expense, perhaps, of the table cell innard heights) that might become involved in our changed gradient_creations.htm “Gradient Creations” live run link.

Is the 5 seconds enough on your thinner mobile platform widths? That’s debatable, but the “spreading” gesture awaits those more accepting mobile phone users!


Previous relevant CSS Gradient Creations Width Makeover Tutorial is shown below.

CSS Gradient Creations Width Makeover Tutorial

CSS Gradient Creations Width Makeover Tutorial

Revisits to a web application, after some time, can bring “adverse” categories of reaction to me …

  • UX (user experience) Javascript criticism …
  • styling CSS annoyance

… and today’s work, on our “Gradient Creations” web application, is as a result of that second “styling CSS annoyance”.

Possibly the second is “less serious” in our mind, but, nonetheless, invariably we learn (or remember) quite a bit, researching them.

Maybe you can see from today’s tutorial animated GIF picture we categorized the slides into …

Slide … … with our commentary regarding our changed gradient_creations.htm “Gradient Creations” live run link
The problem … At 100% zoom level with the Google Chrome browser pointing at the previous “Gradient Creations” web application incarnation we saw that it overshot the right hand border on the MacBook Air webpage screen.
The culprit … Looking at the web page in Crome’s web inspector we identify the “Colour Name” textboxes (whose “id” starts with “sc” (as we mention later, to our advantage)) as being too wide and to lessen that width could improve the aesthetics.
The pathway …
  1. This search, thanks, got us to html – How to get CSS to select ID that begins with a string (not in Javascript)? – Stack Overflow, thanks, which taught us that, yes, “regex” is a friend to CSS selectors … as well as …
  2. This search, thanks, got us to css – sizing div based on window width – Stack Overflow which taught us (and reminded us) that the CSS width unit “vw” could be used like a percentage of screen width, our preferred expression of width, since we knew how many cells we wanted to cater for across the webpage, ahead of time, and so we picked “the conservative” “8vw” as this improved [id^=sc] selector improvement.
The intervention … Within the webpage’s <head> … </head> section we add …
<style>
[id^=sc] {
width: 8vw;
}
</style>
The improvement … The test shows improved aesthetics. Yay!

By the way, further reading on this topic (and web application) is available with CSS Gradient Creations Sharing Tutorial below.


Previous relevant CSS Gradient Creations Sharing Tutorial is shown below.

CSS Gradient Creations Sharing Tutorial

CSS Gradient Creations Sharing Tutorial

Turning a web application like yesterday’s CSS Gradient Creations Tutorial “Gradient Creations” one into a web application where you can share your discoveries is an exercise in both …

  • sharing and collaboration … as well as …
  • accountability

… opening up something that used to be just for private use only, to being one that is open to the rest of the online wooooorrrrllllddd.

As well as this new email and SMS sharing capability we add another contenteditable=true incursion into the mix as another selling product for our web application. Just quietly, perhaps you can use it as a “digital card” creator, as we offer to augment …

  • the table cell with a gradient background … with the idea that the user …
  • can write their wording (of say, a card) in the foreground of that same table cell

… and then allow the user to append a space to their Javascript prompt window answering of the emailee address to indicate to the web application that the email should just be that table cell content. On the way a collaboration phase is possible by tweaking the HTML …


xform.append('body',(document.body.outerHTML.split('</form>')[0] + '</form></body>').replace(/NONE\;/g, 'inline-block;').replace('<div ','<input type=text style=width:50%; ').replace('>background:', ' value="').replace('</div>', '"></input>').replace('"></textarea>', '">' + document.getElementById('tdlook').innerHTML.replace(/\<br\>/g,String.fromCharCode(10)) + '</textarea>'));

… to work with a form method=GET way for the emailee to adjust the gradient CSS to send off a return email (or one to a third party) in response to that first email. No collaboration here, but we also allow for SMS communications too.

Also, along the way, we allow for a colour to be defined by its name, if it makes the web application’s colour array list.

You can try our our changed gradient_creations.htm live run link, to see what we mean.


Previous relevant CSS Gradient Creations Tutorial is shown below.

CSS Gradient Creations Tutorial

CSS Gradient Creations Tutorial

The great CSS background “gradient” functionalities can come in four forms, those being …

  • linear gradient (and repeating linear gradient)
  • radial gradient (and repeating radial gradient)

… as a means to add background interest, even to the point where the background can have some (different) transparency (level) compared to the foreground, as per example CSS like …


<style>
html::before {
background: linear-gradient(rgba(255,255,255,0.8),rgba(255,255,255,0.8)),URL('//www.rjmprogramming.com.au/MyBusinessUnidad/Welcome_files/logo.jpg') repeat;
}
</style>

With tutorials like CSS Repeating Radial Gradients Primer Tutorial we allowed you to create some gradients, but we wanted a more detailed approach that was generic in its approach and left you with some CSS of use, which is often not the go with many other (albeit useful and inspiring) websites on the net.

There are a whole range of what you might call “directional” nuances you can apply to your gradients. There is opacity to allow for. There are “hard colour stops” you can apply. For linear gradients you can apply a variable angle. For radial gradients there are positional nuances that can be applied.

And then there are the colours. We are not sure of the limits, but we allow for up to eight colours. Enough to simulate the seven colours of the rainbow we go for with today’s tutorial picture arrangement whereby it tweaked with us that the HTML input type=color elements are all well and good but we needed to allow our CSS be editable by nesting into an HTML div contenteditable=true elements that can be tweaked for exact rgb or rgba colour definitions (thanks, Wikipedia), as we could look up for the purposes of displaying a rainbow coloured gradient background (we hope you like)!

Or see a repeating radial gradient example below …

So feel free to try our gradient_creations.html live run link, to see what we mean.


Previous relevant “CSS Gradient Creations Tutorial is shown below.

CSS Radial Gradients Primer Tutorial

CSS Repeating Radial Gradients Primer Tutorial

Way back when with HTML/Javascript Canvas Rainbow Primer Tutorial we talked about CSS linear gradients and radial gradients in the one blog posting, but ever since then, it has so much more that linear gradients have been useful to us here at this blog.

Today, though, we turn a bit of attention to radial gradients, specifically repeated radial gradients.

We’ve got a simple web application to play around with them in terms of …

  • ellipse versus circle
  • coloured versus black and white
  • extent keyword (closest-corner, closest-side, farthest-corner, farthest-side)

Below is one example of the CSS …


.circlefarthest-corner {
background: repeating-radial-gradient(circle farthest-corner,
red, black 5%, blue 5%, green 10%);
}

Feel free to play away at this live run that has this radial_gradients.html downloadable underlying HTML and CSS (and event logic Javascript that changes the HTML div element className property, to suit).


Previous relevant HTML/Javascript Canvas Rainbow Primer Tutorial is shown below.

HTML/Javascript Canvas Rainbow Primer Tutorial

HTML/Javascript Canvas Rainbow Primer Tutorial

The Canvas HTML element tag can be used as the container to draw graphics on the fly usually via the use of Javascript functions for rendering and event management.

In today’s tutorial we touch on a couple of the two dimensional Javascript functions to draw a rectangle or arc, but in the two dimensional context, canvas HTML elements can be used to draw text, lines, boxes and circles as well. We also touch on two functions to create a linear or radial gradient to the fillStyle and/or strokeStyle of your HTML element placed onto the canvas.

You may want to read more at HTML Canvas Reference as a generic reference, or here, at the tutorial javascript – How do I add a simple onClick event handler to a canvas element? – Stack Overflow.

As you can imagine, this HTML canvas element, new to HTML5, can be very useful for some practical client-side web functionality.

Link to some downloadable HTML programming code … rename to canvasrainbow.html

Here is a new link to some downloadable HTML programming source code explaining changes made (from HTML/Javascript Canvas Primer Tutorial) here.

You’ll notice heavy use of the Javascript Math.random() function.

We hope you enjoy this tutorial as a rainbow coloured live run.

Yes … you’ve reached the end … have a top supportive rainbow coloured day!

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