001 package edu.nrao.sss.webapp.faces.component; 002 003 import edu.nrao.sss.webapp.faces.renderer.RendererUtils; 004 005 import javax.faces.context.FacesContext; 006 import javax.faces.context.ResponseWriter; 007 import javax.faces.el.ValueBinding; 008 import javax.faces.component.UIComponentBase; 009 import javax.faces.component.UIComponent; 010 011 import java.io.IOException; 012 013 /** 014 * Provides a Floating dialog component that is popped up when a link is 015 * clicked. The contents of the link tag are the contents of the "linkContent" 016 * facet. <code>linkStyleClass</code> is rendered as the class of the 017 * <code>a</code> tag. The child components of this component are rendered 018 * inside a <code>div</code> as the contents of the popup dialog itself. 019 * <p> 020 * The styleClass attribute is rendered as the class attribute of a 021 * <code>div</code> wrapper around both the link and the hidden popup div. This 022 * attribute is usually specified and the associated css style usually has the 023 * position attribute set to either absolute or relative. This gives a new frame 024 * of reference for the popup dialog to be positioned at. However, since the 025 * dialogStyleClass attribute is mapped to the class attribute of the popup 026 * div, the user can position that popup anywhere really. 027 * </p> 028 * <p> 029 * This class (and it's javascript) is aware of the javascript double 030 * submission solution that was implemented to prevent users from submitting a 031 * for multiple times. That solution uses a flag named <code>processing</code> 032 * to determine if it should allow a link to be clicked. Since we clicked a 033 * link to get the dialog to popup, the page would now disallow anymore buttons 034 * or links to be clicked until the page reloaded....clearly this will not work 035 * here. Therefore, the javascript here sets the processing flag to false if it 036 * exists. 037 * </p> 038 */ 039 public class FloatingDialogUIComponent extends UIComponentBase 040 { 041 //This javascript displays our popup 042 private static final String javaScriptBegin = "var element = document.getElementById('"; 043 private static final String javaScriptEnd = "');" + 044 "element.style.display='block'; return false;"; 045 046 public static final String LINK_CONTENT_FACET_NAME = "linkContent"; 047 048 private Boolean enabled = null, 049 openOnMouseOver = null, 050 openOnClick = null, 051 closeOnMouseOut = null, 052 closeOnClick = null; 053 054 private String title = null; 055 private String linkId = null; 056 057 public FloatingDialogUIComponent() 058 { 059 setRendererType(null); 060 } 061 062 public boolean getRendersChildren() 063 { 064 return true; 065 } 066 067 public void encodeBegin(FacesContext context) 068 throws IOException 069 { 070 if (!isRendered()) 071 return; 072 073 String linkStyleClass = (String)getAttributes().get("linkStyleClass"); 074 String disabledLinkStyleClass = (String)getAttributes().get("disabledLinkStyleClass"); 075 String dialogStyleClass = (String)getAttributes().get("dialogStyleClass"); 076 String styleClass = (String)getAttributes().get("styleClass"); 077 078 String id = getClientId(context); 079 String dialogId = id + ":popup"; 080 081 ResponseWriter writer = context.getResponseWriter(); 082 writer.write('\n'); 083 writer.write('\n'); 084 085 //Start a wrapper div with position: relative so the popup can be 086 //positioned relative to it. 087 writer.startElement("div", this); 088 writer.writeAttribute("id", id, null); 089 090 if (styleClass != null) 091 writer.writeAttribute("class", styleClass, null); 092 093 writer.write('\n'); 094 095 //This is our link section. Needs to be retrieved from the facet. 096 String title = getTitle(); 097 String lid = getLinkId(); 098 099 if (isEnabled()) 100 { 101 writer.startElement("a", this); 102 writer.writeAttribute("href", "#", null); 103 104 if (lid != null) 105 writer.writeAttribute("id", id + ":" + lid, null); 106 107 if (title != null) 108 writer.writeAttribute("title", title, null); 109 110 if (linkStyleClass != null) 111 writer.writeAttribute("class", linkStyleClass, null); 112 113 String onclick = javaScriptBegin + dialogId + javaScriptEnd; 114 if (getOpenOnClick()) 115 writer.writeAttribute("onclick", onclick, null); 116 117 if (getOpenOnMouseOver()) 118 writer.writeAttribute("onmouseover", onclick, null); 119 } 120 121 else 122 { 123 writer.startElement("span", this); 124 125 if (lid != null) 126 writer.writeAttribute("id", lid, null); 127 128 if (title != null) 129 writer.writeAttribute("title", title, null); 130 131 if (disabledLinkStyleClass != null) 132 writer.writeAttribute("class", disabledLinkStyleClass, null); 133 } 134 135 writer.write('\n'); 136 137 UIComponent linkContent = getFacet(LINK_CONTENT_FACET_NAME); 138 if (linkContent != null) 139 { 140 RendererUtils.renderChild(context, linkContent); 141 } 142 143 if (isEnabled()) 144 { 145 writer.endElement("a"); 146 } 147 148 else 149 { 150 writer.endElement("span"); 151 } 152 153 writer.write('\n'); 154 155 //This is our popupDialog 156 writer.startElement("div", this); 157 writer.writeAttribute("id", dialogId, null); 158 writer.writeAttribute("style", "display:none;", null); 159 160 if (dialogStyleClass != null) 161 writer.writeAttribute("class", dialogStyleClass, null); 162 163 if (getCloseOnMouseOut()) 164 writer.writeAttribute("onmouseout", "this.style.display='none';", null); 165 166 if (getCloseOnClick()) 167 { 168 writer.writeAttribute("onclick", "this.style.display='none';", null); 169 } 170 171 writer.write('\n'); 172 //render our children as the contents of our dialog in the encodeChildren 173 //method. 174 } 175 176 public void encodeChildren(FacesContext context) 177 throws IOException 178 { 179 if (!isRendered()) 180 return; 181 182 RendererUtils.renderChildren(context, this); 183 } 184 185 /** 186 * closes our popup dialog's div 187 */ 188 public void encodeEnd(FacesContext context) 189 throws IOException 190 { 191 if (!isRendered()) 192 return; 193 194 ResponseWriter writer = context.getResponseWriter(); 195 196 writer.write('\n'); 197 198 //End the hidden popup 199 writer.endElement("div"); 200 writer.write('\n'); 201 202 //End the wrapper; 203 writer.endElement("div"); 204 writer.write('\n'); 205 writer.write('\n'); 206 } 207 208 public Boolean isEnabled() 209 { 210 if (this.enabled != null) 211 return this.enabled; 212 213 ValueBinding vb = getValueBinding("enabled"); 214 if (vb != null) 215 { 216 Object val = vb.getValue(getFacesContext()); 217 218 if (val instanceof Boolean && val != null) 219 return (Boolean)val; 220 } 221 222 //else 223 return Boolean.TRUE; 224 } 225 226 public void setEnabled(Boolean e) 227 { 228 this.enabled = e; 229 } 230 231 public void setOpenOnMouseOver(Boolean o) 232 { 233 this.openOnMouseOver = o; 234 } 235 236 public Boolean getOpenOnMouseOver() 237 { 238 if (this.openOnMouseOver != null) 239 return this.openOnMouseOver; 240 241 ValueBinding vb = getValueBinding("openOnMouseOver"); 242 if (vb != null) 243 { 244 Object val = vb.getValue(getFacesContext()); 245 246 if (val instanceof Boolean && val != null) 247 return (Boolean)val; 248 } 249 250 //else 251 return Boolean.FALSE; 252 } 253 254 public void setOpenOnClick(Boolean o) 255 { 256 this.openOnClick = o; 257 } 258 259 public Boolean getOpenOnClick() 260 { 261 if (this.openOnClick != null) 262 return this.openOnClick; 263 264 ValueBinding vb = getValueBinding("openOnClick"); 265 if (vb != null) 266 { 267 Object val = vb.getValue(getFacesContext()); 268 269 if (val instanceof Boolean && val != null) 270 return (Boolean)val; 271 } 272 273 //else 274 return Boolean.TRUE; 275 } 276 277 public void setCloseOnMouseOut(Boolean c) 278 { 279 this.closeOnMouseOut = c; 280 } 281 282 public Boolean getCloseOnMouseOut() 283 { 284 if (this.closeOnMouseOut != null) 285 return this.closeOnMouseOut; 286 287 ValueBinding vb = getValueBinding("closeOnMouseOut"); 288 if (vb != null) 289 { 290 Object val = vb.getValue(getFacesContext()); 291 292 if (val instanceof Boolean && val != null) 293 return (Boolean)val; 294 } 295 296 //else 297 return Boolean.FALSE; 298 } 299 300 public void setCloseOnClick(Boolean c) 301 { 302 this.closeOnClick = c; 303 } 304 305 public Boolean getCloseOnClick() 306 { 307 if (this.closeOnClick != null) 308 return this.closeOnClick; 309 310 ValueBinding vb = getValueBinding("closeOnClick"); 311 if (vb != null) 312 { 313 Object val = vb.getValue(getFacesContext()); 314 315 if (val instanceof Boolean && val != null) 316 return (Boolean)val; 317 } 318 319 //else 320 return Boolean.FALSE; 321 } 322 323 public String getTitle() 324 { 325 if (this.title != null) 326 return this.title; 327 328 ValueBinding vb = getValueBinding("title"); 329 if (vb != null) 330 { 331 Object val = vb.getValue(getFacesContext()); 332 333 if (val instanceof String && val != null) 334 return (String)val; 335 } 336 337 //else 338 return null; 339 } 340 341 public void setTitle(String t) 342 { 343 this.title = t; 344 } 345 346 public String getLinkId() 347 { 348 if (this.linkId != null) 349 return this.linkId; 350 351 ValueBinding vb = getValueBinding("linkId"); 352 if (vb != null) 353 { 354 Object val = vb.getValue(getFacesContext()); 355 356 if (val instanceof String && val != null) 357 return (String)val; 358 } 359 360 //else 361 return null; 362 } 363 364 public void setLinkId(String id) 365 { 366 this.linkId = id; 367 } 368 369 public Object saveState(FacesContext context) 370 { 371 Object[] state = new Object[8]; 372 state[0] = super.saveState(context); 373 state[1] = this.enabled; 374 state[2] = this.title; 375 state[3] = this.linkId; 376 state[4] = this.openOnMouseOver; 377 state[5] = this.openOnClick; 378 state[6] = this.closeOnMouseOut; 379 state[7] = this.closeOnClick; 380 381 return state; 382 } 383 384 public void restoreState(FacesContext context, Object state) 385 { 386 Object[] myState = (Object[])state; 387 super.restoreState(context, myState[0]); 388 setEnabled((Boolean)myState[1]); 389 setTitle((String)myState[2]); 390 setLinkId((String)myState[3]); 391 setOpenOnMouseOver((Boolean)myState[4]); 392 setOpenOnClick((Boolean)myState[5]); 393 setCloseOnMouseOut((Boolean)myState[6]); 394 setCloseOnClick((Boolean)myState[7]); 395 } 396 397 public String getFamily() 398 { 399 return "NRAO"; 400 } 401 }