You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2006/03/12 19:25:07 UTC

svn commit: r385330 - in /cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms: datatype/ formmodel/ generation/ resources/ resources/css/ resources/js/ resources/mattkruse-lib/

Author: sylvain
Date: Sun Mar 12 10:25:06 2006
New Revision: 385330

URL: http://svn.apache.org/viewcvs?rev=385330&view=rev
Log:
New Ajax stuff with Dojo

Added:
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/FilterableSelectionList.java   (with props)
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionList.java   (with props)
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionListBuilder.java   (with props)
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsSuggest.js   (with props)
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/selection-list2json.xsl   (with props)
Modified:
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/DynamicSelectionList.java
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Action.java
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Field.java
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Repeater.java
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/RepeaterDefinition.java
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Submit.java
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/generation/SuggestionListGenerator.java
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/generation/jx-macros.xml
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/css/forms.css
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/forms-advanced-field-styling.xsl
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/forms-field-styling.xsl
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsForm.js
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsRepeater.js
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/__package__.js
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/common.js
    cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/mattkruse-lib/PopupWindow.js

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/DynamicSelectionList.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/DynamicSelectionList.java?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/DynamicSelectionList.java (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/DynamicSelectionList.java Sun Mar 12 10:25:06 2006
@@ -15,44 +15,47 @@
  */
 package org.apache.cocoon.forms.datatype;
 
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.Attributes;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.util.Locale;
+
 import org.apache.avalon.framework.context.Context;
 import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.excalibur.source.SourceResolver;
-import org.apache.excalibur.source.Source;
 import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.components.ContextHelper;
 import org.apache.cocoon.components.source.SourceUtil;
 import org.apache.cocoon.environment.Request;
 import org.apache.cocoon.forms.FormsConstants;
+import org.apache.cocoon.forms.datatype.convertor.ConversionResult;
 import org.apache.cocoon.forms.datatype.convertor.Convertor;
 import org.apache.cocoon.forms.datatype.convertor.DefaultFormatCache;
-import org.apache.cocoon.forms.datatype.convertor.ConversionResult;
-import org.apache.cocoon.xml.AttributesImpl;
 import org.apache.cocoon.xml.AbstractXMLPipe;
+import org.apache.cocoon.xml.AttributesImpl;
 import org.apache.cocoon.xml.SaxBuffer;
 import org.apache.cocoon.xml.XMLUtils;
 import org.apache.cocoon.xml.dom.DOMBuilder;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
 import org.w3c.dom.Element;
-
-import java.io.IOException;
-import java.rmi.server.UID;
-import java.util.Enumeration;
-import java.util.Locale;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
 
 /**
  * SelectionList implementation that always reads its content from the source
  * each time it is requested.
- *
- * <p>Note: the class {@link SelectionListBuilder} also interprets the same
+ * <p>
+ * This list is filterable, and if a filter is provided, the "filter" parameter
+ * is appended to the URL, e.g. <code>&lt;fd:selection-list src="cocoon://pipeline.xml"/&gt;</code>
+ * will call, given the "<code>foo</code>" filter value, the URL <code>cocoon://pipeline.xml?filter=foo</code>.
+ * <p>
+ * Note: the class {@link SelectionListBuilder} also interprets the same
  * <code>fd:selection-list</code> XML, so if anything changes here to how that
  * XML is interpreted, it also needs to change over there and vice versa.</p>
  *
  * @version $Id$
  */
-public class DynamicSelectionList implements SelectionList {
+public class DynamicSelectionList implements FilterableSelectionList {
     private String src;
     private boolean usePerRequestCache;
     private Datatype datatype;
@@ -106,12 +109,12 @@
     /*
      * This method generate SaxFragment directly from source.
      */
-    private void generateSaxFragmentFromSrc(ContentHandler contentHandler, Locale locale) throws SAXException {
+    private void generateSaxFragmentFromSrc(String url, ContentHandler contentHandler, Locale locale) throws SAXException {
         SourceResolver sourceResolver = null;
         Source source = null;
         try {
             sourceResolver = (SourceResolver)serviceManager.lookup(SourceResolver.ROLE);
-            source = sourceResolver.resolveURI(src);
+            source = sourceResolver.resolveURI(url);
             generateSaxFragment(contentHandler, locale, source);
         } catch (SAXException e) {
             throw e;
@@ -127,36 +130,40 @@
         }
     }
 
-    public void generateSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException {
+    public void generateSaxFragment(ContentHandler contentHandler, Locale locale, String filter) throws SAXException {
+        
+        String url = this.src;
+        if (filter != null) {
+            if (url.indexOf('?') != -1) {
+                url += "&filter=" + URLEncoder.encode(filter);
+            } else {
+                url += "?filter=" + URLEncoder.encode(filter);
+            }
+        }
 
         if (usePerRequestCache) {
-            // Search the cacheID in request attributes
+            // Search the sax buffer in request attributes
             Request request = ContextHelper.getRequest(this.context);
-            Enumeration enumeration = request.getAttributeNames();
-            boolean cacheFound = false;
-            String name = null;
-            while (enumeration.hasMoreElements()) {
-                name = (String)enumeration.nextElement();
-                if (name.startsWith(src)) {
-                    cacheFound = true;
-                    break;
-                }
-            }
-            SaxBuffer saxBuffer;
-            if (cacheFound) {
-                saxBuffer = (SaxBuffer)request.getAttribute(name);
-            } else {
-                // Generate the usePerRequestCache and store in a request attribute.
+            String attributeName = "DynamicSelectionListCache/" + url;
+            SaxBuffer saxBuffer = (SaxBuffer)request.getAttribute(attributeName);
+            
+            if (saxBuffer == null) {
+                // Not found: generate the list and store it
                 saxBuffer = new SaxBuffer();
-                generateSaxFragmentFromSrc(saxBuffer, locale);
-                String cacheID = (new UID()).toString();
-                request.setAttribute(src + cacheID, saxBuffer);
+                generateSaxFragmentFromSrc(url, saxBuffer, locale);
+                request.setAttribute(attributeName, saxBuffer);
             }
+            
             // Output the stored saxBuffer to the contentHandler
             saxBuffer.toSAX(contentHandler);
         } else { // We don't use usePerRequestCache => re-read from the source.
-            generateSaxFragmentFromSrc(contentHandler, locale);
+            generateSaxFragmentFromSrc(url, contentHandler, locale);
         }
+    }
+
+    public void generateSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException {
+        // Generate with no filter
+        generateSaxFragment(contentHandler, locale, (String)null);
     }
 
     /**

Added: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/FilterableSelectionList.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/FilterableSelectionList.java?rev=385330&view=auto
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/FilterableSelectionList.java (added)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/FilterableSelectionList.java Sun Mar 12 10:25:06 2006
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.forms.datatype;
+
+import java.util.Locale;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * Extension of {@link org.apache.cocoon.forms.datatype.SelectionList} that can be filtered. Used
+ * primarily to build suggestion lists.
+ * 
+ * @since 2.1.9
+ * @version $Id$
+ */
+public interface FilterableSelectionList extends SelectionList {
+    
+    /**
+     * Generates the filtered selection list
+     * 
+     * @param contentHandler where to stream the XML
+     * @param locale the locale to be used for value formatting
+     * @param filter the filter string
+     * @throws SAXException
+     */
+    void generateSaxFragment(ContentHandler contentHandler, Locale locale, String filter) throws SAXException;
+}

Propchange: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/FilterableSelectionList.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/FilterableSelectionList.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionList.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionList.java?rev=385330&view=auto
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionList.java (added)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionList.java Sun Mar 12 10:25:06 2006
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.forms.datatype;
+
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.avalon.framework.context.Context;
+import org.apache.cocoon.components.ContextHelper;
+import org.apache.cocoon.forms.FormsConstants;
+import org.apache.cocoon.forms.util.I18nMessage;
+import org.apache.cocoon.forms.util.JavaScriptHelper;
+import org.apache.cocoon.util.location.Locatable;
+import org.apache.cocoon.util.location.LocatedRuntimeException;
+import org.apache.cocoon.util.location.Location;
+import org.apache.cocoon.xml.AttributesImpl;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.JavaScriptException;
+import org.mozilla.javascript.NativeArray;
+import org.mozilla.javascript.Scriptable;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * A {@link FilterableSelectionList} based on a JavaScript snippet.
+ * 
+ * @since 2.1.9
+ * @version $Id$
+ */
+public class JavaScriptSelectionList implements FilterableSelectionList, Locatable {
+
+    private Context context;
+    private Datatype type;
+    private Function function;
+    private Location location = null;
+    private boolean labelIsI18nKey = false;
+    private String i18nCatalog = null;
+    
+    public JavaScriptSelectionList(Context context, Datatype type, Function function, String catalogue, Location location) {
+        this.context = context;
+        this.type = type;
+        this.function = function;
+        this.location = location;
+        if (catalogue != null) {
+            this.labelIsI18nKey = true;
+            if (catalogue.length() > 0) {
+                this.i18nCatalog = catalogue;
+            }
+        }
+    }
+    
+    public Location getLocation() {
+        return this.location;
+    }
+
+    public void generateSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException {
+        generateSaxFragment(contentHandler, locale, null);
+    }
+
+    public void generateSaxFragment(ContentHandler contentHandler, Locale locale, String filter) throws SAXException {
+        Map objectModel = ContextHelper.getObjectModel(this.context);
+        Object result;
+        try {
+            result = JavaScriptHelper.callFunction(function, null /*this*/, new Object[] {filter}, objectModel);
+        } catch (JavaScriptException e) {
+            throw new LocatedRuntimeException("Error building JS selection list", e, getLocation());
+        }
+        
+        // Start the selection-list
+        contentHandler.startElement(FormsConstants.INSTANCE_NS, SELECTION_LIST_EL, FormsConstants.INSTANCE_PREFIX_COLON + SELECTION_LIST_EL, XMLUtils.EMPTY_ATTRIBUTES);
+
+        NativeArray array = (NativeArray)result;
+        for (int i = 0; i < array.jsGet_length(); i++) {
+            Scriptable item = (Scriptable)array.get(i, array);
+            
+            Object value = item.get("value", item);
+            String stringValue = value == null ? "" : this.type.convertToString(value, locale);
+            Object label = item.get("label", item);
+            if (label == Scriptable.NOT_FOUND)
+                label = null;
+            
+            // Output this item
+            AttributesImpl itemAttrs = new AttributesImpl();
+            itemAttrs.addCDATAAttribute("value", stringValue);
+            contentHandler.startElement(FormsConstants.INSTANCE_NS, ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON + ITEM_EL, itemAttrs);
+            if (label != null) {
+                contentHandler.startElement(FormsConstants.INSTANCE_NS, LABEL_EL, FormsConstants.INSTANCE_PREFIX_COLON + LABEL_EL, XMLUtils.EMPTY_ATTRIBUTES);
+                if (label instanceof XMLizable) {
+                    ((XMLizable)label).toSAX(contentHandler);
+                }  else if( this.labelIsI18nKey ) {
+                    String stringLabel = label.toString();
+
+                    if( ( this.i18nCatalog != null ) &&
+                        ( this.i18nCatalog.trim(  ).length(  ) > 0 ) ) {
+                        new I18nMessage( stringLabel, this.i18nCatalog ).toSAX( contentHandler );
+                    } else {
+                        new I18nMessage( stringLabel ).toSAX( contentHandler );
+                    }
+                } else {
+                    String stringLabel = label.toString();
+                    contentHandler.characters(stringLabel.toCharArray(), 0, stringLabel.length());
+                }
+                contentHandler.endElement(FormsConstants.INSTANCE_NS, LABEL_EL, FormsConstants.INSTANCE_PREFIX_COLON + LABEL_EL);
+            }
+            contentHandler.endElement(FormsConstants.INSTANCE_NS, ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON + ITEM_EL);
+        }
+
+        // End the selection-list
+        contentHandler.endElement(FormsConstants.INSTANCE_NS, SELECTION_LIST_EL, FormsConstants.INSTANCE_PREFIX_COLON + SELECTION_LIST_EL);
+    }
+
+    public Datatype getDatatype() {
+        return this.type;
+    }
+}

Propchange: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionList.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionList.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionListBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionListBuilder.java?rev=385330&view=auto
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionListBuilder.java (added)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionListBuilder.java Sun Mar 12 10:25:06 2006
@@ -0,0 +1,63 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.forms.datatype;
+
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.cocoon.forms.util.DomHelper;
+import org.apache.cocoon.forms.util.JavaScriptHelper;
+import org.mozilla.javascript.Function;
+import org.w3c.dom.Element;
+
+/**
+ * Builds a selection list that will take its values from a JavaScript snippet.
+ * The snippet runs in scope where the list filter (if any) and the view data are
+ * available as <code>filter</code> and <code>viewData</code> respectively, along
+ * with all flowscript functions. It must return a list of (value, label) pairs.
+ * <p>
+ * If an item has no label, its value is used as the label. If the declaration has
+ * a <code>catalogue</code> attribute, the labels are interpreted as i18n keys in
+ * that catalogue.
+ * <p>
+ * Example:
+ * <pre>
+ *   &lt;fd:selection-list type="flow-function"&gt;
+ *     return [ {value: 3, label: "three"}, {value:4} ];
+ *   &lt;/fd:selection-list&gt;
+ * </pre>
+ *
+ * @see org.apache.cocoon.forms.datatype.JavaScriptSelectionList
+ * @since 2.1.9
+ * @version $Id$
+ */
+public class JavaScriptSelectionListBuilder implements SelectionListBuilder, Contextualizable {
+
+    private Context context;
+
+    public void contextualize(Context context) throws ContextException {
+        this.context = context;
+    }
+
+    public SelectionList build(Element selectionListElement, Datatype datatype) throws Exception {
+
+        String i18nCatalog = DomHelper.getAttribute(selectionListElement, "catalogue", null);
+        
+        Function function = JavaScriptHelper.buildFunction(selectionListElement, "buildSelectionList", new String[] { "filter" });
+
+        return new JavaScriptSelectionList(context, datatype, function, i18nCatalog, DomHelper.getLocationObject(selectionListElement));
+    }
+}

Propchange: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionListBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/datatype/JavaScriptSelectionListBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Action.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Action.java?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Action.java (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Action.java Sun Mar 12 10:25:06 2006
@@ -75,17 +75,27 @@
         }
 
         if (form.getSubmitWidget() == this) {
-            form.addWidgetEvent(new ActionEvent(this, definition.getActionCommand()));
             handleActivate();
         }
     }
+    
+    /**
+     * Performs all actions and calls on-action listeners attached to this object. Note that this
+     * does not register this object as the submit widget and doesn't stop form processing.
+     */
+    public void performAction() {
+        getForm().addWidgetEvent(new ActionEvent(this, definition.getActionCommand()));
+    }
 
     /**
-     * Handle the fact that this action was activated. The default here is to end the
-     * current form processing and redisplay the form, which means that actual behaviour
-     * should be implemented in event listeners.
+     * Handle the fact that this action was activated. The default here is to perform any
+     * action associated to this object, end the current form processing and redisplay the
+     * form.
+     * 
+     * @see #performAction()
      */
     protected void handleActivate() {
+        performAction();
         getForm().endProcessing(true);
     }
 

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Field.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Field.java?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Field.java (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Field.java Sun Mar 12 10:25:06 2006
@@ -15,8 +15,10 @@
  */
 package org.apache.cocoon.forms.formmodel;
 
+import org.apache.cocoon.environment.Request;
 import org.apache.cocoon.forms.FormsConstants;
 import org.apache.cocoon.forms.FormContext;
+import org.apache.cocoon.forms.FormsRuntimeException;
 import org.apache.cocoon.forms.datatype.Datatype;
 import org.apache.cocoon.forms.datatype.SelectionList;
 import org.apache.cocoon.forms.datatype.convertor.ConversionResult;
@@ -27,6 +29,7 @@
 import org.apache.cocoon.xml.AttributesImpl;
 import org.apache.cocoon.xml.XMLUtils;
 import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
@@ -46,6 +49,16 @@
 public class Field extends AbstractWidget
                    implements ValidationErrorAware, DataWidget, SelectableWidget, ValueChangedListenerEnabled {
 
+    /**
+     * If the field was rendered as a suggestion-list and the user chose one of the suggestions,
+     * the field's value is the chosen item's value and the <code>SUGGESTED_LABEL_ATTR</code> field
+     * attribute contains the chosen item's label.
+     * 
+     * @see #isSuggested()
+     * @since 2.1.9
+     */
+    public static final String SUGGESTED_LABEL_ATTR = "suggested-label";
+
     private static final String FIELD_EL = "field";
     private static final String VALUE_EL = "value";
     private static final String VALIDATION_MSG_EL = "validation-message";
@@ -139,6 +152,41 @@
         this.required = this.fieldDefinition.isRequired();
         super.initialize();
     }
+    
+    /**
+     * If this field has a selection-list, indicates if the value comes from that list
+     * or if a new value was input by the user.
+     * 
+     * @since 2.1.9
+     * @return true if the user has chosen a suggested value
+     */
+    public boolean isSuggested() {
+        return this.getAttribute(SUGGESTED_LABEL_ATTR) != null;
+    }
+    
+    /**
+     * Set the suggestion label associated to the widget's current value. This is used to initialize
+     * a combobox's rendering. If not such label exists, the widget's value is used.
+     * 
+     * @since 2.1.9
+     */
+    public void setSuggestionLabel(String label) {
+        if (this.fieldDefinition.getSuggestionList() == null) {
+            throw new FormsRuntimeException(this + " has no suggestion list", this.getLocation());
+        }
+        this.setAttribute(SUGGESTED_LABEL_ATTR, label);
+    }
+    
+    /**
+     * If the user has chosen an item in a suggestion list, returns that item's label.
+     * 
+     * @since 2.1.9
+     * @return the item's label, or <code>null</code> if the user entered a new value or
+     *         if there's not suggestion list.
+     */
+    public String getSuggestionLabel() {
+        return (String)this.getAttribute(SUGGESTED_LABEL_ATTR);
+    }
 
     public Object getValue() {
         // if getValue() is called on this field while we're validating, then it's because a validation
@@ -217,7 +265,25 @@
             return;
         }
 
-        String newEnteredValue = formContext.getRequest().getParameter(getRequestParameterName());
+        String paramName = getRequestParameterName();
+        Request request = formContext.getRequest();
+        
+        String newEnteredValue = request.getParameter(paramName);
+
+        if (this.fieldDefinition.getSuggestionList() != null) {
+            // The Dojo ComboBox sends the typed value or the chosen item's label in the
+            // request parameter and sends an additional "*_selected" parameter containing
+            // the value of the chosen item (if any).
+            // So if *_selected exists, use 
+            String selectedValue = request.getParameter(paramName + "_selected");
+            if (StringUtils.isNotEmpty(selectedValue)) {
+                setSuggestionLabel(newEnteredValue);
+                newEnteredValue = selectedValue;
+            } else {
+                this.removeAttribute(SUGGESTED_LABEL_ATTR);
+            }
+        }
+
         // FIXME: Should we consider only non-null values?
         // Although distinguishing an empty value (input present but blank) from a null value
         // (input not present in the form) is possible, this distinction is not possible for
@@ -443,6 +509,14 @@
             }
             contentHandler.characters(stringValue.toCharArray(), 0, stringValue.length());
             contentHandler.endElement(FormsConstants.INSTANCE_NS, VALUE_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALUE_EL);
+        }
+        
+        // Suggested label, if any
+        String suggestedLabel = getSuggestionLabel();
+        if (suggestedLabel != null) {
+            contentHandler.startElement(FormsConstants.INSTANCE_NS, "suggestion", FormsConstants.INSTANCE_PREFIX_COLON + "suggestion", XMLUtils.EMPTY_ATTRIBUTES);
+            contentHandler.characters(suggestedLabel.toCharArray(), 0, suggestedLabel.length());
+            contentHandler.endElement(FormsConstants.INSTANCE_NS, "suggestion", FormsConstants.INSTANCE_PREFIX_COLON + "suggestion");
         }
 
         // validation message element: only present if the value is not valid

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Repeater.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Repeater.java?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Repeater.java (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Repeater.java Sun Mar 12 10:25:06 2006
@@ -16,17 +16,16 @@
 package org.apache.cocoon.forms.formmodel;
 
 import java.util.ArrayList;
-import java.util.BitSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 
 import org.apache.cocoon.environment.Request;
-import org.apache.cocoon.forms.FormsConstants;
 import org.apache.cocoon.forms.FormContext;
+import org.apache.cocoon.forms.FormsConstants;
 import org.apache.cocoon.forms.FormsRuntimeException;
-import org.apache.cocoon.forms.util.I18nMessage;
 import org.apache.cocoon.forms.event.WidgetEvent;
+import org.apache.cocoon.forms.util.I18nMessage;
 import org.apache.cocoon.forms.validation.ValidationError;
 import org.apache.cocoon.forms.validation.ValidationErrorAware;
 import org.apache.cocoon.xml.AttributesImpl;
@@ -59,7 +58,6 @@
     private final RepeaterDefinition definition;
     protected final List rows = new ArrayList();
     protected ValidationError validationError;
-    private boolean selectable = false;
     private boolean orderable = false;
 
     public Repeater(RepeaterDefinition repeaterDefinition) {
@@ -71,7 +69,6 @@
             rows.add(new RepeaterRow(definition));
         }
         
-        this.selectable = this.definition.getSelectable();
         this.orderable = this.definition.getOrderable();
     }
 
@@ -309,25 +306,6 @@
             row.readFromRequest(formContext);
         }
         
-        // Handle selection
-        if (this.selectable) {
-            String[] selectedIds = req.getParameterValues(paramName + ".select");
-            BitSet selection = new BitSet(getSize());
-            
-            // Create selection bitmask
-            if (selectedIds != null) {
-                for (int i = 0; i < selectedIds.length; i++) {
-                    int rowId = Integer.parseInt(selectedIds[i]);
-                    selection.set(rowId);
-                }
-            }
-            
-            // And update the selected state of all rows
-            for (int i = 0; i < getSize(); i++) {
-                getRow(i).setSelected(selection.get(i));
-            }
-        }
-        
         // Handle repeater-level actions
         String action = req.getParameter(paramName + ".action");
         if (action == null) {
@@ -504,7 +482,6 @@
 
         private int cachedPosition = -100;
         private String cachedId = "--undefined--";
-        private boolean selected = false;
 
         public String getId() {
             int pos = rows.indexOf(this);
@@ -541,17 +518,6 @@
             }
         }
         
-        public boolean getSelected() {
-            return this.selected;
-        }
-        
-        public void setSelected(boolean selected) {
-            if (selected != this.selected) {
-                this.selected = selected;
-                getForm().addWidgetUpdate(this);
-            }
-        }
-
         public boolean validate() {
             // Validate only child widtgets, as the definition's validators are those of the parent repeater
             return widgets.validate();
@@ -577,5 +543,4 @@
             throw new UnsupportedOperationException("Widget " + this.getRequestParameterName() + " doesn't handle events.");
         }
     }
-
 }

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/RepeaterDefinition.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/RepeaterDefinition.java?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/RepeaterDefinition.java (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/RepeaterDefinition.java Sun Mar 12 10:25:06 2006
@@ -24,7 +24,6 @@
     private int initialSize = 0;
     private int minSize;
     private int maxSize;
-    private boolean selectable;
     private boolean orderable;
 
     public RepeaterDefinition(int initialSize, int minSize, int maxSize, boolean selectable, boolean orderable) {
@@ -32,7 +31,6 @@
         this.initialSize = initialSize;
         this.minSize = minSize;
         this.maxSize = maxSize;
-        this.selectable = selectable;
         this.orderable = orderable;
     }
     
@@ -70,9 +68,5 @@
     
     public boolean getOrderable() {
         return this.orderable;
-    }
-
-    public boolean getSelectable() {
-        return this.selectable;
     }
 }

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Submit.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Submit.java?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Submit.java (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/formmodel/Submit.java Sun Mar 12 10:25:06 2006
@@ -31,6 +31,7 @@
     }
     
     protected void handleActivate() {
+        performAction();
         if (!validateForm) {
             // End the form processing now and don't redisplay the form.
             getForm().endProcessing(false);

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/generation/SuggestionListGenerator.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/generation/SuggestionListGenerator.java?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/generation/SuggestionListGenerator.java (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/generation/SuggestionListGenerator.java Sun Mar 12 10:25:06 2006
@@ -19,6 +19,9 @@
 import java.util.Locale;
 import java.util.Map;
 
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.context.Contextualizable;
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
@@ -26,15 +29,21 @@
 import org.apache.cocoon.components.flow.ContinuationsManager;
 import org.apache.cocoon.components.flow.InvalidContinuationException;
 import org.apache.cocoon.components.flow.WebContinuation;
+import org.apache.cocoon.components.flow.javascript.fom.FOM_Cocoon;
+import org.apache.cocoon.components.flow.javascript.fom.FOM_JavaScriptFlowHelper;
+import org.apache.cocoon.components.flow.javascript.fom.FOM_JavaScriptInterpreter.ThreadScope;
 import org.apache.cocoon.environment.ObjectModelHelper;
 import org.apache.cocoon.environment.Request;
 import org.apache.cocoon.environment.SourceResolver;
 import org.apache.cocoon.forms.FormsConstants;
+import org.apache.cocoon.forms.datatype.FilterableSelectionList;
 import org.apache.cocoon.forms.datatype.SelectionList;
 import org.apache.cocoon.forms.formmodel.Field;
 import org.apache.cocoon.forms.formmodel.Form;
 import org.apache.cocoon.generation.ServiceableGenerator;
 import org.apache.cocoon.sitemap.SitemapParameters;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.continuations.Continuation;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
@@ -44,13 +53,18 @@
  * @since 2.1.8
  * @version $Id$
  */
-public class SuggestionListGenerator extends ServiceableGenerator {
+public class SuggestionListGenerator extends ServiceableGenerator implements Contextualizable {
 
     private ContinuationsManager contManager;
     private WebContinuation wk;
     private SelectionList list;
     private String filter;
     private Locale locale;
+    private Context context;
+
+    public void contextualize(Context ctx) throws ContextException {
+        this.context = ctx;
+    }
 
     public void service(ServiceManager manager) throws ServiceException {
         super.service(manager);
@@ -63,9 +77,8 @@
         Request req = ObjectModelHelper.getRequest(objectModel);
         
         String continuationId = par.getParameter("continuation-id", req.getParameter("continuation-id"));
-        String widgetPath = par.getParameter("widget-id", req.getParameter("widget-id")).replace('.', '/');
-        String widgetId = widgetPath.replace('/', '.');
-        this.filter = par.getParameter("filter", req.getParameter(widgetId));
+        String widgetPath = par.getParameter("widget", req.getParameter("widget")).replace('.', '/');
+        this.filter = par.getParameter("filter", req.getParameter("filter"));
         
         // The interpreter id is the sitemap's URI
         String interpreterId = SitemapParameters.getLocation(parameters).getURI();
@@ -92,12 +105,39 @@
         super.contentHandler.startDocument();
         super.contentHandler.startPrefixMapping(FormsConstants.INSTANCE_PREFIX, FormsConstants.INSTANCE_NS);
         ContentHandler handler;
-        if (filter == null || filter.length() == 0) {
+        if (filter == null || filter.length() == 0 || list instanceof FilterableSelectionList) {
             handler = super.contentHandler;
         } else {
             handler = new SelectionListFilter(filter, super.contentHandler);
         }
-        list.generateSaxFragment(handler, this.locale);
+        
+        // Restore the JavaScript execution context, if any
+        Scriptable oldScope = null;
+        FOM_Cocoon cocoon = null;
+        if (wk.getContinuation() instanceof Continuation) {
+            oldScope = FOM_JavaScriptFlowHelper.getFOM_FlowScope(objectModel);
+            
+            Continuation k = (Continuation)wk.getContinuation();
+            Scriptable kScope = (ThreadScope)k.getParentScope();
+            // Register the current scope for scripts indirectly called from this function
+            FOM_JavaScriptFlowHelper.setFOM_FlowScope(objectModel, kScope);
+            cocoon = (FOM_Cocoon)kScope.get("cocoon", kScope);
+            cocoon.pushCallContext(null, null, this.manager, this.context, getLogger(), wk);
+        }
+
+        try {
+            if (list instanceof FilterableSelectionList) {
+                ((FilterableSelectionList)list).generateSaxFragment(handler, this.locale, filter);
+            } else {
+                list.generateSaxFragment(handler, this.locale);
+            }
+        } finally {
+            if (oldScope != null) {
+                // Restore it
+                FOM_JavaScriptFlowHelper.setFOM_FlowScope(objectModel, oldScope);
+                cocoon.popCallContext();
+            }
+        }
         
         super.contentHandler.endPrefixMapping(FormsConstants.INSTANCE_PREFIX);
         super.contentHandler.endDocument();

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/generation/jx-macros.xml
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/generation/jx-macros.xml?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/generation/jx-macros.xml (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/generation/jx-macros.xml Sun Mar 12 10:25:06 2006
@@ -21,8 +21,24 @@
              xmlns:ft="http://apache.org/cocoon/forms/1.0#template"
              xmlns:fi="http://apache.org/cocoon/forms/1.0#instance"
              xmlns:bu="http://apache.org/cocoon/browser-update/1.0">
+
     <!--
-        ft:form-template
+        ft:form
+    -->
+    <jx:macro name="form" targetNamespace="http://apache.org/cocoon/forms/1.0#template">
+      <jx:set var="cformsHelper" value="#{org.apache.cocoon.forms.generation.JXMacrosHelper.createHelper($cocoon/consumer,$cocoon/request,$cocoon/parameters/locale)}"/>
+      <jx:set var="form" value="${cformsHelper.getForm(CocoonFormsInstance, cocoon.parameters['attribute-name'])}"/>
+      <jx:if test="${cformsHelper.isVisible(form)}">
+        <jx:set var="cformsDummy" value="${cformsHelper.startForm(form, macro.arguments)}"/>
+        <!-- the form is also the current widget -->
+        <jx:set var="widget" value="${form}"/>
+        <jx:evalBody/>
+        <jx:set var="cformsDummy" value="${cformsHelper.endForm()}"/>
+      </jx:if>
+    </jx:macro>
+    
+    <!--
+        ft:form-template: preferred syntax is now "ft:form" (we know we're in a template)
     -->
     <jx:macro name="form-template" targetNamespace="http://apache.org/cocoon/forms/1.0#template">
       <jx:set var="cformsHelper" value="#{org.apache.cocoon.forms.generation.JXMacrosHelper.createHelper($cocoon/consumer,$cocoon/request,$cocoon/parameters/locale)}"/>

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/css/forms.css
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/css/forms.css?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/css/forms.css (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/css/forms.css Sun Mar 12 10:25:06 2006
@@ -74,7 +74,21 @@
     width: 40px;
 }
 
-/** Style for drag'n drop indicator */
+/* Style for drag'n drop indicator */
 .forms-dropIndicator {
 	border-top: 4px solid black;
+}
+
+.forms-row-hover {
+	background-color:#F0F0F0;
+}
+
+.forms-row-selected {
+	background-color: rgb(56,117,215); /* Mac highlight color */
+	color: white;
+}
+
+.forms-row-hover.forms-row-selected {
+	background-color: rgb(86, 147, 245);
+	color: white;
 }

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/forms-advanced-field-styling.xsl
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/forms-advanced-field-styling.xsl?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/forms-advanced-field-styling.xsl (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/forms-advanced-field-styling.xsl Sun Mar 12 10:25:06 2006
@@ -227,27 +227,48 @@
       | Field with in-place editing
       +-->
   <xsl:template match="fi:field[fi:styling/@type='inplace' and @state='active']">
-    <xsl:choose>
-      <xsl:when test="fi:value">
-        <span id="{@id}">
-          <script type="text/javascript">dojo.require("dojo.widget.InlineEditBox")</script>
-          <span dojoType="InlineEditBox" onSave="dojo.byId('{@id}:input').value = arguments[0]">
-            <xsl:attribute name="onSave">
-              <xsl:text>dojo.byId('{@id}:input').value = arguments[0];</xsl:text>
-              <xsl:if test="@listening = 'true' and not(fi:styling/@submit-on-change = 'false') and not(fi:styling/@onchange)">
-                <xsl:text>forms_submitForm(dojo.byId('{@id}:input'))</xsl:text>
-              </xsl:if>
-            </xsl:attribute>
+    <span id="{@id}">
+      <span dojoType="InlineEditBox" onSave="dojo.byId('{@id}:input').value = arguments[0]">
+        <xsl:attribute name="onSave">
+          <xsl:text>dojo.byId('</xsl:text>
+          <xsl:value-of select="@id"/>
+          <xsl:text>:input').value = arguments[0];</xsl:text>
+          <xsl:if test="(@listening = 'true' and not(fi:styling/@submit-on-change = 'false')) or fi:styling/@submit-on-change = 'true'">
+            <xsl:text>forms_submitForm(dojo.byId('</xsl:text>
+            <xsl:value-of select="@id"/>
+            <xsl:text>:input'))</xsl:text>
+          </xsl:if>
+        </xsl:attribute>
+        <xsl:choose>
+          <xsl:when test="fi:value">
             <xsl:value-of select="fi:value"/>
-          </span>
-          <input id="{@id}:input" type="hidden" name="{@id}" value="{fi:value}"/>
-        </span>
-      </xsl:when>
-      <xsl:otherwise>
-        <!-- Produce a regular input -->
-        <xsl:apply-imports/>
-      </xsl:otherwise>
-    </xsl:choose>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:attribute name="defaultText">
+              <xsl:text>[</xsl:text>
+              <xsl:value-of select="fi:hint"/>
+              <xsl:text>]</xsl:text>
+            </xsl:attribute>
+            <xsl:text> </xsl:text> <!-- some dumb text, otherwise IE bugs... -->
+          </xsl:otherwise>
+        </xsl:choose>
+      </span>
+      <xsl:apply-templates select="." mode="common"/>
+      <input id="{@id}:input" type="hidden" name="{@id}" value="{fi:value}"/>
+    </span>
   </xsl:template>
 
+  <!--+
+      | Field with a suggestion list
+      +-->
+  <xsl:template match="fi:field[fi:styling/@type='suggest' and @state='active']">
+    <span id="{@id}">
+      <input name="{@id}" id="{@id}:input" value="{fi:value}" dojoType="CFormsSuggest">
+        <xsl:if test="fi:suggestion">
+          <xsl:attribute name="suggestion"><xsl:value-of select="fi:suggestion"/></xsl:attribute>
+        </xsl:if>
+      </input>
+      <xsl:apply-templates select="." mode="common"/>
+    </span>
+  </xsl:template>
 </xsl:stylesheet>

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/forms-field-styling.xsl
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/forms-field-styling.xsl?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/forms-field-styling.xsl (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/forms-field-styling.xsl Sun Mar 12 10:25:06 2006
@@ -31,7 +31,7 @@
          <script> djConfig = {isDebug: true} </script> -->
     <xsl:copy-of select="fi:init/node()"/>
     <script src="{$resources-uri}/dojo/dojo.js" type="text/javascript"/>
-    <script src="{$resources-uri}/ajax/js/cocoon.js" type="text/javascript"/>
+    <script src="{$resources-uri}/ajax/cocoon.js" type="text/javascript"/>
     <script src="{$resources-uri}/forms/js/forms-lib.js" type="text/javascript"/>
     <script type="text/javascript">
         dojo.addOnLoad(forms_onload);

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsForm.js
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsForm.js?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsForm.js (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsForm.js Sun Mar 12 10:25:06 2006
@@ -38,7 +38,6 @@
 	widgetType: "CFormsForm",
     isContainer: true,
     buildRendering: function(args, parserFragment, parentWidget) {
-	
         // Magical statement to get the dom node, stolen in DomWidget
 	    this.domNode = parserFragment["dojo:"+this.widgetType.toLowerCase()].nodeRef;
 
@@ -68,7 +67,7 @@
         // grabClickTarget above, but avoid browser specifics for now.
         var target = /*event.explicitOriginalTarget ||*/ this.lastClickTarget;
 
-        this.submit(target.name);
+        this.submit(target && target.name);
         // If real submit has to occur, it's taken care of in submit()
         return false;
     },
@@ -83,7 +82,7 @@
      */
     submit: function(name, params) {
         var form = this.domNode;
-        
+
         var query = cocoon.forms.buildQueryString(form, name);
         if (!query) {
             if (params) alert("FIXME: handle additional params in CFormsForm.submit()");

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsRepeater.js
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsRepeater.js?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsRepeater.js (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsRepeater.js Sun Mar 12 10:25:06 2006
@@ -37,7 +37,8 @@
 dojo.lang.extend(cocoon.forms.CFormsRepeater, {
 	// Properties
 	orderable: false,
-	select: "none",
+	select: "$no$", // default value used to type the property, but indicating that
+	                // no selection will occur
 	
 	// Widget definition
 	widgetType: "CFormsRepeater",
@@ -48,7 +49,6 @@
 	    this.domNode = parserFragment["dojo:"+this.widgetType.toLowerCase()].nodeRef;
 	    
         this.id = this.domNode.getAttribute("id");
-        dojo.debug("Creating repeater " + this.id);
         if (!this.orderable && this.select == "none") {
             dojo.debug("CFormsRepeater '" + this.id + "' is not orderable nor selectable");
         }
@@ -85,14 +85,25 @@
             }
         }
 
-        if (true || this.select == "single" || this.select == "multiple") {
+        if (this.select != "$no$") {
 	        var row;
 	        var widget = this;
 	        for (var idx = 0; row = dojo.byId(this.id + "." + idx); idx++) {
+	            var selectId = row.getAttribute("id") + "." + this.select + ":input";
+	            var selectInput = dojo.byId(selectId);
+	            if (!selectInput) {
+	                throw "No select input found for row '" + row.getAttribute("id") + "'";
+	            }
+
+                if (selectInput.checked) {
+                    dojo.html.prependClass(row, "forms-row-selected");
+                }
 		        (function() {
 		            var localIdx = idx; // to use it in the closure
 		            var localRow = row;
-		            dojo.event.connect(row, "onclick", function(e) { widget.selectRow(e, localRow, localIdx) })
+		            dojo.event.connect(row, "onclick", function(e) { widget.selectRow(e, localRow, localIdx) });
+		            dojo.event.connect(row, "onmouseover", function(e) { dojo.html.prependClass(localRow, "forms-row-hover") });
+		            dojo.event.connect(row, "onmouseout", function(e) { dojo.html.removeClass(localRow,  "forms-row-hover") });
 			    })()
             }
         }
@@ -134,14 +145,11 @@
 
     selectRow: function(e, row, idx) {
 	    if (this.isValidEvent(e)) {
-	        if (row.getAttribute("selected") == "true") {
-	            row.setAttribute("selected", "false");
-	            row.style.background = "none";
-	        } else {
-	            row.setAttribute("selected", "true");
-	            row.style.background = "green";
-	        }
-		    dojo.debug("clic " + idx); //+ " from " + elt.tagName + " onclick=" + elt.onclick);
+	        var selectInput = dojo.byId(row.getAttribute("id") + "." + this.select + ":input");
+	        // Toggle selection
+	        selectInput.checked = selectInput.checked ? false : true;
+	        // And update CSS class accordingly
+	        (selectInput.checked ? dojo.html.prependClass : dojo.html.removeClass)(row, "forms-row-selected");
 	    }
 	}
 });

Added: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsSuggest.js
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsSuggest.js?rev=385330&view=auto
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsSuggest.js (added)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsSuggest.js Sun Mar 12 10:25:06 2006
@@ -0,0 +1,64 @@
+/*
+ * Copyright 1999-2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+dojo.provide("cocoon.forms.CFormsSuggest");
+dojo.require("dojo.widget.html.ComboBox");
+
+/**
+ * Dojo widget for suggestion-lists. Extends Dojo's ComboBox widget.
+ * Suggestion lists are fetched from the server at the "_cocoon/forms/suggest"
+ * URL.
+ *
+ * The following parameters are passed to that URL:
+ * - widget: the widget's name for which to provide suggestions
+ * - continuation-id: the continuation id, used to find the form
+ * - filter: what the user already typed, used to filter suggestions
+ *
+ * The response must be a JSON array of suggestions, each item being itself
+ * a 2-item array containing a label (displayed) and a value (not displayed but
+ * sent back to the server as the "{widget}_selected parameter".
+ *
+ * @version $Id$
+ */
+
+cocoon.forms.CFormsSuggest = function() {
+    dojo.widget.html.ComboBox.call(this);
+    this.widgetType = "CFormsSuggest";
+}
+
+dojo.inherits(cocoon.forms.CFormsSuggest, dojo.widget.html.ComboBox);
+
+dojo.lang.extend(cocoon.forms.CFormsSuggest, {
+    fillInTemplate: function(args, frag) {
+        this.mode = "remote";
+        var node = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];
+        var form = cocoon.forms.getForm(node);
+        var contId = form["continuation-id"].value;
+        if (!contId) throw "Cannot find continuation Id";
+        
+        if (!this.dataUrl || this.dataUrl == "") {
+            this.dataUrl = "_cocoon/forms/suggest?widget=" + node.getAttribute("name") +
+                "&continuation-id=" + contId + "&filter=%{searchString}";
+        }
+        dojo.widget.html.ComboBox.prototype.fillInTemplate.apply(this, arguments);
+        // Restore the initial value and the associated suggestion text, if any
+        this.setValue(node.getAttribute("suggestion") ? node.getAttribute("suggestion") : node.value);
+        this.setSelectedValue(node.value);
+    }
+})
+
+dojo.widget.tags.addParseTreeHandler("dojo:CFormsSuggest");
+// Register this module as a widget package
+dojo.widget.manager.registerWidgetPackage("cocoon.forms");

Propchange: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsSuggest.js
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/CFormsSuggest.js
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/__package__.js
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/__package__.js?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/__package__.js (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/__package__.js Sun Mar 12 10:25:06 2006
@@ -17,7 +17,9 @@
         common: [
                 "cocoon.forms.common",
                 "cocoon.forms.CFormsForm",
-                "cocoon.forms.CFormsRepeater"
+                "cocoon.forms.CFormsRepeater",
+                "cocoon.forms.CFormsSuggest",
+                "dojo.widget.InlineEditBox" // also needed by advanced-field-styling
         ]
 });
 

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/common.js
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/common.js?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/common.js (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/js/common.js Sun Mar 12 10:25:06 2006
@@ -85,10 +85,13 @@
 cocoon.forms.buildQueryString = function(form, submitId) {
     // Indicate to the server that we're in ajax mode
     var result = "cocoon-ajax=true";
-    
+
     // If the form has a forms_submit_id input, use it to avoid sending the value twice
     if (form["forms_submit_id"]) {
-        form["forms_submit_id"].value = submitId;
+        if (submitId)
+            form["forms_submit_id"].value = submitId;
+        else
+            form["forms_submit_id"].value = null;
     } else {
         if (submitId) result += "&forms_submit_id=" + submitId;
     }
@@ -96,6 +99,9 @@
     // Iterate on all form controls
     for (var i = 0; i < form.elements.length; i++) {
         input = form.elements[i];
+        
+        if (!input.name) continue; // ignore inputs with no name
+
         if (typeof(input.type) == "undefined") {
         	    // Skip fieldset
             continue;

Modified: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/mattkruse-lib/PopupWindow.js
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/mattkruse-lib/PopupWindow.js?rev=385330&r1=385329&r2=385330&view=diff
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/mattkruse-lib/PopupWindow.js (original)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/mattkruse-lib/PopupWindow.js Sun Mar 12 10:25:06 2006
@@ -274,19 +274,20 @@
 function PopupWindow_attachListener() {
 	if (document.layers) {
 		document.captureEvents(Event.MOUSEUP);
-		}
+	}
 	window.popupWindowOldEventListener = document.onmouseup;
-	if (window.popupWindowOldEventListener != null) {
+	if (dojo) {
+		dojo.require("dojo.event");
+		dojo.event.connect(window, "onmouseup", PopupWindow_hidePopupWindows);
+	} else if (window.popupWindowOldEventListener != null) {
 		document.onmouseup = function(e) {
 			window.popupWindowOldEventListener(e);
 			PopupWindow_hidePopupWindows(e);
-		    }
-		//document.onmouseup = new Function("window.popupWindowOldEventListener(); PopupWindow_hidePopupWindows();");
 		}
-	else {
+	} else {
 		document.onmouseup = PopupWindow_hidePopupWindows;
-		}
 	}
+}
 // CONSTRUCTOR for the PopupWindow object
 // Pass it a DIV name to use a DHTML popup, otherwise will default to window popup
 function PopupWindow() {

Added: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/selection-list2json.xsl
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/selection-list2json.xsl?rev=385330&view=auto
==============================================================================
--- cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/selection-list2json.xsl (added)
+++ cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/selection-list2json.xsl Sun Mar 12 10:25:06 2006
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 2006 The Apache Software Foundation
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!--
+  Transforms a fi:selection-list into a JSON fragment.
+  
+  @version $Id$
+-->
+
+<xsl:stylesheet
+  version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:fi="http://apache.org/cocoon/forms/1.0#instance">
+
+<xsl:template match="fi:selection-list">
+  <dummy-root>
+    <xsl:text>[&#10;</xsl:text>
+    <xsl:apply-templates/>
+    <xsl:text>&#10;];</xsl:text>
+  </dummy-root>
+</xsl:template>
+
+<xsl:template match="fi:item">
+  <xsl:text>["</xsl:text>
+  <!-- displayed text -->
+  <xsl:choose>
+    <xsl:when test="fi:label">
+      <xsl:value-of select="fi:label"/>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:value-of select="@value"/>
+    </xsl:otherwise>
+  </xsl:choose>
+  <xsl:text>", "</xsl:text>
+  <!-- value -->
+  <xsl:value-of select="@value"/>
+  <xsl:text>"]</xsl:text>
+  <xsl:if test="position() != last()">
+    <xsl:text>, &#10;</xsl:text>
+  </xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file

Propchange: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/selection-list2json.xsl
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/cocoon-forms/cocoon-forms-impl/src/main/java/org/apache/cocoon/forms/resources/selection-list2json.xsl
------------------------------------------------------------------------------
    svn:keywords = Id