You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by dr...@apache.org on 2007/08/22 18:10:44 UTC

svn commit: r568675 - in /myfaces/trinidad/trunk/trinidad: trinidad-build/src/main/resources/META-INF/maven-faces-plugin/components/trinidad/core/ trinidad-examples/trinidad-demo/src/main/webapp/components/ trinidad-impl/src/main/java/org/apache/myface...

Author: drobinson
Date: Wed Aug 22 09:10:43 2007
New Revision: 568675

URL: http://svn.apache.org/viewvc?rev=568675&view=rev
Log:
Enhanced panelPopup to have triggerType attribute for 'hover' and 'click'.

Modified:
    myfaces/trinidad/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/components/trinidad/core/CorePanelPopup.xml
    myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/webapp/components/panelPopup.jspx
    myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/PanelPopupRenderer.java
    myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/PanelPopup.js
    myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/renderkit/core/resource/CoreBundle.xrts

Modified: myfaces/trinidad/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/components/trinidad/core/CorePanelPopup.xml
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/components/trinidad/core/CorePanelPopup.xml?rev=568675&r1=568674&r2=568675&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/components/trinidad/core/CorePanelPopup.xml (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/components/trinidad/core/CorePanelPopup.xml Wed Aug 22 09:10:43 2007
@@ -45,7 +45,23 @@
       </facet-extension>
     </facet>
     <property>
-      <description><![CDATA[The text to render as a link to launch the popup panel.  If the 'trigger'
+      <description><![CDATA[Defines the launch behaviour of the popup.  If set to 'click' the popup will
+        appear when the trigger is clicked, and disappear when you click off the popup.  The 'hover' value
+        will cause the popup to appear while the mouse is over the trigger, and disappear when the mouse 
+        leaves either the trigger or the popup panel.]]>
+      </description>
+      <property-name>triggerType</property-name>
+      <property-class>java.lang.String</property-class>
+      <default-value>click</default-value>
+      <property-extension>
+        <mfp:property-values>click hover</mfp:property-values>
+        <mfp:property-metadata>
+          <mfp:preferred>true</mfp:preferred>
+        </mfp:property-metadata>
+      </property-extension>
+    </property>
+    <property>
+      <description><![CDATA[The icon to render as a link to launch the popup panel.  If the 'trigger'
         facet is defined, then this attribute is ignored.  If the 'text' attribute is also specified, 
         then the icon and text will both be rendered.
         ]]>
@@ -99,16 +115,38 @@
     </property>
     <property>
       <description><![CDATA[The position of the content container when visible. Defaults to
-         "none" (appears relative control), if not specified. Other values are "center" (centered on screen).]]>
+         "relative" if not specified. Other values are "centered" (centered on screen).]]>
       </description>
-      <property-name>alignment</property-name>
+      <property-name>position</property-name>
       <property-class>java.lang.String</property-class>
-      <default-value>none</default-value>
+      <default-value>relative</default-value>
       <property-extension>
-        <mfp:property-values>none center</mfp:property-values>
+        <mfp:property-values>relative centered</mfp:property-values>
         <mfp:property-metadata>
           <mfp:preferred>true</mfp:preferred>
         </mfp:property-metadata>
+      </property-extension>
+    </property>
+    <property>
+      <description><![CDATA[The popup's 'x' offset in pixels from the current mouse position.  
+        This property only applies to popups using relative positioning.]]>
+      </description>
+      <property-name>xOffset</property-name>
+      <property-class>int</property-class>
+      <default-value>0</default-value>
+      <property-extension>
+        <mfp:required>false</mfp:required>
+      </property-extension>
+    </property>
+    <property>
+      <description><![CDATA[The popup's 'y' offset in pixels from the current mouse position.  
+        This property only applies to popups using relative positioning.]]>
+      </description>
+      <property-name>yOffset</property-name>
+      <property-class>int</property-class>
+      <default-value>0</default-value>
+      <property-extension>
+        <mfp:required>false</mfp:required>
       </property-extension>
     </property>
     <property>

Modified: myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/webapp/components/panelPopup.jspx
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/webapp/components/panelPopup.jspx?rev=568675&r1=568674&r2=568675&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/webapp/components/panelPopup.jspx (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-examples/trinidad-demo/src/main/webapp/components/panelPopup.jspx Wed Aug 22 09:10:43 2007
@@ -33,8 +33,10 @@
             </f:facet>
             <tr:commandLink immediate="true" text="Component Guide"
                 action="guide"/>             
+
             <tr:outputFormatted styleUsage="instruction" value="&lt;b>Simple panelPopup&lt;/b>"/>
-            <tr:panelPopup binding="#{editor.component}" title="Popup Title" text="Click Here"> 
+
+            <tr:panelPopup binding="#{editor.component}" text="Click Here"> 
               <tr:panelGroupLayout layout="vertical"> 
                 <tr:goLink text="item 1" destination="http://www.apache.org"/>
                 <tr:goLink text="item 2" destination="http://www.apache.org"/>
@@ -47,7 +49,7 @@
     
             <tr:outputFormatted styleUsage="instruction" value="&lt;b>Simple PopupPanel&lt;/b>"/>
 
-            <tr:panelPopup text="Simple Popup">
+            <tr:panelPopup text="Hover Popup" triggerType="hover">
               <tr:panelGroupLayout layout="vertical">
                 <tr:outputText value="Line 1" />
                 <tr:outputText value="Line 2" />
@@ -56,11 +58,9 @@
               </tr:panelGroupLayout>
             </tr:panelPopup>
 
-            <tr:outputFormatted styleUsage="instruction" value="&lt;b>PopupPanel containing Date Picker&lt;/b>"/>
-
             <tr:outputFormatted styleUsage="instruction" value="&lt;b>PopupPanel as modal dialog&lt;/b>"/>
 
-            <tr:panelPopup text="Modal Centered Test" title="Centered Panel" alignment="center" modal="true">
+            <tr:panelPopup text="Modal Centered Test" title="Centered Panel" position="centered" modal="true">
               <tr:panelBox>
                 <tr:outputText value="This popup should be centered on screen and modal" />
               </tr:panelBox>
@@ -68,7 +68,7 @@
 
             <tr:outputFormatted styleUsage="instruction" value="&lt;b>PopupPanel of a fixed size with scrolling&lt;/b>"/>
 
-            <tr:panelPopup text="Fixed Size Popup Test" title="Fixed Size Panel" height="300" width="100">
+            <tr:panelPopup text="Fixed Size Popup Test" title="Fixed Size Panel" height="100" width="120">
               <tr:panelBox>
                 <tr:outputText value="This popup is a fixed size.  The content of this popup should be scrollable." />
               </tr:panelBox>

Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/PanelPopupRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/PanelPopupRenderer.java?rev=568675&r1=568674&r2=568675&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/PanelPopupRenderer.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/PanelPopupRenderer.java Wed Aug 22 09:10:43 2007
@@ -24,7 +24,9 @@
 import org.apache.myfaces.trinidad.component.core.layout.CorePanelPopup;
 import org.apache.myfaces.trinidad.context.RenderingContext;
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
 import org.apache.myfaces.trinidad.skin.Icon;
+import org.apache.myfaces.trinidad.util.Service;
 
 /**
  * @author Danny Robinson
@@ -52,11 +54,15 @@
     super.findTypeConstants(type);
     _textKey = type.findKey("text");
     _titleKey = type.findKey("title");
-    _alignmentKey = type.findKey("alignment");
+    _triggerTypeKey = type.findKey("triggerType");
+    _positionKey = type.findKey("position");
     _modalKey = type.findKey("modal");
     _contentStyleKey = type.findKey("contentStyle");
     _widthKey = type.findKey("width");
     _heightKey = type.findKey("height");
+    _xOffsetKey = type.findKey("xOffset");
+    _yOffsetKey = type.findKey("yOffset");
+    _triggerRenderer = new TriggerRenderer();
   }
 
   protected String getText(FacesBean bean)
@@ -69,6 +75,19 @@
     return toString(bean.getProperty(_titleKey));
   }
 
+  protected String getTriggerType(FacesBean bean)
+  {
+    String s = toString(bean.getProperty(_triggerTypeKey));
+    if (s == null || s.length()==0)
+      s = toString(_triggerTypeKey.getDefault());
+    return s;
+  }
+
+  protected String getPosition(FacesBean bean)
+  {
+    return toString(bean.getProperty(_positionKey));
+  }
+
   protected String getContentStyle(FacesBean bean)
   {
     return toString(bean.getProperty(_contentStyleKey));
@@ -79,8 +98,8 @@
     Object o = bean.getProperty(_widthKey);
     if (o == null)
       o = _widthKey.getDefault();
-
-    return toInt(o);
+    int i = toInt(o);
+    return (i<0) ? 0 : i;
   }
 
   protected int getHeight(FacesBean bean)
@@ -88,8 +107,26 @@
     Object o = bean.getProperty(_heightKey);
     if (o == null)
       o = _heightKey.getDefault();
+    int i = toInt(o);
+    return (i<0) ? 0 : i;
+  }
 
-    return toInt(o);
+  protected int getXOffset(FacesBean bean)
+  {
+    Object o = bean.getProperty(_xOffsetKey);
+    if (o == null)
+      o = _xOffsetKey.getDefault();
+    int i = toInt(o);
+    return (i<0) ? 0 : i;
+  }
+
+  protected int getYOffset(FacesBean bean)
+  {
+    Object o = bean.getProperty(_yOffsetKey);
+    if (o == null)
+      o = _yOffsetKey.getDefault();
+    int i = toInt(o);
+    return (i<0) ? 0 : i;
   }
 
   protected boolean isModal(FacesBean bean)
@@ -97,79 +134,17 @@
     Object o = bean.getProperty(_modalKey);
     if (o == null)
       o = _modalKey.getDefault();
-
     return Boolean.TRUE.equals(o);
   }
 
   protected boolean isCentered(FacesBean bean)
   {
-    String centeredString = toString(bean.getProperty(_alignmentKey));
+    String centeredString = toString(bean.getProperty(_positionKey));
     if (centeredString != null)
-      return centeredString.equalsIgnoreCase("center");
+      return centeredString.equalsIgnoreCase(CorePanelPopup.POSITION_CENTERED);
     return false;
   }
 
-  @Override
-  protected String getOnclick(FacesBean bean)
-  {
-    String onclick = super.getOnclick(bean);
-    
-    String clientId = RenderingContext.getCurrentInstance().getCurrentClientId();
-
-    StringBuilder script = new StringBuilder();
-
-    script.append("TrPanelPopup.showPopup('");
-    script.append(XhtmlUtils.getJSIdentifier(clientId));
-    script.append(_POPUP_CONTAINER_ID_SUFFIX); 
-    script.append("', '");
-    script.append(XhtmlUtils.getJSIdentifier(clientId));
-    script.append(_POPUP_TRIGGER_ID_SUFFIX); 
-    script.append("', {");
-    
-    boolean writtenOne = false;
-
-    if (isModal(bean))
-    {
-      script.append("modal:true");
-      writtenOne = true;
-    }
-    
-    if (isCentered(bean))
-    {
-      if (writtenOne)
-        script.append(',');
-      else
-        writtenOne = true;
-      script.append("center:true");
-    }
-
-    int width = getWidth(bean);
-    if (width > 0)
-    {
-      if (writtenOne)
-        script.append(',');
-      else
-        writtenOne = true;
-      script.append("width:");
-      script.append(width);
-    } 
-    
-    int height = getHeight(bean);
-    if (height > 0)
-    {
-      if (writtenOne)
-        script.append(',');
-      else
-        writtenOne = true;
-      script.append("height:");
-      script.append(height);
-    } 
-    
-    script.append("}, event); return false;");
-    
-    return XhtmlUtils.getChainedJS(onclick, script.toString(), true);
-  }
-
   @SuppressWarnings("unchecked")
   @Override
   protected void encodeAll(FacesContext context, RenderingContext arc,
@@ -190,53 +165,54 @@
     // Set current clientId so we can access this in getOnclick 
     arc.setCurrentClientId(clientId);
     
-    _renderTrigger(context, arc, component, bean);
-
-    // Render the outer span that is the actual popup container,
+    // Render the outer span that is the component container,
     // this element is rendered so the component can be updated via ppr.
     writer.startElement(XhtmlConstants.SPAN_ELEMENT, component);
-    writer.writeAttribute(XhtmlConstants.ID_ATTRIBUTE, 
+    writer.writeAttribute(XhtmlConstants.ID_ATTRIBUTE + _POPUP_TRIGGER_ID_SUFFIX, 
         XhtmlUtils.getJSIdentifier(clientId), null);
-
-    // render the outer div that is the actual popup container
+  
+    renderTrigger(context, arc, component, bean);
+    
+    // Render the outer div that is the actual popup container
     writer.startElement(XhtmlConstants.DIV_ELEMENT, null);
     writer.writeAttribute(XhtmlConstants.ID_ATTRIBUTE, XhtmlUtils.getJSIdentifier(clientId)
         + _POPUP_CONTAINER_ID_SUFFIX, null);
+    // Output the non-modifiable styles the keep the popup hidden initially
     writer.writeAttribute(XhtmlConstants.STYLE_ATTRIBUTE,
         _POPUP_CONTAINER_DIV_STYLES, null);
-
-    writer.startElement(XhtmlConstants.TABLE_ELEMENT, null);
+    
+    // Render the skinnable container div
+    writer.startElement(XhtmlConstants.DIV_ELEMENT, null);
     renderStyleClass(context, arc, SkinSelectors.AF_PANEL_POPUP_CONTAINER_STYLE_CLASS);
-    writer.writeAttribute("cellspacing", "0", null);
-
-    writer.startElement(XhtmlConstants.TABLE_BODY_ELEMENT, null);
-
-    _renderTitleBar(context, arc, component, bean);
+    // If width is set, then add that style to the container
+    int width = getWidth(bean);
+    if (width > 0)
+    {
+      String style = "width:" + width + "px";
+      writer.writeAttribute(XhtmlConstants.STYLE_ATTRIBUTE, style, null);
+    }
 
-    writer.startElement(XhtmlConstants.TABLE_ROW_ELEMENT, null);
+    renderTitleBar(context, arc, component, bean);
 
-    // table cell that contains the child components
-    writer.startElement(XhtmlConstants.TABLE_DATA_ELEMENT, null);
+    // Render the child components in a content div
+    writer.startElement(XhtmlConstants.DIV_ELEMENT, null);
     renderStyleClass(context, arc, SkinSelectors.AF_PANEL_POPUP_CONTENT_STYLE_CLASS);
-    // spans both the title and close-icon columns
-    writer.writeAttribute(XhtmlConstants.COLSPAN_ATTRIBUTE, "2", null);
 
-    // render custom styles for content area if specified
-    String style = getContentStyle(bean);
-    if(style != null)
+    // If width is set, then add that style to the content
+    int height = getHeight(bean);
+    if (height > 0)
     {
+      String style = "overflow: auto; height:" + height + "px";
       writer.writeAttribute(XhtmlConstants.STYLE_ATTRIBUTE, style, null);
     }
 
     encodeAllChildren(context, component);
 
-    writer.endElement(XhtmlConstants.TABLE_DATA_ELEMENT);
-
-    writer.endElement(XhtmlConstants.TABLE_ROW_ELEMENT);
-
-    writer.endElement(XhtmlConstants.TABLE_BODY_ELEMENT);
+    // Close skinnable content div
+    writer.endElement(XhtmlConstants.DIV_ELEMENT);
 
-    writer.endElement(XhtmlConstants.TABLE_ELEMENT);
+    // Close skinnable container div
+    writer.endElement(XhtmlConstants.DIV_ELEMENT);
     
     // Close outer show/hide div
     writer.endElement(XhtmlConstants.DIV_ELEMENT);
@@ -248,48 +224,21 @@
     arc.setCurrentClientId(null);
   }
 
-  protected void _renderTrigger(FacesContext context, RenderingContext arc,
-      UIComponent component, FacesBean bean) throws IOException 
+  protected void renderTrigger(FacesContext context, RenderingContext arc,
+      UIComponent component, FacesBean bean) throws IOException
   {
-    ResponseWriter writer = context.getResponseWriter();
+    // Render the trigger, including the facet if specified
+    delegateRendererBegin(context, arc, component, bean, _triggerRenderer);
 
     UIComponent triggerFacet = getFacet(component,
-                                        CorePanelPopup.TRIGGER_FACET);
-
-    String text = getText(bean);
-
-    // start rendering 'control'
-    writer.startElement(XhtmlConstants.LINK_ELEMENT, null);
-
-    String id = getClientId(context, component);
-    writer.writeAttribute(XhtmlConstants.ID_ATTRIBUTE, 
-        XhtmlUtils.getJSIdentifier(id) + _POPUP_TRIGGER_ID_SUFFIX, null);
-    writer.writeAttribute(XhtmlConstants.HREF_ATTRIBUTE, "#", null);
+        CorePanelPopup.TRIGGER_FACET);
     if (triggerFacet != null)
-      renderStyleClass(context, arc, SkinSelectors.AF_PANEL_POPUP_TRIGGER_STYLE_CLASS);
-    else
-      renderStyleClass(context, arc, SkinSelectors.AF_PANEL_POPUP_LINK_STYLE_CLASS);
-    renderAllAttributes(context, arc, bean);
-
-    // Note: render the trigger facet or the text attribute
-    // and if neither is set, leave the popup for display by JS
-
-    // Write out the trigger facet if it exists
-    if (triggerFacet != null)
-    {
-      // render 'control' facet
       encodeChild(context, triggerFacet);
-    } 
-    else if (text != null)
-    {
-      // render 'text' attribute
-      writer.writeText(text, "text");
-    }
-    
-    writer.endElement(XhtmlConstants.LINK_ELEMENT);
+
+    delegateRendererEnd(context, arc, component, bean, _triggerRenderer);
   }
 
-  protected void _renderTitleBar(FacesContext context, RenderingContext arc,
+  protected void renderTitleBar(FacesContext context, RenderingContext arc,
       UIComponent component, FacesBean bean) throws IOException
   {
     ResponseWriter writer = context.getResponseWriter();
@@ -298,30 +247,32 @@
     if (title == null)
       return;
 
-    writer.startElement(XhtmlConstants.TABLE_ROW_ELEMENT, null);
+    // Render the skinnable title bar div
+    writer.startElement(XhtmlConstants.DIV_ELEMENT, null);
     renderStyleClass(context, arc, SkinSelectors.AF_PANEL_POPUP_TITLEBAR_STYLE_CLASS);
-    
-    writer.startElement(XhtmlConstants.TABLE_DATA_ELEMENT, null);
+
+    // Render the skinnable title text
+    writer.startElement(XhtmlConstants.DIV_ELEMENT, null);
     renderStyleClass(context, arc, SkinSelectors.AF_PANEL_POPUP_TITLE_STYLE_CLASS);
-    
+    writer.writeAttribute(XhtmlConstants.STYLE_ATTRIBUTE, "float: left;", null);
+
     writer.writeText(title, "title");
 
-    writer.endElement(XhtmlConstants.TABLE_DATA_ELEMENT);
+    writer.endElement(XhtmlConstants.DIV_ELEMENT);
 
     Icon icon = arc.getIcon(SkinSelectors.AF_PANEL_POPUP_CLOSE_ICON_STYLE_CLASS);
 
     if (isModal(bean))
     {
-      writer.startElement(XhtmlConstants.TABLE_DATA_ELEMENT, null);
+      // Render the skinnable container div
+      writer.startElement(XhtmlConstants.DIV_ELEMENT, null);
       renderStyleClass(context, arc, SkinSelectors.AF_PANEL_POPUP_CLOSE_ICON_STYLE_CLASS);
-
+      
       writer.startElement(XhtmlConstants.LINK_ELEMENT, null);
       writer.writeAttribute(XhtmlConstants.HREF_ATTRIBUTE, "#", null);
 
-      StringBuilder script = new StringBuilder();
-      script.append("TrPanelPopup.hidePopup(); return false;");
-
-      writer.writeAttribute(XhtmlConstants.ONCLICK_ATTRIBUTE, script,
+      writer.writeAttribute(XhtmlConstants.ONCLICK_ATTRIBUTE, 
+          "TrPanelPopup.hidePopup(event); return false;",
           null);
       
       if (icon != null && !icon.isNull())
@@ -334,29 +285,124 @@
         writer.writeText("X", "text");
       }
       writer.endElement(XhtmlConstants.LINK_ELEMENT);
-      writer.endElement(XhtmlConstants.TABLE_DATA_ELEMENT);
+
+      writer.endElement(XhtmlConstants.DIV_ELEMENT);
+    }
+
+    // Render an empty div to terminate title bar layout
+    writer.startElement(XhtmlConstants.DIV_ELEMENT, null);
+    writer.writeAttribute(XhtmlConstants.STYLE_ATTRIBUTE, "clear: left;", null);
+    writer.endElement(XhtmlConstants.DIV_ELEMENT);
+
+    // Close the outer titlebar div
+    writer.endElement(XhtmlConstants.DIV_ELEMENT);
+
+  }
+  
+  // Handles rendering of the trigger text/icon and or 
+  private class TriggerRenderer extends GoLinkRenderer
+  {
+    
+    @Override
+    protected boolean shouldRenderId(FacesContext context, UIComponent component)
+    {
+      // Force rendering of the ID, so the trigger element can be found through scripting
+      return true;
+    }
+    
+    @Override
+    protected String getClientId(FacesContext context, UIComponent component)
+    {
+      // Ensure the ID is encoded, otherwise it will fail when included in tables.
+      return XhtmlUtils.getJSIdentifier(
+          PanelPopupRenderer.this.getClientId(context, component));
     }
+    
+    @Override
+    protected String getOnclick(FacesBean bean)
+    {
+      String onclick = PanelPopupRenderer.this.getOnclick(bean);
+      String script = null;
+      
+      // Only render onclick script for 'click'
+      if (CorePanelPopup.TRIGGER_TYPE_CLICK.equalsIgnoreCase(getTriggerType(bean)))
+      {
+        String componentId = RenderingContext.getCurrentInstance().getCurrentClientId();
+        
+        script = getTriggerScript(bean, componentId);
+      }
 
-    writer.endElement(XhtmlConstants.TABLE_ROW_ELEMENT);
+      return XhtmlUtils.getChainedJS(onclick, script, true);
+    }
+    
+    @Override
+    protected String getOnmouseover(FacesBean bean)
+    {
+      String onclick = super.getOnmouseover(bean);
+      String script = null;
+      
+      // Only render onclick script for 'click'
+      if (CorePanelPopup.TRIGGER_TYPE_HOVER.equalsIgnoreCase(getTriggerType(bean)))
+      {
+        String componentId = RenderingContext.getCurrentInstance().getCurrentClientId();
+        
+        script = getTriggerScript(bean, componentId);
+      }
 
+      return XhtmlUtils.getChainedJS(onclick, script, true);
+    }
+
+    @Override
+    protected String getText(FacesBean bean)
+    {
+      return PanelPopupRenderer.this.getText(bean);
+    }
+    
+    protected String getTriggerScript(FacesBean bean, String componentId)
+    {
+      String clientId = XhtmlUtils.getJSIdentifier(componentId);
+      StringBuilder script = new StringBuilder();
+
+      script.append("TrPanelPopup.showPopup('");
+      script.append(clientId);
+      script.append(_POPUP_CONTAINER_ID_SUFFIX); 
+      script.append("', '");
+      script.append(clientId);
+      script.append("', event, '");
+      script.append(PanelPopupRenderer.this.getTriggerType(bean));
+      script.append("','");
+      script.append(PanelPopupRenderer.this.getPosition(bean));
+      script.append("',");
+      script.append(PanelPopupRenderer.this.isModal(bean));
+      script.append(",");
+      script.append(PanelPopupRenderer.this.getWidth(bean));
+      script.append(",");
+      script.append(PanelPopupRenderer.this.getHeight(bean));
+      script.append(",");
+      script.append(PanelPopupRenderer.this.getXOffset(bean));
+      script.append(",");
+      script.append(PanelPopupRenderer.this.getYOffset(bean));
+      
+      script.append("); return false;");
+      
+      return script.toString();
+    }
   }
 
   private static final TrinidadLogger _LOG = TrinidadLogger
       .createTrinidadLogger(PanelPopupRenderer.class);
 
   private PropertyKey _textKey;
-
   private PropertyKey _titleKey;
-
-  private PropertyKey _alignmentKey;
-
+  private PropertyKey _triggerTypeKey;
+  private PropertyKey _positionKey;
   private PropertyKey _modalKey;
-
   private PropertyKey _contentStyleKey;
-  
   private PropertyKey _widthKey;
-  
   private PropertyKey _heightKey;
+  private PropertyKey _xOffsetKey;
+  private PropertyKey _yOffsetKey;
+  private XhtmlRenderer _triggerRenderer;
   
   private static final String _POPUP_CONTAINER_ID_SUFFIX = "_popupContainer";
 
@@ -367,10 +413,6 @@
    * element, but there's an inner element for skin styling (e.g border,
    * padding, etc.).
    */
-  private static final String _POPUP_CONTAINER_DIV_STYLES = "position: absolute; "
-      + "z-index: 201; "
-      + "top: 0px; "
-      + "left: 0px;  "
-      + "visibility:hidden; " + "padding: 0px;  " + "overflow:hidden;";
+  private static final String _POPUP_CONTAINER_DIV_STYLES = "position:absolute; top:0px; left:0px; visibility:hidden;";
 
 }

Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/PanelPopup.js
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/PanelPopup.js?rev=568675&r1=568674&r2=568675&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/PanelPopup.js (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/PanelPopup.js Wed Aug 22 09:10:43 2007
@@ -21,63 +21,89 @@
  * Simple function for opening a popup
  * @param contentId(String) id of the element to pop
  * @param triggerId(String) optional id of the element that launched the popup
- * @param props(Array) array of settings (modal(boolean), center(boolean), width(int), height(int))
  * @param event(Event) the javascript event object (used to position relative popups)
- **/
-TrPanelPopup.showPopup = function(contentId, triggerId, props, event)
+ * @param triggerType(String) 'click'(default) | 'hover'
+ * @param position(String) 'relative'(default) | 'centered'
+ * @param modal(boolean)
+ * @param width(int) 
+ * @param height(int)
+ * @param xOffset(int)
+ * @param yOffset(int)
+ **/
+TrPanelPopup.showPopup = function(
+  contentId, 
+  triggerId, 
+  event, 
+  triggerType,
+  position, 
+  modal, 
+  width, 
+  height, 
+  xOffset, 
+  yOffset)
 {
-  var popup = TrPanelPopup.POPUP;
-  if (!popup)
-    popup = TrPanelPopup.POPUP = new TrPanelPopup();
+  if (contentId == null)
+    return;
+  
+  // Get/Initialize a map of visible popups
+  var visiblePopups = TrPanelPopup._VISIBLE_POPUPS;
+  if (!visiblePopups)
+    visiblePopups = TrPanelPopup._VISIBLE_POPUPS = new Object();
+  
+  // Check if the popup is already visible
+  if (visiblePopups[contentId])
+    // Popup is already visible
+    return;
+    
+  // Create new popup object and add it to the map of visible popups
+  if (triggerType == "hover")
+    visiblePopups[contentId] = new TrHoverPopup();
   else
-    popup.hide();
+    visiblePopups[contentId] = new TrClickPopup();
+
+  var popup = visiblePopups[contentId];
 
   var content = document.getElementById(contentId);
-   if (!content)
+  if (!content)
      return;
 
-  var trigger = document.getElementById(triggerId);
-   
   popup.setContent(content);
-  popup.setTrigger(trigger);
-  popup.setModal(false);
-  popup.setCentered(false);
-
-  // Register the callback
-  popup.callback = TrPanelPopup._popupCallback;
-
-  if (props)
-  {
-    if (props['modal'])
-      popup.setModal(true);
-
-    if (props['center'])
-      popup.setCentered(true);
-
-    if (props['width'] && props['height'])
-      popup.setSize(props['width'], props['height']);
-  }
+  popup.setTrigger(document.getElementById(triggerId));
+  popup.setModal(modal);
+  popup.setCentered(position == 'centered');
+  popup.setSize(width, height);
+  popup.setRelativeOffsetX(xOffset);
+  popup.setRelativeOffsetY(yOffset);
   
-  popup.show(event);
+  popup.showPopup(event);
 }
 
 /**
  * Public function for hiding the current popup.
  */  
-TrPanelPopup.hidePopup = function()
+TrPanelPopup.hidePopup = function(event)
 {
-  var popup = TrPanelPopup.POPUP;
-  if (popup)
-    popup.hide();
-}
+  var visiblePopups = TrPanelPopup._VISIBLE_POPUPS;
+  if (!visiblePopups)
+    return;
 
-/**
- * Callback function to ensure we clear
- * the POPUP var.
- */  
-TrPanelPopup._popupCallback = function()
-{
-  TrPanelPopup.POPUP = undefined;
+  //loop through element stack and find out which popup the event occured in.
+  var currElement = event.target || event.srcElement;
+  while (currElement)
+  {
+    var id = currElement.id;
+    if (id)
+    {
+      var currPopup = visiblePopups[id];
+      if (currPopup)
+      {
+        // We found the popup, so hide it.
+        currPopup.hide(event);
+        break;
+      }
+    }
+    currElement = currElement.parentNode;
+  }
 }
 
 /**
@@ -91,9 +117,6 @@
   this._centered = false;
   this._modal = false;
   this._visible = false;
-
-  // Store the callback function so we can cleanly cancel it later
-  this._eventCallbackFunction = TrUIUtils.createCallback(this, this._handleEvent);
 }
 
 TrPanelPopup.prototype.getContent = function()
@@ -108,7 +131,7 @@
   //Initialize the styles for the content
   if (this._content)
   {
-    this._content.style.cssText  = "position: absolute; z-index: 201; top: 0px; left: 0px; visibility:hidden; padding: 0px; overflow:auto;";  
+    this._content.style.cssText  = "position: absolute; z-index: 5001; top: 0px; left: 0px; visibility:hidden; padding: 0px;";  
   }
 }
 
@@ -130,7 +153,6 @@
   this._trigger = trigger;
 }
 
-
 /**
  * Sets the popup to be centered on screen when visible
  * @param centered(boolean) true if popup should be centered
@@ -157,6 +179,43 @@
 }
 
 /**
+ * Sets X offset to apply if popup is positioned relative to mouse x.
+ * @param x(int) The x offset value.
+ **/
+TrPanelPopup.prototype.setRelativeOffsetX = function(x)
+{
+  this._relativeOffsetX = parseInt(x);
+}
+
+/**
+ * Gets X offset to apply if popup is positioned relative to mouse x.
+ * @return (int) The x offset value, or zero if unset.
+ **/
+TrPanelPopup.prototype.getRelativeOffsetX = function()
+{
+  return (this._relativeOffsetX) ? this._relativeOffsetX: 0;
+}
+
+/**
+ * Sets Y offset to apply if popup is positioned relative to mouse y.
+ * @param y(int) The y offset value.
+ **/
+TrPanelPopup.prototype.setRelativeOffsetY = function(y)
+{
+  this._relativeOffsetY = parseInt(y);
+}
+
+/**
+ * Gets Y offset to apply if popup is positioned relative to mouse y.
+ * @return (int) The y offset value, or zero if unset.
+ **/
+TrPanelPopup.prototype.getRelativeOffsetY = function()
+{
+  return (this._relativeOffsetY) ? this._relativeOffsetY: 0;
+}
+
+
+/**
  * Returns true if the popup is currently visible.
  **/
 TrPanelPopup.prototype.isVisible = function()
@@ -164,7 +223,6 @@
   return this._visible;
 }
 
-
 /**
  * Holds the return value of the dialog.  Check this property after the 
  * popup has closed.
@@ -204,14 +262,7 @@
   this._calcPosition(event);
   
   if (this.isModal())
-  {
     TrPanelPopup._showMask();
-  }
-  else
-  {
-    // Setup event handler to close the popup if clicked off
-    TrPanelPopup._addEvent(document, "click", this._eventCallbackFunction);
-  }
   
   TrPanelPopup._showIeIframe();
 
@@ -224,21 +275,14 @@
  * Hide the popup if visible.  Hiding the popup causes the callback
  * handler to be invoked (if configured).
  **/
-TrPanelPopup.prototype.hide = function()
+TrPanelPopup.prototype.hide = function(event)
 {
   //we can't hide content that isn't there
   if (!this.getContent())
     return;
 
   if (this.isModal())
-  {
     TrPanelPopup._hideMask();
-  }
-  else
-  {
-    //cancel callbacks
-    TrPanelPopup._removeEvent(document, "click", this._eventCallbackFunction);
-  }
   
   TrPanelPopup._hideIeIframe();
   
@@ -250,10 +294,22 @@
   //call the callback function if attached
   if (this.callback)
   {
-    this.callback(this.callbackProps, this.returnValue);
+    try
+    {
+      this.callback(this.callbackProps, this.returnValue);
+    }
+    catch(ex)
+    {
+      alert("Error calling TrPanelPopup callback function:\n" + ex);
+    }
   }
-
+  
   this._visible = false;
+  
+  // Remove the popup from the list of visible popups
+  var popups = TrPanelPopup._VISIBLE_POPUPS;
+  if (popups)
+    delete popups[this.getContent().id];
 }
 
 /**
@@ -263,49 +319,15 @@
 {
   if (width)
   {
-    this.getContent().style.width = width + "px";
+    var i = parseInt(width);
+    if (i > 0)
+      this.getContent().style.width = i + "px";
   }
   if (height)
   {
-    this.getContent().style.height = height + "px";
-  }
-}
-
-/**
- * Event handler function.  Checks if the event occurred outside
- * of the popup or trigger, and if so causes the popup to hide.
- **/
-TrPanelPopup.prototype._handleEvent = function(event)
-{
-  if (!this.isVisible() || this.isModal())
-    return;
-
-  var currElement = false;
-  if (_agent.isIE)
-  {
-    currElement = event.srcElement;
-  }
-  else
-  {
-    currElement = event.target;
-  }
-
-  //loop through element stack where event occurred
-  while (currElement)
-  {
-    //if clicked on trigger or popup  
-    if (currElement == this.getContent() || 
-        currElement == this.getTrigger())
-    {
-      break;
-    }
-    currElement = currElement.parentNode;
-  }
-
-  if (!currElement)
-  {
-    //if click was on something other than the popupContainer
-    this.hide();
+    var i = parseInt(height);
+    if (i > 0)
+      this.getContent().style.height = i + "px";
   }
 }
 
@@ -324,7 +346,7 @@
     //create mask for modal popups
     TrPanelPopup._mask = document.createElement('div');
     TrPanelPopup._mask.name = "TrPanelPopup._BlockingModalDiv";
-    TrPanelPopup._mask.style.cssText = "display:none;position: absolute; z-index: 200;top: 0px;left: 0px;cursor: not-allowed; background-color: transparent;";
+    TrPanelPopup._mask.style.cssText = "display:none;position: absolute; z-index: 5000;top: 0px;left: 0px;cursor: not-allowed; background-color: transparent;";
     TrPanelPopup._mask.innerHTML = "&nbsp;";
 
     //consume all events
@@ -368,8 +390,8 @@
   var isIE = _agent.isIE;
   
   //bring some sanity to the cross browser measurements
-  var xOffset = isIE ? document.body.scrollLeft : window.pageXOffset;
-  var yOffset = isIE ? document.body.scrollTop : window.pageYOffset;
+  var xOffset = isIE ? document.documentElement.scrollLeft : window.pageXOffset;
+  var yOffset = isIE ? document.documentElement.scrollTop : window.pageYOffset;
   var scrollWidth = document.body.scrollWidth;
   var scrollHeight = document.body.scrollHeight;
   var bodyWidth = isIE ? document.body.clientWidth : window.innerWidth;
@@ -386,16 +408,20 @@
   {
     var eventX = isIE ? window.event.clientX : event.clientX;
     var eventY = isIE ? window.event.clientY : event.clientY;
+    
+    // Apply the offsets
+    eventX += this.getRelativeOffsetX();
+    eventY += this.getRelativeOffsetY();
 
     //ensure we keep popup within current page width
-    if (xOffset + eventX + containerWidth > document.body.scrollWidth)
-      left = document.body.scrollWidth - containerWidth;
+    if (xOffset + eventX + containerWidth > scrollWidth)
+      left = scrollWidth - containerWidth;
     else
       left = xOffset + eventX;
 
     //ensure we keep popup within current page height
-    if (yOffset + eventY + containerHeight > document.body.scrollHeight)
-      top = document.body.scrollHeight - containerHeight;
+    if (yOffset + eventY + containerHeight > scrollHeight)
+      top = scrollHeight - containerHeight;
     else
       top = yOffset + eventY;
   }  
@@ -500,8 +526,7 @@
  **/
 TrPanelPopup._showIeIframe = function()
 {
-  // FIXME: only bother doing this for IE 6 - bypass the code for IE 7
-  if (_agent.isIE)
+  if (_agent.isIE && _agent.version < 7)
   {
     TrPanelPopup._initIeIframe();
     TrPanelPopup._maskIframe.style.display = "block";      
@@ -510,7 +535,7 @@
 
 TrPanelPopup._hideIeIframe = function()
 {
-  if (_agent.isIE)
+  if (_agent.isIE && _agent.version < 7)
   {
     TrPanelPopup._initIeIframe();
     TrPanelPopup._maskIframe.style.display = "none";      
@@ -519,7 +544,7 @@
 
 TrPanelPopup._resizeIeIframe = function(left, top, width, height)
 {
-  if (_agent.isIE)
+  if (_agent.isIE && _agent.version < 7)
   {
     TrPanelPopup._initIeIframe();
     TrPanelPopup._maskIframe.style.left = left;
@@ -542,4 +567,120 @@
     //TrPanelPopup._maskIframe.src = "javascript:false;"
     document.body.appendChild(TrPanelPopup._maskIframe);
   }
+}
+
+
+
+
+
+
+
+
+function TrHoverPopup()
+{
+  TrPanelPopup.call(this);
+
+  // Setup callback function for hiding the popup
+  this._hoverCallbackFunction = TrUIUtils.createCallback(this, this.hidePopup);
+}
+
+// TrHoverPopup inherits from TrPanelPopup
+TrHoverPopup.prototype = new TrPanelPopup();
+
+TrHoverPopup.prototype.showPopup = function(event)
+{
+  // Setup event listener for mouse leaving trigger or content elements
+  TrPanelPopup._addEvent(this.getTrigger(), "mouseout", this._hoverCallbackFunction);
+  TrPanelPopup._addEvent(this.getContent(), "mouseout", this._hoverCallbackFunction);
+  
+  this.show(event);
+}
+
+TrHoverPopup.prototype.hidePopup = function(event)
+{
+  // Only hide the popup if the event has a relatedTarget other than the
+  // trigger, the content, or their child elements.  This allows mouse
+  // to move between trigger and content without re-showing the popup
+
+  //loop through element stack where event occurred
+  var currElement = event.relatedTarget || event.toElement;
+  while (currElement)
+  {
+    //if over trigger or popup  
+    if (currElement == this.getContent() || 
+        currElement == this.getTrigger())
+    {
+      break;
+    }
+    currElement = currElement.parentNode;
+  }
+
+  if (!currElement)
+  {
+    // Cancel event listeners
+    TrPanelPopup._removeEvent(this.getTrigger(), "mouseout", this._hoverCallbackFunction);
+    TrPanelPopup._removeEvent(this.getContent(), "mouseout", this._hoverCallbackFunction);
+
+    this.hide(event);
+  }
+}
+
+TrHoverPopup.prototype.isModal = function()
+{
+  // Prevent modal for hover popups
+  return false;
+}
+
+
+
+
+
+
+
+
+
+function TrClickPopup()
+{
+  TrPanelPopup.call(this);
+
+  // Setup callback function for hiding the popup
+  this._clickCallbackFunction = TrUIUtils.createCallback(this, this.hidePopup);
+}
+
+// TrHoverPopup inherits from TrPanelPopup
+TrClickPopup.prototype = new TrPanelPopup();
+
+TrClickPopup.prototype.showPopup = function(event)
+{
+  if (!this.isModal())
+    // Setup event listener for clicking off the popup
+    TrPanelPopup._addEvent(document, "click", this._clickCallbackFunction);
+    
+  this.show(event);
+}
+
+TrClickPopup.prototype.hidePopup = function(event)
+{
+  //loop through element stack where event occurred
+  var currElement = event.target || event.srcElement;
+  while (currElement)
+  {
+    //if clicked on trigger or popup  
+    if (currElement == this.getContent() || 
+        currElement == this.getTrigger())
+    {
+      break;
+    }
+    currElement = currElement.parentNode;
+  }
+  
+  if (!currElement)
+  {
+    // Cancel event listeners
+    TrPanelPopup._removeEvent(document, "click", this._clickCallbackFunction);
+
+    //if click was on something other than the popupContainer
+    this.hide(event);
+  }
+
 }

Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/renderkit/core/resource/CoreBundle.xrts
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/renderkit/core/resource/CoreBundle.xrts?rev=568675&r1=568674&r2=568675&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/renderkit/core/resource/CoreBundle.xrts (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/xrts/org/apache/myfaces/trinidadinternal/renderkit/core/resource/CoreBundle.xrts Wed Aug 22 09:10:43 2007
@@ -443,6 +443,7 @@
        content -->
   <resource key="af_panelPage.SKIP_PAST_NAVIGATION">Skip navigation elements to page contents</resource>
 
+  <resource key="af_panelPopup.CLOSE">Hide</resource>    
 
   <!-- Nav block titles for screenReader mode -->
   <resource key="af_menuButtons.BLOCK_TITLE">Global buttons</resource>