You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by bobby rullo <br...@alexanderinteractive.com> on 2005/03/01 22:48:52 UTC

Re: JavaScript calling a listener

Funnily enough I ran into the same issue today! It took some doing, but what I
ended up doing is creating a custom component called DirectOnChange. What you
do is you give the DirectOnChange (DOC from now on) two params: one is the
form component that you wish to have trigger a listener, and the second is 
the listener itself.

Whenever you change the value of the form component on the client side, a
javascript method triggers the listener method with the param being the new 
value.

Caveats: 
  1) Right now it only works with radios (cuz that's what I needed it for. But
this is EASILY fixed with a little more javascript.
  2) I've only tested this with Integers as the listener params, but String
should work.

Here is the code. It is VERY rough, but I just wanted to get it up here asap to

help. I obscured the package names to protect the guilty:

DirectOnChange.jwc:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE component-specification
      PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
      "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
<!-- generated by Spindle, http://spindle.sourceforge.net -->

<component-specification 
    class="com.xxx.xxx.xxx.DirectOnChange" 
    allow-body="yes" 
    allow-informal-parameters="yes">
    
    <description>[CDATA[   Enter a description   ]]</description>

    <parameter name="listener" type="org.apache.tapestry.IActionListener" 
               direction="auto" 
               required="yes"/>

    <parameter name="component" 
               type="org.apache.tapestry.form.AbstractFormComponent"
    		   direction="auto"
               required="yes"/>
    
</component-specification>


DirectOnChange.java

package com.xxx.xxx.xxx.xxx
import java.util.HashMap;

import org.apache.tapestry.AbstractComponent;
import org.apache.tapestry.IActionListener;
import org.apache.tapestry.IDirect;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.IResourceLocation;
import org.apache.tapestry.IScript;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.engine.DirectService;
import org.apache.tapestry.engine.IScriptSource;
import org.apache.tapestry.form.AbstractFormComponent;
import org.apache.tapestry.html.Body;

/**
 * @author br
 *
 */
public abstract class DirectOnChange extends AbstractComponent
implements IDirect{

    private IScript script = null;
    
    protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) 
    {
        if (cycle.isRewinding()){
            return;
        }
        DirectService direct = (DirectService) cycle.getEngine().getService(
                Tapestry.DIRECT_SERVICE);
        String url  = direct.getLink(cycle, this,
                new Object[] { "REPLACE_ME" }).getURL();
        
        HashMap symbols = new HashMap();
        symbols.put("component", getComponent());
        symbols.put("url", url);
        getScript(cycle).execute(cycle, Body.get(cycle), symbols);
    }
    
    private IScript getScript(IRequestCycle cycle){
        if (script == null){
        IScriptSource source = cycle.getEngine().getScriptSource();
            IResourceLocation specLocation = getSpecification().getLocation()
                    .getResourceLocation();
            IResourceLocation scriptLocation = specLocation
                    .getRelativeLocation("DirectOnChange.script");
            script = source.getScript(scriptLocation);
        } 
        
        return script;
        
    }

    /** 
     * @param cycle
     *
     * @see org.apache.tapestry.IDirect#trigger(org.apache.tapestry.
     * IRequestCycle)
     */
    public void trigger(IRequestCycle cycle) {
        IActionListener listener = getListener();

        if (listener == null)
        	throw Tapestry.createRequiredParameterException(this, "listener");

        listener.actionTriggered(this, cycle);
    }

    /** 
     * @return
     *
     * @see org.apache.tapestry.IDirect#isStateful()
     */
    public boolean isStateful() {
        return false;
    }
    
    public abstract IActionListener getListener();
    public abstract AbstractFormComponent getComponent();
    
}

DirectOnChange.script

<?xml version="1.0"?>

<!DOCTYPE script PUBLIC
  "-//Apache Software Foundation//Tapestry Script Specification 3.0//EN"
	"http://jakarta.apache.org/tapestry/dtd/Script_3_0.dtd">

<script>
<!-- 
This script is to support the DirectOnChange component
  component: the component that when changed will trigger a listener.
  url: the url with REPLACE_ME as the service params
  

-->

<input-symbol key="component"
class="org.apache.tapestry.form.AbstractFormComponent" required="yes"/>
<input-symbol key="url" class="java.lang.String" required="yes" />

<let key="formObject">
	document.${component.form.name}
</let>

<let key="functionName" unique="yes">
	onchange_${component.name}
</let>

<body>
<![CDATA[
function ${functionName}(param) {
    var re = /SREPLACE_ME/ ;
    var url = "${url}"
    url = url.replace(re, param);
    location.replace(url);
}
]]>
</body>

<initialization>
<![CDATA[
{
  var element = ${formObject}["${component.name}"];
  var elements = ${formObject}.elements;
  
  //this means the element is a radio group or check group
  if (element.length) {
      //first define the function
      var myFunction = function(){
          var element = ${formObject}["${component.name}"];
          var value;
          for (var x = 0; x < element.length;x++) {
              //alert(element[x]);
              if (element[x].checked){
                 value = element[x].value;
                 ${functionName}(value);
                 return;
	  	      }
	      }
      };
      
      for (x = 0 ; x < elements.length; x++) {
          element[x].onchange = myFunction;
      }
  } else {
     //alert("no!");
     if (element.type == "radio") {
         //alert("it's a radio");
         var myFunction = function(){
             var element = ${formObject}["${component.name}"];
             ${functionName}(element.value);
         }
         element.onchange = myFunction;
     }
  }
  

}
]]>
</initialization>

    
</script>



---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org