Support nested bind elements (bug 265471). Remove use of nsIXTFPrivate, to make the code cleaner (and more efficient, as well). Implement the readonly property for inputs.

This commit is contained in:
bryner%brianryner.com 2004-10-26 00:34:03 +00:00
parent 46655dce46
commit 9c43217e31
18 changed files with 878 additions and 594 deletions

View File

@ -65,12 +65,16 @@ REQUIRES = \
js \
$(NULL)
XPIDLSRCS = nsIXFormsModelElement.idl
XPIDLSRCS = \
nsIXFormsModelElement.idl \
nsIInstanceElementPrivate.idl \
nsIModelElementPrivate.idl \
nsIXFormsControl.idl \
$(NULL)
CPPSRCS = \
nsXFormsElementFactory.cpp \
nsXFormsElement.cpp \
nsXFormsControl.cpp \
nsXFormsUtils.cpp \
nsXFormsModelElement.cpp \
nsXFormsInputElement.cpp \
nsXFormsSubmissionElement.cpp \

View File

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- 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
*
@ -36,24 +36,19 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsXFormsElement_h_
#define nsXFormsElement_h_
#include "nsISupports.idl"
#include "prtypes.h"
#include "nsIID.h"
/**
* Private interface implemented by the instance element.
*/
// base class for all XForms elements
interface nsIDOMDocument;
#define NS_NAMESPACE_XFORMS "http://www.w3.org/2002/xforms"
#define NS_NAMESPACE_XHTML "http://www.w3.org/1999/xhtml"
class nsXFormsElement
[uuid(8c9dd10d-4189-4a7b-a2eb-fd695cf33b27)]
interface nsIInstanceElementPrivate : nsISupports
{
protected:
NS_HIDDEN_(nsresult) CloneScriptingInterfaces(const nsIID *aIIDList,
unsigned int aIIDCount,
PRUint32 *aOutCount,
nsIID ***aOutArray);
/**
* The document which holds the live instance data.
*/
attribute nsIDOMDocument document;
};
#endif

View File

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- 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
*
@ -36,41 +36,49 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsXFormsControl_h_
#define nsXFormsControl_h_
/**
* Private interface implemented by the model element for other
* elements to use.
*/
#include "nscore.h"
#include "nsIXTFXMLVisualWrapper.h"
#include "nsIDOMNode.h"
#include "nsCOMPtr.h"
#include "nsXFormsElement.h"
#include "nsIXFormsModelElement.idl"
class nsXFormsModelElement;
class nsIDOMElement;
class nsIDOMXPathResult;
interface nsIXFormsControl;
interface nsISchemaType;
interface nsIInstanceElementPrivate;
#define NS_XFORMSCONTROL_IID \
{0x49bad098, 0xaa62, 0x49be, {0x98, 0x7b, 0xdb, 0x32, 0x66, 0x92, 0x1e, 0x0a}}
// Common implementation for XForms form controls
class nsXFormsControl : public nsXFormsElement,
public nsISupports
[uuid(b21b65d3-3305-4ce0-a604-3648cff61aca)]
interface nsIModelElementPrivate : nsIXFormsModelElement
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_XFORMSCONTROL_IID)
/**
* Called by form control elements when they are bound to or unbound from
* this model. These form controls will be refreshed when refresh() is
* called on the model.
*/
void addFormControl(in nsIXFormsControl control);
void removeFormControl(in nsIXFormsControl control);
NS_DECL_ISUPPORTS
/**
* Determine the type for a form control based on the schema included by
* this model.
*/
nsISchemaType getTypeForControl(in nsIXFormsControl control);
virtual NS_HIDDEN_(void) Refresh() = 0;
/**
* Notification that an instance element has started or finished loading
* its instance data. Model contstruction cannot complete until all of
* the instances have loaded their data.
*/
void instanceLoadStarted();
void instanceLoadFinished(in boolean success);
NS_HIDDEN_(nsXFormsModelElement*) GetModelAndBind(nsIDOMElement **aBindElement);
NS_HIDDEN_(already_AddRefed<nsIDOMXPathResult>)
EvaluateBinding(PRUint16 aResultType,
nsXFormsModelElement **aModel, nsIDOMElement **aBind);
/**
* Locate the instance element child with the given id.
*/
nsIInstanceElementPrivate findInstanceElement(in AString id);
protected:
nsCOMPtr<nsIXTFXMLVisualWrapper> mWrapper;
/**
* Track whether there is a form submit in progress for this model.
*/
attribute boolean submissionActive;
};
#endif

View File

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- 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
*
@ -36,34 +36,18 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsXFormsElement.h"
#include "nsMemory.h"
/**
* Interface implemented by all XForms form control classes.
*/
nsresult
nsXFormsElement::CloneScriptingInterfaces(const nsIID *aIIDList,
unsigned int aIIDCount,
PRUint32 *aOutCount,
nsIID ***aOutArray)
#include "nsISupports.idl"
[uuid(8377c845-5d55-4eee-9a76-0f86751dcbc8)]
interface nsIXFormsControl : nsISupports
{
nsIID **iids = NS_STATIC_CAST(nsIID**,
nsMemory::Alloc(aIIDCount * sizeof(nsIID*)));
if (!iids) {
return NS_ERROR_OUT_OF_MEMORY;
}
for (PRUint32 i = 0; i < aIIDCount; ++i) {
iids[i] = NS_STATIC_CAST(nsIID*,
nsMemory::Clone(&aIIDList[i], sizeof(nsIID)));
if (!iids[i]) {
for (PRUint32 j = 0; j < i; ++j)
nsMemory::Free(iids[j]);
nsMemory::Free(iids);
return NS_ERROR_OUT_OF_MEMORY;
}
}
*aOutArray = iids;
*aOutCount = aIIDCount;
return NS_OK;
}
/**
* This tells the form control to update its state based on the current
* instance data.
*/
void refresh();
};

View File

@ -38,6 +38,16 @@
#include "domstubs.idl"
/**
* The nsIXFormsModelElement interface defines scriptable methods for
* manipulating instance data and updating computed and displayed values.
*
* For more information on this interface please see
* http://www.w3.org/TR/xforms/
*
* @status FROZEN
*/
interface nsIDOMDocument;
interface nsIDOMDOMException;

View File

@ -1,187 +0,0 @@
/* -*- 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 "nsXFormsControl.h"
#include "nsXFormsModelElement.h"
#include "nsString.h"
#include "nsXFormsAtoms.h"
#include "nsIDOMElement.h"
#include "nsIDocument.h"
#include "nsINameSpaceManager.h"
#include "nsINodeInfo.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXPathEvaluator.h"
#include "nsIDOMXPathResult.h"
#include "nsIDOMXPathNSResolver.h"
NS_IMPL_ISUPPORTS1(nsXFormsControl, nsXFormsControl)
nsXFormsModelElement*
nsXFormsControl::GetModelAndBind(nsIDOMElement **aBindElement)
{
*aBindElement = nsnull;
NS_ENSURE_TRUE(mWrapper, nsnull);
nsCOMPtr<nsIDOMElement> node;
mWrapper->GetElementNode(getter_AddRefs(node));
nsCOMPtr<nsIDOMDocument> domDoc;
node->GetOwnerDocument(getter_AddRefs(domDoc));
if (!domDoc)
return nsnull;
nsAutoString bindId;
node->GetAttribute(NS_LITERAL_STRING("bind"), bindId);
nsCOMPtr<nsIDOMNode> modelWrapper;
if (!bindId.IsEmpty()) {
// Get the bind element with the given id.
domDoc->GetElementById(bindId, aBindElement);
if (*aBindElement) {
// Walk up the tree looking for the containing model.
(*aBindElement)->GetParentNode(getter_AddRefs(modelWrapper));
nsAutoString localName, namespaceURI;
nsCOMPtr<nsIDOMNode> temp;
while (modelWrapper) {
modelWrapper->GetLocalName(localName);
if (localName.EqualsLiteral("model")) {
modelWrapper->GetNamespaceURI(namespaceURI);
if (namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS))
break;
}
temp.swap(modelWrapper);
temp->GetParentNode(getter_AddRefs(modelWrapper));
}
}
} else {
// If no bind was given, we use model.
nsAutoString modelId;
node->GetAttribute(NS_LITERAL_STRING("model"), modelId);
if (modelId.IsEmpty()) {
// No model given, so use the first one in the document.
nsCOMPtr<nsIDOMNodeList> nodes;
domDoc->GetElementsByTagNameNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS),
NS_LITERAL_STRING("model"),
getter_AddRefs(nodes));
if (!nodes)
return nsnull;
nodes->Item(0, getter_AddRefs(modelWrapper));
} else {
nsCOMPtr<nsIDOMElement> wrapperElement;
domDoc->GetElementById(modelId, getter_AddRefs(wrapperElement));
modelWrapper = wrapperElement;
}
}
nsCOMPtr<nsIXTFPrivate> modelPrivate = do_QueryInterface(modelWrapper);
nsCOMPtr<nsISupports> modelElement;
if (modelPrivate)
modelPrivate->GetInner(getter_AddRefs(modelElement));
nsISupports *modelRaw = NS_STATIC_CAST(nsISupports*, modelElement.get());
return NS_STATIC_CAST(nsXFormsModelElement*,
NS_STATIC_CAST(nsIXFormsModelElement*, modelRaw));
}
already_AddRefed<nsIDOMXPathResult>
nsXFormsControl::EvaluateBinding(PRUint16 aResultType,
nsXFormsModelElement **aModel,
nsIDOMElement **aBind)
{
// A control may be attached to a model by either using the 'bind'
// attribute to give the id of a bind element, or using the 'model'
// attribute to give the id of a model. If neither of these are given,
// the control belongs to the first model in the document.
*aBind = nsnull;
NS_IF_ADDREF(*aModel = GetModelAndBind(aBind));
if (!*aModel)
return nsnull;
nsCOMPtr<nsIDOMElement> resolverNode;
nsAutoString expr;
if (*aBind) {
resolverNode = *aBind;
resolverNode->GetAttribute(NS_LITERAL_STRING("nodeset"), expr);
} else {
mWrapper->GetElementNode(getter_AddRefs(resolverNode));
resolverNode->GetAttribute(NS_LITERAL_STRING("ref"), expr);
}
if (expr.IsEmpty())
return nsnull;
// Get the instance data and evaluate the xpath expression.
// XXXfixme when xpath extensions are implemented (instance())
nsCOMPtr<nsIDOMDocument> instanceDoc;
(*aModel)->GetInstanceDocument(NS_LITERAL_STRING(""),
getter_AddRefs(instanceDoc));
if (!instanceDoc)
return nsnull;
nsCOMPtr<nsIDOMXPathEvaluator> eval = do_QueryInterface(instanceDoc);
nsCOMPtr<nsIDOMXPathNSResolver> resolver;
eval->CreateNSResolver(resolverNode, getter_AddRefs(resolver));
NS_ENSURE_TRUE(resolver, nsnull);
nsCOMPtr<nsIDOMElement> docElement;
instanceDoc->GetDocumentElement(getter_AddRefs(docElement));
if (!docElement)
return nsnull; // this will happen if the doc is still loading
nsCOMPtr<nsISupports> result;
eval->Evaluate(expr, docElement, resolver, aResultType, nsnull,
getter_AddRefs(result));
nsIDOMXPathResult *xpResult = nsnull;
if (result)
CallQueryInterface(result, &xpResult); // addrefs
return xpResult;
}

View File

@ -45,14 +45,17 @@
#include "nsString.h"
#include "nsIXTFXMLVisualWrapper.h"
#include "nsIDOMDocument.h"
#include "nsXFormsControl.h"
#include "nsIXFormsControl.h"
#include "nsISchema.h"
#include "nsXFormsModelElement.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsXFormsAtoms.h"
#include "nsAutoPtr.h"
#include "nsIDOMXPathResult.h"
#include "nsIDOMFocusListener.h"
#include "nsXFormsUtils.h"
#include "nsIModelElementPrivate.h"
#include "nsIContent.h"
#include "nsIDOMXPathExpression.h"
static const nsIID sScriptingIIDs[] = {
NS_IDOMELEMENT_IID,
@ -60,15 +63,16 @@ static const nsIID sScriptingIIDs[] = {
NS_IDOM3NODE_IID
};
class nsXFormsInputElement : public nsXFormsControl,
public nsIXTFXMLVisual,
public nsIDOMFocusListener
class nsXFormsInputElement : public nsIXTFXMLVisual,
public nsIDOMFocusListener,
public nsIXFormsControl
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXTFXMLVISUAL
NS_DECL_NSIXTFVISUAL
NS_DECL_NSIXTFELEMENT
NS_DECL_NSIXFORMSCONTROL
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
@ -77,11 +81,11 @@ public:
NS_IMETHOD Focus(nsIDOMEvent *aEvent);
NS_IMETHOD Blur(nsIDOMEvent *aEvent);
// nsXFormsControl
virtual NS_HIDDEN_(void) Refresh();
nsXFormsInputElement() : mElement(nsnull) {}
private:
nsCOMPtr<nsIDOMHTMLInputElement> mInput;
nsIDOMElement *mElement;
};
NS_IMPL_ADDREF(nsXFormsInputElement)
@ -92,6 +96,7 @@ NS_INTERFACE_MAP_BEGIN(nsXFormsInputElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener)
NS_INTERFACE_MAP_ENTRY(nsIXFormsControl)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXTFXMLVisual)
NS_INTERFACE_MAP_END
@ -101,12 +106,19 @@ NS_IMETHODIMP
nsXFormsInputElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper)
{
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_WILL_SET_ATTRIBUTE |
nsIXTFElement::NOTIFY_ATTRIBUTE_SET);
mWrapper = aWrapper;
nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
nsIXTFElement::NOTIFY_PARENT_CHANGED);
nsCOMPtr<nsIDOMElement> node;
mWrapper->GetElementNode(getter_AddRefs(node));
aWrapper->GetElementNode(getter_AddRefs(node));
// It's ok to keep a weak 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");
nsCOMPtr<nsIDOMDocument> domDoc;
node->GetOwnerDocument(getter_AddRefs(domDoc));
@ -191,9 +203,9 @@ nsXFormsInputElement::GetIsAttributeHandler(PRBool *aIsHandler)
NS_IMETHODIMP
nsXFormsInputElement::GetScriptingInterfaces(PRUint32 *aCount, nsIID ***aArray)
{
return CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
return nsXFormsUtils::CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
}
NS_IMETHODIMP
@ -217,6 +229,9 @@ nsXFormsInputElement::WillChangeParent(nsIDOMElement *aNewParent)
NS_IMETHODIMP
nsXFormsInputElement::ParentChanged(nsIDOMElement *aNewParent)
{
// We need to re-evaluate our instance data binding when our parent
// changes, since xmlns declarations in effect could have changed.
Refresh();
return NS_OK;
}
@ -261,7 +276,9 @@ nsXFormsInputElement::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
{
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
nsCOMPtr<nsIDOMElement> bindElement;
nsXFormsModelElement *model = GetModelAndBind(getter_AddRefs(bindElement));
nsCOMPtr<nsIModelElementPrivate> model;
model = do_QueryInterface(nsXFormsUtils::GetModelAndBind(mElement, getter_AddRefs(bindElement)));
if (model)
model->RemoveFormControl(this);
}
@ -324,11 +341,13 @@ nsXFormsInputElement::Blur(nsIDOMEvent *aEvent)
if (!mInput)
return NS_OK;
nsRefPtr<nsXFormsModelElement> model;
nsCOMPtr<nsIDOMNode> modelNode;
nsCOMPtr<nsIDOMElement> bindElement;
nsCOMPtr<nsIDOMXPathResult> result =
EvaluateBinding(nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(model), getter_AddRefs(bindElement));
nsXFormsUtils::EvaluateNodeBinding(mElement,
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(modelNode),
getter_AddRefs(bindElement));
if (!result)
return NS_OK;
@ -372,26 +391,54 @@ nsXFormsInputElement::Blur(nsIDOMEvent *aEvent)
// other methods
void
NS_IMETHODIMP
nsXFormsInputElement::Refresh()
{
if (!mInput)
return;
return NS_OK;
nsRefPtr<nsXFormsModelElement> model;
nsCOMPtr<nsIDOMNode> modelNode;
nsCOMPtr<nsIDOMElement> bindElement;
nsCOMPtr<nsIDOMXPathResult> result =
EvaluateBinding(nsIDOMXPathResult::STRING_TYPE,
getter_AddRefs(model), getter_AddRefs(bindElement));
nsXFormsUtils::EvaluateNodeBinding(mElement,
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(modelNode),
getter_AddRefs(bindElement));
nsCOMPtr<nsIModelElementPrivate> model = do_QueryInterface(modelNode);
if (model) {
model->AddFormControl(this);
if (result) {
nsAutoString nodeValue;
result->GetStringValue(nodeValue);
nsCOMPtr<nsIDOMNode> resultNode;
if (result)
result->GetSingleNodeValue(getter_AddRefs(resultNode));
nsCOMPtr<nsISchemaType> type = model->GetTypeForControl(this);
if (resultNode) {
PRUint16 nodeType = 0;
resultNode->GetNodeType(&nodeType);
nsAutoString text;
switch (nodeType) {
case nsIDOMNode::TEXT_NODE:
case nsIDOMNode::ATTRIBUTE_NODE:
resultNode->GetNodeValue(text);
break;
case nsIDOMNode::ELEMENT_NODE:
{
nsCOMPtr<nsIDOMNode> firstChild;
resultNode->GetFirstChild(getter_AddRefs(firstChild));
if (firstChild)
firstChild->GetNodeValue(text);
break;
}
default:
NS_ERROR("form control references invalid node type in instance data");
}
nsCOMPtr<nsISchemaType> type;
model->GetTypeForControl(this, getter_AddRefs(type));
nsCOMPtr<nsISchemaBuiltinType> biType = do_QueryInterface(type);
PRUint16 typeValue = nsISchemaBuiltinType::BUILTIN_TYPE_STRING;
@ -402,14 +449,35 @@ nsXFormsInputElement::Refresh()
mInput->SetAttribute(NS_LITERAL_STRING("type"),
NS_LITERAL_STRING("checkbox"));
mInput->SetChecked(nodeValue.EqualsLiteral("true") ||
nodeValue.EqualsLiteral("1"));
mInput->SetChecked(text.EqualsLiteral("true") ||
text.EqualsLiteral("1"));
} else {
mInput->RemoveAttribute(NS_LITERAL_STRING("type"));
mInput->SetValue(nodeValue);
mInput->SetValue(text);
}
PRBool isReadOnly = PR_FALSE;
nsCOMPtr<nsIContent> nodeContent = do_QueryInterface(resultNode);
if (nodeContent) {
nsIDOMXPathExpression *expr =
NS_STATIC_CAST(nsIDOMXPathExpression*,
nodeContent->GetProperty(nsXFormsAtoms::readonly));
if (expr) {
expr->Evaluate(mElement,
nsIDOMXPathResult::BOOLEAN_TYPE, nsnull,
getter_AddRefs(result));
if (result) {
result->GetBooleanValue(&isReadOnly);
}
}
}
mInput->SetReadOnly(isReadOnly);
}
}
return NS_OK;
}
NS_HIDDEN_(nsresult)

View File

@ -46,6 +46,8 @@
#include "nsIDOMEventReceiver.h"
#include "nsIDOMXMLDocument.h"
#include "nsIDOMDOMImplementation.h"
#include "nsIXTFGenericElementWrapper.h"
#include "nsXFormsUtils.h"
static const nsIID sScriptingIIDs[] = {
NS_IDOMELEMENT_IID,
@ -59,12 +61,17 @@ NS_IMPL_RELEASE(nsXFormsInstanceElement)
NS_INTERFACE_MAP_BEGIN(nsXFormsInstanceElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFGenericElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFPrivate)
NS_INTERFACE_MAP_ENTRY(nsIInstanceElementPrivate)
NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXTFGenericElement)
NS_INTERFACE_MAP_END
nsXFormsInstanceElement::nsXFormsInstanceElement()
: mElement(nsnull)
{
}
NS_IMETHODIMP
nsXFormsInstanceElement::OnDestroyed()
{
@ -93,9 +100,9 @@ NS_IMETHODIMP
nsXFormsInstanceElement::GetScriptingInterfaces(PRUint32 *aCount,
nsIID ***aArray)
{
return CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
return nsXFormsUtils::CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
}
NS_IMETHODIMP
@ -206,12 +213,8 @@ nsXFormsInstanceElement::DoneAddingChildren()
// and have all of our child elements, so this is our first opportunity
// to create the instance document.
nsCOMPtr<nsIDOMElement> element;
mWrapper->GetElementNode(getter_AddRefs(element));
NS_ASSERTION(element, "no wrapper element");
nsAutoString src;
element->GetAttribute(NS_LITERAL_STRING("src"), src);
mElement->GetAttribute(NS_LITERAL_STRING("src"), src);
if (src.IsEmpty()) {
// If we don't have a linked external instance, use our inline data.
@ -238,7 +241,16 @@ nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED |
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
mWrapper = aWrapper;
nsCOMPtr<nsIDOMElement> node;
aWrapper->GetElementNode(getter_AddRefs(node));
// It's ok to keep a weak 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;
}
@ -247,9 +259,9 @@ nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
NS_IMETHODIMP
nsXFormsInstanceElement::Load(nsIDOMEvent *aEvent)
{
nsXFormsModelElement *model = GetModel();
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
if (model)
model->RemovePendingInstance();
model->InstanceLoadFinished(PR_TRUE);
return NS_OK;
}
@ -269,11 +281,9 @@ nsXFormsInstanceElement::Unload(nsIDOMEvent *aEvent)
NS_IMETHODIMP
nsXFormsInstanceElement::Abort(nsIDOMEvent *aEvent)
{
nsXFormsModelElement *model = GetModel();
if (model) {
model->RemovePendingInstance();
model->DispatchEvent(eEvent_LinkException);
}
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
if (model)
model->InstanceLoadFinished(PR_FALSE);
return NS_OK;
}
@ -281,11 +291,9 @@ nsXFormsInstanceElement::Abort(nsIDOMEvent *aEvent)
NS_IMETHODIMP
nsXFormsInstanceElement::Error(nsIDOMEvent *aEvent)
{
nsXFormsModelElement *model = GetModel();
if (model) {
model->RemovePendingInstance();
model->DispatchEvent(eEvent_LinkException);
}
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
if (model)
model->InstanceLoadFinished(PR_FALSE);
return NS_OK;
}
@ -298,17 +306,21 @@ nsXFormsInstanceElement::HandleEvent(nsIDOMEvent *aEvent)
return NS_OK;
}
// nsIXTFPrivate
// nsIInstanceElementPrivate
NS_IMETHODIMP
nsXFormsInstanceElement::GetInner(nsISupports **aInner)
nsXFormsInstanceElement::GetDocument(nsIDOMDocument **aDocument)
{
NS_ENSURE_ARG_POINTER(aInner);
NS_ADDREF(*aInner = NS_STATIC_CAST(nsIXTFGenericElement*, this));
NS_IF_ADDREF(*aDocument = mDocument);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::SetDocument(nsIDOMDocument *aDocument)
{
mDocument = aDocument;
return NS_OK;
}
// private methods
@ -321,11 +333,8 @@ nsXFormsInstanceElement::CloneInlineInstance()
return rv; // don't warn, we might just not be in the document yet
// look for our first child element (skip over text nodes, etc.)
nsCOMPtr<nsIDOMElement> element;
mWrapper->GetElementNode(getter_AddRefs(element));
nsCOMPtr<nsIDOMNode> child, temp;
element->GetFirstChild(getter_AddRefs(child));
mElement->GetFirstChild(getter_AddRefs(child));
while (child) {
PRUint16 nodeType;
child->GetNodeType(&nodeType);
@ -363,30 +372,23 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc)
nsCOMPtr<nsIDOMXMLDocument> xmlDoc = do_QueryInterface(mDocument);
NS_ASSERTION(xmlDoc, "we created a document but it's not an XMLDocument?");
nsCOMPtr<nsIDOMElement> element;
mWrapper->GetElementNode(getter_AddRefs(element));
PRBool success;
xmlDoc->Load(aSrc, &success);
nsXFormsModelElement *model = GetModel();
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
if (model) {
if (success)
model->AddPendingInstance();
else
model->DispatchEvent(eEvent_LinkException);
model->InstanceLoadStarted();
if (!success) {
model->InstanceLoadFinished(PR_FALSE);
}
}
}
nsresult
nsXFormsInstanceElement::CreateInstanceDocument()
{
nsCOMPtr<nsIDOMElement> element;
mWrapper->GetElementNode(getter_AddRefs(element));
NS_ASSERTION(element, "no wrapper element");
nsCOMPtr<nsIDOMDocument> doc;
nsresult rv = element->GetOwnerDocument(getter_AddRefs(doc));
nsresult rv = mElement->GetOwnerDocument(getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
if (!doc) // could be we just aren't inserted yet, so don't warn
@ -400,30 +402,16 @@ nsXFormsInstanceElement::CreateInstanceDocument()
getter_AddRefs(mDocument));
}
nsXFormsModelElement*
already_AddRefed<nsIModelElementPrivate>
nsXFormsInstanceElement::GetModel()
{
nsCOMPtr<nsIDOMElement> element;
mWrapper->GetElementNode(getter_AddRefs(element));
NS_ASSERTION(element, "no wrapper element");
nsCOMPtr<nsIDOMNode> parentNode;
element->GetParentNode(getter_AddRefs(parentNode));
mElement->GetParentNode(getter_AddRefs(parentNode));
nsCOMPtr<nsIXFormsModelElement> modelElt = do_QueryInterface(parentNode);
if (!modelElt)
return nsnull;
nsCOMPtr<nsIXTFPrivate> xtfPriv = do_QueryInterface(modelElt);
NS_ENSURE_TRUE(xtfPriv, nsnull);
nsCOMPtr<nsISupports> modelInner;
xtfPriv->GetInner(getter_AddRefs(modelInner));
NS_ENSURE_TRUE(modelInner, nsnull);
nsISupports *isupp = NS_STATIC_CAST(nsISupports*, modelInner.get());
return NS_STATIC_CAST(nsXFormsModelElement*,
NS_STATIC_CAST(nsIXFormsModelElement*, isupp));
nsIModelElementPrivate *model = nsnull;
if (parentNode)
CallQueryInterface(parentNode, &model);
return model;
}
nsresult

View File

@ -46,24 +46,23 @@
#define nsXFormsInstanceElement_h_
#include "nsIXTFGenericElement.h"
#include "nsIXTFPrivate.h"
#include "nsXFormsElement.h"
#include "nsIDOMDocument.h"
#include "nsCOMPtr.h"
#include "nsIXTFGenericElementWrapper.h"
#include "nsIDOMLoadListener.h"
#include "nsXFormsModelElement.h"
#include "nsIModelElementPrivate.h"
#include "nsIInstanceElementPrivate.h"
class nsXFormsInstanceElement : public nsXFormsElement,
public nsIXTFGenericElement,
public nsIXTFPrivate,
class nsIDOMElement;
class nsXFormsInstanceElement : public nsIXTFGenericElement,
public nsIInstanceElementPrivate,
public nsIDOMLoadListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXTFELEMENT
NS_DECL_NSIXTFGENERICELEMENT
NS_DECL_NSIXTFPRIVATE
NS_DECL_NSIINSTANCEELEMENTPRIVATE
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
@ -75,17 +74,16 @@ public:
NS_IMETHOD Abort(nsIDOMEvent *aEvent);
NS_IMETHOD Error(nsIDOMEvent *aEvent);
NS_HIDDEN_(nsIDOMDocument*) GetDocument() { return mDocument; }
NS_HIDDEN_(void) SetDocument(nsIDOMDocument *doc) { mDocument = doc; }
nsXFormsInstanceElement() NS_HIDDEN;
private:
NS_HIDDEN_(nsresult) CloneInlineInstance();
NS_HIDDEN_(void) LoadExternalInstance(const nsAString &aSrc);
NS_HIDDEN_(nsresult) CreateInstanceDocument();
NS_HIDDEN_(nsXFormsModelElement*) GetModel();
NS_HIDDEN_(already_AddRefed<nsIModelElementPrivate>) GetModel();
nsCOMPtr<nsIDOMDocument> mDocument;
nsCOMPtr<nsIXTFGenericElementWrapper> mWrapper;
nsCOMPtr<nsIDOMDocument> mDocument;
nsIDOMElement *mElement;
};
NS_HIDDEN_(nsresult)

View File

@ -62,11 +62,12 @@
#include "nsIScriptGlobalObject.h"
#include "nsIContent.h"
#include "nsNetUtil.h"
#include "nsXFormsControl.h"
#include "nsIXFormsControl.h"
#include "nsXFormsTypes.h"
#include "nsXFormsXPathParser.h"
#include "nsXFormsXPathAnalyzer.h"
#include "nsXFormsInstanceElement.h"
#include "nsIInstanceElementPrivate.h"
#include "nsXFormsUtils.h"
#include "nsISchemaLoader.h"
#include "nsAutoPtr.h"
@ -121,8 +122,8 @@ NS_IMPL_RELEASE(nsXFormsModelElement)
NS_INTERFACE_MAP_BEGIN(nsXFormsModelElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFGenericElement)
NS_INTERFACE_MAP_ENTRY(nsIXTFPrivate)
NS_INTERFACE_MAP_ENTRY(nsIXFormsModelElement)
NS_INTERFACE_MAP_ENTRY(nsIModelElementPrivate)
NS_INTERFACE_MAP_ENTRY(nsISchemaLoadListener)
NS_INTERFACE_MAP_ENTRY(nsIWebServiceErrorHandler)
NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
@ -188,9 +189,9 @@ nsXFormsModelElement::GetIsAttributeHandler(PRBool *aIsHandler)
NS_IMETHODIMP
nsXFormsModelElement::GetScriptingInterfaces(PRUint32 *aCount, nsIID ***aArray)
{
return CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
return nsXFormsUtils::CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
}
NS_IMETHODIMP
@ -395,7 +396,7 @@ nsXFormsModelElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled)
// refresh all of our form controls
PRInt32 controlCount = mFormControls.Count();
for (PRInt32 i = 0; i < controlCount; ++i) {
NS_STATIC_CAST(nsXFormsControl*, mFormControls[i])->Refresh();
NS_STATIC_CAST(nsIXFormsControl*, mFormControls[i])->Refresh();
}
} else if (type.EqualsLiteral("xforms-revalidate")) {
Revalidate();
@ -438,15 +439,6 @@ nsXFormsModelElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
return NS_OK;
}
// nsIXTFPrivate
NS_IMETHODIMP
nsXFormsModelElement::GetInner(nsISupports **aInner)
{
NS_ENSURE_ARG_POINTER(aInner);
NS_ADDREF(*aInner = NS_STATIC_CAST(nsIXFormsModelElement*, this));
return NS_OK;
}
// nsIXFormsModelElement
NS_IMETHODIMP
@ -455,7 +447,7 @@ nsXFormsModelElement::GetInstanceDocument(const nsAString& aInstanceID,
{
NS_ENSURE_ARG_POINTER(aDocument);
NS_IF_ADDREF(*aDocument = FindInstanceDocument(aInstanceID));
*aDocument = FindInstanceDocument(aInstanceID).get(); // transfer reference
return *aDocument ? NS_OK : NS_ERROR_FAILURE;
}
@ -609,16 +601,64 @@ nsXFormsModelElement::Error(nsIDOMEvent* aEvent)
return NS_OK;
}
// internal methods
// nsIModelElementPrivate
nsXFormsInstanceElement *
nsXFormsModelElement::FindInstanceElement(const nsAString &aID)
NS_IMETHODIMP
nsXFormsModelElement::AddFormControl(nsIXFormsControl *aControl)
{
if (mFormControls.IndexOf(aControl) == -1)
mFormControls.AppendElement(aControl);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::RemoveFormControl(nsIXFormsControl *aControl)
{
mFormControls.RemoveElement(aControl);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::GetTypeForControl(nsIXFormsControl *aControl,
nsISchemaType **aType)
{
*aType = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::InstanceLoadStarted()
{
++mPendingInstanceCount;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::InstanceLoadFinished(PRBool aSuccess)
{
--mPendingInstanceCount;
if (!aSuccess) {
DispatchEvent(eEvent_LinkException);
} else if (IsComplete()) {
nsresult rv = FinishConstruction();
if (NS_SUCCEEDED(rv))
DispatchEvent(eEvent_Refresh);
}
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::FindInstanceElement(const nsAString &aID,
nsIInstanceElementPrivate **aElement)
{
*aElement = nsnull;
nsCOMPtr<nsIDOMNodeList> children;
mElement->GetChildNodes(getter_AddRefs(children));
if (!children)
return nsnull;
return NS_OK;
PRUint32 childCount = 0;
children->GetLength(&childCount);
@ -637,40 +677,42 @@ nsXFormsModelElement::FindInstanceElement(const nsAString &aID)
element->GetAttribute(NS_LITERAL_STRING("id"), id);
if (aID.IsEmpty() || aID.Equals(id)) {
// make sure this is an xforms instance element
nsAutoString namespaceURI, localName;
element->GetNamespaceURI(namespaceURI);
element->GetLocalName(localName);
if (localName.EqualsLiteral("instance") &&
namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
// This is the requested instance, so get its document.
nsCOMPtr<nsIXTFPrivate> xtfPriv = do_QueryInterface(element);
NS_ENSURE_TRUE(xtfPriv, nsnull);
nsCOMPtr<nsISupports> instanceInner;
xtfPriv->GetInner(getter_AddRefs(instanceInner));
NS_ENSURE_TRUE(instanceInner, nsnull);
nsISupports *isupp = NS_STATIC_CAST(nsISupports*, instanceInner.get());
nsXFormsInstanceElement *instance =
NS_STATIC_CAST(nsXFormsInstanceElement*,
NS_STATIC_CAST(nsIXTFGenericElement*, isupp));
return instance;
}
CallQueryInterface(element, aElement);
if (*aElement)
break;
}
}
return nsnull;
return NS_OK;
}
nsIDOMDocument *
NS_IMETHODIMP
nsXFormsModelElement::GetSubmissionActive(PRBool *aIsActive)
{
*aIsActive = mSubmissionActive;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::SetSubmissionActive(PRBool aIsActive)
{
mSubmissionActive = aIsActive;
return NS_OK;
}
// internal methods
already_AddRefed<nsIDOMDocument>
nsXFormsModelElement::FindInstanceDocument(const nsAString &aID)
{
nsXFormsInstanceElement *instance = FindInstanceElement(aID);
return instance ? instance->GetDocument() : nsnull;
nsCOMPtr<nsIInstanceElementPrivate> instance;
nsXFormsModelElement::FindInstanceElement(aID, getter_AddRefs(instance));
nsIDOMDocument *doc = nsnull;
if (instance)
instance->GetDocument(&doc); // addrefs
return doc;
}
nsresult
@ -683,7 +725,8 @@ nsXFormsModelElement::FinishConstruction()
// we get the instance data from our instance child nodes
nsIDOMDocument *firstInstanceDoc = FindInstanceDocument(EmptyString());
nsCOMPtr<nsIDOMDocument> firstInstanceDoc =
FindInstanceDocument(EmptyString());
if (!firstInstanceDoc)
return NS_OK;
@ -710,7 +753,7 @@ nsXFormsModelElement::FinishConstruction()
if (localName.EqualsLiteral("bind")) {
child->GetNamespaceURI(namespaceURI);
if (namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
if (!ProcessBind(xpath, firstInstanceRoot,
if (!ProcessBind(xpath, firstInstanceRoot, nsnull,
nsCOMPtr<nsIDOMElement>(do_QueryInterface(child)))) {
DispatchEvent(eEvent_BindingException);
return NS_OK;
@ -744,18 +787,10 @@ ReleaseExpr(void *aElement,
PRBool
nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
nsIDOMNode *aContextNode,
nsIDOMElement *aBindElement)
nsIDOMNode *aContextNode,
nsIDOMXPathResult *aOuterNodeset,
nsIDOMElement *aBindElement)
{
// Get the expression for the nodes that this <bind> applies to.
nsAutoString expr;
aBindElement->GetAttribute(NS_LITERAL_STRING("nodeset"), expr);
if (expr.IsEmpty())
return PR_TRUE;
nsCOMPtr<nsIDOMXPathNSResolver> resolver;
aEvaluator->CreateNSResolver(aBindElement, getter_AddRefs(resolver));
// Get the model item properties specified by this <bind>.
nsCOMPtr<nsIDOMXPathExpression> props[eModel__count];
nsAutoString exprStrings[eModel__count];
@ -763,6 +798,9 @@ nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
nsresult rv = NS_OK;
nsAutoString attrStr;
nsCOMPtr<nsIDOMXPathNSResolver> resolver;
aEvaluator->CreateNSResolver(aBindElement, getter_AddRefs(resolver));
for (int i = 0; i < eModel__count; ++i) {
sModelPropsList[i]->ToString(attrStr);
@ -777,15 +815,20 @@ nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
}
}
if (propCount == 0)
return PR_TRUE; // successful, but nothing to do
// Find the nodeset that this bind applies to.
nsCOMPtr<nsIDOMXPathResult> result;
rv = aEvaluator->Evaluate(expr, aContextNode, resolver,
nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
nsnull, getter_AddRefs(result));
if (NS_FAILED(rv))
return PR_FALSE;
nsAutoString expr;
aBindElement->GetAttribute(NS_LITERAL_STRING("nodeset"), expr);
if (expr.IsEmpty()) {
result = aOuterNodeset;
} else {
rv = aEvaluator->Evaluate(expr, aContextNode, resolver,
nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
nsnull, getter_AddRefs(result));
if (NS_FAILED(rv))
return PR_FALSE; // dispatch a binding exception
}
PRUint32 snapLen;
rv = result->GetSnapshotLength(&snapLen);
@ -839,7 +882,38 @@ nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
}
}
// Now evaluate any child <bind> elements.
nsCOMPtr<nsIDOMNode> childContext;
result->SnapshotItem(0, getter_AddRefs(childContext));
nsCOMPtr<nsIDOMNodeList> children;
aBindElement->GetChildNodes(getter_AddRefs(children));
if (children) {
PRUint32 childCount = 0;
children->GetLength(&childCount);
nsCOMPtr<nsIDOMNode> child;
nsAutoString value;
for (PRUint32 k = 0; k < childCount; ++k) {
children->Item(k, getter_AddRefs(child));
if (child) {
child->GetLocalName(value);
if (!value.EqualsLiteral("bind"))
continue;
child->GetNamespaceURI(value);
if (!value.EqualsLiteral(NS_NAMESPACE_XFORMS))
continue;
if (!ProcessBind(aEvaluator, childContext, result,
nsCOMPtr<nsIDOMElement>(do_QueryInterface(child))))
return PR_FALSE;
}
}
}
return PR_TRUE;
}
@ -864,36 +938,6 @@ nsXFormsModelElement::DispatchEvent(nsXFormsModelEvent aEvent)
return target->DispatchEvent(event, &cancelled);
}
already_AddRefed<nsISchemaType>
nsXFormsModelElement::GetTypeForControl(nsXFormsControl *aControl)
{
return nsnull;
}
void
nsXFormsModelElement::AddFormControl(nsXFormsControl *aControl)
{
if (mFormControls.IndexOf(aControl) == -1)
mFormControls.AppendElement(aControl);
}
void
nsXFormsModelElement::RemoveFormControl(nsXFormsControl *aControl)
{
mFormControls.RemoveElement(aControl);
}
void
nsXFormsModelElement::RemovePendingInstance()
{
--mPendingInstanceCount;
if (IsComplete()) {
nsresult rv = FinishConstruction();
if (NS_SUCCEEDED(rv))
DispatchEvent(eEvent_Refresh);
}
}
/* static */ void
nsXFormsModelElement::Startup()
{

View File

@ -40,8 +40,7 @@
#define nsXFormsModelElement_h_
#include "nsIXTFGenericElement.h"
#include "nsIXTFPrivate.h"
#include "nsIXFormsModelElement.h"
#include "nsIModelElementPrivate.h"
#include "nsISchema.h"
#include "nsCOMArray.h"
#include "nsVoidArray.h"
@ -49,7 +48,6 @@
#include "nsIDOMLoadListener.h"
#include "nsIDOMDocument.h"
#include "nsXFormsMDG.h"
#include "nsXFormsElement.h"
#include "nsISchemaLoader.h"
#include "nsISchema.h"
@ -58,7 +56,6 @@ class nsIDOMElement;
class nsIDOMNode;
class nsIDOMXPathEvaluator;
class nsXFormsControl;
class nsXFormsInstanceElement;
enum nsXFormsModelEvent {
eEvent_ModelConstruct,
@ -76,10 +73,8 @@ enum nsXFormsModelEvent {
eEvent_ComputeException
};
class nsXFormsModelElement : public nsXFormsElement,
public nsIXTFGenericElement,
public nsIXTFPrivate,
public nsIXFormsModelElement,
class nsXFormsModelElement : public nsIXTFGenericElement,
public nsIModelElementPrivate,
public nsISchemaLoadListener,
public nsIDOMLoadListener
{
@ -89,8 +84,8 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXTFELEMENT
NS_DECL_NSIXTFGENERICELEMENT
NS_DECL_NSIXTFPRIVATE
NS_DECL_NSIXFORMSMODELELEMENT
NS_DECL_NSIMODELELEMENTPRIVATE
NS_DECL_NSISCHEMALOADLISTENER
NS_DECL_NSIWEBSERVICEERRORHANDLER
NS_DECL_NSIDOMEVENTLISTENER
@ -102,30 +97,20 @@ public:
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
NS_IMETHOD Error(nsIDOMEvent* aEvent);
NS_HIDDEN_(nsresult) DispatchEvent(nsXFormsModelEvent aEvent);
NS_HIDDEN_(already_AddRefed<nsISchemaType>)
GetTypeForControl(nsXFormsControl *aControl);
NS_HIDDEN_(void) AddFormControl(nsXFormsControl *aControl);
NS_HIDDEN_(void) RemoveFormControl(nsXFormsControl *aControl);
NS_HIDDEN_(void) AddPendingInstance() { ++mPendingInstanceCount; }
NS_HIDDEN_(void) RemovePendingInstance();
NS_HIDDEN_(nsXFormsInstanceElement*) FindInstanceElement(const nsAString &aID);
NS_HIDDEN_(nsIDOMDocument*) FindInstanceDocument(const nsAString &aID);
NS_HIDDEN_(PRBool) IsSubmissionActive() { return mSubmissionActive; }
NS_HIDDEN_(void) SetSubmissionActive(PRBool val) { mSubmissionActive = val; }
// Called after nsXFormsAtoms is registered
static NS_HIDDEN_(void) Startup();
private:
NS_HIDDEN_(nsresult) DispatchEvent(nsXFormsModelEvent aEvent);
NS_HIDDEN_(already_AddRefed<nsIDOMDocument>)
FindInstanceDocument(const nsAString &aID);
NS_HIDDEN_(nsresult) FinishConstruction();
NS_HIDDEN_(PRBool) ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
nsIDOMNode *aContextNode,
nsIDOMXPathResult *aOuterNodeset,
nsIDOMElement *aBindElement);
NS_HIDDEN_(void) RemoveModelFromDocument();

View File

@ -40,6 +40,7 @@
#include "nsXFormsElementFactory.h"
#include "nsXFormsAtoms.h"
#include "nsXFormsModelElement.h"
#include "nsXFormsUtils.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXFormsElementFactory)

View File

@ -41,6 +41,7 @@
#include "nsIDOMEventTarget.h"
#include "nsIDOM3Node.h"
#include "nsMemory.h"
#include "nsXFormsUtils.h"
static const nsIID sScriptingIIDs[] = {
NS_IDOMELEMENT_IID,
@ -73,9 +74,9 @@ nsXFormsStubElement::GetIsAttributeHandler(PRBool *aIsAttributeHandler)
NS_IMETHODIMP
nsXFormsStubElement::GetScriptingInterfaces(PRUint32 *aCount, nsIID ***aArray)
{
return CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
return nsXFormsUtils::CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
}
NS_IMETHODIMP

View File

@ -40,10 +40,8 @@
#define nsXFormsStubElement_h_
#include "nsIXTFGenericElement.h"
#include "nsXFormsElement.h"
class nsXFormsStubElement : public nsXFormsElement,
public nsIXTFGenericElement
class nsXFormsStubElement : public nsIXTFGenericElement
{
NS_DECL_ISUPPORTS
NS_DECL_NSIXTFELEMENT

View File

@ -45,11 +45,8 @@
#include <stdlib.h>
#include "nsXFormsModelElement.h"
#include "nsXFormsInstanceElement.h"
#include "nsXFormsSubmissionElement.h"
#include "nsXFormsAtoms.h"
#include "nsIXFormsModelElement.h"
#include "nsIInstanceElementPrivate.h"
#include "nsIXTFGenericElementWrapper.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
@ -61,9 +58,6 @@
#include "nsIDOM3Node.h"
#include "nsIDOMXMLDocument.h"
#include "nsIDOMXPathResult.h"
#include "nsIDOMXPathEvaluator.h"
#include "nsIDOMXPathNSResolver.h"
#include "nsIDOMXPathExpression.h"
#include "nsIDOMSerializer.h"
#include "nsIDOMDOMImplementation.h"
#include "nsIDOMProcessingInstruction.h"
@ -89,6 +83,7 @@
#include "nsMemory.h"
#include "nsCOMPtr.h"
#include "nsNetUtil.h"
#include "nsXFormsUtils.h"
// namespace literals
#define NAMESPACE_XML_SCHEMA \
@ -272,9 +267,9 @@ nsXFormsSubmissionElement::GetIsAttributeHandler(PRBool *aIsAttributeHandler)
NS_IMETHODIMP
nsXFormsSubmissionElement::GetScriptingInterfaces(PRUint32 *aCount, nsIID ***aArray)
{
return CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
return nsXFormsUtils::CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
}
NS_IMETHODIMP
@ -448,26 +443,16 @@ nsXFormsSubmissionElement::OnStopRequest(nsIRequest *request, nsISupports *ctx,
// private methods
nsXFormsModelElement*
already_AddRefed<nsIModelElementPrivate>
nsXFormsSubmissionElement::GetModel()
{
nsCOMPtr<nsIDOMNode> parentNode;
mElement->GetParentNode(getter_AddRefs(parentNode));
nsCOMPtr<nsIXFormsModelElement> modelElt = do_QueryInterface(parentNode);
if (!modelElt)
return nsnull;
nsCOMPtr<nsIXTFPrivate> xtfPriv = do_QueryInterface(modelElt);
NS_ENSURE_TRUE(xtfPriv, nsnull);
nsCOMPtr<nsISupports> modelInner;
xtfPriv->GetInner(getter_AddRefs(modelInner));
NS_ENSURE_TRUE(modelInner, nsnull);
nsISupports *isupp = NS_STATIC_CAST(nsISupports*, modelInner.get());
return NS_STATIC_CAST(nsXFormsModelElement*,
NS_STATIC_CAST(nsIXFormsModelElement*, isupp));
nsIModelElementPrivate *model = nsnull;
if (parentNode)
CallQueryInterface(parentNode, &model);
return model;
}
nsresult
@ -510,9 +495,14 @@ nsXFormsSubmissionElement::LoadReplaceInstance(nsIChannel *channel)
}
}
nsXFormsInstanceElement *instance =
GetModel()->FindInstanceElement(EmptyString());
instance->SetDocument(newDoc);
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
if (model) {
nsCOMPtr<nsIInstanceElementPrivate> instance;
model->FindInstanceElement(EmptyString(), getter_AddRefs(instance));
if (instance) {
instance->SetDocument(newDoc);
}
}
return NS_OK;
}
@ -553,8 +543,12 @@ nsXFormsSubmissionElement::Submit()
nsresult rv;
// 1. ensure that we are not currently processing a xforms-submit on our model
nsXFormsModelElement *model = GetModel();
NS_ENSURE_STATE(!model->IsSubmissionActive());
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
PRBool submissionActive = PR_FALSE;
model->GetSubmissionActive(&submissionActive);
NS_ENSURE_STATE(!submissionActive);
model->SetSubmissionActive(PR_TRUE);
@ -595,7 +589,8 @@ nsXFormsSubmissionElement::SubmitEnd(PRBool succeeded)
{
LOG(("xforms submission complete [succeeded=%d]\n", succeeded));
GetModel()->SetSubmissionActive(PR_FALSE);
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
model->SetSubmissionActive(PR_FALSE);
nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
@ -628,60 +623,18 @@ nsXFormsSubmissionElement::SubmitEnd(PRBool succeeded)
nsresult
nsXFormsSubmissionElement::GetSelectedInstanceData(nsIDOMNode **result)
{
// XXX need to support 'instance(id)' xpath function. for now, we assume
// that any xpath expression is relative to the first <instance> element.
nsCOMPtr<nsIDOMNode> model;
nsCOMPtr<nsIDOMElement> bind;
nsCOMPtr<nsIDOMXPathResult> xpRes =
nsXFormsUtils::EvaluateNodeBinding(mElement,
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
getter_AddRefs(model),
getter_AddRefs(bind));
nsCOMPtr<nsIDOMNode> instance;
GetDefaultInstanceData(getter_AddRefs(instance));
NS_ENSURE_TRUE(instance, NS_ERROR_UNEXPECTED);
if (!xpRes)
return NS_ERROR_UNEXPECTED;
nsAutoString value;
mElement->GetAttribute(NS_LITERAL_STRING("bind"), value);
if (value.IsEmpty())
{
// inspect 'ref' attribute
mElement->GetAttribute(NS_LITERAL_STRING("ref"), value);
}
else
{
// ok, value contains the 'ID' of a <bind> element.
nsCOMPtr<nsIDOMDocument> doc;
mElement->GetOwnerDocument(getter_AddRefs(doc));
nsCOMPtr<nsIDOMElement> bindElement;
doc->GetElementById(value, getter_AddRefs(bindElement));
NS_ENSURE_TRUE(bindElement, NS_ERROR_UNEXPECTED);
bindElement->GetAttribute(NS_LITERAL_STRING("nodeset"), value);
}
if (value.IsEmpty())
{
// select first <instance> element
// instance->GetFirstChild(result);
NS_ADDREF(*result = instance);
return NS_OK;
}
// evaluate 'value' as an xpath expression
nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDOMXPathEvaluator> xpath = do_QueryInterface(domDoc);
NS_ENSURE_TRUE(xpath, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIDOMXPathNSResolver> resolver;
xpath->CreateNSResolver(instance, getter_AddRefs(resolver));
NS_ENSURE_TRUE(resolver, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsISupports> xpathResult;
xpath->Evaluate(value, instance, resolver,
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, nsnull,
getter_AddRefs(xpathResult));
nsCOMPtr<nsIDOMXPathResult> nodeset = do_QueryInterface(xpathResult);
NS_ENSURE_TRUE(nodeset, NS_ERROR_UNEXPECTED);
return nodeset->GetSingleNodeValue(result);
return xpRes->GetSingleNodeValue(result);
}
PRBool

View File

@ -42,10 +42,9 @@
#include "nsIXTFGenericElement.h"
#include "nsIRequestObserver.h"
#include "nsIInputStream.h"
#include "nsXFormsElement.h"
#include "nsCOMPtr.h"
#include "nsIModelElementPrivate.h"
class nsXFormsModelElement;
class nsIMultiplexInputStream;
class nsIDOMElement;
class nsIChannel;
@ -55,8 +54,7 @@ class nsString;
class SubmissionAttachmentArray;
class nsXFormsSubmissionElement : public nsXFormsElement,
public nsIXTFGenericElement,
class nsXFormsSubmissionElement : public nsIXTFGenericElement,
public nsIRequestObserver
{
public:
@ -69,7 +67,7 @@ public:
: mElement(nsnull)
{}
NS_HIDDEN_(nsXFormsModelElement *) GetModel();
NS_HIDDEN_(already_AddRefed<nsIModelElementPrivate>) GetModel();
NS_HIDDEN_(nsresult) LoadReplaceInstance(nsIChannel *);
NS_HIDDEN_(nsresult) LoadReplaceAll(nsIChannel *);

View File

@ -0,0 +1,312 @@
/* -*- 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 "nsXFormsUtils.h"
#include "nsString.h"
#include "nsXFormsAtoms.h"
#include "nsIDOMElement.h"
#include "nsIDocument.h"
#include "nsINameSpaceManager.h"
#include "nsINodeInfo.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXPathEvaluator.h"
#include "nsIDOMXPathResult.h"
#include "nsIDOMXPathNSResolver.h"
#include "nsIDOMDocument.h"
#include "nsIXFormsModelElement.h"
/* static */ nsIDOMNode*
nsXFormsUtils::GetModelAndBind(nsIDOMElement *aElement,
nsIDOMElement **aBindElement)
{
*aBindElement = nsnull;
NS_ENSURE_TRUE(aElement, nsnull);
nsCOMPtr<nsIDOMDocument> domDoc;
aElement->GetOwnerDocument(getter_AddRefs(domDoc));
if (!domDoc)
return nsnull;
nsAutoString bindId;
aElement->GetAttribute(NS_LITERAL_STRING("bind"), bindId);
nsCOMPtr<nsIDOMNode> modelWrapper;
if (!bindId.IsEmpty()) {
// Get the bind element with the given id.
domDoc->GetElementById(bindId, aBindElement);
if (*aBindElement) {
// Walk up the tree looking for the containing model.
(*aBindElement)->GetParentNode(getter_AddRefs(modelWrapper));
nsAutoString localName, namespaceURI;
nsCOMPtr<nsIDOMNode> temp;
while (modelWrapper) {
modelWrapper->GetLocalName(localName);
if (localName.EqualsLiteral("model")) {
modelWrapper->GetNamespaceURI(namespaceURI);
if (namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS))
break;
}
temp.swap(modelWrapper);
temp->GetParentNode(getter_AddRefs(modelWrapper));
}
}
} else {
// If no bind was given, we use model.
nsAutoString modelId;
aElement->GetAttribute(NS_LITERAL_STRING("model"), modelId);
if (modelId.IsEmpty()) {
// No model given, so use the first one in the document.
nsCOMPtr<nsIDOMNodeList> nodes;
domDoc->GetElementsByTagNameNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS),
NS_LITERAL_STRING("model"),
getter_AddRefs(nodes));
if (!nodes)
return nsnull;
nodes->Item(0, getter_AddRefs(modelWrapper));
} else {
nsCOMPtr<nsIDOMElement> wrapperElement;
domDoc->GetElementById(modelId, getter_AddRefs(wrapperElement));
modelWrapper = wrapperElement;
}
}
// We're releasing this reference, but the node is owned by the DOM.
return modelWrapper;
}
/* static */ already_AddRefed<nsIDOMXPathResult>
nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
nsIDOMNode *aContextNode,
nsIDOMNode *aResolverNode,
PRUint16 aResultType)
{
nsCOMPtr<nsIDOMDocument> doc;
aContextNode->GetOwnerDocument(getter_AddRefs(doc));
NS_ENSURE_TRUE(doc, nsnull);
nsCOMPtr<nsIDOMXPathEvaluator> eval = do_QueryInterface(doc);
NS_ENSURE_TRUE(eval, nsnull);
nsCOMPtr<nsIDOMXPathNSResolver> resolver;
eval->CreateNSResolver(aResolverNode, getter_AddRefs(resolver));
NS_ENSURE_TRUE(resolver, nsnull);
nsCOMPtr<nsISupports> supResult;
eval->Evaluate(aExpression, aContextNode, resolver, aResultType, nsnull,
getter_AddRefs(supResult));
nsIDOMXPathResult *result = nsnull;
if (supResult)
CallQueryInterface(supResult, &result); // addrefs
return result;
}
/* static */ already_AddRefed<nsIDOMNode>
nsXFormsUtils::FindBindContext(nsIDOMElement *aElement,
nsIXFormsModelElement *aModel)
{
// Figure out the context node for this <bind>.
// The outermost bind has the root element of the [first] instance document
// as its context node. For inner binds, the first node in the nodeset
// of the parent is used as the context node.
nsCOMPtr<nsIDOMNode> modelNode = do_QueryInterface(aModel);
nsCOMPtr<nsIDOMNode> parentNode;
aElement->GetParentNode(getter_AddRefs(parentNode));
if (!parentNode)
return nsnull; // illegal, a bind must be contained in a model.
if (parentNode == modelNode) {
// This is the outermost bind.
nsCOMPtr<nsIDOMDocument> instanceDoc;
aModel->GetInstanceDocument(NS_LITERAL_STRING(""),
getter_AddRefs(instanceDoc));
if (!instanceDoc)
return nsnull;
nsIDOMElement *docElement = nsnull;
instanceDoc->GetDocumentElement(&docElement); // addrefs
return docElement;
}
// The context node is the first node in the nodeset of the parent bind.
nsCOMPtr<nsIDOMXPathResult> parentNodeSet =
EvaluateNodeset(nsCOMPtr<nsIDOMElement>(do_QueryInterface(parentNode)),
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE);
nsIDOMNode *nodeResult = nsnull;
if (parentNodeSet)
parentNodeSet->GetSingleNodeValue(&nodeResult); // addrefs
return nodeResult;
}
/* static */ already_AddRefed<nsIDOMXPathResult>
nsXFormsUtils::EvaluateNodeset(nsIDOMElement *aElement, PRUint16 aResultType)
{
// The first thing we need to do is ensure that we have a nodeset attribute.
// If we don't, we walk up and check for it on outer bind elements.
// While we're walking up, we also locate the model element.
nsCOMPtr<nsIXFormsModelElement> model;
nsCOMPtr<nsIDOMElement> bindElement, element = aElement;
nsCOMPtr<nsIDOMNode> temp;
nsAutoString nodeset;
while (element) {
model = do_QueryInterface(element);
if (model)
break;
if (!bindElement) {
element->GetAttribute(NS_LITERAL_STRING("nodeset"), nodeset);
if (!nodeset.IsEmpty()) {
// Verify that this is a <bind> element;
nsAutoString value;
element->GetNamespaceURI(value);
if (value.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
element->GetLocalName(value);
if (value.EqualsLiteral("bind")) {
bindElement = element;
}
}
}
}
element->GetParentNode(getter_AddRefs(temp));
element = do_QueryInterface(temp);
}
if (!bindElement || !model)
return nsnull;
nsCOMPtr<nsIDOMNode> contextNode = FindBindContext(bindElement, model);
if (!contextNode)
return nsnull;
return EvaluateXPath(nodeset, contextNode, bindElement, aResultType);
}
/* static */ already_AddRefed<nsIDOMXPathResult>
nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement,
PRUint16 aResultType,
nsIDOMNode **aModel,
nsIDOMElement **aBind)
{
// A control may be attached to a model by either using the 'bind'
// attribute to give the id of a bind element, or using the 'model'
// attribute to give the id of a model. If neither of these are given,
// the control belongs to the first model in the document.
*aBind = nsnull;
NS_IF_ADDREF(*aModel = GetModelAndBind(aElement, aBind));
if (!*aModel)
return nsnull;
// If there is a bind element, we just evaluate its nodeset.
if (*aBind)
return EvaluateNodeset(*aBind, aResultType);
// If not, we expect there to be a ref attribute.
nsAutoString expr;
aElement->GetAttribute(NS_LITERAL_STRING("ref"), expr);
if (expr.IsEmpty())
return nsnull;
// Get the instance data and evaluate the xpath expression.
// XXXfixme when xpath extensions are implemented (instance())
nsCOMPtr<nsIDOMDocument> instanceDoc;
nsCOMPtr<nsIXFormsModelElement> model = do_QueryInterface(*aModel);
if (!model) {
// The referenced model is not actually a model element, or does not exist.
return nsnull;
}
model->GetInstanceDocument(NS_LITERAL_STRING(""),
getter_AddRefs(instanceDoc));
if (!instanceDoc)
return nsnull;
nsCOMPtr<nsIDOMElement> docElement;
instanceDoc->GetDocumentElement(getter_AddRefs(docElement));
if (!docElement)
return nsnull; // this will happen if the doc is still loading
return EvaluateXPath(expr, docElement, aElement, aResultType);
}
/* static */ nsresult
nsXFormsUtils::CloneScriptingInterfaces(const nsIID *aIIDList,
unsigned int aIIDCount,
PRUint32 *aOutCount,
nsIID ***aOutArray)
{
nsIID **iids = NS_STATIC_CAST(nsIID**,
nsMemory::Alloc(aIIDCount * sizeof(nsIID*)));
if (!iids) {
return NS_ERROR_OUT_OF_MEMORY;
}
for (PRUint32 i = 0; i < aIIDCount; ++i) {
iids[i] = NS_STATIC_CAST(nsIID*,
nsMemory::Clone(&aIIDList[i], sizeof(nsIID)));
if (!iids[i]) {
for (PRUint32 j = 0; j < i; ++j)
nsMemory::Free(iids[j]);
nsMemory::Free(iids);
return NS_ERROR_OUT_OF_MEMORY;
}
}
*aOutArray = iids;
*aOutCount = aIIDCount;
return NS_OK;
}

View File

@ -0,0 +1,124 @@
/* -*- 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 ***** */
#ifndef nsXFormsUtils_h_
#define nsXFormsUtils_h_
/**
* This class has static helper methods that don't fit into a specific place
* in the class hierarchy.
*/
#include "prtypes.h"
#include "nsCOMPtr.h"
#include "nsIDOMXPathResult.h"
class nsIDOMNode;
class nsIDOMElement;
class nsIXFormsModelElement;
#define NS_NAMESPACE_XFORMS "http://www.w3.org/2002/xforms"
#define NS_NAMESPACE_XHTML "http://www.w3.org/1999/xhtml"
class nsXFormsUtils
{
public:
/**
* Locate the model that |aElement| is bound to, and if applicable, the
* <bind> element that it uses. The model is returned and the
* bind element is returned (addrefed) in |aBindElement|.
*/
static NS_HIDDEN_(nsIDOMNode*)
GetModelAndBind(nsIDOMElement *aElement, nsIDOMElement **aBindElement);
/**
* Evaluate a 'bind' or 'ref' attribute on |aElement|. |aResultType| is
* used as the desired result type for the XPath evaluation. The model and
* bind elements (if applicable) are located as part of this evaluation,
* and are returned (addrefed) in |aModel| and |aBind|.
*
* The return value is an XPathResult as returned from
* nsIDOMXPathEvaluator::Evaluate().
*/
static NS_HIDDEN_(already_AddRefed<nsIDOMXPathResult>)
EvaluateNodeBinding(nsIDOMElement *aElement,
PRUint16 aResultType,
nsIDOMNode **aModel,
nsIDOMElement **aBind);
/**
* Given a bind element |aElement|, return the nodeset that it applies to.
* |aResultType| is used as the desired result type for the XPath
* evaluation.
*/
static NS_HIDDEN_(already_AddRefed<nsIDOMXPathResult>)
EvaluateNodeset(nsIDOMElement *aElement, PRUint16 aResultType);
/**
* Given a bind element |aElement|, find the context node to be used
* for evaluating its nodeset.
*/
static NS_HIDDEN_(already_AddRefed<nsIDOMNode>)
FindBindContext(nsIDOMElement *aBindElement,
nsIXFormsModelElement *aModelElement);
/**
* Convenience method for doing XPath evaluations. This gets a
* nsIDOMXPathEvaluator from |aContextNode|'s ownerDocument, and calls
* nsIDOMXPathEvaluator::Evalute using the given expression, context node,
* namespace resolver, and result type.
*/
static NS_HIDDEN_(already_AddRefed<nsIDOMXPathResult>)
EvaluateXPath(const nsAString &aExpression,
nsIDOMNode *aContextNode,
nsIDOMNode *aResolverNode,
PRUint16 aResultType);
/**
* Clone the set of IIDs in |aIIDList| into |aOutArray|.
* |aOutCount| is set to |aIIDCount|.
*/
static NS_HIDDEN_(nsresult) CloneScriptingInterfaces(const nsIID *aIIDList,
unsigned int aIIDCount,
PRUint32 *aOutCount,
nsIID ***aOutArray);
};
#endif