Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling a user defined javascript function? #12

Closed
lrq3000 opened this issue Apr 6, 2020 · 12 comments
Closed

Calling a user defined javascript function? #12

lrq3000 opened this issue Apr 6, 2020 · 12 comments

Comments

@lrq3000
Copy link

lrq3000 commented Apr 6, 2020

Is it possible to make an ink-component such as ink-range callback a user-defined javascript function?

I tried to do something like this but this doesn't work:

<ink-range :value="x" bind="{x: value, display_alert()}"></ink-range>
@lrq3000
Copy link
Author

lrq3000 commented Apr 6, 2020

In fact I just found that it's possible to do this:

<ink-range :value="x" bind="{x: value | alert('lala')}"></ink-range>

Is that the correct way?

@lrq3000
Copy link
Author

lrq3000 commented Apr 6, 2020

Ok so the above works for a native javascript function, but not for user-defined functions.

Here is what I tried and which does not work:

<script src="https://unpkg.com/ink-components"></script>
<script type="text/javascript">
function show_msg2() {
	alert('Working!');
}
</script>
<ink-var name="x" value="2"></ink-var>
X: <ink-range :value="x" bind="{x: value | show_msg2()}"></ink-range>, which is <ink-display name="x">2.0</ink-display>
<button type="button" onclick="show_msg2()">Alert test</button>

https://jsbin.com/cagogafada/1/edit?html,output

The button works, but not the slider. The error I get in the console is the following:

Uncaught ReferenceError: show_msg2 is not defined
    at eval (eval at xe (ink.min.js:637), <anonymous>:3:25)
    at HTMLElement.dispatch (ink.min.js:671)
    at HTMLElement._changeHandler (ink.min.js:671)
    at x.handleEvent (ink.min.js:403)
    at HTMLInputElement._boundHandleEvent (ink.min.js:403)

@lrq3000
Copy link
Author

lrq3000 commented Apr 6, 2020

This may be pertinent to this issue: http://perfectionkills.com/global-eval-what-are-the-options/

@lrq3000
Copy link
Author

lrq3000 commented Apr 6, 2020

Found a way by combining with the answer provided in #10 , it seems there is no way to bind to a callable (and pass the value), so the only way is add an onclick event calling a function and from the function fetch the variable's value from the document DOM:

<script src="https://unpkg.com/ink-components"></script>
<script type="text/javascript">
function show_msg() {
    x = document.getElementsByName("x")[0];
    // Alternative to get ink-var values, but it's more prone to error since it's not based on the variable's name
    //x = document.getElementsByTagName("ink-var")[0];
    alert("Working! x="+x.value);
}
</script>
<ink-var name="x" value="2"></ink-var>
X: <ink-range :value="x" bind="{x: value}" onclick=show_msg()></ink-range>, which is <ink-display name="x">2.0</ink-display>
<button type="button" onclick="show_msg()">Alert test</button>

https://jsbin.com/hoxuxibinu/edit?html,output

If there is a better way of doing this, I would be very interested in hearing it @rowanc1 :-) I think the ability to callback user-defined function would add a lot of flexibility to ink-components.

@lrq3000
Copy link
Author

lrq3000 commented Apr 6, 2020

(Also adding such an example in the documentation would be very helpful! :D)

@rowanc1
Copy link
Member

rowanc1 commented Apr 6, 2020

I am working on updating things at the moment on the v1 branch. Hoping to have something testable in the next few days, and would love your input on it!

Right now this works (on the v1 branch):
image

I think that if you also wanted to update the value of x, you could do it in the handler (there is going to be a global ink variable) or return {x: value} from the handler.

@rowanc1
Copy link
Member

rowanc1 commented Apr 6, 2020

Another comment on the current version, the eval is actually inside an iframe that is defined for your scope. I was trying to ensure that the user-defined functions could execute securely. In the next iteration, I am taking that out by default as in most use cases it makes more sense for the evaluation to happen in the main window and the developer is in control of the page (i.e. no user-generated content). When it is necessary to strip out the evaluation, that can be done through the upgrades I am making.

@rowanc1 rowanc1 mentioned this issue Apr 6, 2020
17 tasks
@lrq3000
Copy link
Author

lrq3000 commented Apr 7, 2020

@rowanc1 That is AWESOME!!! I wholeheartedly agree with the change of bind to change, it's much less confusing like this (and allows for other kinds of events).

Anyway the example in #10 and that I used here for inspiration is I think still useful in case when we need to use multiple variables to update a function, eg for a graph.

Let's say I have 2 variables x and y, can the onchange of one widget provide the value of both? Eg:

<script src="https://unpkg.com/ink-components"></script>
<script type="text/javascript">
function show_msg(x,y) {
    alert("Working! x="+x.value+" y="+y);
}
</script>
<ink-var name="x" value="2"></ink-var>
<ink-var name="y" value="10"></ink-var>
X: <ink-range :value="x" :change="show_msg(x,y)"></ink-range>, which is <ink-display name="x">2.0</ink-display>
Y: <ink-range :value="y" :change="show_msg(x,y)"></ink-range>, which is <ink-display name="y">10.0</ink-display>

Would this work, or then we need to fallback to the solution in #10 by fetching manually the variables from the DOM? /EDIT: or as you write in #13, through the exposed ink js object (which would be much cleaner indeed :-) )?

Please note I don't mind if it's not possible or it's too complex to implement, I'm fine with the exposed ink js object or even with the DOM access, as long as it's an expected usage case and I don't run into unexpected issues, I think it's simple enough :-)

@rowanc1
Copy link
Member

rowanc1 commented Apr 7, 2020

Huh, yeah, that seems to work too, nice when that happens! The :change has access to anything globally as well as anything in that scope.

image

I will also add some helper functions on ink to allow you to access these in javascript as well. ink.get('x') or something.

For the ink-chart-drag, the event will override x and y in the local namespace in a similar way to the change handler overriding value (even if you have a variable named that). This is actually creating a function like:

var x = 2; // your variables (or other ink-vars)
function change(x, y){ return logToConsole(x, y); } // the change handler has it's own x

@lrq3000
Copy link
Author

lrq3000 commented Apr 8, 2020

That is just PERFECT! :D I can imagine so many things we can do with this simple scheme, awesome, very exciting!!!

@rowanc1
Copy link
Member

rowanc1 commented Apr 9, 2020

@stevejpurves just ran into this as well. The running PR in #13 is fixing things up and I will add to the docs as well. :)

image

@rowanc1
Copy link
Member

rowanc1 commented Apr 29, 2020

Now possible and documented!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants