You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2008/07/14 11:07:39 UTC
svn commit: r676517 -
/myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/dialog/ModalDialogRenderer.java
Author: skitching
Date: Mon Jul 14 02:07:38 2008
New Revision: 676517
URL: http://svn.apache.org/viewvc?rev=676517&view=rev
Log:
Add comments, clean up code layout. No logic changes.
Modified:
myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/dialog/ModalDialogRenderer.java
Modified: myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/dialog/ModalDialogRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/dialog/ModalDialogRenderer.java?rev=676517&r1=676516&r2=676517&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/dialog/ModalDialogRenderer.java (original)
+++ myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/dialog/ModalDialogRenderer.java Mon Jul 14 02:07:38 2008
@@ -38,21 +38,47 @@
import java.util.StringTokenizer;
/**
+ * Renderer for the s:modalDialog component.
+ * <p>
+ * This component works in one of two different ways:
+ * <ul>
+ * <li>The component can contain child components, in which case the child components
+ * are initially hidden but are displayed in a "popup" modal window when the "show"
+ * javascript method is invoked. In this mode, a DIV is rendered to wrap the child
+ * components.
+ * <li>The component can have a "viewId" property defined, in which case the specified
+ * JSF view will be fetched into a "popup" modal window when the "show" javascript
+ * method is invoked. In this mode, a DIV containing an IFrame is rendered into the
+ * html page; the iframe is used to load the specified view.
+ * </ul>
+ * It is the page author's responsibility to have some other HTML control on the
+ * page whose "onclick" attribute contains javascript to invoke the "show" method
+ * of the modal dialog. Component property "dialogVar" specifies the name of a global
+ * javascript variable to be created, and its "show" method can be invoked to display
+ * the popup.
+ * <p>
+ * The Dojo library uses css tricks to make the DIV component act like a modal
+ * window.
*
* @JSFRenderer
* renderKitId = "HTML_BASIC"
* family = "javax.faces.Panel"
* type = "org.apache.myfaces.ModalDialog"
- *
*/
-public class ModalDialogRenderer extends HtmlRenderer {
+public class ModalDialogRenderer extends HtmlRenderer
+{
public static final String RENDERER_TYPE = "org.apache.myfaces.ModalDialog";
public static final String DIV_ID_PREFIX = "_div";
+ /**
+ * Writes a DIV opening tag, plus javascript to make sure that the Dojo
+ * library is initialised.
+ */
//@Override
public void encodeBegin(FacesContext context, UIComponent component)
- throws IOException {
+ throws IOException
+ {
String javascriptLocation = (String) component.getAttributes().get(JSFAttr.JAVASCRIPT_LOCATION);
DojoUtils.addMainInclude(context, component, javascriptLocation,
DojoUtils.getDjConfigInstance(context));
@@ -62,7 +88,12 @@
}
//@Override
- public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
+ /**
+ * Writes a DIV closing tag, plus javascript to declare the global "dialogVar"
+ * object that can be invoked to show the modal dialog.
+ */
+ public void encodeEnd(FacesContext context, UIComponent component) throws IOException
+ {
ModalDialog dlg = (ModalDialog) component;
StringBuffer buf = new StringBuffer();
@@ -88,6 +119,7 @@
{
hiders.addAll(Arrays.asList(dlg.getHiderIds().split(",")));
}
+
if (isRenderCloseButton(dlg) && dlg.getDialogTitle() != null)
{
hiders.add(dlg.getDialogVar() + "Closer");
@@ -96,15 +128,26 @@
for (int i = 0; i < hiders.size(); i++)
{
String varName = "btn" + i;
- buf.append("var ").append(varName).append(" = document.getElementById(\"")
- .append(((String) hiders.get(i)).trim()).append("\");")
- .append(dlg.getDialogVar()).append(".setCloseControl(").append(varName).append(");");
+ buf
+ .append("var ")
+ .append(varName)
+ .append(" = document.getElementById(\"")
+ .append(((String) hiders.get(i)).trim())
+ .append("\");")
+
+ .append(dlg.getDialogVar())
+ .append(".setCloseControl(")
+ .append(varName)
+ .append(");");
}
}
- private void appendDialogAttributes(StringBuffer buf, ModalDialog dlg) {
+ private void appendDialogAttributes(StringBuffer buf, ModalDialog dlg)
+ {
if(dlg.getDialogAttr() == null)
+ {
return;
+ }
StringTokenizer it = new StringTokenizer(dlg.getDialogAttr(), " ");
while(it.hasMoreElements())
@@ -112,27 +155,43 @@
String[] pair = it.nextToken().split("=");
String attribute = pair[0];
String value = pair[1].replaceAll("'", "");
- try {
+ try
+ {
Double number = new Double(value);
}
- catch(NumberFormatException e) {
+ catch(NumberFormatException e)
+ {
value = new StringBuffer("\"").append(value).append("\"").toString();
}
- buf.append(", ").append(attribute).append(":").append(value);
+ buf
+ .append(", ")
+ .append(attribute)
+ .append(":")
+ .append(value);
}
}
- private void writeModalDialogBegin(FacesContext context, ModalDialog dlg, ResponseWriter writer) throws IOException {
+ /**
+ * Write an html DIV whose css style the Dojo library will manipulate to make it
+ * look like a popup window.
+ * <p>
+ * The child components (or the nested iframe) will be rendered inside this div.
+ */
+ private void writeModalDialogBegin(FacesContext context, ModalDialog dlg, ResponseWriter writer)
+ throws IOException
+ {
StringBuffer buf = new StringBuffer();
- // writeDialogLoader(context, dlg, buf);
-
String dlgId = getDialogId(dlg);
buf.append("<div id=\"").append(dlgId).append("\"");
if(dlg.getStyle() != null)
+ {
buf.append(" style=\"").append(dlg.getStyle()).append("\"");
+ }
if(dlg.getStyleClass() != null)
+ {
buf.append(" class=\"").append(dlg.getStyleClass()).append("\"");
+ }
buf.append(">");
writer.write(buf.toString());
@@ -146,14 +205,30 @@
return dlgId;
}
+ /**
+ * Write a javascript block that declares a single global variable of type Object that
+ * provides methods for showing and hiding the modal dialog.
+ * <p>
+ * The name of the javascript variable is specified by component property "dialogVar".
+ */
private String writeDialogLoader(FacesContext context, ModalDialog dlg, StringBuffer buf)
{
String dlgId = getDialogId(dlg);
- buf.append("<script type=\"text/javascript\">")
- .append("var ").append(dlg.getDialogVar()).append(";")
- .append("function "+dlg.getDialogVar()+"_loader(e) {").append(dlg.getDialogVar())
- .append(" = dojo.widget.createWidget(\"dialog\", {id:")
- .append("\"").append(dlg.getDialogId()).append("\"");
+ String dialogVar = dlg.getDialogVar();
+ buf.append("<script type=\"text/javascript\">");
+
+ // Declare a global variable whose name is specified by dialogVar.
+ // This variable will be initialized to point to a Dojo Widget object
+ // when page load is complete.
+ buf.append("var ").append(dialogVar).append(";");
+
+ // Declare a function that will be called on page load to initialize dialogVar
+ buf .append("function " + dialogVar + "_loader(e) {")
+ .append(dialogVar)
+ .append(" = dojo.widget.createWidget(\"dialog\", {id:")
+ .append("\"")
+ .append(dlg.getDialogId())
+ .append("\"");
appendDialogAttributes(buf, dlg);
@@ -166,19 +241,33 @@
appendShowHideView(context, buf, dlg);
}
- buf.append("}")
+ buf.append("}");
- // do not user timout, else you'll break the submitOnEvent component
- // .append("setTimeout('"+dlg.getDialogVar()+"_loader();', 50);")
- // do not user direct loading, else you'll break IE sometimes (always?)
- // .append(dlg.getDialogVar()+"_loader();")
- // looks like this works best for now
- .append("dojo.addOnLoad(function() {"+dlg.getDialogVar()+"_loader();});")
+ // Emit some global javascript that causes the initialization function
+ // defined above.
+ //
+ // We cannot use a standard javascript setTimeout call, as this breaks the
+ // submitOnEvent component.
+ //
+ // We cannot call the loader function immediately, as it appears that this
+ // breaks IE sometimes (always?).
+ //
+ // So it looks like using dojo's addOnLoad function is the best solution..
+ buf.append("dojo.addOnLoad(function() {" + dialogVar + "_loader();});");
- .append("</script>");
+ buf.append("</script>");
return dlgId;
}
+ /**
+ * This is invoked only when the ModalDialog component has a viewId property
+ * defined, ie the dialog should automatically load a specific JSF view when
+ * it is shown.
+ * <p>
+ * Javascript is generated which override the standard Dojo modal dialog
+ * show and hide methods to do some initialisation, including loading the
+ * required view into the iframe.
+ */
private void appendShowHideView(FacesContext context, StringBuffer buf, ModalDialog dlg)
{
StringBuffer sbUrl = new StringBuffer();
@@ -187,30 +276,54 @@
sbUrl.append(dlg.getViewId());
String encodedUrl = context.getExternalContext().encodeActionURL(sbUrl.toString());
- buf.append(dlg.getDialogVar()).append(".oldOnShow=").append(dlg.getDialogVar()).append(".onShow;")
- .append(dlg.getDialogVar())
+ String dialogVar = dlg.getDialogVar();
+
+ // save original onShow function (the standard dojo widget implementation)
+ buf .append(dialogVar)
+ .append(".oldOnShow=")
+ .append(dialogVar)
+ .append(".onShow;");
+
+ // Define a new onShow function which first shows the modal window then
+ // causes it to do a GET to the server to fetch a specific page that is
+ // defined by the "viewId" property on the JSF component.
+ //
+ // TODO: What is the purpose of variable window._myfaces_currentModal?
+ // There doesn't appear to be anything that *reads* it...
+ //
+ // TODO: What is the purpose of ${dialogVar}._myfaces_ok? Nothing appears
+ // to read it.
+ buf .append(dialogVar)
.append(".onShow = function() {")
- .append("this.oldOnShow();")
+ .append("this.oldOnShow();")
.append("var content = document.getElementById(\"modalDialogContent")
- .append(dlg.getDialogVar())
+ .append(dialogVar)
.append("\"); ")
.append("window._myfaces_currentModal=")
- .append(dlg.getDialogVar())
+ .append(dialogVar)
.append("; ")
- .append(dlg.getDialogVar())
+ .append(dialogVar)
.append("._myfaces_ok=false; ")
.append("content.contentWindow.location.replace('")
.append(encodedUrl)
.append("'); ")
.append("}; ");
- buf.append(dlg.getDialogVar()).append(".oldOnHide=").append(dlg.getDialogVar()).append(".onHide;")
- .append(dlg.getDialogVar())
+ // save original onHide function (the standard dojo widget implementation)
+ buf .append(dialogVar)
+ .append(".oldOnHide=")
+ .append(dialogVar)
+ .append(".onHide;");
+
+ // Define a new onHide function which first shows the modal window then
+ // causes it to do a GET to the server to fetch a specific page that is
+ // defined by the "viewId" property on the JSF component.
+ buf .append(dialogVar)
.append(".onHide = function() {")
- .append("this.oldOnHide();")
+ .append("this.oldOnHide();")
.append("window._myfaces_currentModal=null;")
.append("var content = document.getElementById(\"modalDialogContent")
- .append(dlg.getDialogVar())
+ .append(dialogVar)
.append("\"); ")
.append("content.contentWindow.location.replace('javascript:false;'); ")
.append("}; ");
@@ -220,8 +333,14 @@
{
return true;
}
- /*
- * (non-Javadoc)
+
+ /**
+ * Override normal "encodeChildren" method to either render the children in
+ * normal manner, or to render an IFrame instead.
+ * <p>
+ * When the ModalDialog component has its "viewId" property set, then all
+ * children (except facets) are ignored, and instead an IFrame is rendered
+ * into which a specific JSF viewId will later be loaded.
*
* @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext,
* javax.faces.component.UIComponent)
@@ -296,6 +415,9 @@
return "";
}
+ /**
+ * Invoked only when the ModalDialog component has property viewId defined.
+ */
private void renderDialogViewFrame(FacesContext facesContext, ModalDialog dlg) throws IOException
{
ResponseWriter writer = facesContext.getResponseWriter();