001    /*
002     * Apache License
003     * Version 2.0, January 2004
004     * http://www.apache.org/licenses/
005     *
006     * Copyright 2008-2010 by chenillekit.org
007     *
008     * Licensed under the Apache License, Version 2.0 (the "License");
009     * you may not use this file except in compliance with the License.
010     * You may obtain a copy of the License at
011     *
012     * http://www.apache.org/licenses/LICENSE-2.0
013     */
014    
015    package org.chenillekit.tapestry.core.components;
016    
017    import org.apache.tapestry5.BindingConstants;
018    import org.apache.tapestry5.ClientElement;
019    import org.apache.tapestry5.ComponentResources;
020    import org.apache.tapestry5.Link;
021    import org.apache.tapestry5.MarkupWriter;
022    import org.apache.tapestry5.annotations.Environmental;
023    import org.apache.tapestry5.annotations.Import;
024    import org.apache.tapestry5.annotations.Parameter;
025    import org.apache.tapestry5.annotations.SupportsInformalParameters;
026    import org.apache.tapestry5.corelib.components.PageLink;
027    import org.apache.tapestry5.ioc.Messages;
028    import org.apache.tapestry5.ioc.annotations.Inject;
029    import org.apache.tapestry5.services.PageRenderLinkSource;
030    import org.apache.tapestry5.services.javascript.JavaScriptSupport;
031    
032    import java.util.List;
033    
034    /**
035     * Render a button tag element and bind to it's "click" event an event on the server side.
036     * The event name is customizable and it defaults to "CLICKED".
037     * <p/>
038     * If parameter <code>pageName</code> is given the component act like a {@link PageLink}
039     * to the page corresponding to the logical name <code>pageName</code>.
040     *
041     * @version $Id: Button.java 674 2010-07-29 12:47:25Z homburgs $
042     */
043    @SupportsInformalParameters
044    @Import(library = {"../Chenillekit.js", "CkOnEvents.js"})
045    public class Button implements ClientElement
046    {
047            static final String CLICKED_EVENT = "clicked";
048    
049            static final String TYPE_BUTTON = "button";
050            static final String TYPE_SUBMIT = "submit";
051            static final String TYPE_RESET = "reset";
052    
053            /**
054             * Type of the button, possible value are "button", "submit" and "reset".
055             */
056            @Parameter(defaultPrefix = BindingConstants.LITERAL, value = TYPE_BUTTON)
057            private String type;
058    
059            /**
060             * The name of the event fired. Defaults to <code>clicked</code>.
061             */
062            @Parameter(defaultPrefix = BindingConstants.LITERAL, value = CLICKED_EVENT)
063            private String event;
064    
065            /**
066             * If specified the components act as a {@link PageLink} doing a link
067             * for rendering the logical <code>pageName</code>.
068             */
069            @Parameter(defaultPrefix = BindingConstants.LITERAL, required = false)
070            private String pageName;
071    
072            /**
073             * <code>Disabled</code> attribute of the element.
074             */
075            @Parameter(value = "false")
076            private boolean disabled;
077    
078            /**
079             * The id used to generate a page-unique client-side identifier for the component. If a component renders multiple
080             * times, a suffix will be appended to the to id to ensure uniqueness.
081             */
082            @Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL)
083            private String clientId;
084    
085            /**
086             * To ask for a confirmation or not
087             */
088            @Parameter(value = "literal:false")
089            private boolean confirm;
090    
091            /**
092             * The context for the link (optional parameter). This list of values will
093             * be converted into strings and included in the URI. The strings will be
094             * coerced back to whatever their values are and made available to event
095             * handler methods or the passivate mthod of the page to link to in case
096             * a <code>pageName</code> has been specified.
097             */
098            @Parameter
099            private List<?> context;
100    
101            @Environmental
102            private JavaScriptSupport javascriptSupport;
103    
104            @Inject
105            private ComponentResources resources;
106    
107            @Inject
108            private PageRenderLinkSource pageRenderResources;
109    
110            @Inject
111            private Messages messages;
112    
113            private String assignedClientId;
114    
115            private Object[] contextArray;
116    
117            void setupRender()
118            {
119                    assignedClientId = javascriptSupport.allocateClientId(clientId);
120                    contextArray = context == null ? new Object[0] : context.toArray();
121            }
122    
123            void beginRender(MarkupWriter writer)
124            {
125                    writer.element("button", "type", type, "id", getClientId());
126                    resources.renderInformalParameters(writer);
127            }
128    
129            void afterRender(MarkupWriter writer)
130            {
131                    if (!disabled && type.equalsIgnoreCase(TYPE_BUTTON))
132                    {
133                            Link link;
134    
135                            if (pageName != null)
136                            {
137                                    link = pageRenderResources.createPageRenderLinkWithContext(pageName, contextArray);
138                            }
139                            else
140                            {
141                                    link = resources.createEventLink(event, contextArray);
142                            }
143    
144                            String message = "";
145    
146                            if (this.confirm)
147                                    message = messages.format("ck-button-confirm-message", clientId);
148    
149                            javascriptSupport.addScript("new Ck.ButtonEvent('%s', '%s', '%s');",
150                                                                                    getClientId(), link.toAbsoluteURI(), message);
151                    }
152    
153                    // Close the button tag
154                    writer.end();
155            }
156    
157            /**
158             * Returns a unique id for the element. This value will be unique for any given rendering of a
159             * page. This value is intended for use as the id attribute of the client-side element, and will
160             * be used with any DHTML/Ajax related JavaScript.
161             */
162            public String getClientId()
163            {
164                    return assignedClientId;
165            }
166    }