001    package net.sf.tacos.components;
002    
003    import java.util.HashMap;
004    import java.util.Map;
005    
006    import org.apache.tapestry.AbstractComponent;
007    import org.apache.tapestry.IActionListener;
008    import org.apache.tapestry.IDirect;
009    import org.apache.tapestry.IMarkupWriter;
010    import org.apache.tapestry.IRequestCycle;
011    import org.apache.tapestry.IScript;
012    import org.apache.tapestry.Tapestry;
013    import org.apache.tapestry.TapestryUtils;
014    import org.apache.tapestry.engine.DirectServiceParameter;
015    import org.apache.tapestry.engine.IEngineService;
016    import org.apache.tapestry.engine.ILink;
017    import org.apache.tapestry.listener.ListenerInvoker;
018    
019    /**
020     * A component for creating a javascript function whose body
021     * is a call of an url definied by the direct service. This component is similar to
022     * <a href="http://tapestry.apache.org/tapestry4.1/components/link/directlink.html">DirectLink</a>
023     * component but allows you to call listener methods from javascript code without to click on any link or button.
024     * <p>The required parameters are: a listener method and the name of the function to generate.</p>
025     * <pre>
026     *&lt;span jwcid="@tacos:ClientLink" listener="listener:onClick" function="myFunction"/&gt;
027     *</pre>
028     *<p>The generated function can be used like this:</p>
029     *<pre>
030     *function test(){
031     *      ...
032     *      myFunction();
033     *}
034     *</pre>
035     * 
036     * @author Igor Drobiazko
037     *
038     */
039    public abstract class ClientLink extends AbstractComponent implements IDirect{
040            /**
041             * {@inheritDoc}
042             */
043            protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) {             
044            renderBody(writer, cycle);
045            
046            if (!cycle.isRewinding()) {
047                Map params = new HashMap();
048                params.put("url", getLink().getURL());        
049                params.put("function", getFunction());
050                getScript().execute(this, cycle, TapestryUtils.getPageRenderSupport(cycle, this), params);
051            }
052            }
053            
054            /**
055             * {@inheritDoc}
056             */
057            public void trigger(IRequestCycle cycle) {
058            IActionListener listener = getListener();
059            if (listener == null)
060                throw Tapestry.createRequiredParameterException(this, "listener");
061            
062            getListenerInvoker().invokeListener(listener, this, cycle);
063            }
064            
065            /**Returns a link*/
066            private ILink getLink(){
067                    DirectServiceParameter dsp = new DirectServiceParameter(this);
068                    return getEngine().getLink(isStateful(), dsp);
069            }
070    
071        /** The required listener parameter. */
072        public abstract IActionListener getListener();
073        /** Name of the javascript function to generate. */
074        public abstract String getFunction();
075        
076        /** Injected script. */
077        public abstract IScript getScript();
078        /** Injected listener invoker. */
079        public abstract ListenerInvoker getListenerInvoker();
080        /** Injected engine service . */
081        public abstract IEngineService getEngine();
082    }