Hype Global Behavior (Custom Behavior Extension)

This idea got triggered back in the day :face_with_monocle: when trying to explain Custom Behavior as Tweets. The idea stuck with me …

Mostly I use Hype these days for Widgets in CMS-Projects, hence I thought I share the concept of a unified communication pipeline across individual widget. So, I recreated LocalConnection from the Flash-days with a little Twitter-twist and named it GlobalBehavior:

Hint: The code is an extension. It enables all Hype-Widget loaded on the same page to form a broadcast network. Inside the widget are just plain Custom Behavior calls following the rules mentioned in the example. The code from the JS-files below can also just be pasted into the Head-HTML.

Explanation:
You can find more info in this reply with flowcharts

Demonstration:
https://playground.maxziebell.de/Hype/GlobalBehavior/


Documentation

There is a JSDoc based documentation of the functions at

Code repository on GitHub

Version-History:
1.0 Initial release #-syntax, @-syntax based on Hype Observer Pattern
1.1 Added callbacks in JS hypedocument.onGlobalBehavior
1.2 Added iFrame (onedirectional), onedirectional postMessage
1.3 Refactored code to Revealing Module Pattern, compiled against Closure-compiler, Bidirectional postMessage (Bubble Up, Bubble Down, Bubble Branching)
1.4 Refactored to new naming and interface, corrected to american english
1.5 Fixed a bug with iFrame propagation and added a “Singleton” check
1.6 Added Custom Behavior Ticker feature, code cleanup
1.7 Removed a bug when triggering a Hype widget in a iFrame that was not present on the same page level

Content Delivery Network (CDN)

Latest version can be linked into your project using the following in the head section of your project:

<script src="https://cdn.jsdelivr.net/gh/worldoptimizer/HypeGlobalBehavior/HypeGlobalBehavior.min.js"></script>

Optionally you can also link a SRI version or specific releases.
Read more about that on the JsDelivr (CDN) page for this extension at https://www.jsdelivr.com/package/gh/worldoptimizer/HypeGlobalBehavior

Learn how to use the latest extension version and how to combine extensions into one file at

7 Likes

↑ look at project

/* code and version notes moved to file as it's easier to maintain */

Work in progress on / note to self:

  • Trigger from anywhere outside the broadcast network (body etc.) done
  • Listener as pure JS inside the widget or in Head-HTML extension (onLocalConnection) done
  • Trigger multiple targets done done
  • Tdb.: Evaluation of passing arguments around (URL-encode, Json) Update: can be done with command pipeline, Todo: needs some tweaking of command pipeline (hence checking if HypeGlobalBehavior is loaded and split at @symbol)
  • Tdb.: Sending multiple commands in one go (cmd1|cmd2@widget) Hint: Not going todo this… because I don’t want to compromise possible alternative use cases of the commands by introducing reserved symbols in the command section. The @ symbol is currently the only reserved delimiter
  • Example: Allow user to send command via textbox
  • Example: combination with startBehaviourTicker

Ideas along Widget (or Blocks) - Network / Sidenotes (tbd.)

  • Allow block to go mute
  • Evaluation of shared state storage (Update: Rather separate solution!)
  • Evaluation of persistent state store (Update: Rather separate solution!)
  • Issue commands to LocalConnection exclusively
    –> Mute, Groupsets, State
  • getHypeInstances
  • getHypeDocumentnames
  • These last two ideas will be probably be scrapped for a HypeGlobalBehavior.getListenersForBehavior … still thinking about it. It would be a command that returns all possible listeners. Much like a u-boat radar ping. Would need to send a special ping behavior and the instances would ping back.

@MaxZieb

Thank You - what a useful (in progress) tool to offer!

It occurred to me as I was going through things that it might be valuable to post the (3) HTML Widget’s in your demo (as Hype projects) so those that like to “learn by doing” would have a complete reference to work with based on your previous posts.

@JimScott For now I won’t release my Hype-file as it has my special quirks and might be more confusing then helpful (I am using a single file and extended exporter). The whole point of Hype LocalConnection is that apart of the extension (Head-HTML) and the command-structure it is independent of any given Hype-file or way you export them. That said I will release some examples based on single Hype-file per Widget in the future.

2 Likes

↑ look at project
Updated to version 1.1

Very cool!

  • There was recent question about triggering a custom behavior on a specific symbol. I haven’t thought too much about ways to do this, but at the very lease the triggering @ syntax is an interesting development.
  • Have you thought about the backbone being postMessage? In this way you could send to Hype documents in different iframes.
  • The “here” link in localConnectionTest.html is broken.

Thanks.

This solution also doesn't solve the recent question as it is ment to work across instances. The solution, you suggested, to just use hypeDocument.getSymbolInstanceById('id') was the best way to go. I think targeting a single instance with a Custom Behaviour that was setup to trigger others defies the purpose. Then he should have just set up a new Custom Behaviour with only one listener.

LocalConnection on the other hand broadcasts the "hastag" version through the whole Hype-Instance-Network and all it's internal listeners with the benefit that all Hype-Instances on the page are now potentially targeted. So the @ is to limit Hype-Instances without much hassle.

For now the callstack is direct and postMessage introduces the async aspect but why not. I'll probably just send the trigger so that an iFrame could catch it and participate in LocalConnection (but don't think I'll switch over entirely to PostMessage).

Fixed and now I added a link to an online version

(To clarify I was just musing that it was an interesting solution to a similar problem!)

1 Like

↑ look at project
Updated to version 1.2
It now supports iFrames (one directional for now)

1 Like

↑ look at project
Updated to version 1.3
Rewritten against Closure-Compiler and expanded on bubbling

1 Like

↑ look at project

Here are some thoughts I am having for this Extension and others to follow:


Features per Extension

I cleaned up the public interface (upcoming release to only two commands). Less is more and less to maintain and support. Also rather have something that just does the job then offer a million features.


Mountingpoint

I am still thinking about the mounting point. I currently have the part facing HTML in window['LB'] that allows to trigger functions specific to the extension from the page scope. This allows for a very short notation LB.triggerCustomBehaviour('RedAlert') but means if every Extension does this it rather quickly pollutes window. One could collect them in window['Extension']. For this case resulting in window['Extension']['LocalConnection'] producing the command path Extension.LocalConnetion.triggerCustomBehaviour('RedAlert'). My other thought was going into window['HYPE']. The later could mess with Hype itself so I am hesitant given Hype uses the following to init…

    if (window['HYPE'] == null) {
        window['HYPE'] = window['HYPE_584'];
        window['HYPE']['documents'] = {};
    }

… one could easyly break Hype through setting window['HYPE'] to not null to create window['HYPE']['LocalConnection']. On the other hand one could just do the following in Extensions …

    if (window['HYPE'] != null) {
        /*init in here*/
        window['HYPE']['ExtensionName'] = …
    }

That would have the downside that Extensions depend on Hype being loaded first otherwise they break and are not initialized. Also not ideal… but the command path looks neat HYPE.LocalConnection.triggerCustomBehaviour('RedAlert')

Got any thoughts on the matter?

I would strongly discourage against attaching to HYPE globals/variables if possible.

1 Like

↑ look at project
Updated to version 1.4
Refactored to new naming and interface, renamed from Behaviour :uk: to Behavior :us:


After thinking about the naming (thanks@jonathan) and scope I decided that each functional extension has it’s own name space called like the JS-file. Therefor HypeGlobalBehaviour.js can be found at window.HypeGlobalBehaviour

1 Like

↑ look at project
Updated to version 1.5
Fixed a bug with iFrame propagation and added a "Singleton" check

↑ look at project
Updated to version 1.6
* Added Custom Behavior Ticker feature, code cleanup

↑ look at project
No updates to main code but a thread containing an code example with a single Hype file (see below):

i had a first deeper look and have to say this extension is really great stuff!

as you’ve intitiated the whole extension thread -> this really takes hype functionality further

1 Like

Hi @MaxZieb,

It looks great extension.

I am using HYPE wordpress plugin:
Tumult Hype Animations Wordpress Plugin

and I already add your JS into my project, but it does not work me, and the issue is at this post:

And here are my two Hype files(I do not know why I can not upload hype files here):
https://www.dropbox.com/s/wlvit2e1rh9m70o/product1.hype.zip?dl=0
https://www.dropbox.com/s/cbeqypfwla0vdg0/product2.hype.zip?dl=0

It would be great appreciated if you could let me know how to make them work at same time in one page.

By the way, is it possible to add your JS libraries into Hype wordpress plugin and make them work automatically? it would be much helpful and effective if it works in this way.

Have a nice day.

Alex

You have to add the custom behavior script library to your WordPress header. Use a childtheme and functions.php with some actions (https://developer.wordpress.org/themes/basics/including-css-javascript/) or use a plugin that can add to the header (for example https://wordpress.org/plugins/header-and-footer-scripts/).

Another solution you can test is to use iFrames instead of divs in the Hype-WordPress-Plugin. There is a setting on each hype upload. That way your original HTML with the script in the header is used but it will load the library multiple times. But the browser will work it’s magic and fetch it from cache.

I’d personally rather use the first solution but the second option might be easier todo quickly.