Update

Started a new JavaScript project using ParcelJS based on an older project. This meant I installed parcel-bundler which is at version 1.3.1 or some such and upon doing an npm install I got a whole heap of high secuirty alerts, still it worked. Looking at the docs online I found out that there is a new version 2.7.0 and to install that I needed to npm add --saveDev parcel. That aside, I have an index.html and a src/loading-bar.js which loads and attaches some basic onclick functionality to a button on an HTML page.

https://github.com/saramic/100-days-of-code/tree/main/003_smooth_progress_bar

Adding an animated progress bar

I decided to use the first best search result for “loading bar in pure javascript” and it was a good starting point to create an interval which updated the style.width of an element until it reached 100. After some tweaking I got rid of some variables, reading the value from the bar instead and created some elements on the fly to create the actual progress-bar.

Interestingly I had a //@ts-check typescript check at the top of my file. I beieve this makes Typescript type checking run in VSCode and a few red squiggly lines showed up. Not wanting to install Typescript and allthat jazz I looked up how to add annotations with JS comments and it was pretty simple.

An example below of a method signure that takes a param and returns a HTMLDivElement and another of a querySelector that will later have .disable called on the resultent element so it needs to be an HTMLInputElement. The ... | null was interesting in that it made me deal with the chance that the result is a null and in this case I just don’t make a progress bar

//@ts-check

/**
 * @param {HTMLDivElement} progressBarContainer
 * @returns {HTMLDivElement}
 */
const setupProgressBar = (progressBarContainer) => {

...

/** @type {HTMLInputElement | null}  */
const startJobButton = document.querySelector("button[id=start-job]");

That said, as I am using ParcelJS it actually probably would just compile my file if it was a .ts file. I presume this as when I decided to add some scss this just worked (although I did not actually use any scss hmm?)

<link rel="stylesheet" href="style.scss">

Progress so far

In Day 002 I got a clunky progress-bar with sidekiq-status gem that is tied to a job. Now in day 003 I have a smooth animated Javascript progress-bar that just smoothly does it’s own thing. Below the blue line is the polled/clunky reloading progress bar and the green one is the smooth Javascript one (any jitter may be due to the limited animated gif framerate to keep the gif to a reasonable size)

smooth vs clunky progress bar

At some stage the idea will be to make the Javascript bar poll sidekiq-status and result in a smooth bar.

Next Up

I think tomorrow I will diverge onto something that has interested me for a while and that is using the gem ClosureTree/clsure_tree to work with hierarchical tree data structures in ActiveRecord.

we wil see ¯_(ツ)_/¯

Update 003.1

Might be worth mentioning how I generate the animated gif.

  • I first do a screen recording using quickTimePlayer on a mac
  • then using ffmpeg (which I install using brew install ffmpeg)
  • speed up the original .mov
ffmpeg -i progress.mov -filter:v "setpts=0.5*PTS" progress-fast.mov
  • analyze the .mov for colours by creating a palette.png pallet file
ffmpeg -y -t 10 -i palette-fast.mov \
  -vf fps=5,scale=740:-1:flags=lanczos,palettegen \
  palette.png
  • convert the .mov to a .gif using the palette generated
ffmpeg -i palette-fast.mov \
  -i ~/local_documents/palette.png \
  -filter_complex "fps=5,scale=740:-1:flags=lanczos[x];[x][1:v]paletteuse" \
  smooth-vs-clunky-progress-bar.gif

And that’s it. I usually play around with the fps=5 the frames per seconds and scale=740 to try and get it down to ~1Mb, in particular as that seems to be the limit of an animated gif that is displayed automatically in Slack without asking users to download it first.