jsf-extensions
  1. jsf-extensions
  2. JSF_EXTENSIONS-90

Ensure scripts in replacement markup are evaluated prior to postReplace, when appropriate

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: current
    • Fix Version/s: not determined
    • Component/s: runtime
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

    • Issuezilla Id:
      90

      Description

      if you set the postreplace attribute of an Ajax transaction, the function
      receives incorrect call parameters:

      <?xml version="1.0" encoding="UTF-8"?>
      <!--
      Document : Page1
      Created on : 26-mar-2008, 15.56.38
      Author : mauro
      -->
      <jsp:root version="2.1" xmlns:df="http://java.sun.com/jsf/dynamicfaces"
      xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
      xmlns:jsp="http://java.sun.com/JSP/Page"
      xmlns:webuijsf="http://www.sun.com/webui/webuijsf">
      <jsp:directive.page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"/>
      <f:view>
      <webuijsf:page binding="#

      {Page1.page1}

      " id="page1">
      <webuijsf:html binding="#

      {Page1.html1}

      " id="html1">
      <webuijsf:head id="head1">
      <webuijsf:link binding="#

      {Page1.link1}

      " id="link1"
      url="/resources/stylesheet.css"/>
      <df:ajaxTransaction binding="#

      {Page1.tx1}

      " id="tx1"
      inputs="page1:html1:body1:form1:button1" postReplace="pr"
      render="page1:html1:body1:form1:staticText1"/>
      <webuijsf:script id="script1">
      function pr(a,b,c)

      { alert(a + " " + b + " " + c); }

      </webuijsf:script>
      </webuijsf:head>
      <webuijsf:body id="body1" style="-rave-layout: grid">
      <webuijsf:form id="form1">
      <webuijsf:staticText binding="#

      {Page1.staticText1}

      "
      id="staticText1" style="position: absolute; left: 444px; top: 108px"
      text="provaaaaaaaaa"/>
      <webuijsf:button
      actionExpression="#

      {Page1.button1_action}

      " id="button1"
      onClick="DynaFaces.Tx.fire('tx1');return false;"
      style="height: 36px; left: 72px; top: 108px;
      position: absolute; width: 107px" text="Button"/>
      </webuijsf:form>
      </webuijsf:body>
      </webuijsf:html>
      </webuijsf:page>
      </f:view>
      </jsp:root>

      whatever the button action handler does, the javascript function named pr()
      receives the 1st and 3rd parameters as null or undefined, making it impossible
      to use it

        Activity

        Hide
        rogerk added a comment -

        Taking ownership

        Show
        rogerk added a comment - Taking ownership
        Hide
        rogerk added a comment -

        I'm not familiar with how thw Woodstock components encapsulate the underlying
        Dynamic Faces javascript apis and..
        I haven't used the postReplace function myself but the documentation states:

        postReplace

        The name of a globally scoped function that conforms to the following signature.

        function postReplace(ajaxZone, innerHTML, [closure], [xjson]);

        This function is called after the markup replacement for each component that
        needs to be re-rendered with data from this ajax response. The optional argument
        closure is whatever was passed as the closure option to the
        DynaFaces.fireAjaxTransaction or DynaFaces.installDeferredAjaxTransaction that
        initiated the ajax request for this response. The optional argument xjson is
        whatever was passed as the xjson option to the DynaFaces.fireAjaxTransaction or
        DynaFaces.installDeferredAjaxTransaction that initiated the ajax request for
        this response. The xjson agrument is passed to the server and may have been
        modified by the server.
        ----------------------------

        An example usage of this in dynamic faces is the jmaki integration.
        Take a look under:
        jsf-extensions/trunk/code/run-time/samples/jmaki/src/main/webapp
        Take a look at:
        mainColumn.jsp
        devtime.js

        devtime.js has a postReplace function:

        function postReplace(ajaxZone, innerHTML) {
        var isJmaki;
        if ((isJmaki = (-1 != ajaxZone.id.indexOf("form:table"))))

        { jmaki.clearWidgets(); }

        innerHTML.evalScripts();
        if (isJmaki)

        { window.onload(); }

        }

        Seems like the args to your function should be "ajaxZone" and "innerHTML"

        Show
        rogerk added a comment - I'm not familiar with how thw Woodstock components encapsulate the underlying Dynamic Faces javascript apis and.. I haven't used the postReplace function myself but the documentation states: postReplace The name of a globally scoped function that conforms to the following signature. function postReplace(ajaxZone, innerHTML, [closure] , [xjson] ); This function is called after the markup replacement for each component that needs to be re-rendered with data from this ajax response. The optional argument closure is whatever was passed as the closure option to the DynaFaces.fireAjaxTransaction or DynaFaces.installDeferredAjaxTransaction that initiated the ajax request for this response. The optional argument xjson is whatever was passed as the xjson option to the DynaFaces.fireAjaxTransaction or DynaFaces.installDeferredAjaxTransaction that initiated the ajax request for this response. The xjson agrument is passed to the server and may have been modified by the server. ---------------------------- An example usage of this in dynamic faces is the jmaki integration. Take a look under: jsf-extensions/trunk/code/run-time/samples/jmaki/src/main/webapp Take a look at: mainColumn.jsp devtime.js devtime.js has a postReplace function: function postReplace(ajaxZone, innerHTML) { var isJmaki; if ((isJmaki = (-1 != ajaxZone.id.indexOf("form:table")))) { jmaki.clearWidgets(); } innerHTML.evalScripts(); if (isJmaki) { window.onload(); } } Seems like the args to your function should be "ajaxZone" and "innerHTML"
        Hide
        autozoom added a comment -

        I read the documentation and it's pretty clear how it's supposed to work, but
        it's not working with woodstock components, and woodstock team points me to JSF
        extension website

        Show
        autozoom added a comment - I read the documentation and it's pretty clear how it's supposed to work, but it's not working with woodstock components, and woodstock team points me to JSF extension website
        Hide
        rogerk added a comment -

        Reassinging to Matt at his request.

        Show
        rogerk added a comment - Reassinging to Matt at his request.
        Hide
        mattbohm added a comment -

        Because woodstock is heavily based on JavaScript, currently you must go a little
        further in your application to ensure that the scripts of woodstock components
        are evaluated prior to the invocation of your custom postReplace function.

        I was able to resolve this by doing two things:

        1. Manually replace the jsf-extensions-dynamic-faces-0.1.jar and
        jsf-extensions-common-0.1.jar inside the dynamicfaces.complib (0.2) with the
        versions of those jars used in woodstock. (If you are building netbeans from
        sources, you can find those jars inside
        visualweb.woodstock.webui.jsf/external/woodstock-components-4.2.zip.)

        2. Specify a custom replace function, as shown below, calling markup.evalScripts
        after DynaFaces.replace:

        <?xml version="1.0" encoding="UTF-8"?>
        <jsp:root version="2.1" xmlns:df="http://java.sun.com/jsf/dynamicfaces"
        xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
        xmlns:jsp="http://java.sun.com/JSP/Page"
        xmlns:webuijsf="http://www.sun.com/webui/webuijsf">
        <jsp:directive.page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"/>
        <f:view>
        <webuijsf:page id="page1">
        <webuijsf:html id="html1">
        <webuijsf:head debug="true" id="head1">
        <webuijsf:link id="link1" url="/resources/stylesheet.css"/>
        <df:ajaxTransaction id="tx1"
        inputs="page1:html1:body1:form1:button1" postReplace="customPostReplace"
        render="page1:html1:body1:form1:staticText1"
        replaceElement="customReplace"/>
        <webuijsf:script id="script1"><![CDATA[
        function customPostReplace(element, markup, closure)

        { alert(element + "|||" + markup + "|||" + closure); }

        function customReplace(id, markup)

        { DynaFaces.replace(id, markup); markup.evalScripts(); }

        ]]></webuijsf:script>
        </webuijsf:head>
        <webuijsf:body id="body1" style="-rave-layout: grid">
        <webuijsf:form id="form1">
        <webuijsf:staticText binding="#

        {Page1.staticText1}

        "
        id="staticText1" style="position: absolute; left: 120px; top: 48px"/>
        <webuijsf:button
        actionExpression="#

        {Page1.button1_action}

        " id="button1"
        onClick="DynaFaces.Tx.fire('tx1');return false;"
        style="position: absolute; left: 120px; top: 96px"
        text="Button"/>
        <webuijsf:messageGroup id="messageGroup1"
        style="position: absolute; left: 336px; top: 144px"/>
        </webuijsf:form>
        </webuijsf:body>
        </webuijsf:html>
        </webuijsf:page>
        </f:view>
        </jsp:root>

        Now the element parameter passed in to customPostReplace is non-null.

        The closure parameter passed in to customPostReplace is still unpopulated,
        because we are not passing any closure to the DynaFaces.fireAjaxTransaction call
        (see
        https://jsf-extensions.dev.java.net/nonav/mvn/reference-ajax.html#DynaFaces.fireAjaxTransaction).
        If you do want to use a closure, as, for instance, the Currency Trader sample
        application does (it does so conditionally), you can specify a closure as
        follows. The following appears in the poll function in currencytrader.js:

        DynaFaces.Tx.config.pollTx.closure = ...;
        ...
        DynaFaces.Tx.fire('pollTx');

        You could emulate this technique, replacing occurrences of pollTx with the name
        of your AjaxTransaction (for example, tx1). By doing so, the logic in
        DynaFaces.Tx.fire will pass your closure in when it calls
        DynaFaces.fireAjaxTransaction.

        Marking as enhancement, to devise a cleaner way to ensure scripts embedded in
        the replacement markup are evaluated prior to postReplace, but only when
        appropriate.

        Show
        mattbohm added a comment - Because woodstock is heavily based on JavaScript, currently you must go a little further in your application to ensure that the scripts of woodstock components are evaluated prior to the invocation of your custom postReplace function. I was able to resolve this by doing two things: 1. Manually replace the jsf-extensions-dynamic-faces-0.1.jar and jsf-extensions-common-0.1.jar inside the dynamicfaces.complib (0.2) with the versions of those jars used in woodstock. (If you are building netbeans from sources, you can find those jars inside visualweb.woodstock.webui.jsf/external/woodstock-components-4.2.zip.) 2. Specify a custom replace function, as shown below, calling markup.evalScripts after DynaFaces.replace: <?xml version="1.0" encoding="UTF-8"?> <jsp:root version="2.1" xmlns:df="http://java.sun.com/jsf/dynamicfaces" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:webuijsf="http://www.sun.com/webui/webuijsf"> <jsp:directive.page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"/> <f:view> <webuijsf:page id="page1"> <webuijsf:html id="html1"> <webuijsf:head debug="true" id="head1"> <webuijsf:link id="link1" url="/resources/stylesheet.css"/> <df:ajaxTransaction id="tx1" inputs="page1:html1:body1:form1:button1" postReplace="customPostReplace" render="page1:html1:body1:form1:staticText1" replaceElement="customReplace"/> <webuijsf:script id="script1"><![CDATA[ function customPostReplace(element, markup, closure) { alert(element + "|||" + markup + "|||" + closure); } function customReplace(id, markup) { DynaFaces.replace(id, markup); markup.evalScripts(); } ]]></webuijsf:script> </webuijsf:head> <webuijsf:body id="body1" style="-rave-layout: grid"> <webuijsf:form id="form1"> <webuijsf:staticText binding="# {Page1.staticText1} " id="staticText1" style="position: absolute; left: 120px; top: 48px"/> <webuijsf:button actionExpression="# {Page1.button1_action} " id="button1" onClick="DynaFaces.Tx.fire('tx1');return false;" style="position: absolute; left: 120px; top: 96px" text="Button"/> <webuijsf:messageGroup id="messageGroup1" style="position: absolute; left: 336px; top: 144px"/> </webuijsf:form> </webuijsf:body> </webuijsf:html> </webuijsf:page> </f:view> </jsp:root> Now the element parameter passed in to customPostReplace is non-null. The closure parameter passed in to customPostReplace is still unpopulated, because we are not passing any closure to the DynaFaces.fireAjaxTransaction call (see https://jsf-extensions.dev.java.net/nonav/mvn/reference-ajax.html#DynaFaces.fireAjaxTransaction ). If you do want to use a closure, as, for instance, the Currency Trader sample application does (it does so conditionally), you can specify a closure as follows. The following appears in the poll function in currencytrader.js: DynaFaces.Tx.config.pollTx.closure = ...; ... DynaFaces.Tx.fire('pollTx'); You could emulate this technique, replacing occurrences of pollTx with the name of your AjaxTransaction (for example, tx1). By doing so, the logic in DynaFaces.Tx.fire will pass your closure in when it calls DynaFaces.fireAjaxTransaction. Marking as enhancement, to devise a cleaner way to ensure scripts embedded in the replacement markup are evaluated prior to postReplace, but only when appropriate.
        Hide
        autozoom added a comment -

        Yes this way it works thanks, I think the trick is that we cannot use a custom
        postreplace without using a custom replace at the same time.
        This is the kind of samples and docs we need to effectively use the libraries.
        thanks

        Show
        autozoom added a comment - Yes this way it works thanks, I think the trick is that we cannot use a custom postreplace without using a custom replace at the same time. This is the kind of samples and docs we need to effectively use the libraries. thanks
        Hide
        Ed Burns added a comment -

        I am no longer tracking progress of these projects on java.net.

        Show
        Ed Burns added a comment - I am no longer tracking progress of these projects on java.net.

          People

          • Assignee:
            Ed Burns
            Reporter:
            autozoom
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: