Pass value to JS function directly in the Timeline Action dialog

Just thinking that would be very convenient in some cases to be able to pass a value directly in the UI:

image

I've made a "quick & dirty" mockup:
image

What do you think? :slight_smile:

1 Like

the above enables that:
timelinevalue_HypePowerPack.hype.zip (13.3 KB)

2 Likes

There is a more powerful version coming but if you want to develop your own Hype Power Pack has all you need for a working starting point! Sneak peak of upcoming Hype Bundles (no downloads yet):


Will release a beta download next week, I am releasing the sneak peak to force myself to release this project as it got a bit held up by recent work related tasks and my drive to have multiple bundles ready for the release. But a public beta will do for now.
1 Like

Wow! This is just amazing :star_struck: Would be nice to have a little guide to understand better how to use these new options: I'm a bit stuck :sweat_smile:

In saw the @h_classen example and in my case should be even more simple because I just need to pass a string value without extra variables:
image

    hypeDocument.functions().color("Orange")

The problem is that in this way I don't pass hypeDocument, element, event which are fundamental to run the script properly!

Here's my script:

function color(hypeDocument, element, event) {
    let color = ???;
     var allSymbolInstances = hypeDocument.getSymbolInstancesByName('Anim');
     for (var i = 0; i < allSymbolInstances.length; i++) {
     	var symbolInstance = allSymbolInstances[i];
     	symbolInstance.startTimelineNamed(color, hypeDocument.kDirectionForward);
     }
}

How to call the color() the function passing the new value but without lose the context? :thinking:

In Hype Power Pack expressions this is the same as hypeDocument so you should be able to call this.functions().color('Orange') hypeDocument.functions().color('Orange') … but beware you are passing in your own variable into the first parameter usually reserved for hypeDocument.

I would just create a init function in your project that runs on scene load and sets something like this:

hypeDocument.color = function(val){
    //doSomething
}

And in expressions you can use it like this:

this.color('red').
hypeDocument.color('red').

But if you only want to call some functions without an export script you can just use:

this doesn't seems to work, I did console.log(this) and returns undefined :thinking:
image
any clue about why this doesn't work?

btw I solved with hypeDocument.color = "Orange" and calling the function after:
image

wow, you made so much stuff :star_struck: but for now I just wanted something simple and integrated in the UI :wink:

Wait! I got it, that was not working properly.

At the beginning of the timeline I inject the function inside hypeDocument which calls the real function using this:
image

function changeColor(hypeDocument, element, event) {
    	hypeDocument.c = function(color) {
    		this.color = color;
    		hypeDocument.functions().color(this);
    	}
}

then I call it N times with the value I want:
image

Yeah :grin:

2 Likes

Okay, so it wasn't this. I actually just recalled it from memory, but I seem to have mapped hypeDocument in there. Nice. Sorry, about putting you on the wrong track.

I remember now, I create a function expression with hypeDocument in the signature ① and pass in hypeDocument ②. As I now recall, all variables you previously defined using the set variable action are also rendered into your context (see ③). They reside in hypeDocument.customData if you ever want to access them outside the actions and in your functions. Your setup still seems a bit more complicated than needed but whatever gets the job done, and we certainly have enough computing cycles these days :wink: ...

2 Likes

Awesome, could you show me how you would have done it?

Also I don't understand how "Run Function by Selector" works! :thinking:

Thanks!

It really depends on what is in your color function and why you are forwarding the call instead of directly using it. Everything that is in your color function could actually be directly in your c function, initMyApp runs on scene load or prepare:

function initMyApp(hypeDocument, element, event) {
    	hypeDocument.c = function(color) {
    		// do whatever your doing in color directly here
    	}
}

Run Function by Selector is pretty straightforward. So, you can define a selector and a function name. It searches for the selector in your scene and runs the Hype function you specified setting the element to each element found. Look at the simple, but effective JavaScript found in the Export Script to see what is going on under the hood.

This is a little guide to use "Run Function by Selector":

  • function = just the name of an Hype function you created, without parentheses
  • selector = a classic "CSS style" selector (you can separate them using a comma)

Some screens about how to use it to control a symbol animation:

image

Hope this can help others! :slight_smile:

For my needs I made a little modification to your script, passing the selector value inside the event:

		hypeDocument.runFunctionBySelector = function (fnc, selector) {
			if (!hypeDocument.functions()[fnc] || !selector) return;
			var sceneElm = document.getElementById(hypeDocument.currentSceneId());
			var elms = sceneElm.querySelectorAll(selector);
			elms.forEach(function(elm){
				hypeDocument.functions()[fnc].call(window, hypeDocument, elm, {type:'runFunctionBySelector',selector:selector});
			});
		}

I believe this change can be useful: in this way I can read the original data inside the function and use it for different purposes :slight_smile:

This is how I use it in my specific case:
image

This gives me all I need (selector, function and value) in one single place :smiley:
I know my case is a bit hackish, but I find it less complicated and cleaner than using "Run Javascript Expression".

1 Like

Hype Power Pack is all about hacking … but I wouldn't approve of this hack as you are invoking a querySelector with your second argument as selectors CAN contain commas to list multiple targets… and that might create unwanted side effects etc. If you are tweaking the exports script, and again that is what it is for, why not just create your own interface!?

On line 127 insert your command name:

{"label" : "Color", "function" : "HypePowerPack.color", "arguments":[{"label":"color", "type": "String"}]},

And in the function definition section add your own function! Around line 46

hypeDocument.color = function (c) {
     // do what you need to do here…
}

The export script rewrites HypePowerPack.color --> hypeDocument.color when processing the generated output. Just if you are wondering how the mapping happens. In Hype Bundles I changed this a bit but it's also much more feature rich.

2 Likes

My hack as nothing to do with the proposal to add selector:selector which might be helpful in other situations. :wink:

Anyway I see your point, that's the best way to do it, of course! :smiley:

1 Like

There is a misunderstanding as it is not a proposal to do selector, selector that is already in there. You can chain multiple selectors just by the ways they are specified anyway:
https://www.w3schools.com/csSref/sel_element_comma.asp

I was just saying your hack is also always looking in the DOM tree for nodes named after the color you are passing in unwittingly as a second selector. Mostly querySelectorAll won't find any, but there could be side effects if it does. In the end it's whatever works specially looking at the goal you want to achieve. It is in no way a criticism I just am sharing thoughts. Por cierto, ¡viví en Formentera durante muchos años! Muchos saludos a España.

1 Like

Here is a suggestion. Not tested:
HypePowerPack.hype-export.py.zip (3,7 KB)

This adds… Run Function by Selector With Argument. It's a mouth full.
You can rename it if you want.

3 Likes

Al momento no estoy en España, la hecho de menos! :wink:

Yeah, this is definitely better! :stuck_out_tongue: It makes some use cases a lot easier, like this one!

image

Btw do you know why Hype API allows to change "background-image" but not "background-color"? :thinking:

A lot of CSS properties are missing, I was wondering why:

  • 'top'
  • 'left'
  • 'width'
  • 'height'
  • 'rotateZ'
  • 'scaleX'
  • 'scaleY'
  • 'opacity'
  • 'z-index'
  • 'background-image'

Of course I can use regular JS but would be nicer to use pure Hype functions.

1 Like

Its all about the compression Hype uses in its generated scripts. There is a Lookup involved see

Offering the values in the API involves a reverse lookup and Tumult wants the runtime to be small. That is my educated "guess". That said, you can actually enable all of them using the Export Scripts and some runtime tweaking. The technique can be seen in a file I once relased called Export Script Playground.

1 Like

I had bern coincidentally playing with something similar to this type of export script, to use as a labelling system and function caller.

I am using the hype functions in my arguments.
Which gives me more latitude.

To do this, I am incidentally using 3 arguments in the extra actions.
Which calls back to a function inserted in the head.

The interesting thing is because I you the hypeDocumentLoad. The first call to this callback is from the document not the export script.

So the 3 arguments are fill d by the, hypeDocument,element,event.

I simply test for event.type and if it is hypeDocumentLoad. I copy the hypeDocument to a window.hype global var and return.

Any other calls coming in from the export script will be continued past this.

This allows for me to then use the hypeDocument.functions()

There is no need to do it this way in this approach. All functions defined in Hype Power Pack or Hype Bundles have full access to hypeDocument. It doesn't need to be in the signature as it is in the scope (event callback) the functions are defined in HypeDocumentLoad (see line 41 ).

Hence, when you define a function in there … hypeDocument is available in the scope. You can just define stuff like this.

hypeDocument.myFunction = function(a){
   //use hypeDocument, element is the scene, event is HypeDocumentLoad
   // additionally for geeks "this" is also hypeDocument (harder to read)
}

One thing I wanted to hack into Extra Functions was the ability to receive the actual element. The regular Hype Actions in the stack do receive the regular function signature as they are treated differently. One minor but useful addition would be to allow functions defined in Extra Functions to receive the 3 regular callbacks appended to the ones already defined by the user if requested. So, I am hesitant because I would have to modify the runtime... possible but a breaking change if somebody wants to use the official CDN apart from that it would be fine as the Runtime is anyway bundled with the export. But I didn't pull the trigger on that idea to have the highest compatibility ...

I am not using Hype Power Pack or Hype Bundles .. :grinning:

My line

window.HYPE_eventListeners.push({"type":"HypeDocumentLoad", "callback": docload_});

As I said gets the hypeDocument, element, event anyway, there is no need to define it in the window.HYPE_eventListeners.. because the arguments are included regardless

In my playing , I have asked for similar access. I am hoping it will happen one day.

1 Like