001 package org.apache.myfaces.tobago.renderkit.html.sandbox.standard.tag;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one or more
005 * contributor license agreements. See the NOTICE file distributed with
006 * this work for additional information regarding copyright ownership.
007 * The ASF licenses this file to You under the Apache License, Version 2.0
008 * (the "License"); you may not use this file except in compliance with
009 * the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020 import org.apache.myfaces.tobago.TobagoConstants;
021 import org.apache.myfaces.tobago.util.ComponentUtil;
022 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_DISABLED;
023 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_READONLY;
024 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE;
025 import org.apache.myfaces.tobago.config.ThemeConfig;
026 import org.apache.myfaces.tobago.context.ResourceManager;
027 import org.apache.myfaces.tobago.context.ResourceManagerFactory;
028 import org.apache.myfaces.tobago.context.TobagoFacesContext;
029 import org.apache.myfaces.tobago.renderkit.LayoutableRendererBase;
030 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
031 import org.apache.myfaces.tobago.renderkit.html.HtmlConstants;
032 import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtil;
033 import org.apache.myfaces.tobago.renderkit.html.HtmlStyleMap;
034 import org.apache.myfaces.tobago.renderkit.html.StyleClasses;
035 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
036
037 import javax.faces.component.UIComponent;
038 import javax.faces.component.UIInput;
039 import javax.faces.component.UIViewRoot;
040 import javax.faces.context.FacesContext;
041 import java.io.IOException;
042 import java.util.Map;
043
044 public class InputNumberSliderRenderer extends LayoutableRendererBase {
045
046 private static final String SLIDER_WIDTH_PERCENT = "sliderWidthPercent";
047
048 public void prepareRender(FacesContext facesContext, UIComponent component) throws IOException {
049 super.prepareRender(facesContext, component);
050 if (facesContext instanceof TobagoFacesContext) {
051 final String[] scripts = new String[]{"script/scriptaculous.js"};
052 ((TobagoFacesContext) facesContext).getScriptFiles().add(scripts[0]);
053 }
054 }
055
056 public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
057
058 String id = component.getClientId(facesContext);
059 String currentValue = getCurrentValue(facesContext, component);
060 boolean readonly = ComponentUtil.getBooleanAttribute(component, ATTR_READONLY);
061 boolean disabled = ComponentUtil.getBooleanAttribute(component, ATTR_DISABLED);
062 Integer min = ComponentUtil.getIntAttribute(component, "min");
063 Integer max = ComponentUtil.getIntAttribute(component, "max");
064 TobagoResponseWriter writer = HtmlRendererUtil.getTobagoResponseWriter(facesContext);
065
066
067 HtmlStyleMap style = (HtmlStyleMap) component.getAttributes().get(ATTR_STYLE);
068 int width = -1;
069 int sliderWidthPerc = 33;
070 if (ThemeConfig.hasValue(facesContext, component, SLIDER_WIDTH_PERCENT)) {
071 sliderWidthPerc = getConfiguredValue(facesContext, component, SLIDER_WIDTH_PERCENT);
072 if (sliderWidthPerc <= 25) {
073 sliderWidthPerc = 25;
074 }
075 if (sliderWidthPerc >= 75) {
076 sliderWidthPerc = 75;
077 }
078 }
079 int sliderWidth = 100; // fixme
080 int inputWidth = 50; // fixme;
081 if (style != null && style.containsKey("width")) {
082 width = style.getInt("width");
083 }
084 if (width >= 0) {
085 sliderWidth = (width * sliderWidthPerc) / 100;
086 inputWidth = (width * (100 - sliderWidthPerc)) / 100;
087 }
088
089 writer.startElement(HtmlConstants.TABLE, component);
090 writer.writeIdAttribute(id);
091 writer.writeClassAttribute();
092 writer.writeStyleAttribute();
093 //writer.writeAttribute("border","1",false);
094
095 StyleClasses styleClasses = new StyleClasses();
096 styleClasses.addAspectClass("inputNumberSlider", "min", StyleClasses.Aspect.DEFAULT);
097
098 writer.startElement(HtmlConstants.TR, null);
099 writer.startElement(HtmlConstants.TD, null);
100 writer.writeClassAttribute(styleClasses);
101
102 HtmlStyleMap widthStyle = new HtmlStyleMap();
103 widthStyle.put("width", sliderWidth / 2);
104 writer.writeStyleAttribute(widthStyle);
105 writer.startElement(HtmlConstants.SPAN, null);
106 writer.writeClassAttribute(styleClasses);
107 writer.write(Integer.toString(min));
108 writer.endElement(HtmlConstants.SPAN);
109
110 styleClasses = new StyleClasses();
111 styleClasses.addAspectClass("inputNumberSlider", "max", StyleClasses.Aspect.DEFAULT);
112
113 writer.endElement(HtmlConstants.TD);
114 writer.startElement(HtmlConstants.TD, null);
115 writer.writeClassAttribute(styleClasses);
116 writer.writeStyleAttribute(widthStyle);
117 writer.startElement(HtmlConstants.SPAN, null);
118 writer.writeClassAttribute(styleClasses);
119 writer.write(Integer.toString(max));
120 writer.endElement(HtmlConstants.SPAN);
121 writer.endElement(HtmlConstants.TD);
122
123 // the input field starts here
124 writer.startElement(HtmlConstants.TD, null);
125 writer.writeAttribute("rowspan", "2", false);
126 writer.writeClassAttribute("tobago-inputNumberSlider-input-default");
127
128 writer.startElement(HtmlConstants.INPUT, null);
129 writer.writeClassAttribute("tobago-in-default");
130 widthStyle.put("width", inputWidth);
131 writer.writeStyleAttribute(widthStyle);
132 String inputIdAndName = getIdForInputField(facesContext, component);
133 writer.writeNameAttribute(inputIdAndName);
134 writer.writeIdAttribute(inputIdAndName);
135 if (currentValue != null) {
136 writer.writeAttribute(HtmlAttributes.VALUE, currentValue, false);
137 }
138 writer.writeAttribute(HtmlAttributes.READONLY, readonly);
139 writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
140 //writer.writeAttribute(HtmlAttributes.STYLE, null, ATTR_STYLE);
141 writer.endElement(HtmlConstants.INPUT);
142 writer.endElement(HtmlConstants.TD);
143
144 writer.endElement(HtmlConstants.TR);
145 writer.startElement(HtmlConstants.TR, null);
146 writer.startElement(HtmlConstants.TD, null);
147 writer.writeAttribute("colspan", 2);
148
149 //track
150 writer.startElement(HtmlConstants.DIV, null);
151 writer.writeClassAttribute("tobago-inputNumberSlider-slider-default");
152 writer.writeIdAttribute(getIdForSliderTrack(facesContext, component));
153
154 // handle
155 writer.startElement(HtmlConstants.DIV, null);
156 writer.writeIdAttribute(getIdForSliderHandle(facesContext, component));
157 writer.writeStyleAttribute("position:relative; top:-6px; width:12px; height:6px");
158 writer.startElement(HtmlConstants.IMG, null);
159 writer.writeAttribute(HtmlAttributes.SRC, getAbsoluteImagePath(facesContext, "image/sliderTriangle.gif"), true);
160 writer.endElement(HtmlConstants.IMG);
161 writer.endElement(HtmlConstants.DIV);
162 writer.endElement(HtmlConstants.DIV);
163 writer.endElement(HtmlConstants.TD);
164 writer.endElement(HtmlConstants.TR);
165 writer.endElement(HtmlConstants.TABLE);
166
167 writeSliderJavaScript(facesContext, component, writer);
168 //HtmlRendererUtil.renderFocusId(facesContext, component);
169 }
170
171 public void decode(FacesContext context, UIComponent component) {
172 UIInput uiInput;
173 if (component instanceof UIInput && !ComponentUtil.isOutputOnly(component)) {
174 uiInput = (UIInput) component;
175 } else {
176 return;
177 }
178 String inputId = getIdForInputField(context, component);
179 Map requestParameterMap = context.getExternalContext().getRequestParameterMap();
180 if (requestParameterMap.containsKey(inputId)) {
181 String newValue = (String) requestParameterMap.get(inputId);
182 uiInput.setSubmittedValue(newValue);
183 }
184 }
185
186 private String getAbsoluteImagePath(FacesContext facesContext, String relativeImagePath) {
187 ResourceManager resourceManager = ResourceManagerFactory.getResourceManager(facesContext);
188 UIViewRoot viewRoot = facesContext.getViewRoot();
189 String contextPath = facesContext.getExternalContext().getRequestContextPath();
190 return contextPath + resourceManager.getImage(viewRoot, relativeImagePath);
191 }
192
193 private String getIdForInputField(FacesContext context,
194 UIComponent component) {
195 String id = component.getClientId(context);
196 return id + TobagoConstants.SUBCOMPONENT_SEP + "input";
197 }
198
199 private String getIdForSliderTrack(FacesContext context,
200 UIComponent component) {
201 String id = component.getClientId(context);
202 return id + TobagoConstants.SUBCOMPONENT_SEP + "track";
203 }
204
205 private String getIdForSliderHandle(FacesContext context,
206 UIComponent component) {
207 String id = component.getClientId(context);
208 return id + TobagoConstants.SUBCOMPONENT_SEP + "handle";
209 }
210
211 private void writeSliderJavaScript(FacesContext context, UIComponent component,
212 TobagoResponseWriter writer) throws IOException {
213 String trackId = getIdForSliderTrack(context, component);
214 String handleId = getIdForSliderHandle(context, component);
215 String inputId = getIdForInputField(context, component);
216 String jsId = component.getClientId(context).replace(":", "_");
217 Integer min = ComponentUtil.getIntAttribute(component, "min");
218 Integer max = ComponentUtil.getIntAttribute(component, "max");
219 String script = " var slider_" + jsId + " = new Control.Slider('" + handleId + "', '" + trackId + "', {\n"
220 + " sliderValue:$('" + inputId + "').value,\n"
221 + " range : $R(" + min + ", " + max + "),\n"
222 + " values: $R(" + min + ", " + max + ").toArray(),\n"
223 + " onSlide:function(v) {\n"
224 + " $('" + inputId + "').value = v;\n"
225 + " },\n"
226 + " onChange:function(v) {\n"
227 + " $('" + inputId + "').value = v;\n"
228 + " }\n"
229 + " });\n"
230 + "\n"
231 + " Event.observe('value', 'change', function() {\n"
232 + " slider_" + jsId + ".setValue($('" + inputId + "').value);\n"
233 + " });\n";
234 writer.writeJavascript(script);
235 }
236
237 }