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();