Taming the JS event beast

It was getting old real quick putting up all these local flags in my JS functions to try to control the processing of events when an end-user clicks on various HTML and non-HTML elements in XVG.

After a while, it was becoming impossible to cover all the permutations of completely random clicks that I was using to test the app.

That is the essential problem of JS, a single-threaded yet frustratingly asynchronous language where you have to account for a multitude of events that may be executed in some order that you might not be expecting at all. A quick explanation of this issue can be found here.

As a result, weirdo bugs kept popping up at runtime — such as objects you thought existed suddenly becoming null, or failing to instantiate in time due to some split second delay somewhere.

This is why has all the laborious promises, async and await concepts that really fry your brains all out of proportion for what you may be trying to do in a simple SPA such as XVG.

Finally I’d had enough.

What I needed was a way of creating a JS event architecture that forces user-initiated events to pass through a single directional event funnel — kinda like what FB tried to do with Flux.

If I could somehow distinguish between SVG and HTML events, that might be a good starting off point.  I could then create a delegation-based hierarchy of event listeners in either “execution context” path.

I would of course also have to code a timed-based, semaphore daemon.

Its job would be to ensure that whatever the end user was doing in SVG would not get confused (by XVG) with what was also going with the various HTML buttons and inputs boxes.

For example, a user might create 8 sections in an SVG circle using the Radii button and then click on the Markers button.

This would allow the end-user to draw a precise line between two points, by clicking on Point 1, first, then on Point 2 (ie, the “markers”).

XVG handles this without any problem.

But, what if in the middle of this action, that is to say, before the user clicks on Point 2, the end user also decides to draw a line by dragging the mouse.

Now XVG might be getting confused, because it was expecting the end user to click on point 2, and instead, has to create some new line, without the use of markers.

And we are still in the context of SVG execution.  This problem can be handled with a variety of global flags and other little tricks.  Not pretty, but it works.

Now imagine if the end user decides to also create new markers (which are not to be confused with standard SVG markers), still before clicking on Point 2, by using the Angles input box and clicking on its button to create, say 32 sectors.

Now we are in the context of HTML event execution.

Given this particular end-user action, XVG will now redraw the vectors.

And if the end user now clicks on the Markers button, XVG will create a new set of radius vertices on the main XVG circle.  Still in HTML execution context.

But now the end-user clicks on the new markers.  Yup, back to SVG execution context, which, though distinct, still makes use of the same mouseup, mousedown, mouseover, and click parameters used to keep track of HTML events.

As a result, the internal array that XVG uses to keep track of line drawing blows up and the user can no longer reliably draw lines anywhere on the XVG workspace.

How does one solve this nightmare?

Keeping the event handling separate might help a lot.

If one could block or just delay the end-user from executing event (HTML) before event (SVG) is completed or canceled, well — that might simplify the task considerably.

And if the event listeners responsible for executing drawing functions could somehow be funneled down one of two paths, in a particular order, with highly specific, pseudo procedural expected outcomes, then life might be worth living again.

Sounds great, but wait a minute… is it possible, for starters, to tell the difference between HTML and SVG event types?

Well, yes — and pretty easily, as it turns out.

(See the example code I wrote in the demo Pen above).

It may not seem like much, but I am going to use this simple approach as the basis of my event handling solution.

Maybe I’ll call it Flix.

Lastly, know & remember this.  Events do have timestamps.

Stay tuned!

Note:  I eagerly turned to the chapter on events in the 800-page Using SVG book (written principally by the somewhat unfortunately named Amelia Bellamy-Royds) I just bought (see previous post), but alas found it to be rather skimpy on the subject of events.

The books itself is really comprehensive and well-written, and I shall be studying it in great detail when I attempt to figure out how to use SCG Bezier curves to allow end-users to create curved lines by dragging the mouse.