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 }