Implementation of select, select1, item, choices, and itemset elements (bug 270572). r=beaufour.

This commit is contained in:
bryner%brianryner.com 2005-01-15 01:04:02 +00:00
Родитель d6eec31d99
Коммит c42324ab83
17 изменённых файлов: 2035 добавлений и 50 удалений

Просмотреть файл

@ -77,6 +77,8 @@ XPIDLSRCS = \
nsIXFormsActionModuleElement.idl \
nsIXFormsSwitchElement.idl \
nsIXFormsCaseElement.idl \
nsIXFormsSelectChild.idl \
nsIXFormsValueElement.idl \
$(NULL)
CPPSRCS = \
@ -87,7 +89,7 @@ CPPSRCS = \
nsXFormsGroupElement.cpp \
nsXFormsOutputElement.cpp \
nsXFormsRepeatElement.cpp \
nsXFormsRepeatItemElement.cpp \
nsXFormsContextContainer.cpp \
nsXFormsTriggerElement.cpp \
nsXFormsSubmissionElement.cpp \
nsXFormsStubElement.cpp \
@ -118,6 +120,11 @@ CPPSRCS = \
nsXFormsCaseElement.cpp \
nsXFormsSwitchElement.cpp \
nsXFormsUploadElement.cpp \
nsXFormsSelectElement.cpp \
nsXFormsItemElement.cpp \
nsXFormsValueElement.cpp \
nsXFormsChoicesElement.cpp \
nsXFormsItemSetElement.cpp \
$(NULL)
EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS)

Просмотреть файл

@ -0,0 +1,94 @@
/* -*- Mode: IDL; 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
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com>
*
* 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 nsIDOMNode;
interface nsIDOMElement;
interface nsIArray;
%{C++
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)]
interface nsIXFormsSelectChild : nsISupports
{
/**
* The DOM elements returned by this attribute are inserted into the select
* element's anonymous content tree.
*/
readonly attribute nsIArray anonymousNodes;
/**
* 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);
void selectItemsByContent(in nsIDOMNode node);
/**
* Instructs the item to serialize its selected elements into |container|.
* For children that have a value child, they should append the value of
* any selected items to the text node child of |container|. For children
* that have a copy child, they should copy the instance data element into
* |container|.
*/
void writeSelectedItems(in nsIDOMNode container);
/**
* Set the context node, position, and size to be used for XPath evaluation.
* This is used by itemset to create a context for its anonymous item
* elements.
*/
void setContext(in nsIDOMElement node, in long position, in long size);
};

Просмотреть файл

@ -0,0 +1,53 @@
/* -*- Mode: IDL; 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
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com>
*
* 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 ***** */
/**
* This interface is implemented by XForms value elements.
*/
#include "nsISupports.idl"
[uuid(bf2611d6-890b-4a64-95bd-db6aced79136)]
interface nsIXFormsValueElement : nsISupports
{
/**
* Returns the value for this element, which can come from inline text
* or from instance data.
*/
readonly attribute AString value;
};

Просмотреть файл

@ -54,6 +54,7 @@ nsIAtom *nsXFormsAtoms::ref;
nsIAtom *nsXFormsAtoms::nodeset;
nsIAtom *nsXFormsAtoms::model;
nsIAtom *nsXFormsAtoms::selected;
nsIAtom *nsXFormsAtoms::appearance;
const nsStaticAtom nsXFormsAtoms::Atoms_info[] = {
{ "src", &nsXFormsAtoms::src },
@ -70,7 +71,8 @@ const nsStaticAtom nsXFormsAtoms::Atoms_info[] = {
{ "ref", &nsXFormsAtoms::ref },
{ "nodeset", &nsXFormsAtoms::nodeset },
{ "model", &nsXFormsAtoms::model },
{ "selected", &nsXFormsAtoms::selected }
{ "selected", &nsXFormsAtoms::selected },
{ "appearance", &nsXFormsAtoms::appearance }
};
void

Просмотреть файл

@ -59,6 +59,7 @@ class nsXFormsAtoms
static NS_HIDDEN_(nsIAtom *) nodeset;
static NS_HIDDEN_(nsIAtom *) model;
static NS_HIDDEN_(nsIAtom *) selected;
static NS_HIDDEN_(nsIAtom *) appearance;
static NS_HIDDEN_(void) InitAtoms();

Просмотреть файл

@ -0,0 +1,374 @@
/* -*- 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
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com>
*
* 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 ***** */
#include "nsIXFormsSelectChild.h"
#include "nsXFormsStubElement.h"
#include "nsIDOMHTMLOptGroupElement.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIXTFGenericElementWrapper.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNodeList.h"
#include "nsXFormsUtils.h"
#include "nsArray.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,
public nsIXFormsSelectChild
{
public:
nsXFormsChoicesElement() : mElement(nsnull) {}
NS_DECL_ISUPPORTS_INHERITED
// nsIXTFGenericElement overrides
NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *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 BeginAddingChildren();
NS_IMETHOD DoneAddingChildren();
// nsIXFormsSelectChild
NS_DECL_NSIXFORMSSELECTCHILD
private:
NS_HIDDEN_(void) Refresh();
nsIDOMElement *mElement;
nsCOMPtr<nsIDOMHTMLOptGroupElement> mOptGroup;
};
NS_IMPL_ISUPPORTS_INHERITED1(nsXFormsChoicesElement,
nsXFormsStubElement,
nsIXFormsSelectChild)
NS_IMETHODIMP
nsXFormsChoicesElement::OnCreated(nsIXTFGenericElementWrapper *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;
aWrapper->GetElementNode(getter_AddRefs(node));
// It's ok to keep a pointer to mElement. mElement will have an
// owning reference to this object, so as long as we null out mElement in
// OnDestroyed, it will always be valid.
mElement = node;
NS_ASSERTION(mElement, "Wrapper is not an nsIDOMElement, we'll crash soon");
// Our anonymous content structure will look like this:
//
// <optgroup label="myLabel"/> (mOptGroup)
//
nsCOMPtr<nsIDOMDocument> domDoc;
node->GetOwnerDocument(getter_AddRefs(domDoc));
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);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsChoicesElement::ParentChanged(nsIDOMElement *aNewParent)
{
if (aNewParent)
Refresh();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsChoicesElement::ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex)
{
nsCOMPtr<nsIXFormsSelectChild> item = do_QueryInterface(aChild);
if (item) {
// XXX get anonymous nodes and insert them at the correct place
} else if (nsXFormsUtils::IsLabelElement(aChild)) {
// If a label child was inserted, we need to clone it into our
// anonymous content.
Refresh();
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsChoicesElement::ChildAppended(nsIDOMNode *aChild)
{
nsCOMPtr<nsIXFormsSelectChild> item = do_QueryInterface(aChild);
if (item) {
// XXX get anonymous nodes and insert them at the correct place
} else if (nsXFormsUtils::IsLabelElement(aChild)) {
// If a label child was inserted, we need to clone it into our
// anonymous content.
Refresh();
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsChoicesElement::ChildRemoved(PRUint32 aIndex)
{
// TODO: should remove the anonymous content owned by the removed item.
// TOOD: only need to Refresh() when a label child is removed, but it's
// not possible to get ahold of the actual removed child at this point.
Refresh();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsChoicesElement::BeginAddingChildren()
{
// Suppress child notifications until we're done getting children.
nsCOMPtr<nsIXTFElementWrapper> wrapper = do_QueryInterface(mElement);
NS_ASSERTION(wrapper, "huh? our element must be an xtf wrapper");
wrapper->SetNotificationMask(nsIXTFElement::NOTIFY_PARENT_CHANGED |
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsChoicesElement::DoneAddingChildren()
{
// Unsuppress notifications
nsCOMPtr<nsIXTFElementWrapper> wrapper = do_QueryInterface(mElement);
NS_ASSERTION(wrapper, "huh? our element must be an xtf wrapper");
wrapper->SetNotificationMask(nsIXTFElement::NOTIFY_PARENT_CHANGED |
nsIXTFElement::NOTIFY_CHILD_INSERTED |
nsIXTFElement::NOTIFY_CHILD_APPENDED |
nsIXTFElement::NOTIFY_CHILD_REMOVED);
// Walk our children and get their anonymous content.
nsCOMPtr<nsIDOMNodeList> children;
nsresult rv = mElement->GetChildNodes(getter_AddRefs(children));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> childNode, childAnonymousNode, nodeReturn;
nsCOMPtr<nsIXFormsSelectChild> childItem;
PRUint32 childCount = 0;
children->GetLength(&childCount);
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(childNode));
childItem = do_QueryInterface(childNode);
if (childItem) {
nsCOMPtr<nsIArray> childItems;
childItem->GetAnonymousNodes(getter_AddRefs(childItems));
if (childItems) {
PRUint32 childNodesLength = 0;
childItems->GetLength(&childNodesLength);
for (PRUint32 j = 0; j < childNodesLength; ++j) {
childAnonymousNode = do_QueryElementAt(childItems, j);
mOptGroup->AppendChild(childAnonymousNode,
getter_AddRefs(nodeReturn));
}
}
}
}
// Assume that we've got something worth refreshing now.
Refresh();
return NS_OK;
}
// nsIXFormsSelectChild
NS_IMETHODIMP
nsXFormsChoicesElement::GetAnonymousNodes(nsIArray **aNodes)
{
nsCOMPtr<nsIMutableArray> array;
nsresult rv = NS_NewArray(getter_AddRefs(array));
NS_ENSURE_SUCCESS(rv, rv);
array->AppendElement(mOptGroup, PR_FALSE);
NS_ADDREF(*aNodes = array);
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);
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->SelectItemsByValue(aValueList);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsChoicesElement::SelectItemsByContent(nsIDOMNode *aNode)
{
// Not applicable for choices element.
return NS_OK;
}
NS_IMETHODIMP
nsXFormsChoicesElement::WriteSelectedItems(nsIDOMNode *aContainer)
{
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->WriteSelectedItems(aContainer);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsChoicesElement::SetContext(nsIDOMElement *aContextNode,
PRInt32 aContextPosition,
PRInt32 aContextSize)
{
// choices cannot be created by an itemset, so we don't need to worry
// about this case.
return NS_OK;
}
// internal methods
void
nsXFormsChoicesElement::Refresh()
{
// Remove any existing first child that is not an option, to clear out
// any existing label.
nsCOMPtr<nsIDOMNode> firstChild, child2;
nsresult rv = mOptGroup->GetFirstChild(getter_AddRefs(firstChild));
if (NS_FAILED(rv))
return;
nsAutoString value;
if (firstChild) {
firstChild->GetLocalName(value);
if (!value.EqualsLiteral("option")) {
mOptGroup->RemoveChild(firstChild, getter_AddRefs(child2));
mOptGroup->GetFirstChild(getter_AddRefs(firstChild));
}
}
// We need to find our label element and clone it into the optgroup.
// This content will appear before any of the optgroup's options.
nsCOMPtr<nsIDOMNodeList> children;
rv = mElement->GetChildNodes(getter_AddRefs(children));
if (NS_FAILED(rv))
return;
PRUint32 childCount;
children->GetLength(&childCount);
nsCOMPtr<nsIDOMNode> child;
nsAutoString labelValue;
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(child));
if (nsXFormsUtils::IsLabelElement(child)) {
// Clone our label into the optgroup
child->CloneNode(PR_TRUE, getter_AddRefs(child2));
mOptGroup->InsertBefore(child2, firstChild, getter_AddRefs(child));
}
}
}
NS_HIDDEN_(nsresult)
NS_NewXFormsChoicesElement(nsIXTFElement **aResult)
{
*aResult = new nsXFormsChoicesElement();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -54,14 +54,15 @@
#include "nsXFormsUtils.h"
#ifdef DEBUG
//#define DEBUG_XF_REPEATITEM
//#define DEBUG_XF_CONTEXTCONTAINER
#endif
/**
* Implementation of \<repeatitem\>.
* Implementation of \<contextcontainer\>.
*
* \<repeatitem\> is a pseudo-element that is wrapped around each row in the
* "unrolled" \<repeat\>. @see nsXFormsRepeatElement.
* \<contextcontainer\> is a pseudo-element that is wrapped around each row in
* an "unrolled" \<repeat\> or \<itemset\>. @see nsXFormsRepeatElement and
* nsXFormsItemSetElement.
*
* @todo Should this class inherit from nsIXFormsControl? (XXX)
*
@ -69,7 +70,7 @@
* @see http://www.w3.org/TR/xforms/sliceF.html#id2645142
* @see http://bugzilla.mozilla.org/show_bug.cgi?id=271724
*/
class nsXFormsRepeatItemElement : public nsIXFormsControl,
class nsXFormsContextContainer : public nsIXFormsControl,
public nsXFormsXMLVisualStub,
public nsIXFormsContextControl
{
@ -104,7 +105,7 @@ public:
};
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsRepeatItemElement,
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsContextContainer,
nsXFormsXMLVisualStub,
nsIXFormsControl,
nsIXFormsContextControl)
@ -112,10 +113,10 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsRepeatItemElement,
// nsIXTFXMLVisual
NS_IMETHODIMP
nsXFormsRepeatItemElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper)
nsXFormsContextContainer::OnCreated(nsIXTFXMLVisualWrapper *aWrapper)
{
#ifdef DEBUG_XF_REPEATITEM
printf("nsXFormsRepeatItemElement::OnCreated(aWrapper=%p)\n", (void*) aWrapper);
#ifdef DEBUG_XF_CONTEXTCONTAINER
printf("nsXFormsContextContainer::OnCreated(aWrapper=%p)\n", (void*) aWrapper);
#endif
nsresult rv;
@ -131,19 +132,28 @@ nsXFormsRepeatItemElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper)
rv = node->GetOwnerDocument(getter_AddRefs(domDoc));
NS_ENSURE_SUCCESS(rv, rv);
PRBool isBlock;
// If we're a "contextcontainer" element, then we create a div child.
// If not, we're a "contextcontainer-inline" element and create a span child.
nsAutoString localName;
mElement->GetLocalName(localName);
isBlock = localName.EqualsLiteral("contextcontainer");
// Create UI element
rv = domDoc->CreateElementNS(NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"),
NS_LITERAL_STRING("div"),
isBlock ? NS_LITERAL_STRING("div") :
NS_LITERAL_STRING("span"),
getter_AddRefs(mHTMLElement));
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsRepeatItemElement::GetVisualContent(nsIDOMElement **aElement)
nsXFormsContextContainer::GetVisualContent(nsIDOMElement **aElement)
{
#ifdef DEBUG_XF_REPEATITEM
printf("nsXFormsRepeatItemElement::GetVisualContent()\n");
#ifdef DEBUG_XF_CONTEXTCONTAINER
printf("nsXFormsContextContainer::GetVisualContent()\n");
#endif
NS_IF_ADDREF(*aElement = mHTMLElement);
@ -151,10 +161,10 @@ nsXFormsRepeatItemElement::GetVisualContent(nsIDOMElement **aElement)
}
NS_IMETHODIMP
nsXFormsRepeatItemElement::GetInsertionPoint(nsIDOMElement **aElement)
nsXFormsContextContainer::GetInsertionPoint(nsIDOMElement **aElement)
{
#ifdef DEBUG_XF_REPEATITEM
printf("nsXFormsRepeatItemElement::GetInsertionPoint()\n");
#ifdef DEBUG_XF_CONTEXTCONTAINER
printf("nsXFormsContextContainer::GetInsertionPoint()\n");
#endif
NS_IF_ADDREF(*aElement = mHTMLElement);
@ -164,7 +174,7 @@ nsXFormsRepeatItemElement::GetInsertionPoint(nsIDOMElement **aElement)
// nsIXTFElement
NS_IMETHODIMP
nsXFormsRepeatItemElement::OnDestroyed()
nsXFormsContextContainer::OnDestroyed()
{
mHTMLElement = nsnull;
mElement = nsnull;
@ -175,14 +185,14 @@ nsXFormsRepeatItemElement::OnDestroyed()
// nsIXFormsContextControl
NS_IMETHODIMP
nsXFormsRepeatItemElement::SetContextNode(nsIDOMElement *aContextNode)
nsXFormsContextContainer::SetContextNode(nsIDOMElement *aContextNode)
{
mContextNode = aContextNode;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsRepeatItemElement::GetContext(nsAString& aModelID,
nsXFormsContextContainer::GetContext(nsAString& aModelID,
nsIDOMElement **aContextNode,
PRInt32 *aContextPosition,
PRInt32 *aContextSize)
@ -206,16 +216,16 @@ nsXFormsRepeatItemElement::GetContext(nsAString& aModelID,
// nsXFormsControl
nsresult
nsXFormsRepeatItemElement::Refresh()
nsXFormsContextContainer::Refresh()
{
return NS_OK;
}
// Factory
NS_HIDDEN_(nsresult)
NS_NewXFormsRepeatItemElement(nsIXTFElement **aResult)
NS_NewXFormsContextContainer(nsIXTFElement **aResult)
{
*aResult = new nsXFormsRepeatItemElement();
*aResult = new nsXFormsContextContainer();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;

Просмотреть файл

@ -52,14 +52,19 @@ NS_HIDDEN_(nsresult) NS_NewXFormsOutputElement(nsIXTFElement **aElement);
NS_HIDDEN_(nsresult) NS_NewXFormsRepeatElement(nsIXTFElement **aElement);
NS_HIDDEN_(nsresult) NS_NewXFormsUploadElement(nsIXTFElement **aElement);
/// @todo Having \<repeatitem\> in the factory means that the item can be used
/// by a user in a document. Not optimal, as it is not a legal XForms tag, but
/// only a pseudo-element. But nsXFormsRepeatElement needs to be able to
/// create the tag, so is there a "backdoor way" to do that? (XXX)
NS_HIDDEN_(nsresult) NS_NewXFormsRepeatItemElement(nsIXTFElement **aElement);
/// @todo Having \<contextcontainer\> in the factory means that the item can be
/// 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_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);
@ -102,10 +107,21 @@ nsXFormsElementFactory::CreateElement(const nsAString& aTagName,
return NS_NewXFormsOutputElement(aElement);
if (aTagName.EqualsLiteral("repeat"))
return NS_NewXFormsRepeatElement(aElement);
if (aTagName.EqualsLiteral("repeatitem"))
return NS_NewXFormsRepeatItemElement(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"))
return NS_NewXFormsSelectElement(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);
if (aTagName.EqualsLiteral("dispatch"))
return NS_NewXFormsDispatchElement(aElement);
if (aTagName.EqualsLiteral("send"))

Просмотреть файл

@ -284,7 +284,8 @@ nsXFormsGroupElement::Process()
model->AddFormControl(this);
}
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
if (!result)
return NS_ERROR_FAILURE;
// Get model ID
nsCOMPtr<nsIDOMElement> modelElement = do_QueryInterface(modelNode);

Просмотреть файл

@ -0,0 +1,419 @@
/* -*- 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
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com>
*
* 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 ***** */
#include "nsIXFormsSelectChild.h"
#include "nsXFormsStubElement.h"
#include "nsIDOMHTMLOptionElement.h"
#include "nsXFormsAtoms.h"
#include "nsIDOMNodeList.h"
#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 "nsIXFormsContextControl.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
{
public:
nsXFormsItemElement() : mElement(nsnull),
mContextPosition(0),
mContextSize(0)
{
}
NS_DECL_ISUPPORTS_INHERITED
// nsIXTFGenericElement overrides
NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *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();
// nsIXFormsSelectChild
NS_DECL_NSIXFORMSSELECTCHILD
private:
NS_HIDDEN_(void) Refresh();
NS_HIDDEN_(nsresult) GetValue(nsString &aValue);
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_IMETHODIMP
nsXFormsItemElement::OnCreated(nsIXTFGenericElementWrapper *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;
aWrapper->GetElementNode(getter_AddRefs(node));
// It's ok to keep a pointer to mElement. mElement will have an
// owning reference to this object, so as long as we null out mElement in
// OnDestroyed, it will always be valid.
mElement = node;
NS_ASSERTION(mElement, "Wrapper is not an nsIDOMElement, we'll crash soon");
// Our anonymous content structure will look like this:
//
// <option/> (mOption, also insertion point)
//
nsCOMPtr<nsIDOMDocument> domDoc;
node->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDOMElement> element;
domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
NS_LITERAL_STRING("option"),
getter_AddRefs(element));
mOption = do_QueryInterface(element);
NS_ENSURE_TRUE(mOption, NS_ERROR_FAILURE);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemElement::ParentChanged(nsIDOMElement *aNewParent)
{
if (aNewParent)
Refresh();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemElement::ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex)
{
// If a label child was inserted, we need to clone it into our
// anonymous content.
if (nsXFormsUtils::IsLabelElement(aChild))
Refresh();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemElement::ChildAppended(nsIDOMNode *aChild)
{
// If a label child was inserted, we need to clone it into our
// anonymous content.
if (nsXFormsUtils::IsLabelElement(aChild))
Refresh();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemElement::WillRemoveChild(PRUint32 aIndex)
{
nsCOMPtr<nsIDOMNodeList> children;
nsresult rv = mElement->GetChildNodes(getter_AddRefs(children));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> child;
children->Item(aIndex, getter_AddRefs(child));
if (child && nsXFormsUtils::IsLabelElement(child)) {
// If a label child was removed, we need to remove the label from our
// anonymous content.
Refresh();
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemElement::BeginAddingChildren()
{
// Suppress child notifications until we're done getting children.
nsCOMPtr<nsIXTFElementWrapper> wrapper = do_QueryInterface(mElement);
NS_ASSERTION(wrapper, "huh? our element must be an xtf wrapper");
wrapper->SetNotificationMask(nsIXTFElement::NOTIFY_PARENT_CHANGED |
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemElement::DoneAddingChildren()
{
// Unsuppress notifications
nsCOMPtr<nsIXTFElementWrapper> wrapper = do_QueryInterface(mElement);
NS_ASSERTION(wrapper, "huh? our element must be an xtf wrapper");
wrapper->SetNotificationMask(nsIXTFElement::NOTIFY_PARENT_CHANGED |
nsIXTFElement::NOTIFY_CHILD_INSERTED |
nsIXTFElement::NOTIFY_CHILD_APPENDED |
nsIXTFElement::NOTIFY_WILL_REMOVE_CHILD);
// Assume that we've got something worth refreshing now.
Refresh();
return NS_OK;
}
// nsIXFormsSelectChild
NS_IMETHODIMP
nsXFormsItemElement::GetAnonymousNodes(nsIArray **aNodes)
{
nsCOMPtr<nsIMutableArray> array;
nsresult rv = NS_NewArray(getter_AddRefs(array));
NS_ENSURE_SUCCESS(rv, rv);
array->AppendElement(mOption, PR_FALSE);
NS_ADDREF(*aNodes = array);
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) {
if (aValueList[i]->Equals(value)) {
mOption->SetSelected(PR_TRUE);
break;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemElement::SelectItemsByContent(nsIDOMNode *aNode)
{
// TODO: implement support for \<copy\> element.
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemElement::WriteSelectedItems(nsIDOMNode *aContainer)
{
PRBool selected;
mOption->GetSelected(&selected);
if (!selected)
return NS_OK;
nsCOMPtr<nsIDOMNodeList> children;
nsresult rv = aContainer->GetChildNodes(getter_AddRefs(children));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 childCount;
children->GetLength(&childCount);
nsCOMPtr<nsIDOMNode> child, textNode;
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(child));
PRUint16 nodeType;
child->GetNodeType(&nodeType);
if (nodeType == nsIDOMNode::TEXT_NODE) {
textNode = child;
break;
}
}
if (!textNode) {
// No text node, so make one.
nsCOMPtr<nsIDOMDocument> doc;
aContainer->GetOwnerDocument(getter_AddRefs(doc));
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMText> text;
rv = doc->CreateTextNode(EmptyString(), getter_AddRefs(text));
NS_ENSURE_SUCCESS(rv, rv);
rv = aContainer->AppendChild(text, getter_AddRefs(child));
NS_ENSURE_SUCCESS(rv, rv);
textNode = text;
}
NS_ASSERTION(textNode, "We should have a text node by now");
nsAutoString value;
rv = GetValue(value);
NS_ENSURE_SUCCESS(rv, rv);
return textNode->SetNodeValue(value);
}
NS_IMETHODIMP
nsXFormsItemElement::SetContext(nsIDOMElement *aContextNode,
PRInt32 aContextPosition, PRInt32 aContextSize)
{
mContextNode = aContextNode;
mContextPosition = aContextPosition;
mContextSize = aContextSize;
return NS_OK;
}
// internal methods
nsresult
nsXFormsItemElement::GetValue(nsString &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);
nsCOMPtr<nsIDOMNode> child;
nsAutoString value;
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(child));
nsCOMPtr<nsIXFormsValueElement> valueElement = do_QueryInterface(child);
if (valueElement) {
return valueElement->GetValue(aValue);
}
}
// No value children, so our value is empty
aValue.Truncate(0);
return NS_OK;
}
void
nsXFormsItemElement::Refresh()
{
// Clear out all of the existing option text
nsCOMPtr<nsIDOMNode> child, child2;
while (NS_SUCCEEDED(mOption->GetFirstChild(getter_AddRefs(child))) && child)
mOption->RemoveChild(child, getter_AddRefs(child2));
// We need to find our label child, serialize its contents
// (which can be xtf-generated), and set that as our label attribute.
nsCOMPtr<nsIDOMNodeList> children;
nsresult rv = mElement->GetChildNodes(getter_AddRefs(children));
if (NS_FAILED(rv))
return;
PRUint32 childCount;
children->GetLength(&childCount);
nsAutoString value;
nsCOMPtr<nsIDOMDocument> doc;
mElement->GetOwnerDocument(getter_AddRefs(doc));
nsCOMPtr<nsIDOMElement> container;
doc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS),
NS_LITERAL_STRING("contextcontainer-inline"),
getter_AddRefs(container));
NS_NAMED_LITERAL_STRING(modelStr, "model");
nsAutoString modelID;
mElement->GetAttribute(modelStr, modelID);
container->SetAttribute(modelStr, modelID);
nsCOMPtr<nsIXFormsContextControl> context = do_QueryInterface(container);
context->SetContextNode(mContextNode);
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(child));
child->GetLocalName(value);
if (value.EqualsLiteral("label")) {
child->GetNamespaceURI(value);
if (value.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
child->CloneNode(PR_TRUE, getter_AddRefs(child2));
container->AppendChild(child2, getter_AddRefs(child));
}
}
}
nsCOMPtr<nsIDOMNode> childReturn;
mOption->AppendChild(container, getter_AddRefs(childReturn));
}
NS_HIDDEN_(nsresult)
NS_NewXFormsItemElement(nsIXTFElement **aResult)
{
*aResult = new nsXFormsItemElement();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,311 @@
/* -*- 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
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com>
*
* 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 ***** */
#include "nsIXFormsSelectChild.h"
#include "nsXFormsStubElement.h"
#include "nsIDOMHTMLOptGroupElement.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIXTFGenericElementWrapper.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNodeList.h"
#include "nsXFormsUtils.h"
#include "nsArray.h"
class nsXFormsItemSetElement : public nsXFormsStubElement,
public nsIXFormsSelectChild
{
public:
nsXFormsItemSetElement() : mElement(nsnull) {}
NS_DECL_ISUPPORTS_INHERITED
// nsIXTFGenericElement overrides
NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *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();
// nsIXFormsSelectChild
NS_DECL_NSIXFORMSSELECTCHILD
private:
NS_HIDDEN_(void) Refresh();
nsIDOMElement *mElement;
nsCOMArray<nsIXFormsSelectChild> mItems;
};
NS_IMPL_ISUPPORTS_INHERITED1(nsXFormsItemSetElement,
nsXFormsStubElement,
nsIXFormsSelectChild)
NS_IMETHODIMP
nsXFormsItemSetElement::OnCreated(nsIXTFGenericElementWrapper *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;
aWrapper->GetElementNode(getter_AddRefs(node));
// It's ok to keep a pointer to mElement. mElement will have an
// owning reference to this object, so as long as we null out mElement in
// OnDestroyed, it will always be valid.
mElement = node;
NS_ASSERTION(mElement, "Wrapper is not an nsIDOMElement, we'll crash soon");
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemSetElement::ParentChanged(nsIDOMElement *aNewParent)
{
if (aNewParent)
Refresh();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemSetElement::ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex)
{
Refresh();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemSetElement::ChildAppended(nsIDOMNode *aChild)
{
Refresh();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemSetElement::WillRemoveChild(PRUint32 aIndex)
{
Refresh();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemSetElement::BeginAddingChildren()
{
// Suppress child notifications until we're done getting children.
nsCOMPtr<nsIXTFElementWrapper> wrapper = do_QueryInterface(mElement);
NS_ASSERTION(wrapper, "huh? our element must be an xtf wrapper");
wrapper->SetNotificationMask(nsIXTFElement::NOTIFY_PARENT_CHANGED |
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemSetElement::DoneAddingChildren()
{
// Unsuppress child notifications until we're done getting children.
nsCOMPtr<nsIXTFElementWrapper> wrapper = do_QueryInterface(mElement);
NS_ASSERTION(wrapper, "huh? our element must be an xtf wrapper");
wrapper->SetNotificationMask(nsIXTFElement::NOTIFY_PARENT_CHANGED |
nsIXTFElement::NOTIFY_CHILD_INSERTED |
nsIXTFElement::NOTIFY_CHILD_APPENDED |
nsIXTFElement::NOTIFY_WILL_REMOVE_CHILD);
// Walk our children and get their anonymous content.
Refresh();
return NS_OK;
}
// nsIXFormsSelectChild
NS_IMETHODIMP
nsXFormsItemSetElement::GetAnonymousNodes(nsIArray **aNodes)
{
nsCOMPtr<nsIMutableArray> array;
nsresult rv = NS_NewArray(getter_AddRefs(array));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 itemCount = mItems.Count();
nsCOMPtr<nsIArray> childNodes;
nsCOMPtr<nsIDOMNode> childOption;
for (PRInt32 i = 0; i < itemCount; ++i) {
mItems[i]->GetAnonymousNodes(getter_AddRefs(childNodes));
if (!childNodes)
continue;
PRUint32 anonLength = 0;
childNodes->GetLength(&anonLength);
for (PRUint32 j = 0; j < anonLength; ++j) {
childOption = do_QueryElementAt(childNodes, j);
NS_ASSERTION(childOption, "invalid nodelist");
array->AppendElement(childOption, PR_FALSE);
}
}
NS_ADDREF(*aNodes = array);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemSetElement::SelectItemsByValue(const nsStringArray &aValueList)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemSetElement::SelectItemsByContent(nsIDOMNode *aNode)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemSetElement::WriteSelectedItems(nsIDOMNode *aContainer)
{
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;
}
// internal methods
void
nsXFormsItemSetElement::Refresh()
{
mItems.Clear();
// We need to create item elements for each element referenced by the
// nodeset. Each of these items will create an anonymous HTML option element
// which will return from GetAnonymousNodes. We then clone our template
// content and insert the cloned content as children of the HTML option.
nsCOMPtr<nsIDOMNode> modelNode;
nsCOMPtr<nsIDOMElement> bindElement;
nsCOMPtr<nsIDOMXPathResult> result =
nsXFormsUtils::EvaluateNodeBinding(mElement,
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
NS_LITERAL_STRING("nodeset"),
EmptyString(),
nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
getter_AddRefs(modelNode),
getter_AddRefs(bindElement));
if (!result)
return;
nsCOMPtr<nsIDOMNode> node, templateNode, cloneNode;
nsCOMPtr<nsIDOMElement> itemNode, itemWrapperNode;
nsCOMPtr<nsIDOMNodeList> templateNodes;
mElement->GetChildNodes(getter_AddRefs(templateNodes));
PRUint32 templateNodeCount = 0;
if (templateNodes)
templateNodes->GetLength(&templateNodeCount);
nsCOMPtr<nsIDOMDocument> document;
mElement->GetOwnerDocument(getter_AddRefs(document));
if (!document)
return;
PRUint32 nodeCount;
result->GetSnapshotLength(&nodeCount);
for (PRUint32 i = 0; i < nodeCount; ++i) {
result->SnapshotItem(i, getter_AddRefs(node));
NS_ASSERTION(node, "incorrect snapshot length");
document->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS),
NS_LITERAL_STRING("item"),
getter_AddRefs(itemNode));
if (!itemNode)
return;
nsCOMPtr<nsIDOMElement> modelElement = do_QueryInterface(modelNode);
nsAutoString modelID;
modelElement->GetAttribute(NS_LITERAL_STRING("id"), modelID);
itemNode->SetAttribute(NS_LITERAL_STRING("model"), modelID);
nsCOMPtr<nsIXFormsSelectChild> item = do_QueryInterface(itemNode);
NS_ASSERTION(item, "item must be a SelectChild!");
item->SetContext(nsCOMPtr<nsIDOMElement>(do_QueryInterface(node)),
i, nodeCount);
// Clone the template content under the item
for (PRUint32 j = 0; j < templateNodeCount; ++j) {
templateNodes->Item(j, getter_AddRefs(templateNode));
templateNode->CloneNode(PR_TRUE, getter_AddRefs(cloneNode));
itemNode->AppendChild(cloneNode, getter_AddRefs(templateNode));
}
mItems.AppendObject(item);
}
}
NS_HIDDEN_(nsresult)
NS_NewXFormsItemSetElement(nsIXTFElement **aResult)
{
*aResult = new nsXFormsItemSetElement();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -355,11 +355,7 @@ nsXFormsModelElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled)
aEvent->GetType(type);
if (type.EqualsLiteral("xforms-refresh")) {
// refresh all of our form controls
PRInt32 controlCount = mFormControls.Count();
for (PRInt32 i = 0; i < controlCount; ++i) {
NS_STATIC_CAST(nsIXFormsControl*, mFormControls[i])->Refresh();
}
Refresh();
} else if (type.EqualsLiteral("xforms-revalidate")) {
Revalidate();
} else if (type.EqualsLiteral("xforms-recalculate")) {
@ -479,6 +475,12 @@ nsXFormsModelElement::Refresh()
printf("nsXFormsModelElement::Refresh()\n");
#endif
// refresh all of our form controls
PRInt32 controlCount = mFormControls.Count();
for (PRInt32 i = 0; i < controlCount; ++i) {
NS_STATIC_CAST(nsIXFormsControl*, mFormControls[i])->Refresh();
}
return NS_OK;
}

Просмотреть файл

@ -74,15 +74,15 @@
* On Refresh(), nsXFormsRepeatElement, does the following for each node in
* the nodeset the \<repeat\> tag is bound to:
*
* 1) Creates a new \<repeatitem\> (nsXFormsRepeatItemElement)
* 1) Creates a new \<contextcontainer\> (nsXFormsContextContainer)
*
* 2) Clones all its children (that is children of its nsIXTFXMLVisualWrapper)
* and appends them as children to the nsXFormsRepeatItemElement
* and appends them as children to the nsXFormsContextContainer
*
* 3) Sets the context node and size for the nsXFormsRepeatItemElement, so
* 3) Sets the context node and size for the nsXFormsContextContainer, so
* that children can retrieve this through nsIXFormsContextControl.
*
* 4) Inserts the nsXFormsRepeatItemElement into its visual content node
* 4) Inserts the nsXFormsContextContainer into its visual content node
* (mHTMLElement).
*
* For example, this instance data:
@ -105,12 +105,12 @@
* will be expanded to:
* <pre>
* <repeat nodeset="n">
* <repeatitem> (contextNode == "n[0]" and contextPosition == 1)
* <contextcontainer> (contextNode == "n[0]" and contextPosition == 1)
* Val: <output ref="."/> (that is: 'val1')
* </repeatitem>
* <repeatitem> (contextNode == "n[1]" and contextPosition == 2)
* </contextcontainer>
* <contextcontainer> (contextNode == "n[1]" and contextPosition == 2)
* Val: <output ref="."/> (that is: 'val2')
* </repeatitem>
* </contextcontainer>
* </repeat>
* </pre>
*
@ -381,10 +381,10 @@ nsXFormsRepeatElement::Refresh()
for (PRUint32 i = NS_MAX((PRUint32) 1, startIndex);
i < NS_MIN(contextSize + 1, number + startIndex);
++i) {
// Create <repeatitem>
// Create <contextcontainer>
nsCOMPtr<nsIDOMElement> riElement;
rv = domDoc->CreateElementNS(NS_LITERAL_STRING("http://www.w3.org/2002/xforms"),
NS_LITERAL_STRING("repeatitem"),
NS_LITERAL_STRING("contextcontainer"),
getter_AddRefs(riElement));
NS_ENSURE_SUCCESS(rv, rv);
@ -410,7 +410,7 @@ nsXFormsRepeatElement::Refresh()
rv = riContext->SetContextNode(contextElement);
NS_ENSURE_SUCCESS(rv, rv);
// Iterate over template children, clone them, and append them to <repeatitem>
// Iterate over template children, clone them, and append them to <contextcontainer>
nsCOMPtr<nsIDOMNode> child;
rv = mElement->GetFirstChild(getter_AddRefs(child));
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -0,0 +1,542 @@
/* -*- 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
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com>
*
* 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 ***** */
#include "nsXFormsStubElement.h"
#include "nsIXFormsControl.h"
#include "nsIXTFXMLVisualWrapper.h"
#include "nsIDOMFocusListener.h"
#include "nsVoidArray.h"
#include "nsIDOMElement.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIDOMHTMLSelectElement.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNodeList.h"
#include "nsXFormsUtils.h"
#include "nsXFormsAtoms.h"
#include "nsIModelElementPrivate.h"
#include "nsIXFormsSelectChild.h"
#include "nsArray.h"
#include "nsIDOMEventListener.h"
#include "nsIDOMEventTarget.h"
class nsXFormsSelectElement : public nsXFormsXMLVisualStub,
public nsIXFormsControl,
public nsIDOMEventListener
{
public:
nsXFormsSelectElement() : mElement(nsnull) {}
NS_DECL_ISUPPORTS_INHERITED
// nsIXTFXMLVisual overrides
NS_IMETHOD OnCreated(nsIXTFXMLVisualWrapper *aWrapper);
// nsIXTFVisual overrides
NS_IMETHOD GetVisualContent(nsIDOMElement **aElement);
NS_IMETHOD GetInsertionPoint(nsIDOMElement **aPoint);
// nsIXTFElement overrides
NS_IMETHOD OnDestroyed();
NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent);
NS_IMETHOD WillSetAttribute(nsIAtom *aName, const nsAString &aValue);
NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue);
NS_IMETHOD ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex);
NS_IMETHOD ChildAppended(nsIDOMNode *aChild);
NS_IMETHOD WillRemoveChild(PRUint32 aIndex);
NS_IMETHOD BeginAddingChildren();
NS_IMETHOD DoneAddingChildren();
// nsIXFormsControl
NS_DECL_NSIXFORMSCONTROL
// nsIDOMEventListener
NS_DECL_NSIDOMEVENTLISTENER
private:
NS_HIDDEN_(void) SelectItemsInList(const nsString &aValueList);
NS_HIDDEN_(void) SelectCopiedItem(nsIDOMNode *aNode);
NS_HIDDEN_(void) SelectItemsByValue(nsIDOMNode *aNode,
const nsStringArray &aItems);
nsCOMPtr<nsIDOMElement> mLabel;
nsCOMPtr<nsIDOMHTMLSelectElement> mSelect;
nsIDOMElement *mElement;
nsVoidArray mOptions;
};
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsSelectElement,
nsXFormsXMLVisualStub,
nsIXFormsControl,
nsIDOMEventListener)
// nsIXTFXMLVisual
NS_IMETHODIMP
nsXFormsSelectElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper)
{
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_PARENT_CHANGED |
nsIXTFElement::NOTIFY_WILL_SET_ATTRIBUTE |
nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
nsIXTFElement::NOTIFY_CHILD_INSERTED |
nsIXTFElement::NOTIFY_CHILD_REMOVED |
nsIXTFElement::NOTIFY_WILL_REMOVE_CHILD |
nsIXTFElement::NOTIFY_BEGIN_ADDING_CHILDREN |
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
nsCOMPtr<nsIDOMElement> node;
aWrapper->GetElementNode(getter_AddRefs(node));
// It's ok to keep pointer to mElement. mElement will have an
// owning reference to this object, so as long as we null out mElement in
// OnDestroyed, it will always be valid.
mElement = node;
NS_ASSERTION(mElement, "Wrapper is not an nsIDOMElement, we'll crash soon");
// Our anonymous content structure will look like this:
//
// <label> (mLabel)
// <span/> (insertion point)
// <select/> (mSelect)
// </label>
//
nsCOMPtr<nsIDOMDocument> domDoc;
node->GetOwnerDocument(getter_AddRefs(domDoc));
domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
NS_LITERAL_STRING("label"),
getter_AddRefs(mLabel));
NS_ENSURE_TRUE(mLabel, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMElement> element;
nsCOMPtr<nsIDOMNode> childReturn;
domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
NS_LITERAL_STRING("span"),
getter_AddRefs(element));
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
mLabel->AppendChild(element, getter_AddRefs(childReturn));
domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
NS_LITERAL_STRING("select"),
getter_AddRefs(element));
mSelect = do_QueryInterface(element);
NS_ENSURE_TRUE(mSelect, NS_ERROR_FAILURE);
// Unless we're a select1, set multiple=true
nsAutoString tag;
mElement->GetLocalName(tag);
if (!tag.EqualsLiteral("select1")) {
mSelect->SetMultiple(PR_TRUE);
// TODO: should leave default size=1 for select1, but options don't
// select correctly if we do that. Need to figure out why.
// mSelect->SetSize(4);
}
// Default to minimal/compact appearance
mSelect->SetSize(4);
// TODO: support "selection" and "incremental" attributes.
mLabel->AppendChild(mSelect, getter_AddRefs(childReturn));
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(mSelect);
NS_ASSERTION(targ, "Select must be an event target");
// We need an onchange handler to support non-incremental mode, and
// a blur handler to support incremental mode.
targ->AddEventListener(NS_LITERAL_STRING("change"), this, PR_FALSE);
targ->AddEventListener(NS_LITERAL_STRING("blur"), this, PR_FALSE);
return NS_OK;
}
// nsIXTFVisual
NS_IMETHODIMP
nsXFormsSelectElement::GetVisualContent(nsIDOMElement **aElement)
{
NS_ADDREF(*aElement = mLabel);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectElement::GetInsertionPoint(nsIDOMElement **aPoint)
{
nsCOMPtr<nsIDOMNode> childNode;
mLabel->GetFirstChild(getter_AddRefs(childNode));
return CallQueryInterface(childNode, aPoint);
}
// nsIXTFElement
NS_IMETHODIMP
nsXFormsSelectElement::OnDestroyed()
{
mElement = nsnull;
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(mSelect);
if (NS_LIKELY(targ != nsnull)) {
targ->RemoveEventListener(NS_LITERAL_STRING("blur"), this, PR_FALSE);
targ->RemoveEventListener(NS_LITERAL_STRING("change"), this, PR_FALSE);
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectElement::ParentChanged(nsIDOMElement *aNewParent)
{
// We need to re-evaluate our instance data binding when our parent
// changes, since xmlns declarations in effect could have changed.
if (aNewParent)
Refresh();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectElement::WillSetAttribute(nsIAtom *aName,
const nsAString &aValue)
{
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
nsCOMPtr<nsIDOMNode> model;
nsCOMPtr<nsIDOMElement> bind, context;
nsXFormsUtils::GetNodeContext(mElement,
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
getter_AddRefs(model),
getter_AddRefs(bind),
getter_AddRefs(context));
if (model) {
nsCOMPtr<nsIModelElementPrivate> modelPrivate = do_QueryInterface(model);
modelPrivate->RemoveFormControl(this);
}
} else if (aName == nsXFormsAtoms::appearance) {
// if (aValue.EqualsLiteral("full")) {
// XXX todo
// }
mSelect->SetSize(4);
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectElement::AttributeSet(nsIAtom *aName, const nsAString &aValue)
{
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
Refresh();
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectElement::ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectElement::ChildAppended(nsIDOMNode *aChild)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectElement::WillRemoveChild(PRUint32 aIndex)
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectElement::BeginAddingChildren()
{
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectElement::DoneAddingChildren()
{
Refresh();
return NS_OK;
}
// nsIXFormsControl
NS_IMETHODIMP
nsXFormsSelectElement::Refresh()
{
nsCOMPtr<nsIDOMNode> childNode, nodeReturn;
while (NS_SUCCEEDED(mSelect->GetFirstChild(getter_AddRefs(childNode))) &&
childNode) {
mSelect->RemoveChild(childNode, getter_AddRefs(nodeReturn));
}
nsCOMPtr<nsIDOMNodeList> childNodes;
nsresult rv = mElement->GetChildNodes(getter_AddRefs(childNodes));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXFormsSelectChild> childItem;
nsCOMPtr<nsIArray> childContent;
PRUint32 childCount;
childNodes->GetLength(&childCount);
for (PRUint32 i = 0; i < childCount; ++i) {
childNodes->Item(i, getter_AddRefs(childNode));
childItem = do_QueryInterface(childNode);
if (!childItem)
continue;
childItem->GetAnonymousNodes(getter_AddRefs(childContent));
PRUint32 nodeCount;
childContent->GetLength(&nodeCount);
for (PRUint32 j = 0; j < nodeCount; ++j) {
childNode = do_QueryElementAt(childContent, j);
mSelect->AppendChild(childNode, getter_AddRefs(nodeReturn));
}
}
nsCOMPtr<nsIDOMNode> modelNode;
nsCOMPtr<nsIDOMElement> bindElement;
nsCOMPtr<nsIDOMXPathResult> result =
nsXFormsUtils::EvaluateNodeBinding(mElement,
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
NS_LITERAL_STRING("ref"),
EmptyString(),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(modelNode),
getter_AddRefs(bindElement));
nsCOMPtr<nsIModelElementPrivate> model = do_QueryInterface(modelNode);
if (model) {
model->AddFormControl(this);
nsCOMPtr<nsIDOMNode> resultNode;
if (result)
result->GetSingleNodeValue(getter_AddRefs(resultNode));
if (!resultNode)
return NS_OK;
nsCOMPtr<nsIDOMNodeList> children;
resultNode->GetChildNodes(getter_AddRefs(children));
if (!children)
return NS_OK;
nsCOMPtr<nsIDOMNode> child;
PRUint32 childCount;
children->GetLength(&childCount);
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(child));
PRUint16 nodeType;
child->GetNodeType(&nodeType);
switch (nodeType) {
case nsIDOMNode::TEXT_NODE:
{
nsAutoString nodeValue;
child->GetNodeValue(nodeValue);
SelectItemsInList(nodeValue);
}
break;
case nsIDOMNode::ELEMENT_NODE:
SelectCopiedItem(child);
break;
default:
break;
}
}
}
return NS_OK;
}
// nsIDOMEventListener
NS_IMETHODIMP
nsXFormsSelectElement::HandleEvent(nsIDOMEvent *aEvent)
{
nsAutoString type;
aEvent->GetType(type);
nsAutoString value;
mElement->GetAttribute(NS_LITERAL_STRING("incremental"), value);
PRBool isIncremental = value.EqualsLiteral("true");
if ((isIncremental && type.EqualsLiteral("change")) ||
(!isIncremental && type.EqualsLiteral("blur"))) {
// Update the instance data with our selected items.
nsCOMPtr<nsIDOMNode> modelNode;
nsCOMPtr<nsIDOMElement> bindElement;
nsCOMPtr<nsIDOMXPathResult> result =
nsXFormsUtils::EvaluateNodeBinding(mElement,
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
NS_LITERAL_STRING("ref"),
EmptyString(),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(modelNode),
getter_AddRefs(bindElement));
nsCOMPtr<nsIDOMNode> resultNode;
if (result)
result->GetSingleNodeValue(getter_AddRefs(resultNode));
if (!resultNode)
return NS_OK;
nsCOMPtr<nsIDOMNodeList> children;
nsresult rv = mElement->GetChildNodes(getter_AddRefs(children));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> child;
nsCOMPtr<nsIXFormsSelectChild> childItem;
PRUint32 childCount;
children->GetLength(&childCount);
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(child));
childItem = do_QueryInterface(child);
if (childItem) {
childItem->WriteSelectedItems(resultNode);
}
}
}
return NS_OK;
}
// internal methods
inline PRBool
IsWhiteSpace(PRUnichar c)
{
return (c == PRUnichar(' ') || c == PRUnichar('\r') || c == PRUnichar('\n')
|| c == PRUnichar('\t'));
}
void
nsXFormsSelectElement::SelectItemsInList(const nsString &aValueList)
{
// Start by separating out the space-separated list of values.
const PRUnichar *start = aValueList.get();
nsStringArray valueList;
do {
// Skip past any whitespace.
while (*start && IsWhiteSpace(*start))
++start;
const PRUnichar *valueStart = start;
// Now search for the end of the value
while (*start && !IsWhiteSpace(*start))
++start;
valueList.AppendString(nsDependentSubstring(valueStart, start));
} while (*start);
// Now walk our children and figure out which ones to select.
// We use a helper function for this that can recurse into choices
// and itemset nodes.
SelectItemsByValue(mElement, valueList);
}
void
nsXFormsSelectElement::SelectItemsByValue(nsIDOMNode *aNode,
const nsStringArray &aItems)
{
// If we have no children, we can stop immediately.
nsCOMPtr<nsIDOMNodeList> children;
aNode->GetChildNodes(getter_AddRefs(children));
if (!children)
return;
PRUint32 childCount;
children->GetLength(&childCount);
nsAutoString temp;
nsCOMPtr<nsIDOMNode> child;
nsCOMPtr<nsIXFormsSelectChild> item;
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(child));
item = do_QueryInterface(child);
if (item)
item->SelectItemsByValue(aItems);
}
}
void
nsXFormsSelectElement::SelectCopiedItem(nsIDOMNode *aNode)
{
// TODO: this should select the item which is a copy of |aNode|.
}
NS_HIDDEN_(nsresult)
NS_NewXFormsSelectElement(nsIXTFElement **aResult)
{
*aResult = new nsXFormsSelectElement();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -794,8 +794,8 @@ nsXFormsUtils::FindParentContext(nsIDOMElement *aElement,
// context but it is invalid, ie. the XPath expression could have
// generated an error.
if (childModelID.IsEmpty()
|| childModelID.Equals(contextModelID)) {
if (tempNode && (childModelID.IsEmpty()
|| childModelID.Equals(contextModelID))) {
NS_ADDREF(*aContextNode = tempNode);
if (aContextSize)
*aContextSize = cSize;
@ -886,3 +886,16 @@ nsXFormsUtils::IsXFormsElement(nsIDOMNode* aNode, const nsAString& aName)
}
return PR_FALSE;
}
/* static */ PRBool
nsXFormsUtils::IsLabelElement(nsIDOMNode *aElement)
{
nsAutoString value;
aElement->GetLocalName(value);
if (value.EqualsLiteral("label")) {
aElement->GetNamespaceURI(value);
return value.EqualsLiteral(NS_NAMESPACE_XFORMS);
}
return PR_FALSE;
}

Просмотреть файл

@ -305,6 +305,11 @@ public:
*/
static NS_HIDDEN_(PRBool) IsXFormsElement(nsIDOMNode* aNode,
const nsAString& aName);
/**
* Returns true if the given element is an XForms label.
*/
static NS_HIDDEN_(PRBool) IsLabelElement(nsIDOMNode *aElement);
};
#endif

Просмотреть файл

@ -0,0 +1,135 @@
/* -*- 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
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com>
*
* 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 ***** */
#include "nsIXFormsValueElement.h"
#include "nsXFormsStubElement.h"
#include "nsIXTFGenericElementWrapper.h"
#include "nsIDOM3Node.h"
#include "nsXFormsUtils.h"
#include "nsIDOMElement.h"
#include "nsString.h"
/**
* Implementation of the XForms \<value\> element.
*
* @note The value element does not display any content, it simply provides
* a value from inline text or instance data.
*/
class nsXFormsValueElement : public nsXFormsStubElement,
public nsIXFormsValueElement
{
public:
nsXFormsValueElement() : mElement(nsnull) {}
NS_DECL_ISUPPORTS_INHERITED
// nsIXTFGenericElement overrides
NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper);
// nsIXFormsValueElement
NS_DECL_NSIXFORMSVALUEELEMENT
private:
nsIDOMElement *mElement;
};
NS_IMPL_ISUPPORTS_INHERITED1(nsXFormsValueElement,
nsXFormsStubElement,
nsIXFormsValueElement)
NS_IMETHODIMP
nsXFormsValueElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
{
nsCOMPtr<nsIDOMElement> node;
aWrapper->GetElementNode(getter_AddRefs(node));
// It's ok to keep pointer to mElement. mElement will have an
// owning reference to this object, so as long as we null out mElement in
// OnDestroyed, it will always be valid.
mElement = node;
NS_ASSERTION(mElement, "Wrapper is not an nsIDOMElement, we'll crash soon");
return NS_OK;
}
// nsIXFormsValueElement
NS_IMETHODIMP
nsXFormsValueElement::GetValue(nsAString &aValue)
{
nsCOMPtr<nsIDOMNode> modelNode;
nsCOMPtr<nsIDOMElement> bindElement;
nsCOMPtr<nsIDOMXPathResult> result =
nsXFormsUtils::EvaluateNodeBinding(mElement,
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
NS_LITERAL_STRING("ref"),
EmptyString(),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(modelNode),
getter_AddRefs(bindElement));
if (result) {
nsCOMPtr<nsIDOMNode> singleNode;
result->GetSingleNodeValue(getter_AddRefs(singleNode));
if (singleNode) {
nsString value;
nsXFormsUtils::GetNodeValue(singleNode, value);
aValue.Assign(value);
return NS_OK;
}
}
nsCOMPtr<nsIDOM3Node> node3 = do_QueryInterface(mElement);
NS_ASSERTION(node3, "dom elements must support dom3");
return node3->GetTextContent(aValue);
}
NS_HIDDEN_(nsresult)
NS_NewXFormsValueElement(nsIXTFElement **aResult)
{
*aResult = new nsXFormsValueElement();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}