001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.form;
016    
017    import java.util.HashMap;
018    import java.util.Map;
019    
020    import org.apache.hivemind.ApplicationRuntimeException;
021    import org.apache.hivemind.HiveMind;
022    import org.apache.tapestry.IComponent;
023    import org.apache.tapestry.IForm;
024    import org.apache.tapestry.IMarkupWriter;
025    import org.apache.tapestry.IRequestCycle;
026    import org.apache.tapestry.IScript;
027    import org.apache.tapestry.PageRenderSupport;
028    import org.apache.tapestry.TapestryUtils;
029    
030    /**
031     * Implements a component that submits its enclosing form via a JavaScript link. [ <a
032     * href="../../../../../ComponentReference/LinkSubmit.html">Component Reference </a>]
033     * 
034     * @author Richard Lewis-Shell
035     */
036    
037    public abstract class LinkSubmit extends AbstractSubmit
038    {
039    
040        /**
041         * The name of an {@link org.apache.tapestry.IRequestCycle}attribute in which the current
042         * submit link is stored. LinkSubmits do not nest.
043         */
044    
045        public static final String ATTRIBUTE_NAME = "org.apache.tapestry.form.LinkSubmit";
046    
047        protected boolean isClicked(IRequestCycle cycle, String name)
048        {
049            String value = cycle.getParameter(name);
050    
051            return HiveMind.isNonBlank(value);
052        }
053    
054        public abstract IScript getScript();
055    
056        /**
057         * @see org.apache.tapestry.form.AbstractFormComponent#renderFormComponent(org.apache.tapestry.IMarkupWriter,
058         *      org.apache.tapestry.IRequestCycle)
059         */
060        protected void renderFormComponent(IMarkupWriter writer, IRequestCycle cycle)
061        {
062            boolean disabled = isDisabled();
063    
064            IForm form = getForm();
065            String name = getName();
066    
067            String hiddenId = cycle.getUniqueId(TapestryUtils
068                    .convertTapestryIdToNMToken(getIdParameter()));
069    
070            // Store for later access by the FieldLabel (or JavaScript).
071    
072            setClientId(hiddenId);
073    
074            // Add a hidden field used to identify the link that caused the submission.
075            // Client-side JavaScript will set the value to non-null when the link is clicked,
076            // then force the form to submit.
077    
078            form.addHiddenValue(name, hiddenId, "");
079    
080            if (!disabled)
081            {
082                PageRenderSupport pageRenderSupport = TapestryUtils.getPageRenderSupport(cycle, this);
083    
084                Map symbols = new HashMap();
085                symbols.put("form", form);
086                symbols.put("hiddenId", hiddenId);
087    
088                getScript().execute(cycle, pageRenderSupport, symbols);
089    
090                writer.begin("a");
091                writer.attribute("href", (String) symbols.get("href"));
092                renderInformalParameters(writer, cycle);
093            }
094    
095            renderBody(writer, cycle);
096    
097            if (!disabled)
098                writer.end();
099    
100        }
101    
102        /**
103         * @see org.apache.tapestry.AbstractComponent#prepareForRender(org.apache.tapestry.IRequestCycle)
104         */
105        protected void prepareForRender(IRequestCycle cycle)
106        {
107            IComponent outer = (IComponent) cycle.getAttribute(ATTRIBUTE_NAME);
108    
109            if (outer != null)
110                throw new ApplicationRuntimeException(FormMessages.linkSubmitMayNotNest(this, outer),
111                        this, getLocation(), null);
112    
113            cycle.setAttribute(ATTRIBUTE_NAME, this);
114        }
115    
116        /**
117         * @see org.apache.tapestry.AbstractComponent#cleanupAfterRender(org.apache.tapestry.IRequestCycle)
118         */
119        protected void cleanupAfterRender(IRequestCycle cycle)
120        {
121            cycle.removeAttribute(ATTRIBUTE_NAME);
122        }
123    
124        /**
125         * Links can not take focus, ever.
126         */
127        protected boolean getCanTakeFocus()
128        {
129            return false;
130        }
131    
132        /**
133         * Returns true; the LinkSubmit's body should render during a rewind, even if the component is
134         * itself disabled.
135         */
136        protected boolean getRenderBodyOnRewind()
137        {
138            return true;
139        }
140    
141    }