зеркало из https://github.com/mozilla/gecko-dev.git
fixes bug 265216 "Tracking bug for XForms Group Module" patch by allan@beaufour.dk r=bryner
This commit is contained in:
Родитель
30fd3c6d9a
Коммит
898bfde5e8
|
@ -1,3 +1,4 @@
|
||||||
|
# vim:set ts=8 sw=8 sts=8 noet:
|
||||||
#
|
#
|
||||||
# ***** BEGIN LICENSE BLOCK *****
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
@ -70,6 +71,7 @@ XPIDLSRCS = \
|
||||||
nsIInstanceElementPrivate.idl \
|
nsIInstanceElementPrivate.idl \
|
||||||
nsIModelElementPrivate.idl \
|
nsIModelElementPrivate.idl \
|
||||||
nsIXFormsControl.idl \
|
nsIXFormsControl.idl \
|
||||||
|
nsIXFormsContextControl.idl \
|
||||||
nsIXFormsActionElement.idl \
|
nsIXFormsActionElement.idl \
|
||||||
nsIXFormsActionModuleElement.idl \
|
nsIXFormsActionModuleElement.idl \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
@ -79,6 +81,7 @@ CPPSRCS = \
|
||||||
nsXFormsUtils.cpp \
|
nsXFormsUtils.cpp \
|
||||||
nsXFormsModelElement.cpp \
|
nsXFormsModelElement.cpp \
|
||||||
nsXFormsInputElement.cpp \
|
nsXFormsInputElement.cpp \
|
||||||
|
nsXFormsGroupElement.cpp \
|
||||||
nsXFormsOutputElement.cpp \
|
nsXFormsOutputElement.cpp \
|
||||||
nsXFormsTriggerElement.cpp \
|
nsXFormsTriggerElement.cpp \
|
||||||
nsXFormsSubmissionElement.cpp \
|
nsXFormsSubmissionElement.cpp \
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* -*- 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
|
||||||
|
* Novell, Inc.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Allan Beaufour <abeaufour@novell.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 "nsISupports.idl"
|
||||||
|
|
||||||
|
interface nsIDOMElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for elements that sets the XPath context of its children.
|
||||||
|
*/
|
||||||
|
[uuid(38a904ba-147c-4c7f-9356-9fff88107868)]
|
||||||
|
interface nsIXFormsContextControl : nsISupports
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Used by children to retrieve the context of their parent.
|
||||||
|
*
|
||||||
|
* @param aModelID The modelID
|
||||||
|
* @param aContextNode The context node
|
||||||
|
* @param aContextPosition The context position
|
||||||
|
* @param aContextSize The context size
|
||||||
|
*
|
||||||
|
* @note The actual model ID must be returned. An empty |aModelID| should
|
||||||
|
* only be returned if the default model has an id="".
|
||||||
|
*/
|
||||||
|
void getContext(out AString aModelID, out nsIDOMElement aContextNode, out long aContextPosition, out long aContextSize);
|
||||||
|
};
|
|
@ -45,6 +45,7 @@
|
||||||
|
|
||||||
// Form controls
|
// Form controls
|
||||||
NS_HIDDEN_(nsresult) NS_NewXFormsInputElement(nsIXTFElement **aElement);
|
NS_HIDDEN_(nsresult) NS_NewXFormsInputElement(nsIXTFElement **aElement);
|
||||||
|
NS_HIDDEN_(nsresult) NS_NewXFormsGroupElement(nsIXTFElement **aElement);
|
||||||
NS_HIDDEN_(nsresult) NS_NewXFormsOutputElement(nsIXTFElement **aElement);
|
NS_HIDDEN_(nsresult) NS_NewXFormsOutputElement(nsIXTFElement **aElement);
|
||||||
NS_HIDDEN_(nsresult) NS_NewXFormsTriggerElement(nsIXTFElement **aElement);
|
NS_HIDDEN_(nsresult) NS_NewXFormsTriggerElement(nsIXTFElement **aElement);
|
||||||
NS_HIDDEN_(nsresult) NS_NewXFormsSubmitElement(nsIXTFElement **aElement);
|
NS_HIDDEN_(nsresult) NS_NewXFormsSubmitElement(nsIXTFElement **aElement);
|
||||||
|
@ -77,6 +78,8 @@ nsXFormsElementFactory::CreateElement(const nsAString& aTagName,
|
||||||
return NS_NewXFormsStubElement(aElement);
|
return NS_NewXFormsStubElement(aElement);
|
||||||
if (aTagName.EqualsLiteral("input"))
|
if (aTagName.EqualsLiteral("input"))
|
||||||
return NS_NewXFormsInputElement(aElement);
|
return NS_NewXFormsInputElement(aElement);
|
||||||
|
if (aTagName.EqualsLiteral("group"))
|
||||||
|
return NS_NewXFormsGroupElement(aElement);
|
||||||
if (aTagName.EqualsLiteral("output"))
|
if (aTagName.EqualsLiteral("output"))
|
||||||
return NS_NewXFormsOutputElement(aElement);
|
return NS_NewXFormsOutputElement(aElement);
|
||||||
if (aTagName.EqualsLiteral("label"))
|
if (aTagName.EqualsLiteral("label"))
|
||||||
|
|
|
@ -0,0 +1,343 @@
|
||||||
|
/* -*- 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
|
||||||
|
* Novell, Inc.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Allan Beaufour <abeaufour@novell.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 "nsAutoPtr.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
|
||||||
|
#include "nsIDOM3Node.h"
|
||||||
|
#include "nsIDOMElement.h"
|
||||||
|
#include "nsIDOMDocument.h"
|
||||||
|
#include "nsIDOMEventTarget.h"
|
||||||
|
#include "nsIDOMXPathResult.h"
|
||||||
|
#include "nsIDOMHTMLDivElement.h"
|
||||||
|
|
||||||
|
#include "nsIXTFXMLVisual.h"
|
||||||
|
#include "nsIXTFXMLVisualWrapper.h"
|
||||||
|
|
||||||
|
#include "nsIXFormsControl.h"
|
||||||
|
#include "nsIXFormsContextControl.h"
|
||||||
|
#include "nsIModelElementPrivate.h"
|
||||||
|
#include "nsXFormsAtoms.h"
|
||||||
|
#include "nsXFormsStubElement.h"
|
||||||
|
#include "nsXFormsUtils.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// #define DEBUG_XF_GROUP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the XForms \<group\> control.
|
||||||
|
*
|
||||||
|
* @see http://www.w3.org/TR/xforms/slice9.html#id2631290
|
||||||
|
*
|
||||||
|
* @todo If a \<label\> is the first element child for \<group\> it is the
|
||||||
|
* label for the entire group
|
||||||
|
*
|
||||||
|
* @todo "Setting the input focus on a group results in the focus being set to
|
||||||
|
* the first form control in the navigation order within that group."
|
||||||
|
* (spec. 9.1.1)
|
||||||
|
*
|
||||||
|
* @bug If a group only has a model attribute, the group fails to set this for
|
||||||
|
* children, as it is impossible to distinguish between a failure and absence
|
||||||
|
* of binding attributes when calling EvaluateNodeBinding().
|
||||||
|
*/
|
||||||
|
class nsXFormsGroupElement : public nsIXFormsControl,
|
||||||
|
public nsXFormsXMLVisualStub,
|
||||||
|
public nsIXFormsContextControl
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/** The DOM element for the node */
|
||||||
|
nsCOMPtr<nsIDOMElement> mElement;
|
||||||
|
|
||||||
|
/** The UI HTML element used to represent the tag */
|
||||||
|
nsCOMPtr<nsIDOMHTMLDivElement> mHTMLElement;
|
||||||
|
|
||||||
|
/** Have DoneAddingChildren() been called? */
|
||||||
|
PRBool mDoneAddingChildren;
|
||||||
|
|
||||||
|
/** The context node for the children of this element */
|
||||||
|
nsCOMPtr<nsIDOMElement> mContextNode;
|
||||||
|
|
||||||
|
/** The current ID of the model node is bound to */
|
||||||
|
nsString mModelID;
|
||||||
|
|
||||||
|
/** Process element */
|
||||||
|
nsresult Process();
|
||||||
|
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
nsXFormsGroupElement();
|
||||||
|
~nsXFormsGroupElement();
|
||||||
|
|
||||||
|
// nsIXTFXMLVisual overrides
|
||||||
|
NS_IMETHOD OnCreated(nsIXTFXMLVisualWrapper *aWrapper);
|
||||||
|
|
||||||
|
// nsIXTFVisual overrides
|
||||||
|
NS_IMETHOD GetVisualContent(nsIDOMElement **aElement);
|
||||||
|
NS_IMETHOD GetInsertionPoint(nsIDOMElement **aElement);
|
||||||
|
|
||||||
|
// nsIXTFElement overrides
|
||||||
|
NS_IMETHOD OnDestroyed();
|
||||||
|
NS_IMETHOD WillSetAttribute(nsIAtom *aName, const nsAString &aValue);
|
||||||
|
NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue);
|
||||||
|
NS_IMETHOD DoneAddingChildren();
|
||||||
|
|
||||||
|
// nsIXFormsControl
|
||||||
|
NS_DECL_NSIXFORMSCONTROL
|
||||||
|
|
||||||
|
// nsIXFormsContextControl
|
||||||
|
NS_DECL_NSIXFORMSCONTEXTCONTROL
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsGroupElement,
|
||||||
|
nsXFormsXMLVisualStub,
|
||||||
|
nsIXFormsControl,
|
||||||
|
nsIXFormsContextControl)
|
||||||
|
|
||||||
|
MOZ_DECL_CTOR_COUNTER(nsXFormsGroupElement)
|
||||||
|
|
||||||
|
nsXFormsGroupElement::nsXFormsGroupElement()
|
||||||
|
: mElement(nsnull)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(nsXFormsGroupElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXFormsGroupElement::~nsXFormsGroupElement()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(nsXFormsGroupElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
// nsIXTFXMLVisual
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsGroupElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_XF_GROUP
|
||||||
|
printf("nsXFormsGroupElement::OnCreated(aWrapper=%p)\n", (void*) aWrapper);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialize member(s)
|
||||||
|
nsCOMPtr<nsIDOMElement> node;
|
||||||
|
aWrapper->GetElementNode(getter_AddRefs(node));
|
||||||
|
mElement = node;
|
||||||
|
NS_ASSERTION(mElement, "Wrapper is not an nsIDOMElement, we'll crash soon");
|
||||||
|
|
||||||
|
mDoneAddingChildren = PR_FALSE;
|
||||||
|
|
||||||
|
// Create HTML tag
|
||||||
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||||
|
node->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMElement> domElement;
|
||||||
|
domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
|
||||||
|
NS_LITERAL_STRING("div"),
|
||||||
|
getter_AddRefs(domElement));
|
||||||
|
|
||||||
|
mHTMLElement = do_QueryInterface(domElement);
|
||||||
|
NS_ENSURE_TRUE(mHTMLElement, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
// Setup which notifications to receive
|
||||||
|
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN |
|
||||||
|
nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
|
||||||
|
nsIXTFElement::NOTIFY_WILL_SET_ATTRIBUTE);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nsIXTFVisual
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsGroupElement::GetVisualContent(nsIDOMElement * *aVisualContent)
|
||||||
|
{
|
||||||
|
NS_ADDREF(*aVisualContent = mHTMLElement);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsGroupElement::GetInsertionPoint(nsIDOMElement **aElement)
|
||||||
|
{
|
||||||
|
NS_ADDREF(*aElement = mHTMLElement);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nsIXTFElement
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsGroupElement::OnDestroyed()
|
||||||
|
{
|
||||||
|
mHTMLElement = nsnull;
|
||||||
|
mContextNode = nsnull;
|
||||||
|
mElement = nsnull;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsGroupElement::WillSetAttribute(nsIAtom *aName, const nsAString& aNewValue)
|
||||||
|
{
|
||||||
|
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
|
||||||
|
nsCOMPtr<nsIDOMNode> modelNode = nsXFormsUtils::GetModel(mElement);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIModelElementPrivate> model = do_QueryInterface(modelNode);
|
||||||
|
if (model) {
|
||||||
|
model->RemoveFormControl(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsGroupElement::AttributeSet(nsIAtom *aName, const nsAString& aNewValue)
|
||||||
|
{
|
||||||
|
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXFormsGroupElement::DoneAddingChildren()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_XF_GROUP
|
||||||
|
printf("nsXFormsGroupElement::DoneAddingChildren()\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mDoneAddingChildren = PR_TRUE;
|
||||||
|
Refresh();
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nsXFormsControl
|
||||||
|
nsresult
|
||||||
|
nsXFormsGroupElement::Refresh()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_XF_GROUP
|
||||||
|
printf("nsXFormsGroupElement::Refresh(mDoneAddingChildren=%d)\n", mDoneAddingChildren);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
if (mDoneAddingChildren) {
|
||||||
|
rv = Process();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nsXFormsGroupElement
|
||||||
|
nsresult
|
||||||
|
nsXFormsGroupElement::Process()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_XF_GROUP
|
||||||
|
printf("nsXFormsGroupElement::Process()\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mModelID.Truncate();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
// Get model ID
|
||||||
|
nsCOMPtr<nsIDOMElement> modelElement = do_QueryInterface(modelNode);
|
||||||
|
NS_ENSURE_TRUE(modelElement, NS_ERROR_FAILURE);
|
||||||
|
modelElement->GetAttribute(NS_LITERAL_STRING("id"), mModelID);
|
||||||
|
|
||||||
|
// Get context node, if any
|
||||||
|
nsCOMPtr<nsIDOMNode> singleNode;
|
||||||
|
result->GetSingleNodeValue(getter_AddRefs(singleNode));
|
||||||
|
mContextNode = do_QueryInterface(singleNode);
|
||||||
|
NS_ENSURE_TRUE(mContextNode, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nsIXFormsContextControl
|
||||||
|
nsresult
|
||||||
|
nsXFormsGroupElement::GetContext(nsAString& aModelID,
|
||||||
|
nsIDOMElement **aContextNode,
|
||||||
|
PRInt32 *aContextPosition,
|
||||||
|
PRInt32 *aContextSize)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_XF_GROUP
|
||||||
|
printf("nsXFormsGroupElement::GetContext()\n");
|
||||||
|
#endif
|
||||||
|
NS_ENSURE_ARG(aContextSize);
|
||||||
|
NS_ENSURE_ARG(aContextPosition);
|
||||||
|
|
||||||
|
/** @todo Not too elegant to call Process() here, but DoneAddingChildren is,
|
||||||
|
* logically, called on children before us. We need a notification
|
||||||
|
* that goes from the document node and DOWN, where the controls
|
||||||
|
* should Refresh().
|
||||||
|
*/
|
||||||
|
*aContextPosition = 1;
|
||||||
|
*aContextSize = 1;
|
||||||
|
|
||||||
|
nsresult rv = Process();
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
NS_IF_ADDREF(*aContextNode = mContextNode);
|
||||||
|
aModelID = mModelID;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Factory
|
||||||
|
NS_HIDDEN_(nsresult)
|
||||||
|
NS_NewXFormsGroupElement(nsIXTFElement **aResult)
|
||||||
|
{
|
||||||
|
*aResult = new nsXFormsGroupElement();
|
||||||
|
if (!*aResult)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
NS_ADDREF(*aResult);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
|
@ -216,13 +216,9 @@ NS_IMETHODIMP
|
||||||
nsXFormsInputElement::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
|
nsXFormsInputElement::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
|
||||||
{
|
{
|
||||||
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
|
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
|
||||||
nsCOMPtr<nsIDOMElement> bindElement;
|
nsCOMPtr<nsIDOMNode> modelNode = nsXFormsUtils::GetModel(mElement);
|
||||||
nsCOMPtr<nsIModelElementPrivate> model;
|
|
||||||
|
|
||||||
model = do_QueryInterface(
|
nsCOMPtr<nsIModelElementPrivate> model = do_QueryInterface(modelNode);
|
||||||
nsXFormsUtils::GetModelAndBind(mElement,
|
|
||||||
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
|
|
||||||
getter_AddRefs(bindElement)));
|
|
||||||
if (model)
|
if (model)
|
||||||
model->RemoveFormControl(this);
|
model->RemoveFormControl(this);
|
||||||
}
|
}
|
||||||
|
@ -315,6 +311,10 @@ nsXFormsInputElement::Refresh()
|
||||||
|
|
||||||
nsCOMPtr<nsIModelElementPrivate> model = do_QueryInterface(modelNode);
|
nsCOMPtr<nsIModelElementPrivate> model = do_QueryInterface(modelNode);
|
||||||
|
|
||||||
|
// @bug / todo: If \<input\> has binding attributes that are invalid, we
|
||||||
|
// should clear the content. But the content should be left if the element
|
||||||
|
// is unbound.
|
||||||
|
// @see https://bugzilla.mozilla.org/show_bug.cgi?id=265216
|
||||||
if (model) {
|
if (model) {
|
||||||
model->AddFormControl(this);
|
model->AddFormControl(this);
|
||||||
|
|
||||||
|
|
|
@ -180,13 +180,9 @@ NS_IMETHODIMP
|
||||||
nsXFormsOutputElement::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
|
nsXFormsOutputElement::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
|
||||||
{
|
{
|
||||||
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
|
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
|
||||||
nsCOMPtr<nsIDOMElement> bindElement;
|
nsCOMPtr<nsIDOMNode> modelNode = nsXFormsUtils::GetModel(mElement);
|
||||||
nsCOMPtr<nsIModelElementPrivate> model;
|
|
||||||
|
|
||||||
model = do_QueryInterface(
|
nsCOMPtr<nsIModelElementPrivate> model = do_QueryInterface(modelNode);
|
||||||
nsXFormsUtils::GetModelAndBind(mElement,
|
|
||||||
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
|
|
||||||
getter_AddRefs(bindElement)));
|
|
||||||
if (model)
|
if (model)
|
||||||
model->RemoveFormControl(this);
|
model->RemoveFormControl(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,10 +54,8 @@ NS_IMETHODIMP
|
||||||
nsXFormsRebuildElement::HandleAction(nsIDOMEvent* aEvent,
|
nsXFormsRebuildElement::HandleAction(nsIDOMEvent* aEvent,
|
||||||
nsIXFormsActionElement *aParentAction)
|
nsIXFormsActionElement *aParentAction)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMNode> model =
|
nsCOMPtr<nsIDOMNode> model = nsXFormsUtils::GetModel(mElement);
|
||||||
nsXFormsUtils::GetModelAndBind(mElement,
|
|
||||||
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
|
|
||||||
nsnull);
|
|
||||||
if (model) {
|
if (model) {
|
||||||
if (aParentAction) {
|
if (aParentAction) {
|
||||||
aParentAction->SetRebuild(model, PR_FALSE);
|
aParentAction->SetRebuild(model, PR_FALSE);
|
||||||
|
|
|
@ -54,10 +54,8 @@ NS_IMETHODIMP
|
||||||
nsXFormsRecalculateElement::HandleAction(nsIDOMEvent* aEvent,
|
nsXFormsRecalculateElement::HandleAction(nsIDOMEvent* aEvent,
|
||||||
nsIXFormsActionElement *aParentAction)
|
nsIXFormsActionElement *aParentAction)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMNode> model =
|
nsCOMPtr<nsIDOMNode> model = nsXFormsUtils::GetModel(mElement);
|
||||||
nsXFormsUtils::GetModelAndBind(mElement,
|
|
||||||
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
|
|
||||||
nsnull);
|
|
||||||
if (model) {
|
if (model) {
|
||||||
if (aParentAction) {
|
if (aParentAction) {
|
||||||
aParentAction->SetRecalculate(model, PR_FALSE);
|
aParentAction->SetRecalculate(model, PR_FALSE);
|
||||||
|
|
|
@ -54,10 +54,8 @@ NS_IMETHODIMP
|
||||||
nsXFormsRefreshElement::HandleAction(nsIDOMEvent* aEvent,
|
nsXFormsRefreshElement::HandleAction(nsIDOMEvent* aEvent,
|
||||||
nsIXFormsActionElement *aParentAction)
|
nsIXFormsActionElement *aParentAction)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMNode> model =
|
nsCOMPtr<nsIDOMNode> model = nsXFormsUtils::GetModel(mElement);
|
||||||
nsXFormsUtils::GetModelAndBind(mElement,
|
|
||||||
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
|
|
||||||
nsnull);
|
|
||||||
if (model) {
|
if (model) {
|
||||||
if (aParentAction) {
|
if (aParentAction) {
|
||||||
aParentAction->SetRefresh(model, PR_FALSE);
|
aParentAction->SetRefresh(model, PR_FALSE);
|
||||||
|
|
|
@ -53,10 +53,8 @@ NS_IMETHODIMP
|
||||||
nsXFormsResetElement::HandleAction(nsIDOMEvent* aEvent,
|
nsXFormsResetElement::HandleAction(nsIDOMEvent* aEvent,
|
||||||
nsIXFormsActionElement *aParentAction)
|
nsIXFormsActionElement *aParentAction)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMNode> model =
|
nsCOMPtr<nsIDOMNode> model = nsXFormsUtils::GetModel(mElement);
|
||||||
nsXFormsUtils::GetModelAndBind(mElement,
|
|
||||||
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
|
|
||||||
nsnull);
|
|
||||||
if (model) {
|
if (model) {
|
||||||
if (aParentAction) {
|
if (aParentAction) {
|
||||||
aParentAction->SetRebuild(model, PR_FALSE);
|
aParentAction->SetRebuild(model, PR_FALSE);
|
||||||
|
|
|
@ -54,10 +54,8 @@ NS_IMETHODIMP
|
||||||
nsXFormsRevalidateElement::HandleAction(nsIDOMEvent* aEvent,
|
nsXFormsRevalidateElement::HandleAction(nsIDOMEvent* aEvent,
|
||||||
nsIXFormsActionElement *aParentAction)
|
nsIXFormsActionElement *aParentAction)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMNode> model =
|
nsCOMPtr<nsIDOMNode> model = nsXFormsUtils::GetModel(mElement);
|
||||||
nsXFormsUtils::GetModelAndBind(mElement,
|
|
||||||
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
|
|
||||||
nsnull);
|
|
||||||
if (model) {
|
if (model) {
|
||||||
if (aParentAction) {
|
if (aParentAction) {
|
||||||
aParentAction->SetRevalidate(model, PR_FALSE);
|
aParentAction->SetRevalidate(model, PR_FALSE);
|
||||||
|
|
|
@ -65,11 +65,8 @@ nsXFormsSetValueElement::HandleAction(nsIDOMEvent* aEvent,
|
||||||
if (!mElement)
|
if (!mElement)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMElement> bind;
|
nsCOMPtr<nsIDOMNode> dommodel = nsXFormsUtils::GetModel(mElement);
|
||||||
nsCOMPtr<nsIDOMNode> dommodel =
|
|
||||||
nsXFormsUtils::GetModelAndBind(mElement,
|
|
||||||
nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR,
|
|
||||||
getter_AddRefs(bind));
|
|
||||||
if (!dommodel)
|
if (!dommodel)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "nsIDOMText.h"
|
#include "nsIDOMText.h"
|
||||||
#include "nsIXFormsModelElement.h"
|
#include "nsIXFormsModelElement.h"
|
||||||
|
|
||||||
|
#include "nsIXFormsContextControl.h"
|
||||||
#include "nsIDOMDocumentEvent.h"
|
#include "nsIDOMDocumentEvent.h"
|
||||||
#include "nsIDOMEvent.h"
|
#include "nsIDOMEvent.h"
|
||||||
#include "nsIDOMEventTarget.h"
|
#include "nsIDOMEventTarget.h"
|
||||||
|
@ -179,8 +180,8 @@ nsXFormsUtils::Init()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ nsIDOMNode*
|
/* static */ void
|
||||||
nsXFormsUtils::GetParentModel(nsIDOMElement *aElement)
|
nsXFormsUtils::GetParentModel(nsIDOMElement *aElement, nsIDOMNode **aModel)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMNode> modelWrapper;
|
nsCOMPtr<nsIDOMNode> modelWrapper;
|
||||||
|
|
||||||
|
@ -201,76 +202,108 @@ nsXFormsUtils::GetParentModel(nsIDOMElement *aElement)
|
||||||
temp.swap(modelWrapper);
|
temp.swap(modelWrapper);
|
||||||
temp->GetParentNode(getter_AddRefs(modelWrapper));
|
temp->GetParentNode(getter_AddRefs(modelWrapper));
|
||||||
}
|
}
|
||||||
|
*aModel = nsnull;
|
||||||
// We're releasing this reference, but the node is owned by the DOM.
|
modelWrapper.swap(*aModel);
|
||||||
return modelWrapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ nsIDOMNode*
|
/**
|
||||||
nsXFormsUtils::GetModelAndBind(nsIDOMElement *aElement,
|
* beaufour: Section 7.4 in the specification does a really bad job of
|
||||||
PRUint32 aElementFlags,
|
* explaining how to find the model, so the code below is my interpretation of
|
||||||
nsIDOMElement **aBindElement)
|
* it...
|
||||||
{
|
*
|
||||||
NS_ENSURE_TRUE(aElement, nsnull);
|
* @see http://bugzilla.mozilla.org/show_bug.cgi?id=265216
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* static */ nsresult
|
||||||
|
nsXFormsUtils::GetNodeContext(nsIDOMElement *aElement,
|
||||||
|
PRUint32 aElementFlags,
|
||||||
|
nsIDOMNode **aModel,
|
||||||
|
nsIDOMElement **aBindElement,
|
||||||
|
nsIDOMElement **aContextNode,
|
||||||
|
PRInt32 *aContextPosition,
|
||||||
|
PRInt32 *aContextSize)
|
||||||
|
{
|
||||||
|
*aBindElement = nsnull;
|
||||||
|
NS_ENSURE_ARG(aElement);
|
||||||
|
NS_ENSURE_ARG_POINTER(aContextNode);
|
||||||
|
|
||||||
|
// Find correct model element
|
||||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||||
aElement->GetOwnerDocument(getter_AddRefs(domDoc));
|
aElement->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||||
if (!domDoc)
|
NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
|
||||||
return nsnull;
|
|
||||||
|
|
||||||
if (aBindElement) {
|
|
||||||
*aBindElement = nsnull;
|
|
||||||
|
|
||||||
nsAutoString bindId;
|
|
||||||
aElement->GetAttribute(NS_LITERAL_STRING("bind"), bindId);
|
|
||||||
|
|
||||||
if (!bindId.IsEmpty()) {
|
|
||||||
// Get the bind element with the given id.
|
|
||||||
domDoc->GetElementById(bindId, aBindElement);
|
|
||||||
|
|
||||||
if (*aBindElement)
|
|
||||||
return GetParentModel(*aBindElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aElementFlags & ELEMENT_WITH_MODEL_ATTR) {
|
nsAutoString bindId;
|
||||||
// If no bind was given, we use model.
|
aElement->GetAttribute(NS_LITERAL_STRING("bind"), bindId);
|
||||||
|
///
|
||||||
|
/// @todo: Is there a need for ELEMENT_WITH_BIND_ATTR?
|
||||||
|
if (!bindId.IsEmpty()) {
|
||||||
|
// CASE 1: Use @bind
|
||||||
|
domDoc->GetElementById(bindId, aBindElement);
|
||||||
|
|
||||||
|
if (*aBindElement)
|
||||||
|
GetParentModel(*aBindElement, aModel);
|
||||||
|
|
||||||
|
// Error: There was a bind attribute, but it did not lead us to a model.
|
||||||
|
NS_ENSURE_TRUE(*aModel, NS_ERROR_FAILURE);
|
||||||
|
} else if (aElementFlags & ELEMENT_WITH_MODEL_ATTR) {
|
||||||
|
// CASE 2: Use @model
|
||||||
|
// If bind did not set model, and the element has a model attribute we use this
|
||||||
nsAutoString modelId;
|
nsAutoString modelId;
|
||||||
aElement->GetAttribute(NS_LITERAL_STRING("model"), modelId);
|
aElement->GetAttribute(NS_LITERAL_STRING("model"), modelId);
|
||||||
|
|
||||||
|
if (!modelId.IsEmpty()) {
|
||||||
|
nsCOMPtr<nsIDOMElement> modelElement;
|
||||||
|
domDoc->GetElementById(modelId, getter_AddRefs(modelElement));
|
||||||
|
NS_IF_ADDREF(*aModel = modelElement);
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNode> modelWrapper;
|
// Not tag found for that ID
|
||||||
|
NS_ENSURE_TRUE(*aModel, NS_ERROR_FAILURE);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no bind was given, we assume the given element is a child
|
nsresult rv = FindParentContext(aElement,
|
||||||
// of the model.
|
aModel,
|
||||||
return GetParentModel(aElement);
|
aContextNode,
|
||||||
|
aContextPosition,
|
||||||
|
aContextSize);
|
||||||
|
// CASE 3/4: Use parent's model / first model in document.
|
||||||
|
// If FindParentContext() does not find a parent context but |aModel| is not
|
||||||
|
// set, it sets the model to the first model in the document.
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ already_AddRefed<nsIDOMNode>
|
||||||
|
nsXFormsUtils::GetModel(nsIDOMElement *aElement,
|
||||||
|
PRUint32 aElementFlags)
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMNode> model;
|
||||||
|
nsCOMPtr<nsIDOMElement> contextNode;
|
||||||
|
nsCOMPtr<nsIDOMElement> bind;
|
||||||
|
|
||||||
|
nsresult rv = GetNodeContext(aElement,
|
||||||
|
aElementFlags,
|
||||||
|
getter_AddRefs(model),
|
||||||
|
getter_AddRefs(bind),
|
||||||
|
getter_AddRefs(contextNode));
|
||||||
|
|
||||||
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||||
|
|
||||||
|
nsIDOMNode *result = nsnull;
|
||||||
|
if (model)
|
||||||
|
CallQueryInterface(model, &result); // addrefs
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ already_AddRefed<nsIDOMXPathResult>
|
/* static */ already_AddRefed<nsIDOMXPathResult>
|
||||||
nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
|
nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
|
||||||
nsIDOMNode *aContextNode,
|
nsIDOMNode *aContextNode,
|
||||||
nsIDOMNode *aResolverNode,
|
nsIDOMNode *aResolverNode,
|
||||||
PRUint16 aResultType)
|
PRUint16 aResultType,
|
||||||
|
PRInt32 aContextPosition,
|
||||||
|
PRInt32 aContextSize)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMDocument> doc;
|
nsCOMPtr<nsIDOMDocument> doc;
|
||||||
aContextNode->GetOwnerDocument(getter_AddRefs(doc));
|
aContextNode->GetOwnerDocument(getter_AddRefs(doc));
|
||||||
|
@ -283,6 +316,8 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression,
|
||||||
eval->CreateNSResolver(aResolverNode, getter_AddRefs(resolver));
|
eval->CreateNSResolver(aResolverNode, getter_AddRefs(resolver));
|
||||||
NS_ENSURE_TRUE(resolver, nsnull);
|
NS_ENSURE_TRUE(resolver, nsnull);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @todo Evaluate() should use aContextPosition and aContextSize
|
||||||
nsCOMPtr<nsISupports> supResult;
|
nsCOMPtr<nsISupports> supResult;
|
||||||
eval->Evaluate(aExpression, aContextNode, resolver, aResultType, nsnull,
|
eval->Evaluate(aExpression, aContextNode, resolver, aResultType, nsnull,
|
||||||
getter_AddRefs(supResult));
|
getter_AddRefs(supResult));
|
||||||
|
@ -389,16 +424,25 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement,
|
||||||
nsIDOMNode **aModel,
|
nsIDOMNode **aModel,
|
||||||
nsIDOMElement **aBind)
|
nsIDOMElement **aBind)
|
||||||
{
|
{
|
||||||
// A control may be attached to a model by either using the 'bind'
|
if (!aElement || !aBind || !aModel) {
|
||||||
// attribute to give the id of a bind element, or using the 'model'
|
return nsnull;
|
||||||
// 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;
|
*aBind = nsnull;
|
||||||
|
*aModel = nsnull;
|
||||||
|
|
||||||
NS_IF_ADDREF(*aModel = GetModelAndBind(aElement, aElementFlags, aBind));
|
nsCOMPtr<nsIDOMElement> contextNode;
|
||||||
if (!*aModel)
|
PRInt32 contextPosition;
|
||||||
return nsnull;
|
PRInt32 contextSize;
|
||||||
|
nsresult rv = GetNodeContext(aElement,
|
||||||
|
aElementFlags,
|
||||||
|
aModel,
|
||||||
|
aBind,
|
||||||
|
getter_AddRefs(contextNode),
|
||||||
|
&contextPosition,
|
||||||
|
&contextSize);
|
||||||
|
|
||||||
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||||
|
|
||||||
// If there is a bind element, we just evaluate its nodeset.
|
// If there is a bind element, we just evaluate its nodeset.
|
||||||
if (*aBind)
|
if (*aBind)
|
||||||
|
@ -415,27 +459,34 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement,
|
||||||
expr.Assign(aDefaultRef);
|
expr.Assign(aDefaultRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the instance data and evaluate the xpath expression.
|
if (!contextNode) {
|
||||||
// XXXfixme when xpath extensions are implemented (instance())
|
nsCOMPtr<nsIDOMDocument> instanceDoc;
|
||||||
nsCOMPtr<nsIDOMDocument> instanceDoc;
|
nsCOMPtr<nsIXFormsModelElement> model = do_QueryInterface(*aModel);
|
||||||
nsCOMPtr<nsIXFormsModelElement> model = do_QueryInterface(*aModel);
|
if (!model) {
|
||||||
if (!model) {
|
// The referenced model is not actually a model element, or does not exist.
|
||||||
// The referenced model is not actually a model element, or does not exist.
|
return nsnull;
|
||||||
return nsnull;
|
}
|
||||||
|
|
||||||
|
model->GetInstanceDocument(NS_LITERAL_STRING(""),
|
||||||
|
getter_AddRefs(instanceDoc));
|
||||||
|
|
||||||
|
if (!instanceDoc)
|
||||||
|
return nsnull;
|
||||||
|
|
||||||
|
instanceDoc->GetDocumentElement(getter_AddRefs(contextNode));
|
||||||
|
|
||||||
|
if (!contextNode) {
|
||||||
|
return nsnull; // this will happen if the doc is still loading
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
model->GetInstanceDocument(NS_LITERAL_STRING(""),
|
// Evaluate |expr|
|
||||||
getter_AddRefs(instanceDoc));
|
return EvaluateXPath(expr,
|
||||||
|
contextNode,
|
||||||
if (!instanceDoc)
|
aElement,
|
||||||
return nsnull;
|
aResultType,
|
||||||
|
contextSize,
|
||||||
nsCOMPtr<nsIDOMElement> docElement;
|
contextPosition);
|
||||||
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 */ void
|
/* static */ void
|
||||||
|
@ -694,3 +745,93 @@ nsXFormsUtils::CloneScriptingInterfaces(const nsIID *aIIDList,
|
||||||
*aOutCount = aIIDCount;
|
*aOutCount = aIIDCount;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ nsresult
|
||||||
|
nsXFormsUtils::FindParentContext(nsIDOMElement *aElement,
|
||||||
|
nsIDOMNode **aModel,
|
||||||
|
nsIDOMElement **aContextNode,
|
||||||
|
PRInt32 *aContextPosition,
|
||||||
|
PRInt32 *aContextSize)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG(aElement);
|
||||||
|
NS_ENSURE_ARG_POINTER(aModel);
|
||||||
|
NS_ENSURE_ARG_POINTER(aContextNode);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMNode> elementNode = do_QueryInterface(aElement);
|
||||||
|
NS_ENSURE_TRUE(elementNode, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMNode> curNode;
|
||||||
|
nsresult rv = elementNode->GetParentNode(getter_AddRefs(curNode));
|
||||||
|
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||||
|
|
||||||
|
// If a model is set, get its ID
|
||||||
|
nsAutoString childModelID;
|
||||||
|
if (*aModel) {
|
||||||
|
nsCOMPtr<nsIDOMElement> modelElement = do_QueryInterface(*aModel);
|
||||||
|
NS_ENSURE_TRUE(modelElement, NS_ERROR_FAILURE);
|
||||||
|
modelElement->GetAttribute(NS_LITERAL_STRING("id"), childModelID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find our context:
|
||||||
|
// Iterate over all parents and find first one that implements nsIXFormsContextControl,
|
||||||
|
// and has the same model as us.
|
||||||
|
nsCOMPtr<nsIDOMNode> temp;
|
||||||
|
nsAutoString contextModelID;
|
||||||
|
while (curNode) {
|
||||||
|
nsCOMPtr<nsIXFormsContextControl> contextControl = do_QueryInterface(curNode);
|
||||||
|
nsCOMPtr<nsIDOMElement> cElement = do_QueryInterface(curNode);
|
||||||
|
if (contextControl && cElement) {
|
||||||
|
PRInt32 cSize;
|
||||||
|
PRInt32 cPosition;
|
||||||
|
nsCOMPtr<nsIDOMElement> tempNode;
|
||||||
|
rv = contextControl->GetContext(contextModelID, getter_AddRefs(tempNode), &cPosition, &cSize);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
// If the call failed, it means that we _have_ a parent which sets the
|
||||||
|
// context but it is invalid, ie. the XPath expression could have
|
||||||
|
// generated an error.
|
||||||
|
|
||||||
|
if (childModelID.IsEmpty()
|
||||||
|
|| childModelID.Equals(contextModelID)) {
|
||||||
|
NS_ADDREF(*aContextNode = tempNode);
|
||||||
|
if (aContextSize)
|
||||||
|
*aContextSize = cSize;
|
||||||
|
if (aContextPosition)
|
||||||
|
*aContextPosition = cPosition;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Next ancestor
|
||||||
|
temp.swap(curNode);
|
||||||
|
rv = temp->GetParentNode(getter_AddRefs(curNode));
|
||||||
|
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Child had no model set, set it
|
||||||
|
if (!*aModel) {
|
||||||
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||||
|
nsresult rv = aElement->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
if (!*aContextNode || contextModelID.IsEmpty()) {
|
||||||
|
// We have either not found a context node, or we have found one where
|
||||||
|
// the model ID is empty. That means we use the first model in document
|
||||||
|
nsCOMPtr<nsIDOMNodeList> nodes;
|
||||||
|
domDoc->GetElementsByTagNameNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS),
|
||||||
|
NS_LITERAL_STRING("model"),
|
||||||
|
getter_AddRefs(nodes));
|
||||||
|
// No model element in document!
|
||||||
|
NS_ENSURE_TRUE(nodes, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
nodes->Item(0, aModel);
|
||||||
|
} else {
|
||||||
|
// Get the model with the correct ID
|
||||||
|
nsCOMPtr<nsIDOMElement> modelElement;
|
||||||
|
domDoc->GetElementById(contextModelID, getter_AddRefs(modelElement));
|
||||||
|
NS_IF_ADDREF(*aModel = modelElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -133,18 +133,43 @@ public:
|
||||||
* Locate the model that is a parent of |aElement|. This method walks up the
|
* Locate the model that is a parent of |aElement|. This method walks up the
|
||||||
* content tree looking for the containing model.
|
* content tree looking for the containing model.
|
||||||
*/
|
*/
|
||||||
static NS_HIDDEN_(nsIDOMNode*)
|
static NS_HIDDEN_(void)
|
||||||
GetParentModel(nsIDOMElement *aElement);
|
GetParentModel(nsIDOMElement *aElement, nsIDOMNode **aModel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locate the model that |aElement| is bound to, and if applicable, the
|
* Find the evaluation context for an element.
|
||||||
* \<bind\> element that it uses. The model is returned and the
|
*
|
||||||
* bind element is returned (addrefed) in |aBindElement|.
|
* That is, the model it is bound to (|aModel|), and if applicable the
|
||||||
|
* \<bind\> element that it uses (|aBindElement| and the context node
|
||||||
|
* (|aContextNode|).
|
||||||
|
*
|
||||||
|
* @param aElement The element
|
||||||
|
* @param aElementFlags Flags describing characteristics of aElement
|
||||||
|
* @param aModel The \<model\> for the element
|
||||||
|
* @param aBindElement The \<bind\> the element is bound to (if any)
|
||||||
|
* @param aContextNode The context node for the element
|
||||||
*/
|
*/
|
||||||
static NS_HIDDEN_(nsIDOMNode*)
|
static NS_HIDDEN_(nsresult)
|
||||||
GetModelAndBind(nsIDOMElement *aElement,
|
GetNodeContext(nsIDOMElement *aElement,
|
||||||
PRUint32 aElementFlags,
|
PRUint32 aElementFlags,
|
||||||
nsIDOMElement **aBindElement);
|
nsIDOMNode **aModel,
|
||||||
|
nsIDOMElement **aBindElement,
|
||||||
|
nsIDOMElement **aContextNode,
|
||||||
|
PRInt32 *aContextPosition = nsnull,
|
||||||
|
PRInt32 *aContextSize = nsnull);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate the model for an element.
|
||||||
|
*
|
||||||
|
* @note Actually it is just a shortcut for GetNodeContext().
|
||||||
|
*
|
||||||
|
* @param aElement The element
|
||||||
|
* @param aElementFlags Flags describing characteristics of aElement
|
||||||
|
* @return The model
|
||||||
|
*/
|
||||||
|
static NS_HIDDEN_(already_AddRefed<nsIDOMNode>)
|
||||||
|
GetModel(nsIDOMElement *aElement,
|
||||||
|
PRUint32 aElementFlags = ELEMENT_WITH_MODEL_ATTR);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate a 'bind' or |aBindingAttr| attribute on |aElement|.
|
* Evaluate a 'bind' or |aBindingAttr| attribute on |aElement|.
|
||||||
|
@ -191,7 +216,9 @@ public:
|
||||||
EvaluateXPath(const nsAString &aExpression,
|
EvaluateXPath(const nsAString &aExpression,
|
||||||
nsIDOMNode *aContextNode,
|
nsIDOMNode *aContextNode,
|
||||||
nsIDOMNode *aResolverNode,
|
nsIDOMNode *aResolverNode,
|
||||||
PRUint16 aResultType);
|
PRUint16 aResultType,
|
||||||
|
PRInt32 aContextPosition = 1,
|
||||||
|
PRInt32 aContextSize = 1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a node in the instance data, get its string value according
|
* Given a node in the instance data, get its string value according
|
||||||
|
@ -247,6 +274,24 @@ public:
|
||||||
unsigned int aIIDCount,
|
unsigned int aIIDCount,
|
||||||
PRUint32 *aOutCount,
|
PRUint32 *aOutCount,
|
||||||
nsIID ***aOutArray);
|
nsIID ***aOutArray);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the context for the element, if set by a parent node.
|
||||||
|
*
|
||||||
|
* Controls inheriting from nsIXFormsContextControl sets the context for its children.
|
||||||
|
*
|
||||||
|
* @param aElement The document element of the caller
|
||||||
|
* @param aModel The model for |aElement| (if (!*aModel), it is set)
|
||||||
|
* @param aContextNode The resulting context node
|
||||||
|
* @param aContextPosition The resulting context position
|
||||||
|
* @param aContextSize The resulting context size
|
||||||
|
*/
|
||||||
|
static NS_HIDDEN_(nsresult) FindParentContext(nsIDOMElement *aElement,
|
||||||
|
nsIDOMNode **aModel,
|
||||||
|
nsIDOMElement **aContextNode,
|
||||||
|
PRInt32 *aContextPosition,
|
||||||
|
PRInt32 *aContextSize);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче