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

Ability to pass values from XForms to JavaScript #2499

Closed
ebruchez opened this issue Jan 15, 2016 · 10 comments
Closed

Ability to pass values from XForms to JavaScript #2499

ebruchez opened this issue Jan 15, 2016 · 10 comments
Assignees
Milestone

Comments

@ebruchez
Copy link
Collaborator

Rationale

We often want JavaScript code to be able to access a value stored in an instance or calculated in XPath either in read-only or read/write mode.

Current strategies

The current strategy is to insert in the page an <xf:input style="display: none"> or <xf:output style="display: none"> and to then run JavaScript code on xforms-value-changed with <xxf:script> or to get/set the value with ORBEON.xforms.Document.setValue() and `ORBEON.xforms.Document.getValue()``. This has 2 main downsides:

  • The code is verbose for the developer.
  • The markup sent to browser is heavier then it needs to be, due to the markup generated for the hidden <xf:input> or <xf:output>.

We can also use <xf:load resource="javascript:myFunction($my-uri, $my-uid)"/> with AVTs which allows passing dynamic parameters, but:

  • the target/observer/this is not present
  • parameters must be carefully escaped

Use

When the JavaScript code only needs read-only access to a value, it can be pushed to the JavaScript code on an event. Extending the syntax of <xxf:script> to allow parameters is all we need. The event handler could be declared with:

<xxf:script event="xforms-enabled">
    <xxf:param name="uri" value="$my-uri"/>
    <xxf:param name="uid" value="$my-uid"/>
    <xxf:body>
        console.log(uri, uid); // Parameters can be used directly
    </xxf:body>
</xxf:script>

Notes:

  • Parameters are passed by name with <xxf:param>.
  • There is always something strange about mixing text nodes and elements. So we introduce <xxf:body> which must be used if the <xxf:script> contains one or more <xxf:param>.
  • The JavaScript code already receives an event object, on which the target attribute is defined. We keep this event object unchanged.

In the future, instead of inlining the code, code could be declared in a function and referenced with the function attribute:

<xxf:script event="DOMActivate" function="myFunction">
    <xxf:param name="uri" value="$my-uri"/>
    <xxf:param name="uid" value="$my-uid"/>
</xxf:script>

In which case the function will be called as myFunction(event, uri, uid). But this isn't necessary right now, especially considering that in an XBL we often want to call something like YAHOO.xbl.fr.CodeMirror.instance(this).xformsValueChanged(newValue), where newValue is a parameter.

Implementation

Currently, the JavaScript inside <xxf:script> is put inside a function, inside a <script type="text/javascript">:

function xf_212050c1a4a8fe929144e76531276086ce278067(event) {  }

When <xxf:param> are defined, this would add them to the function:

function xf_212050c1a4a8fe929144e76531276086ce278067(event, uri, uid) {  }

Currently, the Ajax response looks like:

<xxf:script
    name="xf_38b9933d79bd631b81cd7007dbbb1170eb648730"
    target-id="xf-4" 
    observer-id="xf-4"/>

When <xxf:param> are defined, it would pass the values for those parameters as:

<xxf:script
        name="xf_38b9933d79bd631b81cd7007dbbb1170eb648730"
        target-id="xf-4" 
        observer-id="xf-4">
    <xxf:param>…</xxf:param>
    <xxf:param>…</xxf:param>
</xxf:script>

NOTE: This is migrated/adapted from a project on our old wiki from 2009.

@ebruchez
Copy link
Collaborator Author

Quick analysis:

  • outputting function xf_212050c1a4a8fe929144e76531276086ce278067(event, uri, uid) is fairly easy
    • collect script parameters statically
  • evaluating and passing parameters is also fairly easy
    • modify XXFormsScriptAction to evaluate the parameters
    • modify addScriptToRun and related

@ebruchez ebruchez added this to the 4.11 milestone Jan 18, 2016
@ebruchez ebruchez self-assigned this Jan 18, 2016
@ebruchez
Copy link
Collaborator Author

  • We also need to update callUserScript() for scripts which run during page initialization.

ebruchez added a commit that referenced this issue Jan 19, 2016
- clarify case classes to describe scripts
- remove hookup of ServerScript as we don't use it
- script parameters
  - output for JavaScript functions
  - evaluate when running xxf:script/xf:action
  - pass to Ajax response
  - pass to callUserScript()
- consistency fixes for XMLReceiverSupport
- remaining tasks for client code
  - handle xxf:param in Ajax response
  - callUserScript() must support extra parameters
@ebruchez
Copy link
Collaborator Author

Remaining tasks for client code:

  • handle xxf:param in Ajax response
  • callUserScript() must support extra parameters

@ebruchez ebruchez assigned avernet and unassigned ebruchez Jan 19, 2016
@ebruchez
Copy link
Collaborator Author

Note that we don't support the function="myFunction" option yet and probably won't in the immediate future.

@ebruchez
Copy link
Collaborator Author

Documented

@ebruchez
Copy link
Collaborator Author

ebruchez commented Feb 8, 2016

Now moved to xf:param and xf:body, so the new way of writing this is:

<xf:action event="xforms-enabled" type="javascript">
    <xf:param name="uri" value="$my-uri"/>
    <xf:param name="uid" value="$my-uid"/>
    <xf:body>
        console.log(uri, uid); // Parameters can be used directly
    </xf:body>
</xf:action>

@nettree
Copy link

nettree commented Mar 24, 2016

I was wondering where the javascript function should be placed in order for navigate(uri = "javascript:myFunction()") to get effect?

@avernet
Copy link
Collaborator

avernet commented Mar 24, 2016

If this is for a form you created with Form Builder, see the Adding your own JavaScript section of the documentation. And of course, just let us know if anything there isn't quite clear.

@nettree
Copy link

nettree commented Mar 28, 2016

That helps a lot, thank you very much. I will follow this section and see if everything works well. But I believe it will.

@avernet
Copy link
Collaborator

avernet commented Mar 28, 2016

@nettree OK, great. I'm glad this was useful.

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

No branches or pull requests

3 participants