How to sync MP3 music and lyrics to css3 animations.


Got bored so decided to play around with 2D css3 animation. The goal was to sync lyrics and css3 animation to an mp3 file.

Take note: the syncing requires HTML5’s Audio currentTime (audio.currentTime). It will only work in the latest desktop browsers.

On Android mobile it only works in Chrome version 52 or higher (August 2016). It took Chrome 2+ years to fix the broken currentTime in Chrome for Android. In older Chrome for Android versions, the currentTime was always stuck on zero time. Thus, the earth just spun around and no animation are triggered in the switch statements.

Other Android mobile browser screw up in layering and other things. I don’t own an iPhone, so have no idea what happen there.

Recorded my own goofy song in my apartment on a broken Martin and midi drums using Adobe Audition, $50 mike plugged into a M-Audio Fast Track. As I say to my Facebook friend’s “Best heard on Fentanyl and Bath Salts”.

Down to Business:

requestAnimFrame: handles the timing triggers. It fires every 1/10th of a second.
JavaScript switch: handles when to start an animation (can be fractional 8.2).
Someone.css: handles all the ccs3 2d animation (I tried to include most transitions and keyframes).
prefixfree.min.js: Plugin by Lea Verou saves the time of having write older browser css3 prefixs. (however, since it only works in modern browser there is no need for it).

AudioControls.js: You don’t need this if your audio is in a tag. However, when working on a long mp3 file it helps to jump to a section be clicking or dragging the time-line. (Swapping left or right will show or hide the audio control).

Note: this is not Adobe Flash, so forwarding or rewinding will not hide layers (z-index) that are already triggered.

On line 56 I was going to use:
$(“div”).each(function(){ if ($(this).data(“run”)==”true” );
to track all animation then someday reset all css3 animations, etc, etc. The key word is ‘someday’ means ‘never’.

The zip file is 12 MB (the mp3 being 10 MB).


Posted in Sync CCs Animation | Tagged , , , , | Leave a comment

jQuery Fixed Table left Column and Headers with drag scrolling


This example shows a Table with a Fix left column and header using jQuery. Scrolling on second column horizontally while be able to scroll all columns vertically. Auto scrolling while dragging. Don’t use IE (explained later).

Revisiting my jQuery Timeline Range slider post from March 2015, I wanted to see if the slider could be use in a pure HTML UI interface similar to Adobe Flash or Audio software.

This lead to two major hurdles:

  1.  Build a single table that would scroll horizontally while the first column was fixed and also have all columns scrolled vertically while the headers stayed fixed.
  2. Insert a Slider that would scroll the second column when the user dragged it or resized the slider’s handles.

I abandoned using my Slider plug-in for one reason: Chrome and its stubbornness to have a setCapture() API that is available in both IE and Firefox browsers.

Chrome insists that all mouse captures be done on document mousemove event. This approach played Russian roulette if you have additional third party plug-ins that also use the document events.

I has fighting with a third-party table row drag and sort plug-in and I had to either rewrite my plug-in or make changes to the other plug-in’s source code.

Note to Chrome: setCapture() is extremely useful when dragging elements. Pointer-events are not the same, get your act together.
Conclusion: I wrote a new program from scratch, adding the (unnecessary) dragging code to accommodate Chrome.

Part 1 – The Table design:

To start with, I chose to copy the look of Articulate Storyline’s timeline. It is very similar to Adobe Flash and Audio recording software.
On Stackoverflow, I found a four table solution to scrolling tables as mentioned above. However, I needed a single table solution since highlighting and dragging rows required additional code to index and highlight selected rows across four tables.
By the way: Stackoverflow has been taken over by -1 moderators (mostly from Europe) – my two cents.

After many failed attempts, I finally found a way using a sh*t load of CSS, three wrapper divs and a single ScrollTop() trick.
I abandoned the fixed TH headers since I needed a scrolling ruler on the second column which was easier done by wrapping separate divs and adjusting the table top margin.

Note: In IE the horizontal scrollbar will be jumpy (reflow repaints) when scrolling vertically. I added code to hide it when scrolling.

When drag scrolling, IE is wacked. Out-of-order styling, painting and reflow. I added comments in the source code, best to remove and just use Chrome, Firefox or Edge.

Base example of older 4 table Multiple Scrolling interface:

Base example of Single Multiple Scrolling Table with fixed headers:

Part 2 – Scrolling while dragging:

Damn Chrome again: turn off its auto-scrolling when dragging. Auto-scrolling would only be nice if all browsers had it and you were able to adjust the speed.

Manual scrolling required about 100 lines of code that could have been 25 lines if Chrome had a setCapture() API.

I can’t say if my code is the shortest, easiest solution, I’m sure the big boys figured out a mathematical formula that’s simpler.

Note: if you know a better formula please post it here. I lost to many hairs using – offset this, viewport this, left-side, right-side, etc.

The biggest problem was to not scroll when the slider was visible inside the viewport. Hence, the multitude of variables.

View the finished example (tested on IE11, Chrome, Firefox, Edge):
Download the zip file:

Final Notes: I left out a lot code checking and the interface is just for show.

  1. It expects a least one slider (id=’slider1′).
  2. Never wrote code for auto scrolling if slider edges are outside of the viewport:
    if (SoL < offsetLeft || SoR > offsetRight) { insert more code }
  3. IE scroll repaint and/or reflow was a pain. MS announced it’s finally retiring IE below version 11. However, they still need to fix their scrolling in version 11 or I’m I doing something wrong? (Chrome, Firefox and Edge seem to disagree).
  4. Dragging a track up or down (right click and drag) to sort rows uses rowSorter.js by Gökhan Bora.

Finally: it’s a start, since 3 days a Googling I couldn’t even find a .net control that simulates a Audio track layer recording UI.
I suggest using wavesurfer.js and it’s timeline ruler plug-in if going any further as an Audio interface.

  1. Update:  January 12th, 2016:
    Removed mousemove and replace with requestAnimationFrame to save on browser paints and layout calls.
  2.  Change CSS viewport and headerR widths, now uses JavaScript to measure true scrollbar widths: 12px or 17px.
  3. Fixed maxScroll variable. Decided to use getBoundingClientRect() and replace some clamp values with already known values (e.g. vpScrollL).

IE dragging then scrolling: changing styles before, after ??? scroll when??? let it jump, flash, out-of-order???, use Chrome, Firefox or Edge as I have given up on IE. If things change I’ll post it or this is the last update.

Wasted days and wasted nights – Fredrick Fender.

keywords:,  jQuery Drag and Scroll, Fixed Table Column and Headers, jQuery Excel table, jQuery audio tracks, jQuery auto scrolling, jQuery drag, jQuery scroll, jQuery fixed table.

Posted in jQuery Fixed Table Column Drag Scrolling | Tagged , , , , , , , , | 1 Comment

Editor for Closed Captions in Storyline

Close Captions StorylineClosed Captions Editor for Storyline is a HTML5 editor that I built after having to constantly open and publish storyline projects requiring CC in one or two languages.

Why? : Most projects I work on have 50 slides or more. Every time someone made a narration or closed caption change I had to find the slide then the closed captions textbox layer to make the edits. This process had to be repeated for the second storyline translation version.

Close Caption editor builds a single HTML page to display CC in one or two languages.

You need IE11 installed in Windows to run the editor. The outputted HTML will display in any supported Storyline browser. (HTML5 in Chrome, Flash in others).

Note : Windows Edge Browser forgot to add Undo for its right-click context menu. This is why the program uses the MS WebBrowser control that falls back to IE11 engine which is included in Windows 10.

The only downside is the Storyline quirk that doesn’t refresh the web object after editing content in it’s folder. You must rename the folder you put the Closed_Caption.html into and also reload the web object on the master page with the renamed folder. However, I still saves hours now using this program.

Minimum requirements: Windows 8.1 or 10
Internet Explorer 10 or higher.

This program is not free ($39.95) You can try it out on the following web page.
The trail example does not save your file.

Editor example

Storyline :



Posted in Storyline | Tagged , , | Leave a comment

Adding an HTML menu to Articulate Storyline

Run Demo: This deals with adding a HTML CSS3 Jquery menu to a Articulate Storyline eLearning project (Flash version Storyline 1)

The example has only 5 pages only. (the other 41 pages would also work if you added them)

Click image to run Demo: then right click the custom menu (that’s right it’s an HML page). view the source. It’s a table but could have used ul css menus too.

New Version 1.0.2
Updated April 14, 2015

Fixes April 14:
Moved some repeating code to the master slide.
Added the following code so you can have up to 999 slides.
var pagenum = player.GetVar(‘page’).slice(-3).replace(/\D/g,”); //good for 999
if (pagenum && ~~Number(pagenum) > 0 ) { getResumeStates(pagenum,’1′); }

Fixes April 13:
In version 1.0.0 all of the JavaScript code was located in NavMenu.html
Storyline doesn’t insert the iframe until a trigger opens it.
Thus, no loaded NavMenu.html, no updates to the table rows when iframe page is hidden.

To fix this, I had to make a global.js file.
To load the global.js file into the story.html was like pulling teeth.
Storyline is definitely not like Lectora when it comes to adding custom code to the main page. In fact, it can’t do it at all.

I had to add an extra JavaScipt Trigger on the Master slide:

if (! parent.document.getElementById(“globalScript”)) {
var player = GetPlayer();
var webObjectFolder = player.GetVar(‘webObjectFolder’);
var imported = parent.document.createElement(“script”);”globalScript”;
imported.src = “story_content/WebObjects/”+webObjectFolder+”/global.js”;

Why does Storyline put every function call on every slide in user.js ?? Shouldn’t I have a choice? I only neeeded to call the above code once on the page load.
Hence, all the extra (what if) code, to prevent Storyline from insert a million elements to the head of the storyline.html page.
Storyline staff: please add the ability to add custom code to story.html

Why does Storyline generate cryptic keys and ids (and some elements with no ids)
Storyline staff: please add the ability to add your own DOM ids and CSS class names.

Seriously, a HTML menu could have been easy created with just a few lines of code if not for their coding methods.
Are the trying to hide something? Have they never heard of Sothink, decomplilers.
Get with the program. If Lectora ever gets a timeline control I may switch.
By the way, I charge clients twice as much if they insist on Lectora.
Why? because it takes twice as long without a timeline editor.

Next beef: Look at the stupid generate folder name below:
Would have made my life easier if I had the abilty to name the folder in Storyline.

Enough said – Let’s continue:

The example has only 5 pages (the other 41 pages would also work if you added them)

How it works:

There are now 5 custom storyline variable to track:
gotoPage : Number
page : Text
resumeStates : Text
totalPages :  Number
webObjectFolder:  Text

Each Page:

On each page there is a Image Trigger:
The page number is controlled by the last character in the page variable.
example: ‘page 1’ or ‘Viewing page number 1’

Just copy and paste the image trigger to your new pages then change ‘Set page to page #’
e.g. ‘Set page to page 5’ The html table will be given an id of 5 automatically
on the fifth row that does not a ‘.header’ class.

You can edit the HTML table rows and css styles to suit your needs.

Slide Master:

The WebObject html NavMenu is a layer (menu) but it can be placed anywhere.
The menu layer also has a image Trigger and it has a ‘jump to XXX’ for each and every page you add.

Yes. I know, this really sucks – Storyline Development staff (INTERNAL PAGE VARIABLE ANYONE?).
So for now just copy and paste it a gazillion times and change Slide and number to match.

Everything is controlled by the  two JavaScripts triggers on ‘timeline starts’ and ‘timeline ends’ on the Master Slide.

Known problems:
When I refresh the page the ‘Would you like to resume’ does not save our custom variables for the current page.  This may be just be in my JavaScript order. Any JavaScript Master please find and fix.

Update (April 12, 2015): Seems Storyline doesn’t save your custom variable until you change pages. Would be better if they were saved at (both) timeline start and timeline end.

From Articulate Storyline Forum about this:

I am giving this away for free so please post any new version that make this a better solution.  This is Beta version 1.0 – so use at own risk. I have not tested this on LMS to see if resumeStates is stored on LMS.

Update (April 12, 2015); tested on cloud.scorm will Flash cookies turn off on LMS. Worked as expected except for saving the current pages variable as mentioned above.

Hopefully, someone out there will improve this; as a custom navigation menu is sorrily needed in Storyline!

JavaScript testing:
When will Storyline staff fix the Web Object not updating when re-publishing !!!!!
In the meantime, I open the user.js (page triggers) and story_content\WebObjects\XXXX\NavMenu.html in notepad++
for fast editing and testing without re-publishing (just refresh the browser page after edits).
If I make changes, then re-publish, notepad++ will tell you the content has changed.
DO NOT RELOAD ! – click ‘No’ add a space to you edited page and save it or your lost your work to an old copy (the one that was inserted as the webObject). EVEN IF YOU ARE EDITING THE ORIGINAL HTML PAGE for the webobject folder you selected.

This broken webObject feature has been mentioned for over 2 yers on Storylines Forum. The only way to fix this manual is to delete the webObject and start all over again.

PLEASE FIX THIS STORYLINE so I can edit my HTML page from the selected folder of webObject!!!

Page reloads: Since storyline reloads the webObject every time you change pages,
the ‘timeline start’ has a delay so the javascript can load.

setTimeout(function (){visited();}, 200);

function visited() {
player = GetPlayer();
var pagenum = player.GetVar(‘page’).slice(-3).replace(/\D/g,”); //good for 999
if (pagenum && ~~Number(pagenum) > 0 ) { getResumeStates(pagenum,’1′); }

Timeout may not be the best solution. Better solutions anyone?

window.frames[0] and the navMenu.html file name:

It was pointed out to me that frames[0] will break if more than one web object is on page.

Change the following  global.js:

if(window.frames.length > 0) {
if ( typeof window.frames[0].addTableElements == 'function' ) { window.frames[0].addTableElements(resumeStates); }

to the code below (I’ll leave this up to you) as NavMenu.html would also fail if you renames the table page. More variable, more variables…

for (var i = 0; i < window.frames.length; i++) {
if ((window.frames[i].location).toString().indexOf("NavMenu.html") > 0 ) {
window.frames[i].addTableElements(resumeStates); break;
} //end loop through frames collections

In the NavMenu.html these is a windows resize function I got off the internet to resize the font in the web object table. If using IE9 or above or any other browser you can remove this function and simple add change vw font-size in the style section:

#menuTable {
font-family: Arial, Helvetica, sans-serif;
width: 300px;
 font-size: 4.33vw;
color: white;

The CSS3 vw and vh scales elements to 1/100 units of width or height.

e.g. My body font-size is 13px and #menuTable is 300px wide so .130 x 300 = 4.33 vw

This scales the font smaller when you make the browser window smaller and retains the size if you refreshed or reloaded; to which the window resize function could not.

P.S. In a perfect world.

The HTML navigation would be outside the Flash storyline player.
That is, it would be the parent DIV of the storyline FLASH pageDIV.
You would be able to just build your own CSS3 navigation and seekbar, volume, etc.
and storyline would not over write your index page when publishing.
And you could add simple links like ‘GotoPage 19’.
Storyline staff, give up on FLASH what’s the point when you have a canvas version?

How to improve: rewrite code to wrap it around Storyline’s Flash Div as mentioned above. Better still, put Story.html in iframe and have NavMenu as parent, totally high-jack Storyline.html page load so it works for any publishing setting then…  Oh, forget it. Back to the drawing board.


Storyline 1 files:


Posted in Storyline | Tagged , | 1 Comment

Jquery Timeline range control (like Flash, Storyline, Recording Software)

myRangeSlider Jquery Plugin
A horizontally or vertically Timeline Range Slider.


These type of range sliders can be found in timeline animation programs like Flash and Storyline. Range Slider are also used extensively in audio recording programs to display audio wave form ranges on music tracks and as normal mixing sliders.

The jquery plugin code is as minimal as I could get it.
You will need to add your own functions and routines.

Why? I was building an HTML animation timeline that looked and performed exactly like the one found in the Adobe Flash editor. I was used nouiSlider as my control but found it extremely difficult to perform simple tasks like change the handle’s color on mousedown event. The next range slider I used was JQslider which I also abandoned because it used jQuery UI (I prefer to be in total control of my code).

Code break down (Top Section):

;(function($) { $.fn.myRangeSlider = function(options) {
var defaults = { HORIZ:true, BtnWH:20,LowerRange:'',UpperRange:'' }
var option = $.extend(defaults, options);
var Slider = this, handle = Slider.children(0); //jQuery objects.
var _mouseDownLT, _mouseDownXY, _lastMouseDownXY, xy, MouseXY;
var Hclass, origX, origY, origW, origH, origL, origT;
var a,b, constraint, drag, maxL, maxH, maxR, maxB, rs, mouseX, mouseY, formula;
var edge, _mouseDown = false, hasTouch = false, tip, Btn, dragHandle = false;
if (option.HORIZ==true) { edge='left'; } else { edge='top'; }

The Top Section basically just sets all the variables as local so it can run miniumally as a multi-instance plugin:
Add you own Plug init (this one does not conform to Jquery Plugin design best practises).

Next Section:

////////////// Build the drag Handles //////////////////
edge==='left' ? ( a='edgeL', b='edgeR') : ( a='edgeT', b='edgeB');
handle.prepend("<div class='"+a+"'></div><div class='"+b+"'></div>");
////////////// drag Handle routines //////////////////
$('.edgeL, .edgeR, .edgeT, .edgeB', this).on('mousedown', function(e){
dragHandle = true; Hclass = $(this).attr('class'); Btn = option.BtnWH;
origX = e.pageX-$(this).offset().left; origW = handle.outerWidth(); origL = handle.position().left
origY = e.pageY-$(this).offset().top; origH = handle.outerHeight(); origT = handle.position().top

$('.edgeL, .edgeR, .edgeT, .edgeB', this).on('mouseup', function(e){ dragHandle = false; });

Everything is built in the HTML and sized in CSS file except the drag handles on the sliders Btn (drag edges).

Code to init on HTML page:

$(document).ready(function () {
  HORIZ: true,
  BtnWH: 60,
  LowerRange: '#LowerH',
  UpperRange: '#UpperH' });

    <div id="Slider1">
      <div class="Hhandle">H</div>
<div id="LowerH">0</div><div id="UpperH">0</div>

1. Place a DIV on page and give it an ID “e.g. Slider1”.
2. Add a second DIV with the class “Hhandle” (horitontal) or “Vhandle” (vertical)

Rounded.css controls all positioning and styles.
Clean.css is the same without the fancy look.

The $().myRangeSlider parameters:

HORIZ: true (default) the slide is horizontal in design, false for vertical

BtnWH: number (20 default) the minimum width the drag handle (button) can be sized to. Going lower than 20 will have the button edges overlap or disappear.

LowerRange: string (“” default) name of a DIV that will receive lower range value as jquery HTML().

UpperRange: string (“” default) name of a DIV that will receive upper range value as jquery HTML().

Take Note: All dragging and sliding of the handle is executed in the
var Drag = function(e,MouseXY) { code… }
Everything after the Drag function code is just mouse events for desktop and touch events.
You should not have to change anything after the Drag function().

The clamp function does most of the range constraints.
Feed it a number and it return a number that does not exceed the min or max values:

var clamp = function(num, min, max) { return num < min ? min : (num > max ? max : num); };

Clamp uses a shorthand ‘if statement’ (ternary operator) where ?=Then and :=Else.

I also use a similar clamp using JavaScript Math:
constraint = Math.max(lower value, Math.min(Math.min(some value), upper value)));

The CSS.
It is very important to look at the ‘!important’ flags in the css file.
MyRangeFinder is pixel perfect. However, bugs in different versions of jQuery plus lots of bugs in browsers  make it almost impossible to get the exact width or height of elements that have borders, padding and/or margins.

If you exceed the clamp values by only a pixel (e.g. adding a border) then strange effects are produced.  Exceeding the right edge by just a pixel will have the handle move in unexpected ways. I played with changing width() to InnerWisth, OuterWidth(), Position(), offset(). I gave up, so best not to add borders and such. Use insert box shadows to fake borders or use before:after css.

Tip: Just need it to be just a slider?  add  display: none to *[class^=’edge’] in the css.

UPDATE (April 7, 2015): Just noticed that jQuery width() and position() are extremely slow in IE 11.

A Google search netted replies to use native JavaScript style.width and style.height:
I will update the Zip files in May with any other suggestions or fixes. In the mean time, you should change where appropriate, as in the following example:

  if (option.HORIZ==true) {
    if (option.LowerRange > '') { $(option.LowerRange).html(parseInt(handle[0].style.left)); }
    if (option.UpperRange > '') { $(option.UpperRange).html(parseInt(handle[0].style.left) + parseInt(handle[0].style.width)); }
  } else {
    if (option.LowerRange > '') { $(option.LowerRange).html(parseInt(handle[0]; }
    if (option.UpperRange > '') { $(option.UpperRange).html(parseInt(handle[0] + parseInt(handle[0].style.height)); }

Sorry in advance if I do not answer any posts or emails. I am either extremely busy or extremely lazy on days.

View Demo:

Zip file with code:

Thank you.

Posted in html5, jQuery mouseSwipe | Tagged , , , , , , | Leave a comment

So you want Parallax Scrolling on iOS iPad, iPhone and iPod

parallaxparallaxSwipe for all touch and web browsers including iOS touch screens.
This week I looked at a jQuery parallax plugin by Jonathan Nicol at f6design. So, I grapped it and then spent hours designing a page to use for an iPad project for a car manufacturer. It worked OK in my browsers and my Android touch pad but not at all on my Apple iPod.

I then Googled the problem and got a link to a forum on css-tricks that explained Apples problems. Next, I saw a link on the forum to a Nike page that said the Nike jumpman23 parallax page actually worked on his iPad. See jumpman23 (really nice effect).

Well, you guessed it: I looked at the Nike source code and saw a billion js files. So, rather then sift through them, I though: ‘Hey, my mouseSwipe plugin (bottom of page) could do it by adding top layers and looping though them setting different speeds per layer.’

My mouseSwipe plugin does not use browser scroll functions, just math to position its swipe page. I then removed the panel swipe code and other features to leave just the swiping code I wrote for the plugin. Next, I only added three lines of code using the jQuery each() and an array to hold the speed of each parallax layers. My CSS file took care of the positioning.

Here’s the Demo: I used the images and layout from f6Design but shrunk them and re-arranged the layout to explain the code better.

And here’s the code in a zip file.

Have fun!
Apple can send me a donation, as I’m still looking for work.

Posted in jQuery mouseSwipe | Tagged , , , , | Leave a comment

jQuery selectSwipe Select option Scroller

selectSwipeHere’s an ipad/android style menu option select scroller that should work on all browsers and touch pads.

(except ie6 and ie7 due to css incompatibility! e.g. position: absolute, fixed and pointer-events: none; for overlaying glass image)

It might not look to impressive at first look. However it was the first swipe code on the internet that worked on both touch and desktop browsers (In under 100 lines and not using css3 web-kit). I’m sure others will copy the routines to drop about a 1000 lines off their poorly coded crap.

I’ve included the selectSwipe.js file uncompressed at 5kb (should be under 1kb when minimized). I didn’t included the auto Horizontal css code and removed the physics code used in mouseSwipe as apposed to using jQuery animate use in this demo).

My javascript file should give all the jQuery answers to how to adjust swipe panels. I’m posting this in a hope that jQuery plug-in designers will finish this prototype off and post additional updates and other swipe controls to me.

I’ve done most of the browser compatibility code and mouse vs touch events. I do not have the time to answer questions on this code so please take some of your time to understand the under-laying code (it’s really small to begin with).

I wrote this in about a day, using some code from my mouseSwipe plug-in. So lots of inprovemnets and changes can be added or shared here.

I used extra blank panels at the front and end as padding to center the dates. However, there has got to be a better way to do this. Best to work this out in order to get a panel number and the innerHTML dates during the update() function. I’m still looking for full-time work so I have no time at present. Cheers!

Demo of selectSwipe here

Download Zip file of selectSwipe.

Posted in jQuery mouseSwipe | Tagged , , , , , , , | 1 Comment