Hype Action Events

Extension that easily offers to listen to a multitude of events and execute code based on these events. The declaration is as simple as assigning a key and value in the attributes panel (using data attributes). Furthermore, it offers code execution through the Custom Behavior interface.


Introduction

The extension consists of two parts, being Actions and Events. The action part was born out of the necessity to trigger Hype functions and was in a first alpha used in Hype Gesture (only a simple string parser). Now, Actions have matured to be full JavaScript, adding additional benefits in the process. One of them being, small JavaScript snippets wrapped in a Hype Function, only doing some little thing and not worth a full Function in the resource library. The main action related function to consider is:

HypeActionEvents.triggerAction(code, options)

Code can be an JavaScript statement or just a simple function call. For example:

hypeDocument.triggerAction("startTimelineName('mainTimeline')")
hypeDocument.triggerAction("myFunction()")
hypeDocument.triggerAction("counter=0")

The second parts are events that trigger actions for you, without you having to use hypeDocument.triggerAction. This part is certainly the most prevalent to grow in coming releases, but already supports a bunch of use-cases. You can trigger actions whenever you have access to the custom behavior. This would include the Actions inspector, Scene Inspector, Symbol Inspector and the Timeline Actions.

Hype Action Events allows for any type of variables and offers a :star2:magic rule set: If a variable is not existent in execution context, it will be created on the fly. In the following example, the variable counter didn't exist previously, and will now be created in hypeDocument.customData and any subsequent actions referencing it will modify the value there.


Under the hood, variables are mapped to hypeDocument.customData.The example illustrates creating a counter variable using On Prepare For Display using the Scene Inspector


Going forward, we can now modify the counter as seen in the next screenshot. The variable counter is being incremented and then assigned to innerHTML of an rectangle with the id "display". Furthermore, on every fifth count, startTimelineNamed('bounce') is triggered.



Screenshot using Hype Action Events in the Trigger Custom Behavior interface, in this case it is the Actions Inspector panel.
Example_Code_in_Custom_Behavior.hype.zip (19,7 KB)


One thing that should be interesting to anybody whoever used the Hype API is, that the prefix hypeDocument is missing. To save space, the triggerAction interface offers a "smart" and direct access to the function by creating an execution context. This context depends on and is mostly hypeDocument, but can also be symbolInstance given the location and way hypeDocument.triggerAction is used.

Bound Hype functions

To further reduce complexity and length of code snippets, Hype function found under hypeDocument.functions() can be called using the short form as they are automatically bound to hypeDocument, element and event of the current context. This means hypeDocument.functions().test(hypeDocument, element, event) becomes a simple test() call.

Hype or Symbol API

Always available are all function found in hypeDocument (Hype Document API) or the symbolInstance (Symbol Instance API) depending on the calling context and all functions found under hypeDocument.function() in a bound manner. All the methods there in can be called directly (like startTimelineNamed etc.).

Contextual variables

Even though there is some Proxy magic at work, you can always use explicit contextual variables to be sure what you're accessing.

In the spirit of saving space, these explicit contextual variables are offered in a shorthand form and automatically available in an triggerAction context.

  • $ctx Contains the entire context variables, like hypeDocument
  • $doc Is a reference to the current hypeDocument API
  • $sym Is a reference to the closest symbolInstance API
  • $elm Contains the element currently in question (if available)
  • $evt Contains the event currently in question (if available)

Since v1.0.6

  • hypeDocument Is a reference to the current document API
  • element Contains the element currently in question (if available)
  • event Contains the event currently in question (if available)

Even if the original signature is a little long for attribute notation, it is now supported to allow transferring code back and forth between the code editor and direct notation in data attributes easier

Options when trigger actions

Some cases require you to pass some variables in the options like the element or event when called directly from JavaScript.

hypeDocument.triggerAction (code, {
	element: element,
	event:  event
});

Here is a list of all the current options that can be passed in:

  • element Used for Hype function binding and to find the closest symbolInstance
  • event Used for Hype function binding
  • symbolInstance This can be used to pass in a custom symbolInstance
  • strictMode This boolean can be set to force a strict mode for code execution. Removes the execution context and applies all the restrictions entailed with "use strict;"

Subscribing to events using data attributes

It is possible to subscribe specific DOM events using data attributes. The full list out of the box is:

// mouse events ( MouseEvent ):
mousedown, mouseup, click, dblclick, mouseover, mousewheel, mouseout, contextmenu, mousemove,
			
// Touch events ( TouchEvent ): 
touchstart, touchmove, touchend, touchcancel,
			
// Keyboard events ( KeyboardEvent ): 
keydown, keypress, keyup,
			
// Form events: 
focusin, focusout, change, submit,

new since 1.0.3

// Form events: 
input, beforeinput,

// CSS animations
animationstart, animationiteration, animationend, animationcancel

// CSS transitions
transitionstart, transitionrun, transitionend, transitioncancel,

// Pointer events
pointerdown, pointerup, pointerover, pointerout,
pointermove, pointerenter, pointerleave, pointercancel

Event bubbling visualized for DOM Events

As seen in the chart, events are emitted on the element and bubble down to the base of the Hype document. The event handler there extracts the code from the data attribute and passes it on to triggerAction to be processed.

Subscribing to Matter events using data attributes

Furthermore, you can subscribe elements to Matter events being:

// matter events
collision-start, collision-end, collision-active

Subscribing to Hype events using data attributes

It is possible to subscribe elements to multiple Hype events using data attributes. The list of currently supported Hype events is as follows.
new since 1.0.2

scene-load, scene-unload, scene-prepare, layout-request

new since 1.0.6

behavior

Also, allowing to subscribe to specific behavior: behavior names are lower cased and spaces/tabs are replaced with dash. Hence, a behavior like Hello World --- Test would become hello-world-test and the full action hook would be data-behavior-hello-world-test-action

Subscribing to Window events using data attributes

new since version 1.0.3

// window
window-resize, window-focus, window-blur,

// printing
window-beforeprint, window-afterprint, 

// javascript
window-error, 

// other
window-storage,

// connection
window-online, window-offline,

// history
window-hashchange, window-popstate,

// communication
window-message, 

// input
window-wheel

Subscribing to Document events using data attributes

new since version 1.0.3

// tabs
document-visibilitychange, document-scroll,

// fullscreen
document-fullscreenchange,

Event handling on global document and window events

As seen in this chart, global events are captured on the Hype scene base and the appropriate event handler searches for elements in the scene subscribing to the particular event and forwards the code to triggerAction to be processed.

Subscribing to Mutation Observer events using data attributes

new since version 1.0.3

// mutation action
data-mutation-action

// optional modifier
data-mutation-child-list, data-mutation-attributes, data-mutation-character-data, data-mutation-subtree, data-mutation-attribute-filter

// optional modifier to user other target then current element
data-mutation-target

Subscribing to Intersection Observer events using data attributes

new since version 1.0.3

// intersection action
data-intersection-action

// optional modifier
data-intersection-root, data-intersection-margin, data-intersection-threshold

// optional modifier to user other target then current element
data-intersection-target

Subscribing to Resize Observer events using data attributes

new since version 1.0.3

// resize action
data-resize-action

// optional modifier to user other target then current element
data-resize-target

Subscribing to Animation Frame events using data attributes

new since version 1.0.3

// animation frame action
data-animation-frame-action

Subscribe to a supported event using a data attribute

To subscribe, add a data attribute to an element as follows: data-EVENT-action.
For example, to subscribe and element to a click event, you would add an attribute called data-click-action and set the value to some code like alert("You clicked me!");.
Example_Trigger_Action_with_Data_Attribute.hype.zip (35,8 KB)

I intentionally also chose click to illustrate the difference of these DOM events versus using built in Actions under the Actions Inspector. There is not a full parity, but some overlap. Hype Action Events are bound to a bubbled event and don't include fallback logic like interpreting a click as a touch given the device type. Subscribing through the data attribute is in these cases very explicit and intentional. In other cases, Hype Action Events offers events not easily available and manages the listeners. This is only scratching the surface … more documentation coming soon :nerd_face:

Error handling in Hype Action Events

Errors are trapped in a try/catch block and in production fail silently. When previewing your code in the browser directly from Tumult Hype you get information about errors directly in the console:


For example, In this case a user has probably misspelled a function name!

This is the information you are being shown:

  1. You can see the version number of Hype Action Events you're using (good for requesting help)
  2. You are shown the code fragment that is causing the error
  3. You get the error that is caused by the fragment. In case of functions calls, the error might be emanating from withing the function
  4. The element this fragment is attached to is listed (if possible) hovering over it will reveal it in the browser window (if currently visible)

If you need the error information after you have exported your Hype project or need to debug on a production system, you can always force errors to be shown by setting:

HypeActionsEvents.setDefault('debug', true);

Hope this helps!

Release on GitHub:

10 Likes

↑ look at project
1.0.1 Proxy is default (LegacyMode available), firing HypeActionEvents on HypeDocumentLoad and refactored variables


This release marks a move to a Proxy approach. Meaning, it drops support for IE as that interface is not supported on that Legacy Browser. If you really need to support IE you can still enable use:

HypeActionEvents.setDefault('LegacyMode', true);

If this mode is enabled, all variables that are not called contextually are generated in the window scope. For single Hype applications, that shouldn't be a problem and furthermore can be avoided by adding a context variable (customData.myVariable instead of myVariable. See above regarding context variables.

1 Like

↑ look at project
1.0.2 Prioritize user functions over functions in hypeDocument, added events on data-scene-load-action, data-scene-unload-action, data-scene-prepare-action and data-layout-request-action


Added more documentation and another example file

2 Likes

I think it will be very useful. Thank you

1 Like

↑ look at project
1.0.3 Added event functions for ResizeObserver, IntersectionObserver and MutationObserver, changed to passive DOM events, added requestAnimationFrame events, added window and document events


There was a slight regression on the contextual variables since the introduction of the proxy approach in version 1.0.2 ($evt, $sym, $doc, $ctx and $elm where not property resolved), but this has been fixed as well. More examples and documentation soon.

Additional note: the custom behavior context is fired in an agnostic context, so it doesn’t contain an element (and $elm) and the event is a custom behavior context. That is duo to the way Hype handles this internally. The triggerAction interface exposure through custom behavior is at this point an added bonus, with said minor inconveniences like not being aware where it was fired. If you require that context to be populated, just use the data-EVENT-action on an element.

1 Like

Example using the document scroll event

data-document-scroll-action


Here is a simple sticky effect, for demonstration purposes:
Example_Data_Attribute_Document_Scroll.hype.zip (74,8 KB)


Here is a more elaborate approach with more layers:
Example_Data_Attribute_Document_Scroll_Parallax_Forest.hype.zip (1,5 MB)

Preview:

Artwork by digital moon

9 Likes

this project is stunning :+1:

2 Likes

Interesting talk on events, the main loop and how processing of them has evolved …

2 Likes

3 posts were split to a new topic: Using Hype Action Events for scroll animations

Example using the intersection observer event

data-intersection-action


Here is a simple implementation using intersection detection (also using margins)
Example_Data_Attribute_Intersection_Ghost.hype.zip (102,8 KB)

Artwork created by Luis Zuno


↑ look at project
1.0.4 Added the event.symbolInstance to Hype function calls if present

3 Likes

Example using Matter collisions events

data-collision-start-action
data-collision-end-action


Here is a simple demo that continues its fall by being reset

Version with inline code:
Example_Data_Attribute_Matter_Collisions.hype.zip (46,1 KB)

Version using a single Hype function (switch on event.type):
Example_Data_Attribute_Matter_Collisions_Hype_function.hype.zip (46,8 KB)

CleanShot 2022-01-25 at 11.56.26


↑ look at project
1.0.5 Fixed typo that prevented collision events to be detected
Make sure to purge your Browser cache and restart Hype when using examples after I made an GitHub update!

4 Likes

Example using Animation Frame events

data-animation-frame-action


Here is a simple shadow animation driven by the ball element
Example_Data_Attribute_Matter_Animation_Frame.hype.zip (29,3 KB)

4 Likes

↑ look at project
1.0.6 Added hypeDocument, element and event to the triggerAction context, added data-behavior-action


Add your actions on specific element using custom behavior triggers.

data-behavior-action listens to all behavior names
data-behavior-test-action would only listen to the test behavior name*


* behavior names are lower cased and spaces/tabs are replaced with dash. Hence, a behavior like Hello World --- Test would become hello-world-test and the full action hook would be data-behavior-hello-world-test-action

2 Likes

Example using hypeDocument.triggerAction and Symbol Handler


Here is a simple switch button using hypeDocument.triggerAction and also showing how Hype Action Event triggers a function handler named like a symbol if found on HypeSymbolLoad and HypeSymbolUnload (proactive).

Example_Switch_Button_Symbol.hype.zip (47,3 KB)

CleanShot 2022-02-04 at 00.20.33

2 Likes

↑ look at project
1.0.7 Added data-timeline-complete-action, hypeDocument.triggerActionsByAttribute and minor refactoring


1.0.8 Bugfix on data-timeline-complete-action for particular timelines


You can now trigger actions when a timeline completes using data-timeline-complete-action for all timelines or if a specific timeline completes like test it would be data-timeline-complete-test-action

3 Likes

Example of using Hype Drag Gesture


This example uses Hype Action Events, Hype Matter Helper and Hype Drag Gesture to offer drag and drop support with precise drop zones and snapping. Note that this drag'n'drop approach relies on the Matter engine offered by Tumult Hype to determine arbitrary shape intersections. Hence, the export will include the physics engine.

This gesture offers the following events:

data-drag-start-action
data-drag-move-action
data-drag-end-action
data-drop-success-action
data-drop-fail-action
data-intersection-start-action
data-intersection-end-action

And the following selector defining the drop target

data-drop-selector 

This example also uses a snapping mechanism, data-snap-target, but that is specific to this particular example and implemented in the document rather than being part of the gesture.

Example_Hype_Drag_Gesture.hype.zip (177,4 KB)

2 Likes

Another Example using the document scroll event

data-document-scroll-action


With this demo, I am actually not so sure if I do it in such a way in an actual production (hence, the title of experiment). I would probably rather have the entire sticky element be one symbol and use a progress function. In this example file, there is a lot of whitespace just to have room to scroll to drive progress.


The following data attributes can be used to control the behavior of the scroll progress handler:

data-sticky-start: This attribute allows you to set a custom start position for the element's sticky behavior. If this attribute is not set, the element will become sticky when it reaches the top of the page.

data-sticky-end:
This attribute allows you to set a custom end position for the element's sticky behavior. If this attribute is not set, the element will remain sticky until the user scrolls to the bottom of the page.

data-sticky-bounding:
This attribute allows you to set a bounding box for the element's sticky behavior. If this attribute is set, the element will become sticky when it reaches the top of the bounding box, and will remain sticky until the user scrolls to the bottom of the bounding box.


There is a little progress handler action in the example as well (bonus):

data-progress-start:
The top position (in pixels) of the scrollable area.

data-progress-end:
The bottom position (in pixels) of the scrollable area.

data-progress-timeline:
The name of the timeline to be played (defaults to main timeline)


Example_Data_Attribute_Document_Scroll_Experiment.hype.zip (298,8 KB)


Effect was inspired by the page Apple Fitness+ - Apple and the images are from Unsplash

4 Likes

Example of using Hype Slide Gesture

This example is a refactored version of the custom continueAfterDrag functionality. It offers more options and settings than the regular version, built in to Hype.

This gesture offers the following events:

data-timeline-drag-start-action
data-timeline-slide-move-action
data-timeline-slide-end-action
data-timeline-drag-start-action
data-timeline-drag-end-action

The following config options are available

  • minVelocity Set the min velocity. Use only in special cases as it can lead to infinite movement after drag
  • maxVelocity Often a good way to avoid to high values after a drag'n'slide gesture
  • friction defaults to 0.95 and slows down the velocity of the continued drag on each tick. This adds an organic feel to the movement.
  • forceInstance, symbolInstance (can be used to add symbolInstance or hypeDocument, is auto-detected inside of symbols in favor of the symbol)
  • timelineName is the name of the timeline and default to the Main Timeline of either the hypeDocument or the symbolInstance
  • borderMode defaults to none as seen in regular Hype, and the movement just stops at the end or beginning. Using bounce allows bouncing of the end and beginning. In such an event, there is an additional friction applied. Finally, there is the shift mode, and it allows overshoots at the end or beginning. As we are talking about a timeline, this means the timeline restarts in the current play head direction.
  • borderFriction defaults to a factor of 0.1 and is only applied if the borderMode is set to bounce. Setting this to 0.9 allows for much more bouncing.
  • threshold this defaults to 0.01 and is the threshold the velocity must be under to trigger an end for a slide action

Example_Hype_Slide_Gesture.hype.zip (83,2 KB)

CleanShot 2022-02-10 at 15.41.32

1 Like

Example zooming a map and hiding offscreen elements

data-intersection-action
data-scene-prepare-action
data-pointerdown-action



There is a alternative version (only zoom) using a single SVG here

3 Likes

Example to determine offline mode and online connectivity

data-window-online-action
data-window-offline-action