001 package railo.runtime.tag; 002 003 import java.io.IOException; 004 import java.util.Iterator; 005 import java.util.Map.Entry; 006 007 import javax.servlet.jsp.tagext.Tag; 008 009 import railo.commons.lang.HTMLEntities; 010 import railo.runtime.exp.ApplicationException; 011 import railo.runtime.exp.ExpressionException; 012 import railo.runtime.exp.PageException; 013 import railo.runtime.ext.tag.BodyTagImpl; 014 import railo.runtime.op.Caster; 015 import railo.runtime.op.Operator; 016 import railo.runtime.type.Collection.Key; 017 import railo.runtime.type.Struct; 018 import railo.runtime.type.StructImpl; 019 import railo.runtime.type.util.KeyConstants; 020 import railo.runtime.type.util.ListUtil; 021 022 /** 023 * 024 */ 025 public final class Select extends BodyTagImpl { 026 027 private static final int QUERY_POSITION_ABOVE = 0; 028 private static final int QUERY_POSITION_BELOW = 1; 029 private railo.runtime.type.Query query; 030 private String[] selected; 031 private String value; 032 private String display; 033 private String passthrough; 034 035 036 037 private Struct attributes=new StructImpl(); 038 private InputBean input=new InputBean(); 039 private boolean editable=false; 040 private int height=-1; 041 private int width=-1; 042 private String label; 043 private boolean visible=true; 044 private String tooltip; 045 private String group; 046 private int queryPosition=QUERY_POSITION_ABOVE; 047 private boolean caseSensitive=false; 048 049 050 @Override 051 public void release() { 052 super.release(); 053 query=null; 054 selected=null; 055 value=null; 056 display=null; 057 passthrough=null; 058 editable=false; 059 height=-1; 060 width=-1; 061 label=null; 062 visible=true; 063 tooltip=null; 064 group=null; 065 queryPosition=QUERY_POSITION_ABOVE; 066 caseSensitive=false; 067 attributes.clear(); 068 input=new InputBean(); 069 } 070 071 /** 072 * @param cssclass The cssclass to set. 073 */ 074 public void setClass(String cssclass) { 075 attributes.setEL("class",cssclass); 076 } 077 /** 078 * @param cssstyle The cssstyle to set. 079 */ 080 public void setStyle(String cssstyle) { 081 attributes.setEL("style",cssstyle); 082 } 083 /** 084 * @param id The id to set. 085 */ 086 public void setId(String id) { 087 attributes.setEL("id",id); 088 } 089 /** 090 * @param multiple The multiple to set. 091 */ 092 public void setMultiple(String multiple) { 093 // alles ausser false ist true 094 if(Caster.toBooleanValue(multiple,true)) attributes.setEL("multiple","multiple"); 095 } 096 /** 097 * @param name The name to set. 098 */ 099 public void setName(String name) { 100 attributes.setEL(KeyConstants._name,name); 101 input.setName(name); 102 } 103 /** 104 * @param size The size to set. 105 */ 106 public void setSize(double size) { 107 attributes.setEL(KeyConstants._size,Caster.toString(size)); 108 } 109 /** 110 * @param tabindex The tabindex to set. 111 */ 112 public void setTabindex(String tabindex) { 113 attributes.setEL("class",tabindex); 114 } 115 /** 116 * @param title The title to set. 117 */ 118 public void setTitle(String title) { 119 attributes.setEL(KeyConstants._title,title); 120 } 121 /** 122 * @param title The title to set. 123 */ 124 public void setDir(String dir) { 125 attributes.setEL("dir",dir); 126 } 127 /** 128 * @param title The title to set. 129 */ 130 public void setLang(String lang) { 131 attributes.setEL("lang",lang); 132 } 133 /** 134 * @param onblur The onblur to set. 135 */ 136 public void setOnblur(String onblur) { 137 attributes.setEL("onblur",onblur); 138 } 139 /** 140 * @param onchange The onchange to set. 141 */ 142 public void setOnchange(String onchange) { 143 attributes.setEL("onchange",onchange); 144 } 145 /** 146 * @param onclick The onclick to set. 147 */ 148 public void setOnclick(String onclick) { 149 attributes.setEL("onclick",onclick); 150 } 151 /** 152 * @param ondblclick The ondblclick to set. 153 */ 154 public void setOndblclick(String ondblclick) { 155 attributes.setEL("ondblclick",ondblclick); 156 } 157 /** 158 * @param onmousedown The onmousedown to set. 159 */ 160 public void setOnmousedown(String onmousedown) { 161 attributes.setEL("onmousedown",onmousedown); 162 } 163 /** 164 * @param ondblclick The ondblclick to set. 165 */ 166 public void setOnmouseup(String onmouseup) { 167 attributes.setEL("onmouseup",onmouseup); 168 } 169 /** 170 * @param ondblclick The ondblclick to set. 171 */ 172 public void setOnmouseover(String onmouseover) { 173 attributes.setEL("onmouseover",onmouseover); 174 } 175 /** 176 * @param ondblclick The ondblclick to set. 177 */ 178 public void setOnmousemove(String onmousemove) { 179 attributes.setEL("onmousemove",onmousemove); 180 } 181 /** 182 * @param ondblclick The ondblclick to set. 183 */ 184 public void setOnmouseout(String onmouseout) { 185 attributes.setEL("onmouseout",onmouseout); 186 } 187 /** 188 * @param ondblclick The ondblclick to set. 189 */ 190 public void setOnkeypress(String onkeypress) { 191 attributes.setEL("onkeypress",onkeypress); 192 } 193 /** 194 * @param ondblclick The ondblclick to set. 195 */ 196 public void setOnkeydown(String onkeydown) { 197 attributes.setEL("onkeydown",onkeydown); 198 } 199 /** 200 * @param ondblclick The ondblclick to set. 201 */ 202 public void setOnkeyup(String onkeyup) { 203 attributes.setEL("onkeyup",onkeyup); 204 } 205 /** 206 * @param onfocus The onfocus to set. 207 */ 208 public void setOnfocus(String onfocus) { 209 attributes.setEL("onfocus",onfocus); 210 } 211 212 /** 213 * @param message The message to set. 214 */ 215 public void setMessage(String message) { 216 input.setMessage(message); 217 } 218 /** 219 * @param onerror The onerror to set. 220 */ 221 public void setOnerror(String onerror) { 222 input.setOnError(onerror); 223 } 224 /** 225 * @param required The required to set. 226 */ 227 public void setRequired(boolean required) { 228 input.setRequired(required); 229 } 230 /** 231 * @param passthrough The passthrough to set. 232 * @throws PageException 233 */ 234 public void setPassthrough(Object passthrough) throws PageException { 235 if(passthrough instanceof Struct) { 236 Struct sct = (Struct) passthrough; 237 Iterator<Entry<Key, Object>> it = sct.entryIterator(); 238 Entry<Key, Object> e; 239 while(it.hasNext()) { 240 e = it.next(); 241 attributes.setEL(e.getKey(),e.getValue()); 242 } 243 } 244 else this.passthrough = Caster.toString(passthrough); 245 } 246 /** 247 * @param query The query to set. 248 * @throws PageException 249 */ 250 public void setQuery(String strQuery) throws PageException { 251 this.query = Caster.toQuery(pageContext.getVariable(strQuery)); 252 } 253 /** 254 * @param display The display to set. 255 */ 256 public void setDisplay(String display) { 257 this.display = display; 258 } 259 260 public void setDataformatas(String dataformatas) throws ApplicationException { 261 dataformatas=dataformatas.trim(); 262 String lcDataformatas=dataformatas.toLowerCase(); 263 if( "plaintext".equals(lcDataformatas) || 264 "html".equals(lcDataformatas)) { 265 attributes.setEL("dataformatas",dataformatas); 266 } 267 else 268 throw new ApplicationException("attribute dataformatas for tag input has an invalid value ["+dataformatas+"], valid values are [plaintext, html"); 269 } 270 271 public void setDatafld(String datafld) { 272 attributes.setEL("datafld",datafld); 273 } 274 275 public void setDatasrc(String datasrc) { 276 attributes.setEL("datasrc",datasrc); 277 } 278 279 public void setDisabled(String disabled) { 280 // alles ausser false ist true 281 if(Caster.toBooleanValue(disabled,true)) setDisabled(true); 282 } 283 284 private void setDisabled(boolean disabled) { 285 if(disabled) attributes.setEL("disabled","disabled"); 286 } 287 288 /** 289 * @param selected The selected to set. 290 */ 291 public void setSelected(String selected) { 292 this.selected = ListUtil.trimItems(ListUtil.listToStringArray(selected,',')); 293 } 294 /** 295 * @param value The value to set. 296 */ 297 public void setValue(String value) { 298 this.value = value; 299 } 300 301 @Override 302 public int doStartTag() { 303 return EVAL_BODY_BUFFERED; 304 } 305 306 @Override 307 public int doEndTag() throws PageException { 308 try { 309 _doEndTag(); 310 return EVAL_PAGE; 311 } catch (IOException e) { 312 throw Caster.toPageException(e); 313 } 314 } 315 316 317 private void _doEndTag() throws IOException, ExpressionException, PageException { 318 319 // check 320 if(query!=null) { 321 if(value==null) 322 throw new ApplicationException("if you have defined attribute query for tag select, you must also define attribute value"); 323 else if(!query.containsKey(value)) 324 throw new ApplicationException("invalid value for attribute [value], there is no column in query with name ["+value+"]"); 325 326 if(display!=null && !query.containsKey(display)) 327 throw new ApplicationException("invalid value for attribute [display], there is no column in query with name ["+display+"]"); 328 329 if(group!=null && !query.containsKey(group)) 330 throw new ApplicationException("invalid value for attribute [group], there is no column in query with name ["+group+"]"); 331 } 332 333 input.setType(Input.TYPE_SELECT); 334 Tag parent=getParent(); 335 while(parent!=null && !(parent instanceof Form)){ 336 parent=parent.getParent(); 337 } 338 if(parent instanceof Form) { 339 Form form = (Form)parent; 340 form.setInput(input); 341 } 342 else { 343 throw new ApplicationException("Tag cfselect must be inside a cfform tag"); 344 } 345 346 347 pageContext.forceWrite("<select"); 348 349 Iterator<Entry<Key, Object>> it = attributes.entryIterator(); 350 Entry<Key, Object> e; 351 while(it.hasNext()) { 352 e = it.next(); 353 pageContext.forceWrite(" "); 354 pageContext.forceWrite(e.getKey().getString()); 355 pageContext.forceWrite("=\""); 356 pageContext.forceWrite(enc(Caster.toString(e.getValue()))); 357 pageContext.forceWrite("\""); 358 } 359 360 if(passthrough!=null) { 361 pageContext.forceWrite(" "); 362 pageContext.forceWrite(passthrough); 363 } 364 pageContext.forceWrite(">\n"); 365 366 367 if(bodyContent!=null && queryPosition==QUERY_POSITION_BELOW)pageContext.forceWrite(bodyContent.getString()); 368 369 // write query options 370 if(query!=null) { 371 int rowCount=query.getRowCount(); 372 String v,d,currentGroup=null,tmp; 373 boolean hasDisplay=display!=null; 374 boolean hasGroup=group!=null; 375 376 for(int i=1;i<=rowCount;i++) { 377 v = Caster.toString(query.getAt(value,i)); 378 d = hasDisplay?Caster.toString(query.getAt(display,i)):v; 379 if(hasGroup) { 380 tmp=Caster.toString(query.getAt(group,i)); 381 if(currentGroup==null || !Operator.equals(currentGroup,tmp,true)) { 382 if(currentGroup!=null)pageContext.forceWrite("</optgroup>\n"); 383 pageContext.forceWrite("<optgroup label=\""+tmp+"\">\n "); 384 currentGroup=tmp; 385 } 386 } 387 pageContext.forceWrite("<option"+selected(v,selected)+" value=\""+v+"\">"+d+"</option>\n"); 388 } 389 if(hasGroup)pageContext.forceWrite("</optgroup>\n"); 390 } 391 392 if(bodyContent!=null && queryPosition==QUERY_POSITION_ABOVE)pageContext.forceWrite(bodyContent.getString()); 393 pageContext.forceWrite("</select>"); 394 395 396 397 398 } 399 400 private String selected(String str, String[] selected) { 401 if(selected!=null) { 402 for(int i=0;i<selected.length;i++) { 403 if(caseSensitive) { 404 if(str.compareTo(selected[i])==0) return " selected"; 405 } 406 else { 407 if(Operator.compare(str,selected[i])==0) return " selected"; 408 } 409 //if(Operator.compare(str,selected[i])==0) return " selected"; 410 } 411 } 412 return ""; 413 } 414 415 416 417 /** 418 * html encode a string 419 * @param str string to encode 420 * @return encoded string 421 */ 422 private String enc(String str) { 423 return HTMLEntities.escapeHTML(str,HTMLEntities.HTMLV20); 424 } 425 426 /** 427 * @param editable the editable to set 428 * @throws ApplicationException 429 */ 430 public void setEditable(boolean editable) { 431 this.editable=editable; 432 } 433 434 /** 435 * @param group the group to set 436 * @throws ApplicationException 437 */ 438 public void setGroup(String group) { 439 this.group=group; 440 } 441 442 /** 443 * @param height the height to set 444 * @throws ApplicationException 445 */ 446 public void setHeight(double height) { 447 this.height=(int)height; 448 } 449 450 /** 451 * @param label the label to set 452 * @throws ApplicationException 453 */ 454 public void setLabel(String label) { 455 this.label=label; 456 } 457 458 /** 459 * @param queryPosition the queryPosition to set 460 * @throws ApplicationException 461 */ 462 public void setQueryposition(String strQueryPosition) throws ApplicationException { 463 strQueryPosition=strQueryPosition.trim().toLowerCase(); 464 if( "above".equals(strQueryPosition)) queryPosition=QUERY_POSITION_ABOVE; 465 else if( "below".equals(strQueryPosition)) queryPosition=QUERY_POSITION_BELOW; 466 else 467 throw new ApplicationException("attribute queryPosition for tag select has an invalid value ["+strQueryPosition+"], " + 468 "valid values are [above, below]"); 469 470 } 471 472 /** 473 * @param tooltip the tooltip to set 474 * @throws ApplicationException 475 */ 476 public void setTooltip(String tooltip) { 477 this.tooltip=tooltip; 478 } 479 480 /** 481 * @param visible the visible to set 482 * @throws ApplicationException 483 */ 484 public void setVisible(boolean visible) { 485 this.visible=visible; 486 } 487 488 /** 489 * @param width the width to set 490 * @throws ApplicationException 491 */ 492 public void setWidth(double width) { 493 this.width=(int) width; 494 } 495 /** 496 * @param width the width to set 497 * @throws ApplicationException 498 */ 499 public void setEnabled(String enabled) { 500 setDisabled(!Caster.toBooleanValue(enabled,true)); 501 } 502 503 /** 504 * @param caseSensitive the caseSensitive to set 505 */ 506 public void setCasesensitive(boolean caseSensitive) { 507 this.caseSensitive = caseSensitive; 508 } 509 }