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    }