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.EventConstants;
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.OnEvent;
025    import org.apache.tapestry5.annotations.Parameter;
026    import org.apache.tapestry5.ioc.annotations.Inject;
027    import org.apache.tapestry5.services.Request;
028    import org.apache.tapestry5.services.javascript.JavaScriptSupport;
029    
030    import java.util.Locale;
031    
032    
033    /**
034     * a slider component that dont must emmbedded in a form..
035     *
036     * @version $Id: Slider.java 674 2010-07-29 12:47:25Z homburgs $
037     */
038    @Import(library = {"${tapestry.scriptaculous}/controls.js", "${tapestry.scriptaculous}/slider.js"},
039                    stylesheet = {"Slider.css"})
040    public class Slider implements ClientElement
041    {
042            private final static String handleCSS = "ck_slider-handle";
043            private final static String trackCSS = "ck_slider-track";
044            private final static String valueCSS = "ck_slider-value";
045    
046            /**
047             * The id used to generate a page-unique client-side identifier for the component. If a component renders multiple
048             * times, a suffix will be appended to the to id to ensure uniqueness.
049             */
050            @Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL)
051            private String clientId;
052    
053            /**
054             * The value to read or update.
055             */
056            @Parameter(required = true)
057            private Number value;
058    
059            /**
060             * min. slide-able value.
061             */
062            @Parameter(value = "0", required = false)
063            private Number min;
064    
065            /**
066             * max. slide-able value.
067             */
068            @Parameter(value = "100", required = false)
069            private Number max;
070    
071            /**
072             * increments x on every step.
073             */
074            @Parameter(value = "1", required = false)
075            private Number inc;
076    
077            /**
078             * If true, then the field will render out with a disabled attribute (to turn off client-side behavior).
079             * Further, a disabled field ignores any value in the request when the form is submitted.
080             */
081            @Parameter(value = "false", required = false)
082            private boolean disabled;
083    
084            @Inject
085            private ComponentResources componentResources;
086    
087            @Inject
088            private Request request;
089    
090            private String handleId;
091            private String tackId;
092            private String ouputId;
093    
094            @Environmental
095            private JavaScriptSupport javascriptSupport;
096    
097            private String assignedClientId;
098    
099            void setupRender()
100            {
101                    assignedClientId = javascriptSupport.allocateClientId(clientId);
102            }
103    
104            void beginRender(MarkupWriter writer)
105            {
106                    handleId = "handle_" + getClientId();
107                    tackId = "track_" + getClientId();
108                    ouputId = "ouput_" + getClientId();
109    
110                    writer.element("div", "id", tackId,
111                                               "class", trackCSS);
112                    writer.element("div", "id", handleId,
113                                               "class", handleCSS);
114            }
115    
116            void afterRender(MarkupWriter writer)
117            {
118                    writer.end();
119                    writer.end();
120    
121                    writer.element("div", "id", ouputId, "class", valueCSS);
122    
123                    if (value == null)
124                            value = 0;
125    
126                    writer.write(value.toString());
127    
128                    writer.end();
129    
130    
131                    String jsCommand = "new Control.Slider('%s','%s',{sliderValue:" + getNumberPattern(value) + ",range:" +
132                                    "$R(" + getNumberPattern(min) + "," + getNumberPattern(max) + "),increment:" + getNumberPattern(inc) +
133                                    ",onSlide:function(v){$('%s').innerHTML = v}";
134                    jsCommand = String.format(Locale.US, jsCommand, handleId, tackId, value, min, max, inc, ouputId);
135    
136                    if (disabled)
137                            jsCommand += ",disabled:true";
138    
139                    jsCommand += ", onChange:function(value){$('%s').innerHTML = value; new Ajax.Request('%s/' + value,{method:'get', onFailure: function(){ alert('%s')}})}});";
140                    jsCommand = String.format(Locale.US, jsCommand, ouputId, getActionLink(), "Something went wrong...");
141    
142                    javascriptSupport.addScript(jsCommand);
143            }
144    
145            @OnEvent(value = "action")
146            private void onAction(Number value)
147            {
148                    this.value = value;
149            }
150    
151            public Number getValue()
152            {
153                    return value;
154            }
155    
156            public void setValue(Number value)
157            {
158                    this.value = value;
159            }
160    
161            public String getActionLink()
162            {
163                    return componentResources.createEventLink(EventConstants.ACTION).toURI();
164            }
165    
166            private String getNumberPattern(Number value)
167            {
168                    String numberPattern = "%d";
169    
170                    if (value instanceof Float || value instanceof Double)
171                            numberPattern = "%f";
172    
173                    return numberPattern;
174            }
175    
176            /**
177             * Returns a unique id for the element. This value will be unique for any given rendering of a
178             * page. This value is intended for use as the id attribute of the client-side element, and will
179             * be used with any DHTML/Ajax related JavaScript.
180             */
181            public String getClientId()
182            {
183                    return assignedClientId;
184            }
185    }