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/25 12:34:27 UTC

svn commit: r679751 - in /myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/dialog: AbstractModalDialog.java ModalDialogRenderer.java

Author: skitching
Date: Fri Jul 25 03:34:26 2008
New Revision: 679751

URL: http://svn.apache.org/viewvc?rev=679751&view=rev
Log:
Add "contentURL" property to s:modalDialog as an alternative to "viewId".
Add documentation.

Modified:
    myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/dialog/AbstractModalDialog.java
    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/AbstractModalDialog.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/dialog/AbstractModalDialog.java?rev=679751&r1=679750&r2=679751&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/dialog/AbstractModalDialog.java (original)
+++ myfaces/tomahawk/trunk/sandbox/core/src/main/java/org/apache/myfaces/custom/dialog/AbstractModalDialog.java Fri Jul 25 03:34:26 2008
@@ -24,7 +24,34 @@
 import org.apache.myfaces.custom.dojo.DojoWidget;
 
 /**
- * Modal Dojo Dialog (is not working with overridden 'onload')
+ * Embeds into the current page a javascript object with methods which can be called to
+ * display (and hide) a modal popup window. 
+ * <p>
+ * When the popup window is displayed, the current window contents become "greyed out" and
+ * the new window appears on top of the original. The original window does not respond to 
+ * keys or clicks; only the new window can be accessed by the user. When the popup window
+ * is closed then the original window is again accessable.
+ * <p>
+ * When this component has a child facet named "titleBar" then the contents of that facet
+ * are rendered at the top of the popup window. This facet is intended to allow users to
+ * define their own custom window "decoration".
+ * <p>
+ * When this component has no "titleBar" facet, but does have a "dialogTitle" property,
+ * then a default window decoration is generated. It consists of a table row with two
+ * cells. The left cell contains the dialogTitle text. If property renderCloseButton is
+ * true, then the right cell holds a "close" icon. Styles are defined for the row and
+ * cells so that the look-and-feel can be customised.
+ * <p>
+ * The new window can optionally load a page from the server when it is displayed. If
+ * one of viewId or contentURL is defined, then an internal frame is inserted after the
+ * titleBar, and the specified contents is immediately loaded into the popup window when
+ * it is displayed.
+ * <p>
+ * The rest of the child components (ie other than titleBar) are displayed after the
+ * titlebar (and after the contents of viewId or contentURL if it is defined).
+ * <p>
+ * This component internally uses the Dojo modal window widget.
+ * <p>  
  * 
  * @JSFComponent
  *   name = "s:modalDialog"
@@ -46,14 +73,27 @@
     public abstract String getDialogAttr();
 
     /**
-     * The id to control the dialog (dojo widget) with javascript.
+     * An optional raw id to assign to the html div that encloses the modal dialog.
+     * <p>
+     * This id can be useful for controlling the dialog with javascript. However in most
+     * cases it is not necessary.
+     * <p>
+     * If this is property is not defined then an id will be automatically generated.
      * 
      * @JSFProperty
      */
     public abstract String getDialogId();
 
     /**
-     * The name of the variable to control the dialog (dojo widget) with javascript.
+     * Specifies the name of the javascript variable which provides access to the
+     * dialog functionality.
+     * <p>
+     * For example, if this is "myDialog" then a javascript object with name
+     * "myDialog" will be defined. This exposes the following methods:
+     * <ul>
+     * <li>myDialog.show() will display the modal dialog window
+     * <li>myDialog.hide() will hide it (though this is not normally needed). 
+     * </ul>
      * 
      * @JSFProperty
      */
@@ -62,19 +102,57 @@
     public abstract void setDialogVar(String dialogVar);
 
     /**
-     * A comma separated list with ids of input-elements, which can tell (by javascript-code) the dialog to hide.
+     * A list of ids of components which, when activated, should cause the popup
+     * dialog to be hidden.
+     * <p>
+     * If the standard title-bar is displayed (ie no custom titleBar facet exists,
+     * and property dialogTitle is defined) then the standard close-button in that
+     * bar is automatically included.
+     * <p>
+     * If the child components of this component (which will appear in the popup)
+     * include other items that should cause the window to close (ie a button) then
+     * their ids should be defined via this property. This component will then
+     * automatically wire them up to the necessary functions to cause the popup
+     * to be closed when they are activated.
      * 
      * @JSFProperty
      */
     public abstract String getHiderIds();
 
     /**
-     * The URL of the view to show within the content area of the dialog
+     * The URL of the view to show within the content area of the dialog.
+     * <p>
+     * Optional; when not defined (or defined as an EL expression, but that expression returns null)
+     * then the popup dialog will be opened with no content. Presumably custom javascript in the
+     * calling page will arrange to populate the window content appropriately.
+     * <p>
+     * The modalDialog component treats this as a <i>url</i> relative to the webapp base. The value
+     * should not start with a slash.
+     * <p> 
+     * Note that technically this value is not a viewId. A viewId is the internal path to the
+     * page definition (eg "foo.jsp" or "foo.xhtml"). What the browser accesses is a URL (which
+     * contains the path that triggers the facelets servlet, eg "foo.faces" or "foo.jsf" or
+     * "/faces/foo". 
+     * The valueIt should not start with a slash.
      * 
      * @JSFProperty
      */
     public abstract String getViewId();
 
+    /**
+     * The URL to show within the content area of the dialog.
+     * <p>
+     * This may be:
+     * <ul>
+     * <li>an absolute url ("http://..")</li>
+     * <li>a url relative to the current webapp</li>
+     * <li>a url relative to the current page</li>
+     * </ul>
+     * 
+     * @JSFProperty
+     */
+    public abstract String getContentURL();
+
     //@Override
     public boolean getRendersChildren() {
         return true;
@@ -89,6 +167,10 @@
 
     /**
      * The CSS class for this element. Corresponds to the HTML 'class' attribute.
+     * <p>
+     * This value is also used as a base for defining style classes for parts of the
+     * standard window "title bar" decoration.
+     * 
      * 
      * @JSFProperty
      */
@@ -102,22 +184,32 @@
     public abstract String getWidgetId();
 
     /**
-     * The title text to show in the title area
+     * The title text to show in the title area of the popup window 
+     * (ie the "window decoration").
+     * <p>
+     * Ignored if there is a "titleBar" facet as a child.
      * 
      * @JSFProperty
      */
     public abstract String getDialogTitle();
 
     /**
-     * true|false - Set to true if a close button should be rendere within the 
-     * title area (requires a dialogTitle)
+     * Specifies whether there should be a "close" icon to the right of the
+     * popup window title.
+     * <p>
+     * Ignored if there is a "titleBar" facet as a child, or dialogTitle is
+     * not defined. 
+     * <p>
+     * Defaults to true.
      * 
      * @JSFProperty
      */
     public abstract Boolean getCloseButton();
 
     /**
-     * optional widget var name, if this is not used only an autogenerated value is set
+     * An alias for the "dialogVar" property.
+     *
+     * @deprecated use getDialogVar instead.
      * 
      * @JSFProperty
      */

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=679751&r1=679750&r2=679751&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 Fri Jul 25 03:34:26 2008
@@ -106,6 +106,8 @@
 
         if (dlg.getViewId() != null)
         {
+            // when getViewId is set, we did not render the children in the
+            // encodeChildren method, so instead do it now.
             RendererUtils.renderChildren(context, component);
             HtmlRendererUtils.writePrettyLineSeparator(context);
         }
@@ -227,7 +229,7 @@
             .append(dialogVar)
             .append(" = dojo.widget.createWidget(\"dialog\", {id:")
             .append("\"")
-            .append(dlg.getDialogId())
+            .append(dlgId)
             .append("\"");
 
         appendDialogAttributes(buf, dlg);
@@ -236,9 +238,21 @@
 
         appendHiderIds(buf, dlg);
 
-        if (dlg.getViewId() != null)
+        String viewId = dlg.getViewId();
+        String contentURL = dlg.getContentURL();
+        if (viewId != null)
+        {
+            StringBuffer sbUrl = new StringBuffer();
+            sbUrl.append(context.getExternalContext().getRequestContextPath());
+            sbUrl.append("/");
+            sbUrl.append(viewId);
+            String encodedUrl = context.getExternalContext().encodeActionURL(sbUrl.toString());
+            appendShowHideView(context, buf, dialogVar, encodedUrl);
+        }
+        else if (contentURL != null)
         {
-            appendShowHideView(context, buf, dlg);
+            String encodedUrl = context.getExternalContext().encodeActionURL(contentURL);
+            appendShowHideView(context, buf, dialogVar, encodedUrl);
         }
 
         buf.append("}");
@@ -268,16 +282,12 @@
      * 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)
+    private void appendShowHideView(
+            FacesContext context,
+            StringBuffer buf,
+            String dialogVar,
+            String url)
     {
-        StringBuffer sbUrl = new StringBuffer();
-        sbUrl.append(context.getExternalContext().getRequestContextPath());
-        sbUrl.append("/");
-        sbUrl.append(dlg.getViewId());
-        String encodedUrl = context.getExternalContext().encodeActionURL(sbUrl.toString());
-
-        String dialogVar = dlg.getDialogVar();
-
         // save original onShow function (the standard dojo widget implementation)
         buf .append(dialogVar)
             .append(".oldOnShow=")
@@ -286,7 +296,8 @@
 
         // 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.
+        // defined by the "url" parameter (which is defined via property viewId
+        // or contentURL on the JSF component).
         //
         // TODO: What is the purpose of variable window._myfaces_currentModal?
         // There doesn't appear to be anything that *reads* it...
@@ -305,7 +316,7 @@
             .append(dialogVar)
             .append("._myfaces_ok=false; ")
             .append("content.contentWindow.location.replace('")
-            .append(encodedUrl)
+            .append(url)
             .append("'); ")
             .append("}; ");
 
@@ -335,12 +346,20 @@
     }
 
     /**
-     * Override normal "encodeChildren" method to either render the children in
-     * normal manner, or to render an IFrame instead.
+     * Override normal "encodeChildren" method to render the necessary dynamic
+     * parts of this component as well as the children.
+     * <p>
+     * If the user specified a titleBar facet, then that is rendered as the
+     * "window decoration" for the popup window. Otherwise if the user specified
+     * a dialogTitle, then a standard "window decoration" is rendered.
      * <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.
+     * Then if the user did NOT specify a content page to be loaded into the popup,
+     * then the rest of the child components are rendered as normal.
+     * <p>
+     * But if the user DID specify a content page to be loaded, then an empty
+     * IFrame is rendered (javascript will be used to load it later), and the
+     * rendering of the child components is delayed until the encodeEnd method.
+     * TODO: why is child component rendering delayed?
      *
      * @see javax.faces.render.Renderer#encodeChildren(javax.faces.context.FacesContext,
      *      javax.faces.component.UIComponent)
@@ -389,9 +408,12 @@
             writer.endElement(HTML.TABLE_ELEM);
         }
 
-        if (dlg.getViewId() != null)
+        if ((dlg.getViewId() != null) || (dlg.getContentURL() != null))
         {
             renderDialogViewFrame(facesContext, dlg);
+            // TODO: why are the rest of the child components not rendered here?
+            // is it so that subclasses of this component can insert stuff between
+            // the iframe and the normal children? 
         }
         else
         {
@@ -416,7 +438,7 @@
     }
 
     /**
-     * Invoked only when the ModalDialog component has property viewId defined.
+     * Invoked only when the ModalDialog component has property viewId or contentURL defined.
      */
     private void renderDialogViewFrame(FacesContext facesContext, ModalDialog dlg) throws IOException
     {