? extensions/xforms/Doxyfile
? extensions/xforms/__nsXFormsDOMFeatureService.cpp
? extensions/xforms/__nsXFormsDOMFeatureService.h
? extensions/xforms/dependentLibs.h
? extensions/xforms/nsIXFormsItemElement.idl
? extensions/xforms/nsIXFormsLabelElement.idl
? extensions/xforms/nsXFormsSelect1Element.cpp
? extensions/xforms/resources/content/select1.xml
Index: extensions/xforms/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/extensions/xforms/Makefile.in,v
retrieving revision 1.36
diff -u -8 -p -r1.36 Makefile.in
--- extensions/xforms/Makefile.in	29 Jun 2005 18:14:43 -0000	1.36
+++ extensions/xforms/Makefile.in	11 Jul 2005 18:27:48 -0000
@@ -88,16 +88,18 @@ XPIDLSRCS	= \
 		nsIXFormsValueElement.idl \
 		nsIXFormsRepeatElement.idl \
 		nsIXFormsRepeatItemElement.idl \
 		nsIXFormsSubmitElement.idl \
 		nsIXFormsSubmissionElement.idl \
 		nsIXFormsControlBase.idl \
 		nsIXFormsDelegate.idl \
 		nsIXFormsUIWidget.idl \
+		nsIXFormsItemElement.idl \
+		nsIXFormsLabelElement.idl \
 		$(NULL)
 
 CPPSRCS		= \
 		nsXFormsElementFactory.cpp \
 		nsXFormsUtils.cpp \
 		nsXFormsModelElement.cpp \
 		nsXFormsInputElement.cpp \
 		nsXFormsGroupElement.cpp \
@@ -132,16 +134,17 @@ CPPSRCS		= \
 		nsXFormsLoadElement.cpp \
 		nsXFormsMessageElement.cpp \
 		nsXFormsLabelElement.cpp \
 		nsXFormsToggleElement.cpp \
 		nsXFormsCaseElement.cpp \
 		nsXFormsSwitchElement.cpp \
 		nsXFormsUploadElement.cpp \
 		nsXFormsSelectElement.cpp \
+		nsXFormsSelect1Element.cpp \
 		nsXFormsItemElement.cpp \
 		nsXFormsValueElement.cpp \
 		nsXFormsChoicesElement.cpp \
 		nsXFormsItemSetElement.cpp \
 		nsXFormsSchemaValidator.cpp \
 		nsXFormsNodeState.cpp \
 		nsXFormsControlStub.cpp \
 		nsXFormsUtilityService.cpp \
Index: extensions/xforms/jar.mn
===================================================================
RCS file: /cvsroot/mozilla/extensions/xforms/jar.mn,v
retrieving revision 1.5
diff -u -8 -p -r1.5 jar.mn
--- extensions/xforms/jar.mn	28 Jun 2005 16:30:42 -0000	1.5
+++ extensions/xforms/jar.mn	11 Jul 2005 18:27:48 -0000
@@ -2,13 +2,14 @@ xforms.jar:
 % overlay	chrome://browser/content/preferences/preferences.xul	chrome://xforms/content/xforms-prefs.xul
 % content	xforms	%content/xforms/
 % locale	xforms	en-US	%locale/en-US/xforms/
   content/xforms/contents.rdf                  (resources/content/contents.rdf)
 * content/xforms/xforms.css                    (resources/content/xforms.css)
 * content/xforms/xforms-prefs.xul              (resources/content/xforms-prefs.xul)
 * content/xforms/xforms-prefs-ui.xul           (resources/content/xforms-prefs-ui.xul)
 * content/xforms/xforms-prefs.js               (resources/content/xforms-prefs.js)
-	content/xforms/xforms.xml                    (resources/content/xforms.xml)
+  content/xforms/xforms.xml                    (resources/content/xforms.xml)
+  content/xforms/select1.xml                   (resources/content/select1.xml)
 * locale/en-US/xforms/contents.rdf             (resources/locale/en-US/contents.rdf)
   locale/en-US/xforms/xforms.properties        (resources/locale/en-US/xforms.properties)
   locale/en-US/xforms/xforms.dtd               (resources/locale/en-US/xforms.dtd)
 
Index: extensions/xforms/nsIXFormsSelectChild.idl
===================================================================
RCS file: /cvsroot/mozilla/extensions/xforms/nsIXFormsSelectChild.idl,v
retrieving revision 1.3
diff -u -8 -p -r1.3 nsIXFormsSelectChild.idl
--- extensions/xforms/nsIXFormsSelectChild.idl	1 Feb 2005 01:18:27 -0000	1.3
+++ extensions/xforms/nsIXFormsSelectChild.idl	11 Jul 2005 18:27:48 -0000
@@ -47,40 +47,44 @@ class nsStringArray;
 
 [ref] native constStringArray(const nsStringArray);
 
 /**
  * nsIXFormsSelectChild is implemented by elements that can be children
  * of an XForms select element (choices, item, itemset).
  */
 
-[uuid(21e37ef5-ce3e-4ff1-b7b2-fb34c4e2c8be)]
+[scriptable, uuid(21e37ef5-ce3e-4ff1-b7b2-fb34c4e2c8be)]
 interface nsIXFormsSelectChild : nsISupports
 {
   /**
    * The DOM elements returned by this attribute are inserted into the select
    * element's anonymous content tree.
    */
   readonly attribute nsIArray anonymousNodes;
 
+  readonly attribute AString value;
+
   /**
    * These two methods allow the select to synchronize selection with the
    * instance data.
    *
    * selectItemsByValue() handles children that have a value element child.
    * If the value element text for this child is contained in the |values|
    * array, then the item should select itself.
    *
    * selectItemsByContent() handles children that have a copy element child.
    * If |node| points to the same instance data node as the item, then the
    * item should select itself.
    */
-  void selectItemsByValue(in constStringArray values);
+  [noscript] void selectItemsByValue(in constStringArray values);
   void selectItemsByContent(in nsIDOMNode node);
 
+  nsIDOMNode selectItemByValue(in AString value);
+
   /**
    * Instructs the item to serialize its selected elements.
    * For children that have a value child, they should append the value of
    * any selected items to the provided string buffer.  For children
    * that have a copy child, they should copy the instance data element into
    * |container|.
    */
   void writeSelectedItems(in nsIDOMNode container, out AString stringBuffer);
Index: extensions/xforms/nsXFormsChoicesElement.cpp
===================================================================
RCS file: /cvsroot/mozilla/extensions/xforms/nsXFormsChoicesElement.cpp,v
retrieving revision 1.4
diff -u -8 -p -r1.4 nsXFormsChoicesElement.cpp
--- extensions/xforms/nsXFormsChoicesElement.cpp	21 Jun 2005 16:47:29 -0000	1.4
+++ extensions/xforms/nsXFormsChoicesElement.cpp	11 Jul 2005 18:27:48 -0000
@@ -41,59 +41,62 @@
 #include "nsIDOMHTMLOptGroupElement.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIXTFGenericElementWrapper.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMNodeList.h"
 #include "nsXFormsUtils.h"
 #include "nsArray.h"
+#include "nsIXTFXMLVisualWrapper.h"
 
 /**
  * Implementation of XForms \<choices\> element.  This creates an HTML
  * optgroup element and inserts any childrens' anonymous content as children
  * of the optgroup.
  */
 
-class nsXFormsChoicesElement : public nsXFormsStubElement,
+class nsXFormsChoicesElement : public nsXFormsXMLVisualStub,
                                public nsIXFormsSelectChild
 {
 public:
   nsXFormsChoicesElement() : mElement(nsnull) {}
 
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIXTFGenericElement overrides
-  NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper);
+  NS_IMETHOD OnCreated(nsIXTFXMLVisualWrapper *aWrapper);
 
   // nsIXTFElement overrides
   NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent);
   NS_IMETHOD ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex);
   NS_IMETHOD ChildAppended(nsIDOMNode *aChild);
   NS_IMETHOD ChildRemoved(PRUint32 aIndex);
+  NS_IMETHOD GetVisualContent(nsIDOMElement **aContent);
+  NS_IMETHOD GetInsertionPoint(nsIDOMElement **aInsertionPoint);
   NS_IMETHOD BeginAddingChildren();
   NS_IMETHOD DoneAddingChildren();
 
   // nsIXFormsControlBase overrides
   NS_IMETHOD Refresh();
 
   // nsIXFormsSelectChild
   NS_DECL_NSIXFORMSSELECTCHILD
 
 private:
-  nsIDOMElement *mElement;
+  nsIDOMElement* mElement;
+  nsCOMPtr<nsIDOMElement> mVisual;
   nsCOMPtr<nsIDOMHTMLOptGroupElement> mOptGroup;
 };
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsXFormsChoicesElement,
-                             nsXFormsStubElement,
+                             nsXFormsXMLVisualStub,
                              nsIXFormsSelectChild)
 
 NS_IMETHODIMP
-nsXFormsChoicesElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
+nsXFormsChoicesElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper)
 {
   aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_PARENT_CHANGED |
                                 nsIXTFElement::NOTIFY_CHILD_INSERTED |
                                 nsIXTFElement::NOTIFY_CHILD_APPENDED |
                                 nsIXTFElement::NOTIFY_CHILD_REMOVED |
                                 nsIXTFElement::NOTIFY_BEGIN_ADDING_CHILDREN);
 
   nsCOMPtr<nsIDOMElement> node;
@@ -117,16 +120,35 @@ nsXFormsChoicesElement::OnCreated(nsIXTF
   nsCOMPtr<nsIDOMElement> element;
   domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
                           NS_LITERAL_STRING("optgroup"),
                           getter_AddRefs(element));
 
   mOptGroup = do_QueryInterface(element);
   NS_ENSURE_TRUE(mOptGroup, NS_ERROR_FAILURE);
 
+  domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
+                          NS_LITERAL_STRING("div"),
+                          getter_AddRefs(mVisual));
+  NS_ENSURE_TRUE(mVisual, NS_ERROR_FAILURE);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsChoicesElement::GetVisualContent(nsIDOMElement **aContent)
+{
+  NS_ADDREF(*aContent = mVisual);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsChoicesElement::GetInsertionPoint(nsIDOMElement **aInsertionPoint)
+{
+  NS_ADDREF(*aInsertionPoint = mVisual);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXFormsChoicesElement::ParentChanged(nsIDOMElement *aNewParent)
 {
   if (aNewParent)
     Refresh();
@@ -247,16 +269,43 @@ nsXFormsChoicesElement::GetAnonymousNode
 
   array->AppendElement(mOptGroup, PR_FALSE);
 
   NS_ADDREF(*aNodes = array);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsXFormsChoicesElement::SelectItemByValue(const nsAString &aValue, nsIDOMNode **aSelected)
+{
+  *aSelected = nsnull;
+  nsCOMPtr<nsIDOMNodeList> children;
+  nsresult rv = mElement->GetChildNodes(getter_AddRefs(children));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRUint32 childCount = 0;
+  children->GetLength(&childCount);
+
+  nsCOMPtr<nsIDOMNode> childNode;
+  nsCOMPtr<nsIXFormsSelectChild> childItem;
+
+  for (PRUint32 i = 0; i < childCount; ++i) {
+    children->Item(i, getter_AddRefs(childNode));
+    childItem = do_QueryInterface(childNode);
+    if (childItem) {
+      childItem->SelectItemByValue(aValue, aSelected);
+      if (*aSelected)
+        return NS_OK;
+    }
+  }
+  
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsXFormsChoicesElement::SelectItemsByValue(const nsStringArray &aValueList)
 {
   nsCOMPtr<nsIDOMNodeList> children;
   nsresult rv = mElement->GetChildNodes(getter_AddRefs(children));
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRUint32 childCount = 0;
   children->GetLength(&childCount);
@@ -358,16 +407,22 @@ nsXFormsChoicesElement::Refresh()
       child->CloneNode(PR_TRUE, getter_AddRefs(child2));
       mOptGroup->InsertBefore(child2, firstChild, getter_AddRefs(child));
     }
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsXFormsChoicesElement::GetValue(nsAString &aValue)
+{
+  return NS_OK;
+}
+
 NS_HIDDEN_(nsresult)
 NS_NewXFormsChoicesElement(nsIXTFElement **aResult)
 {
   *aResult = new nsXFormsChoicesElement();
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aResult);
Index: extensions/xforms/nsXFormsElementFactory.cpp
===================================================================
RCS file: /cvsroot/mozilla/extensions/xforms/nsXFormsElementFactory.cpp,v
retrieving revision 1.17
diff -u -8 -p -r1.17 nsXFormsElementFactory.cpp
--- extensions/xforms/nsXFormsElementFactory.cpp	18 Feb 2005 21:30:56 -0000	1.17
+++ extensions/xforms/nsXFormsElementFactory.cpp	11 Jul 2005 18:27:48 -0000
@@ -58,16 +58,17 @@ NS_HIDDEN_(nsresult) NS_NewXFormsUploadE
 /// used by a user in a document. Not optimal, as it is not a legal XForms tag,
 /// but only a pseudo-element. But nsXFormsRepeat/SelectElement needs to be
 /// able to create the tag, so is there a "backdoor way" to do that? (XXX)
 NS_HIDDEN_(nsresult) NS_NewXFormsContextContainer(nsIXTFElement **aElement);
 NS_HIDDEN_(nsresult) NS_NewXFormsTriggerElement(nsIXTFElement **aElement);
 NS_HIDDEN_(nsresult) NS_NewXFormsSubmitElement(nsIXTFElement **aElement);
 NS_HIDDEN_(nsresult) NS_NewXFormsLabelElement(nsIXTFElement **aElement);
 NS_HIDDEN_(nsresult) NS_NewXFormsSelectElement(nsIXTFElement **aElement);
+NS_HIDDEN_(nsresult) NS_NewXFormsSelect1Element(nsIXTFElement **aElement);
 NS_HIDDEN_(nsresult) NS_NewXFormsItemElement(nsIXTFElement **aElement);
 NS_HIDDEN_(nsresult) NS_NewXFormsValueElement(nsIXTFElement **aElement);
 NS_HIDDEN_(nsresult) NS_NewXFormsChoicesElement(nsIXTFElement **aElement);
 NS_HIDDEN_(nsresult) NS_NewXFormsItemSetElement(nsIXTFElement **aElement);
 
 //Action Module Elements
 NS_HIDDEN_(nsresult) NS_NewXFormsDispatchElement(nsIXTFElement **aResult);
 NS_HIDDEN_(nsresult) NS_NewXFormsSendElement(nsIXTFElement **aResult);
@@ -120,18 +121,20 @@ nsXFormsElementFactory::CreateElement(co
     return NS_NewXFormsInsertElement(aElement);
   if (aTagName.EqualsLiteral("delete"))
     return NS_NewXFormsDeleteElement(aElement);
   if (aTagName.EqualsLiteral("contextcontainer") ||
       aTagName.EqualsLiteral("contextcontainer-inline"))
     return NS_NewXFormsContextContainer(aElement);
   if (aTagName.EqualsLiteral("label"))
     return NS_NewXFormsLabelElement(aElement);
-  if (aTagName.EqualsLiteral("select") || aTagName.EqualsLiteral("select1"))
+  if (aTagName.EqualsLiteral("select"))
     return NS_NewXFormsSelectElement(aElement);
+  if (aTagName.EqualsLiteral("select1"))
+    return NS_NewXFormsSelect1Element(aElement);
   if (aTagName.EqualsLiteral("item"))
     return NS_NewXFormsItemElement(aElement);
   if (aTagName.EqualsLiteral("itemset"))
     return NS_NewXFormsItemSetElement(aElement);
   if (aTagName.EqualsLiteral("value"))
     return NS_NewXFormsValueElement(aElement);
   if (aTagName.EqualsLiteral("choices"))
     return NS_NewXFormsChoicesElement(aElement);
Index: extensions/xforms/nsXFormsItemElement.cpp
===================================================================
RCS file: /cvsroot/mozilla/extensions/xforms/nsXFormsItemElement.cpp,v
retrieving revision 1.8
diff -u -8 -p -r1.8 nsXFormsItemElement.cpp
--- extensions/xforms/nsXFormsItemElement.cpp	21 Jun 2005 16:47:29 -0000	1.8
+++ extensions/xforms/nsXFormsItemElement.cpp	11 Jul 2005 18:27:49 -0000
@@ -44,74 +44,78 @@
 #include "nsIXTFGenericElementWrapper.h"
 #include "nsIDOMDocument.h"
 #include "nsString.h"
 #include "nsXFormsUtils.h"
 #include "nsIXFormsValueElement.h"
 #include "nsArray.h"
 #include "nsVoidArray.h"
 #include "nsIDOMText.h"
-#include "nsIXTFXMLVisualWrapper.h"
+#include "nsIXTFBindableElementWrapper.h"
 #include "nsIXFormsContextControl.h"
 #include "nsIModelElementPrivate.h"
+#include "nsIXFormsItemElement.h"
+#include "nsIXFormsControl.h"
+#include "nsIXFormsLabelElement.h"
 
 /**
  * nsXFormsItemElement implements the XForms \<item\> element.
  * It creates an anonymous HTML option element with the appropriate label,
  * which is inserted into the anonymous content tree of the containing
  * select element.
  */
 
-class nsXFormsItemElement : public nsXFormsStubElement,
-                            public nsIXFormsSelectChild
+class nsXFormsItemElement : public nsXFormsBindableStub,
+                            public nsIXFormsSelectChild,
+                            public nsIXFormsItemElement
 {
 public:
   nsXFormsItemElement() : mElement(nsnull),
                           mContextPosition(0),
                           mContextSize(0)
   {
   }
 
   NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIXFORMSITEMELEMENT
 
-  // nsIXTFGenericElement overrides
-  NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper);
+  NS_IMETHOD OnCreated(nsIXTFBindableElementWrapper *aWrapper);
 
   // nsIXTFElement overrides
   NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent);
   NS_IMETHOD ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex);
   NS_IMETHOD ChildAppended(nsIDOMNode *aChild);
   NS_IMETHOD WillRemoveChild(PRUint32 aIndex);
   NS_IMETHOD BeginAddingChildren();
   NS_IMETHOD DoneAddingChildren();
 
   // nsIXFormsControlBase overrides
   NS_IMETHOD Refresh();
 
   // nsIXFormsSelectChild
   NS_DECL_NSIXFORMSSELECTCHILD
 
 private:
-  NS_HIDDEN_(nsresult) GetValue(nsString &aValue);
 
-  nsIDOMElement *mElement;
+  nsIDOMElement* mElement;
   nsCOMPtr<nsIDOMHTMLOptionElement> mOption;
 
   // context node (used by itemset)
   nsCOMPtr<nsIDOMElement> mContextNode;
   PRInt32 mContextPosition;
   PRInt32 mContextSize;
 };
 
-NS_IMPL_ISUPPORTS_INHERITED1(nsXFormsItemElement,
-                             nsXFormsStubElement,
-                             nsIXFormsSelectChild)
+NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsItemElement,
+                             nsXFormsBindableStub,
+                             nsIXFormsSelectChild,
+                             nsIXFormsItemElement)
 
 NS_IMETHODIMP
-nsXFormsItemElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
+nsXFormsItemElement::OnCreated(nsIXTFBindableElementWrapper *aWrapper)
 {
   aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_PARENT_CHANGED |
                                 nsIXTFElement::NOTIFY_CHILD_INSERTED |
                                 nsIXTFElement::NOTIFY_CHILD_APPENDED |
                                 nsIXTFElement::NOTIFY_WILL_REMOVE_CHILD |
                                 nsIXTFElement::NOTIFY_BEGIN_ADDING_CHILDREN);
 
   nsCOMPtr<nsIDOMElement> node;
@@ -236,16 +240,29 @@ nsXFormsItemElement::GetAnonymousNodes(n
 
   array->AppendElement(mOption, PR_FALSE);
 
   NS_ADDREF(*aNodes = array);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsXFormsItemElement::SelectItemByValue(const nsAString &aValue, nsIDOMNode **aSelected)
+{
+  nsAutoString value;
+  GetValue(value);
+  if (aValue.Equals(value))
+    NS_ADDREF(*aSelected = mElement);
+  else
+    *aSelected = nsnull;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsXFormsItemElement::SelectItemsByValue(const nsStringArray &aValueList)
 {
   nsAutoString value;
   nsresult rv = GetValue(value);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt32 count = aValueList.Count();
   for (PRInt32 i = 0; i < count; ++i) {
@@ -293,20 +310,18 @@ nsXFormsItemElement::SetContext(nsIDOMEl
                                 PRInt32 aContextPosition, PRInt32 aContextSize)
 {
   mContextNode = aContextNode;
   mContextPosition = aContextPosition;
   mContextSize = aContextSize;
   return NS_OK;
 }
 
-// internal methods
-
-nsresult
-nsXFormsItemElement::GetValue(nsString &aValue)
+NS_IMETHODIMP
+nsXFormsItemElement::GetValue(nsAString &aValue)
 {
   // Find our value child and get its text content.
   nsCOMPtr<nsIDOMNodeList> children;
   nsresult rv = mElement->GetChildNodes(getter_AddRefs(children));
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRUint32 childCount;
   children->GetLength(&childCount);
@@ -377,16 +392,77 @@ nsXFormsItemElement::Refresh()
   }
 
   nsCOMPtr<nsIDOMNode> childReturn;
   mOption->AppendChild(container, getter_AddRefs(childReturn));
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsXFormsItemElement::SetActive(PRBool aActive)
+{
+  NS_NAMED_LITERAL_STRING(active, "_moz_active");
+  
+  return aActive ?
+    mElement->SetAttribute(active, NS_LITERAL_STRING("1")) :
+    mElement->RemoveAttribute(active);
+}
+
+NS_IMETHODIMP
+nsXFormsItemElement::GetLabelText(nsAString& aValue)
+{
+  NS_ENSURE_STATE(mElement);
+  nsCOMPtr<nsIDOMNodeList> children;
+  mElement->GetChildNodes(getter_AddRefs(children));
+  NS_ENSURE_STATE(children);
+
+  PRUint32 childCount;
+  children->GetLength(&childCount);
+
+  nsAutoString value;
+
+  nsCOMPtr<nsIDOMDocument> doc;
+  mElement->GetOwnerDocument(getter_AddRefs(doc));
+
+  nsCOMPtr<nsIDOMNode> child;
+  for (PRUint32 i = 0; i < childCount; ++i) {
+    children->Item(i, getter_AddRefs(child));
+    if (nsXFormsUtils::IsXFormsElement(child, NS_LITERAL_STRING("label"))) {
+      nsCOMPtr<nsIXFormsLabelElement> label(do_QueryInterface(child));
+      if (label) {
+        nsAutoString labelValue;
+        label->GetTextValue(labelValue);
+        value.Append(labelValue);
+      }
+    }
+  }
+  aValue = value;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsItemElement::LabelRefreshed()
+{
+  NS_ENSURE_STATE(mElement);
+  nsCOMPtr<nsIDOMNode> parent, current;
+  current = mElement;
+  do {
+    current->GetParentNode(getter_AddRefs(parent));
+    if (nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("select1"))) {
+      nsCOMPtr<nsIXFormsControl> select1(do_QueryInterface(parent));
+      if (select1)
+        select1->Refresh();
+      return NS_OK;
+    }
+    current = parent;
+  } while(current);
+  return NS_OK;
+}
+
 NS_HIDDEN_(nsresult)
 NS_NewXFormsItemElement(nsIXTFElement **aResult)
 {
   *aResult = new nsXFormsItemElement();
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aResult);
Index: extensions/xforms/nsXFormsItemSetElement.cpp
===================================================================
RCS file: /cvsroot/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp,v
retrieving revision 1.6
diff -u -8 -p -r1.6 nsXFormsItemSetElement.cpp
--- extensions/xforms/nsXFormsItemSetElement.cpp	21 Jun 2005 16:47:29 -0000	1.6
+++ extensions/xforms/nsXFormsItemSetElement.cpp	11 Jul 2005 18:27:49 -0000
@@ -199,16 +199,23 @@ nsXFormsItemSetElement::GetAnonymousNode
     }
   }
 
   NS_ADDREF(*aNodes = array);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsXFormsItemSetElement::SelectItemByValue(const nsAString &aValue, nsIDOMNode **aSelected)
+{
+  *aSelected = nsnull;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsXFormsItemSetElement::SelectItemsByValue(const nsStringArray &aValueList)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXFormsItemSetElement::SelectItemsByContent(nsIDOMNode *aNode)
 {
@@ -218,16 +225,22 @@ nsXFormsItemSetElement::SelectItemsByCon
 NS_IMETHODIMP
 nsXFormsItemSetElement::WriteSelectedItems(nsIDOMNode *aContainer, 
                                            nsAString  &aStringBuffer)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsXFormsItemSetElement::GetValue(nsAString &aValue)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsXFormsItemSetElement::SetContext(nsIDOMElement *aContextNode,
                                    PRInt32 aContextPosition,
                                    PRInt32 aContextSize)
 {
   // itemset can't be inside another itemset, so we don't need to worry about
   // this.
   return NS_OK;
 }
Index: extensions/xforms/nsXFormsLabelElement.cpp
===================================================================
RCS file: /cvsroot/mozilla/extensions/xforms/nsXFormsLabelElement.cpp,v
retrieving revision 1.8
diff -u -8 -p -r1.8 nsXFormsLabelElement.cpp
--- extensions/xforms/nsXFormsLabelElement.cpp	26 Jun 2005 18:30:17 -0000	1.8
+++ extensions/xforms/nsXFormsLabelElement.cpp	11 Jul 2005 18:27:49 -0000
@@ -51,32 +51,37 @@
 #include "nsIDOM3Node.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMText.h"
 #include "nsIXTFXMLVisualWrapper.h"
 #include "nsString.h"
 #include "nsIXFormsUIWidget.h"
 #include "nsIDocument.h"
 #include "nsNetUtil.h"
+#include "nsIXFormsLabelElement.h"
+#include "nsIXFormsItemElement.h"
 
 class nsXFormsLabelElement : public nsXFormsDelegateStub,
                              public nsIStreamListener,
-                             public nsIInterfaceRequestor
+                             public nsIInterfaceRequestor,
+                             public nsIXFormsLabelElement
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIINTERFACEREQUESTOR
+  NS_DECL_NSIXFORMSLABELELEMENT
 
   // nsIXFormsDelegate
   NS_IMETHOD GetValue(nsAString& aValue);
 
   // nsIXFormsControl
   NS_IMETHOD IsEventTarget(PRBool *aOK);
+  NS_IMETHOD Refresh();
 
   NS_IMETHOD OnCreated(nsIXTFBindableElementWrapper *aWrapper);
 
   // nsIXTFElement overrides
   NS_IMETHOD ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex);
   NS_IMETHOD ChildAppended(nsIDOMNode *aChild);
   NS_IMETHOD ChildRemoved(PRUint32 aIndex);
   NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aSrc);
@@ -87,21 +92,22 @@ public:
 #endif
 private:
   NS_HIDDEN_(void) LoadExternalLabel(const nsAString& aValue);
 
   nsCString            mSrcAttrText;
   nsCOMPtr<nsIChannel> mChannel;
 };
 
-NS_IMPL_ISUPPORTS_INHERITED3(nsXFormsLabelElement,
+NS_IMPL_ISUPPORTS_INHERITED4(nsXFormsLabelElement,
                              nsXFormsDelegateStub,
                              nsIRequestObserver,
                              nsIStreamListener,
-                             nsIInterfaceRequestor)
+                             nsIInterfaceRequestor,
+                             nsIXFormsLabelElement)
 
 NS_IMETHODIMP
 nsXFormsLabelElement::OnCreated(nsIXTFBindableElementWrapper *aWrapper)
 {
   nsresult rv = nsXFormsDelegateStub::OnCreated(aWrapper);
   NS_ENSURE_SUCCESS(rv, rv);
 
   aWrapper->SetNotificationMask(kStandardNotificationMask |
@@ -233,16 +239,29 @@ nsXFormsLabelElement::LoadExternalLabel(
       }
     }
   }
 }
 
 // nsIXFormsControl
 
 NS_IMETHODIMP
+nsXFormsLabelElement::Refresh()
+{
+  nsXFormsDelegateStub::Refresh();
+  nsCOMPtr<nsIDOMNode> parent;
+  mElement->GetParentNode(getter_AddRefs(parent));
+  nsCOMPtr<nsIXFormsItemElement> item(do_QueryInterface(parent));
+  if (item)
+    item->LabelRefreshed();
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsXFormsLabelElement::IsEventTarget(PRBool *aOK)
 {
   *aOK = PR_FALSE;
   return NS_OK;
 }
 
 // nsIInterfaceRequestor
 
@@ -327,16 +346,31 @@ nsXFormsLabelElement::OnStopRequest(nsIR
 
   nsCOMPtr<nsIXFormsUIWidget> widget = do_QueryInterface(mElement);
   if (widget)
     widget->Refresh();
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsXFormsLabelElement::GetTextValue(nsAString& aValue)
+{
+  NS_ENSURE_STATE(mElement);
+  GetValue(aValue);
+
+  if (aValue.IsVoid()) {
+    nsCOMPtr<nsIDOM3Node> inner(do_QueryInterface(mElement));
+    if (inner) {
+      inner->GetTextContent(aValue);
+    }
+  }
+
+  return NS_OK;
+}
 
 NS_HIDDEN_(nsresult)
 NS_NewXFormsLabelElement(nsIXTFElement **aResult)
 {
   *aResult = new nsXFormsLabelElement();
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
 
Index: extensions/xforms/resources/content/xforms.css
===================================================================
RCS file: /cvsroot/mozilla/extensions/xforms/resources/content/xforms.css,v
retrieving revision 1.1
diff -u -8 -p -r1.1 xforms.css
--- extensions/xforms/resources/content/xforms.css	28 Jun 2005 16:30:42 -0000	1.1
+++ extensions/xforms/resources/content/xforms.css	11 Jul 2005 18:27:49 -0000
@@ -29,27 +29,35 @@
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 @namespace url(http://www.w3.org/2002/xforms);
+@namespace html url(http://www.w3.org/1999/xhtml);
 @namespace mozType url(http://www.mozilla.org/projects/xforms/2005/type);
 
 repeat,
 repeatitem,
 contextcontainer,
 group,
 switch,
-case {
+case,
+select1 item,
+select1 choices {
   display: block;
 }
 
+select item,
+select choices {
+  display: none;
+}
+
 message[level="ephemeral"], hint {
   background-color: InfoBackground;
   color: InfoText;
   padding: 2px 3px;
   font: message-box;
   border: 1px black solid;
   visibility: hidden !important;
   position: absolute !important;
@@ -89,8 +97,98 @@ trigger[appearance="minimal"], submit[ap
 
 trigger[appearance="minimal"]:hover, submit[appearance="minimal"]:hover {
   cursor: pointer;
 }
 
 label {
   -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-label');
 }
+
+select1 {
+  -moz-binding: url('chrome://xforms/content/select1.xml#xformswidget-select1');
+}
+
+html|input.-moz-xforms-select1-dropdown {
+  width: 12px;
+  height: 1.3em;
+  white-space: nowrap;
+  position: static !important;
+  background-image: url("data:image/gif;base64,R0lGODlhBwAEAIAAAAAAAP%2F%2F%2FyH5BAEAAAEALAAAAAAHAAQAAAIIhA%2BBGWoNWSgAOw%3D%3D") !important;
+  background-repeat: no-repeat !important;
+  background-position: center !important;
+  -moz-appearance: menulist-button;
+  -moz-user-select: none;
+  -moz-binding: none;
+  vertical-align: text-top;
+  margin: 0px !important;
+  margin-top: -1px !important;
+}
+
+html|input.-moz-xforms-select1-dropdown:active:hover {
+  border-style: outset;
+}
+
+html|input.-moz-xforms-select1-input {
+  border: none;
+  margin-right: 0px;
+  padding-left: 0px;
+  font: -moz-list;
+}
+
+html|span.-moz-select1-container {
+  margin: 0px;
+  margin-bottom: 1px;
+  border-color: ThreeDFace;
+  background-color: -moz-Field;
+  color: -moz-FieldText;
+  font: -moz-list;
+  line-height: normal !important;
+  white-space: nowrap !important;
+  text-align: start;
+  cursor: default;
+  -moz-box-sizing: border-box;
+  -moz-appearance: menulist;
+  border-width: 3px;
+  border-style: inset;
+  text-indent: 0;
+  padding-right: 0px;
+  overflow: hidden;
+}
+
+html|div.-moz-xforms-select1-popup {
+  border-width: 1px;
+  top: 0px;
+  left: 0px;
+  border: 1px outset black !important;
+  background-color: -moz-Field;
+  font: -moz-list;
+  text-align: start;
+  visibility: hidden;
+  overflow-y: auto;
+  overflow-x: hidden;
+  position: absolute;
+  -moz-user-select: none;
+  z-index: 2147482647;
+  cursor: default;
+}
+
+item[_moz_active] {
+  color: HighlightText;
+  background: Highlight;
+}
+
+choices > label {
+  display: block;
+  font: -moz-list;
+  line-height: normal !important;
+  font-style: italic;
+  font-weight: bold;
+  font-size: inherit;
+  -moz-user-select: none;
+  text-indent: 0;
+}
+
+choices > item {
+  padding-left: 20px;
+  font-style: normal;
+  font-weight: normal;
+}
--- /dev/null	2005-07-11 20:47:26.569286200 +0300
+++ extensions/xforms/nsIXFormsItemElement.idl	2005-07-05 00:03:57.000000000 +0300
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla XForms support.
+ *
+ * The Initial Developer of the Original Code is
+ * Olli Pettay.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * Interface implemented by the item element.
+ */
+[scriptable, uuid(796a2e26-a40b-4ebf-be2c-42faf5fea6c4)]
+interface nsIXFormsItemElement : nsISupports
+{
+  readonly attribute AString labelText;
+  void setActive(in boolean aActive);
+  void labelRefreshed();
+};
--- /dev/null	2005-07-11 20:47:26.569286200 +0300
+++ extensions/xforms/nsIXFormsLabelElement.idl	2005-04-19 17:36:09.000000000 +0300
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla XForms support.
+ *
+ * The Initial Developer of the Original Code is
+ * Olli Pettay.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+
+/**
+ * Interface implemented by the label element.
+ */
+[uuid(f357747b-a1a2-4044-bd25-cb5d5b4fde3a)]
+interface nsIXFormsLabelElement : nsISupports
+{
+  readonly attribute AString textValue;
+};
--- /dev/null	2005-07-11 20:47:26.569286200 +0300
+++ extensions/xforms/nsXFormsSelect1Element.cpp	2005-07-05 21:53:28.000000000 +0300
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla XForms support.
+ *
+ * The Initial Developer of the Original Code is
+ * Olli Pettay.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Implementation of the XForms \<select1\> element.
+ */
+
+#include "nsXFormsUtils.h"
+#include "nsXFormsControlStub.h"
+#include "nsXFormsDelegateStub.h"
+#include "nsXFormsAtoms.h"
+#include "nsCOMPtr.h"
+#include "nsIDOMElement.h"
+#include "nsIDOMXPathResult.h"
+#include "nsIDOM3Node.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMText.h"
+#include "nsIXTFXMLVisualWrapper.h"
+#include "nsString.h"
+#include "nsIXFormsUIWidget.h"
+#include "nsIDocument.h"
+#include "nsNetUtil.h"
+
+class nsXFormsSelect1Element : public nsXFormsDelegateStub
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  NS_IMETHOD OnCreated(nsIXTFBindableElementWrapper *aWrapper);
+
+  // nsIXTFElement overrides
+  NS_IMETHOD ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex);
+  NS_IMETHOD ChildAppended(nsIDOMNode *aChild);
+  NS_IMETHOD ChildRemoved(PRUint32 aIndex);
+
+  // nsIXFormsDelegate
+  NS_IMETHOD SetValue(const nsAString& aValue);
+#ifdef DEBUG_smaug
+  virtual const char* Name() { return "select1"; }
+#endif
+};
+
+NS_IMPL_ISUPPORTS_INHERITED0(nsXFormsSelect1Element,
+                             nsXFormsDelegateStub)
+
+NS_IMETHODIMP
+nsXFormsSelect1Element::OnCreated(nsIXTFBindableElementWrapper *aWrapper)
+{
+  nsresult rv = nsXFormsDelegateStub::OnCreated(aWrapper);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  aWrapper->SetNotificationMask(kStandardNotificationMask |
+                                nsIXTFElement::NOTIFY_CHILD_INSERTED |
+                                nsIXTFElement::NOTIFY_CHILD_APPENDED |
+                                nsIXTFElement::NOTIFY_CHILD_REMOVED);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsSelect1Element::ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex)
+{
+  Refresh();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsSelect1Element::ChildAppended(nsIDOMNode *aChild)
+{
+  Refresh();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsSelect1Element::ChildRemoved(PRUint32 aIndex)
+{
+  Refresh();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXFormsSelect1Element::SetValue(const nsAString& aValue)
+{
+  if (!mBoundNode || !mModel)
+    return NS_OK;
+
+  PRBool changed;
+  nsresult rv = mModel->SetNodeValue(mBoundNode, aValue, &changed);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (changed) {
+    nsCOMPtr<nsIDOMNode> model = do_QueryInterface(mModel);
+ 
+    if (model) {
+      rv = nsXFormsUtils::DispatchEvent(model, eEvent_Recalculate);
+      NS_ENSURE_SUCCESS(rv, rv);
+      rv = nsXFormsUtils::DispatchEvent(model, eEvent_Revalidate);
+      NS_ENSURE_SUCCESS(rv, rv);
+      rv = nsXFormsUtils::DispatchEvent(model, eEvent_Refresh);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_HIDDEN_(nsresult)
+NS_NewXFormsSelect1Element(nsIXTFElement **aResult)
+{
+  *aResult = new nsXFormsSelect1Element();
+  if (!*aResult)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  NS_ADDREF(*aResult);
+  return NS_OK;
+}
--- /dev/null	2005-07-11 20:47:26.569286200 +0300
+++ extensions/xforms/resources/content/select1.xml	2005-07-11 19:44:02.000000000 +0300
@@ -0,0 +1,495 @@
+<?xml version="1.0"?>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+   -
+   - The contents of this file are subject to the Mozilla Public License Version
+   - 1.1 (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.mozilla.org/MPL/
+   -
+   - Software distributed under the License is distributed on an "AS IS" basis,
+   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+   - for the specific language governing rights and limitations under the
+   - License.
+   -
+   - The Original Code is Mozilla XForms support.
+   -
+   - The Initial Developer of the Original Code is
+   - Olli Pettay
+   - Portions created by the Initial Developer are Copyright (C) 2005
+   - the Initial Developer. All Rights Reserved.
+   -
+   - Contributor(s):
+   -  Olli Pettay <Olli.Pettay@helsinki.fi>
+   -
+   - Alternatively, the contents of this file may be used under the terms of
+   - either the GNU General Public License Version 2 or later (the "GPL"), or
+   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+   - in which case the provisions of the GPL or the LGPL are applicable instead
+   - of those above. If you wish to allow use of your version of this file only
+   - under the terms of either the GPL or the LGPL, and not to allow others to
+   - use your version of this file under the terms of the MPL, indicate your
+   - decision by deleting the provisions above and replace them with the notice
+   - and other provisions required by the GPL or the LGPL. If you do not delete
+   - the provisions above, a recipient may use your version of this file under
+   - the terms of any one of the MPL, the GPL or the LGPL.
+   -
+   - ***** END LICENSE BLOCK ***** -->
+
+<bindings id="select1Bindings"
+   xmlns="http://www.mozilla.org/xbl"
+   xmlns:html="http://www.w3.org/1999/xhtml"
+   xmlns:xbl="http://www.mozilla.org/xbl"
+   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+   xmlns:xforms="http://www.w3.org/2002/xforms">
+
+  <!-- select1 -->
+  <binding id="xformswidget-select1"
+           extends="chrome://xforms/content/xforms.xml#xformswidget-base">
+    <resources>
+      <stylesheet src="chrome://xforms/content/xforms.css"/>
+    </resources>
+    <content>
+      <children includes="label"/>
+      <html:div class="-moz-xforms-select1-popup" anonid="popup"
+                onmouseover="this.parentNode.mouseOver(event);"
+                onmouseup="this.parentNode.mouseUp(event);">
+        <children/>
+      </html:div>
+      <html:span class="-moz-select1-container"
+        anonid="container"><html:input class="-moz-xforms-select1-input"
+                    anonid="control"
+                    onblur="this.parentNode.parentNode.handleBlur();"
+                    onclick="this.parentNode.parentNode.handleControlClick();"
+                    onkeyup="this.parentNode.parentNode.handleKeyUp(event);"
+                    onfocus="this.parentNode.parentNode.handleFocus();"
+                    /><html:input class="-moz-xforms-select1-dropdown"
+                                  type="button"
+                                  anonid="dropmarker"
+                                  onclick="this.parentNode.parentNode.togglePopup();
+                                           if (this.parentNode.parentNode.popupOpen)
+                                             this.previousSibling.focus();"/></html:span></content>
+
+    <implementation implements="nsIXFormsUIWidget">
+      <field name="_inputField">null</field>
+      <field name="_dropMarker">null</field>
+      <field name="_popup">null</field>
+      <field name="_container">null</field>
+      <field name="_width">-1</field>
+      <field name="_selected">null</field>
+      <field name="popupOpen">false</field>
+
+      <property name="selectionOpen" readonly="true">
+        <getter>
+          return this.getAttribute("selection") == "open";
+        </getter>
+      </property>
+
+      <property name="inputField" readonly="true">
+        <getter>
+          if (!this._inputField) {
+            this._inputField =
+              document.getAnonymousElementByAttribute(this, "anonid", "control");
+          }
+          return this._inputField;
+        </getter>
+      </property>
+
+      <property name="dropMarker" readonly="true">
+        <getter>
+          if (!this._dropMarker) {
+            this._dropMarker =
+              document.getAnonymousElementByAttribute(this, "anonid", "dropmarker");
+          }
+          return this._dropMarker;
+        </getter>
+      </property>
+
+      <property name="popup" readonly="true">
+        <getter>
+          if (!this._popup) {
+            this._popup =
+              document.getAnonymousElementByAttribute(this, "anonid", "popup");
+          }
+          return this._popup;
+        </getter>
+      </property>
+
+      <property name="container" readonly="true">
+        <getter>
+          if (!this._container) {
+            this._container =
+              document.getAnonymousElementByAttribute(this, "anonid", "container");
+          }
+          return this._container;
+        </getter>
+      </property>
+
+      <method name="_change">
+        <body>
+          <![CDATA[
+          if (this.selectionOpen && this.getAttribute("incremental") != "false") {
+            this.delegate.value = this.inputField.value;
+          }
+          return true;
+          ]]>
+        </body>
+      </method>
+
+      <method name="handleControlClick">
+        <parameter name="aEvent"/>
+        <body>
+          <![CDATA[
+          if (this.selectionOpen) {
+            this._change();
+          } else {
+            this.togglePopup()
+          }
+          ]]>
+        </body>
+      </method>
+      <method name="handleKeyUp">
+        <parameter name="aEvent"/>
+        <body>
+          <![CDATA[
+            if (aEvent.keyCode == aEvent.DOM_VK_RETURN ||
+                aEvent.keyCode == aEvent.DOM_VK_ENTER) {
+              if (this.popupOpen) {
+                this.inputField.value = this._selected.labelText;
+                this.delegate.value =
+                  this._selected.QueryInterface(Components.interfaces.nsIXFormsSelectChild).value;
+              }
+              this.togglePopup();
+              return true;
+            } else if (aEvent.keyCode == aEvent.DOM_VK_UP ||
+                       aEvent.keyCode == aEvent.DOM_VK_DOWN) {
+              this.internalScroll(aEvent.keyCode == aEvent.DOM_VK_DOWN);
+              return true;
+            }
+
+            if (this.getAttribute("incremental") != "false") {
+              this.delegate.value = this.inputField.value;
+            }
+            return true;
+          ]]>
+        </body>
+      </method>
+
+      <method name="findNextSelectable">
+        <parameter name="aNode"/>
+        <parameter name="aDown"/>
+        <body>
+          <![CDATA[
+            if (!aNode) {
+              return null;
+            }
+
+            var node = aNode;
+            var next = null;
+            while (node) {
+              if (aDown) {
+                next = node.nextSibling;
+              } else {
+                next = node.previousSibling;
+              }
+
+              if (next && next.namespaceURI == "http://www.w3.org/2002/xforms") {
+                if (next.localName == "item") {
+                  return next;
+                } else if (next.localName == "choices") {
+                  var child = null;
+                  if (aDown) {
+                    child = next.firstChild;
+                  } else {
+                    child = next.lastChild;
+                  }
+                  if (child.namespaceURI == "http://www.w3.org/2002/xforms" &&
+                      child.localName == "item") {
+                    return child;
+                  }
+                  child = this.findNextSelectable(child, aDown);
+                  if (child) {
+                    return child;
+                  }
+                }
+              }
+              node = next;
+            }
+
+            // if we are in a choices element
+            var parent = aNode.parentNode;
+            if (parent.namespaceURI == "http://www.w3.org/2002/xforms" &&
+                parent.localName == "choices") {
+              var sibling = aDown ? parent.nextSibling : parent.previousSibling;
+
+              if (sibling.namespaceURI == "http://www.w3.org/2002/xforms" &&
+                  sibling.localName == "item") {
+                return sibling;
+              }
+              return this.findNextSelectable(sibling, aDown);
+            }
+            return null;
+          ]]>
+        </body>
+      </method>
+
+      <method name="internalScroll">
+        <parameter name="aDown"/>
+        <body>
+          <![CDATA[
+            var label = null;
+            var next = null;
+            var node = this.firstChild;
+            while (node) {
+              if (node.namespaceURI == "http://www.w3.org/2002/xforms" &&
+                  node.localName == "label") {
+                label = node;
+                break;
+              }       
+              node = node.nextSibling;
+            }
+
+            if (this._selected) {
+              node = this._selected.QueryInterface(Components.interfaces.nsIDOMNode);
+            } else if (label) {
+              node = label.nextSibling;
+            } else {
+              node = this.firstChild;
+            }
+
+            next = this.findNextSelectable(node, aDown);
+            if (next) {
+              if (this._selected) {
+                this._selected.setActive(false);
+              }
+
+              this._selected = next.QueryInterface(Components.interfaces.nsIXFormsItemElement);
+              if (this._selected) {
+                this._selected.setActive(true);
+                this.inputField.value = this._selected.labelText;
+              }
+              return true;
+            }
+
+            if (!aDown && this.selectionOpen) {
+              if (this._selected) {
+                this._selected.setActive(false);
+                this._selected = null;
+              }
+              this.inputField.value = "";
+            }
+          ]]>
+        </body>
+      </method>
+
+      <method name="mouseUp">
+        <parameter name="aEvent"/>
+        <body>
+          <![CDATA[
+            if (this._selected) {
+              this.inputField.value = this._selected.labelText;
+              this.delegate.value =
+                this._selected.QueryInterface(Components.interfaces.nsIXFormsSelectChild).value;
+            }
+          ]]>
+        </body>
+      </method>
+
+      <method name="mouseOver">
+        <parameter name="aEvent"/>
+        <body>
+          <![CDATA[
+          var target = aEvent.target;
+          while (target && target != this) {
+            if (target.namespaceURI == "http://www.w3.org/2002/xforms" &&
+                target.localName == "item") {
+              if (this._selected) {
+                this._selected.setActive(false);
+              }
+
+              var item =
+                target.QueryInterface(Components.interfaces.nsIXFormsItemElement);
+              if (item) {
+                item.setActive(true);
+                this._selected = item;
+              }
+              break;
+            }
+            target = target.parentNode;
+          }
+          ]]>
+        </body>
+      </method>
+
+      <method name="hidePopup">
+        <body>
+          this.popup.style.visibility = "hidden";
+          this.popupOpen = false;
+        </body>
+      </method>
+
+      <method name="refreshWidth">
+        <body>
+          <![CDATA[
+          if (!this.popupOpen) {
+            this.inputField.removeAttribute("style");
+            this.popup.style.width = "auto";
+            this._width = -1;
+            var popupBox = document.getBoxObjectFor(this.popup);
+            var w = popupBox.width;
+            if (w > 0) {
+              w = w + 5; // Adding some 'padding'.
+              this.inputField.setAttribute("style", "width:" + w + "px;");
+              this._width = w + document.getBoxObjectFor(this.dropMarker).width;
+            }
+            
+          }
+          ]]>
+        </body>
+      </method>
+
+      <method name="togglePopup">
+        <body>
+          <![CDATA[
+          if (!this.popupOpen && !this.delegate.isReadonly) {
+            var style = "";
+            var containerBox = document.getBoxObjectFor(this.container);
+            var x = containerBox.x;
+            var y = containerBox.y;
+            var h = containerBox.height;
+            var w = containerBox.width;
+            var targetY = y + h;
+            var popupBox = document.getBoxObjectFor(this.popup);
+            var popupHeight = popupBox.height;
+            var pY = window.pageYOffset;
+            var iH = window.innerHeight;
+            var belowSelect = iH - (y + h - pY) - h;
+            if (belowSelect < popupHeight) {
+              if ((y - pY) > popupHeight) {
+                targetY = y - popupHeight;
+              } else if (belowSelect < (y - pY)) {
+                style = style + "max-height:" + (y - pY) + "px;";
+                targetY = pY;
+              } else {
+                style = style + "max-height:" + belowSelect + "px;";
+              }
+            }
+            style = style + "left:" + x + "px;";
+            style = style + "top:" + targetY + "px;";
+
+            style = style + "width:";
+            /*if (false) { // selectionOpen
+              ;
+            } else*/ if (this._width < 0) {
+              style = style + "auto;"
+            } else {
+              style = style + this._width + "px;";
+            }
+
+            style = style + "visibility:visible;";
+            this.popup.setAttribute("style", style);
+            this.popupOpen = true;
+          } else {
+            this.hidePopup();
+            return;
+          }
+          ]]>
+        </body>
+      </method>
+
+      <method name="refresh">
+        <body>
+          <![CDATA[
+          try {
+            this.refreshWidth();
+            var newValue = this.stringValue;
+            if (!this.selectionOpen || this.delegate.isReadonly) {
+              this.inputField.setAttribute("readonly", "readonly");
+            } else {
+              this.inputField.removeAttribute("readonly");
+            }
+            
+            if (this._selected) {
+              this._selected.setActive(false);
+              this._selected = null;
+            }
+
+            this.selectItemByValue(newValue);
+            
+            if (this._selected) {
+              this.inputField.value = this._selected.labelText
+            } else if (this.selectionOpen) {
+              this.inputField.value = newValue;
+            } else {
+              // @todo out-of-range
+              this.inputField.value = "";
+            }
+          } catch (ex) {}
+
+          return true;
+          ]]>
+        </body>
+      </method>
+
+      <method name="focus">
+        <body>
+          this.inputField.focus();
+          return true;
+        </body>
+      </method>
+
+      <method name="selectItemByValue">
+        <parameter name="aValue"/>
+        <body>
+          <![CDATA[
+          var node = this.firstChild;
+          var item;
+          while (node) {
+            item = null;
+            try {
+              if (node.nodeType == document.ELEMENT_NODE &&
+                  node.namespaceURI == "http://www.w3.org/2002/xforms" &&
+                  node.localName != "label") {
+
+                item = node.QueryInterface(Components.interfaces.nsIXFormsSelectChild);
+                if (item) {
+                  item = item.selectItemByValue(aValue);
+                  if (item) {
+                    this._selected = item.QueryInterface(Components.interfaces.nsIXFormsItemElement);
+                  }
+                }
+              }
+            } catch (ex) {}
+            node = node.nextSibling;
+          }
+          ]]>
+        </body>
+      </method>
+
+      <method name="handleBlur">
+        <body>
+          <![CDATA[
+          this.hidePopup();
+          if (this.selectionOpen && !this._selected) {
+            this.delegate.value = this.inputField.value;
+          } else if (this._selected) {
+            this.inputField.value = this._selected.labelText;
+            this.delegate.value =
+              this._selected.QueryInterface(Components.interfaces.nsIXFormsSelectChild).value;
+          }
+          ]]>
+        </body>
+      </method>
+      <method name="handleFocus">
+        <body>
+          <![CDATA[
+          if (this.selectionOpen) {
+            this._selected = null;
+          }
+          ]]>
+        </body>
+      </method>
+    </implementation>
+  </binding>
+</bindings>
