XForms bug 294441 - fix model-construct-done processing. Patch by aaronr, r=smaug/me a=mkaply
git-svn-id: svn://10.0.0.236/trunk@175315 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
403260a8fd
commit
25a72b45f8
@ -71,6 +71,7 @@ REQUIRES = \
|
||||
schemavalidation \
|
||||
intl \
|
||||
pref \
|
||||
htmlparser \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
@ -145,6 +146,7 @@ CPPSRCS = \
|
||||
nsXFormsControlStub.cpp \
|
||||
nsXFormsUtilityService.cpp \
|
||||
nsXFormsDelegateStub.cpp \
|
||||
nsXFormsLazyInstanceElement.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS)
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
|
||||
|
||||
<!-- list all the packages being supplied by this jar -->
|
||||
<RDF:Seq about="urn:mozilla:package:root">
|
||||
<RDF:li resource="urn:mozilla:package:xforms"/>
|
||||
</RDF:Seq>
|
||||
|
||||
<!-- package information -->
|
||||
<RDF:Description about="urn:mozilla:package:xforms"
|
||||
chrome:name="xforms"/>
|
||||
</RDF:RDF>
|
||||
@ -39,6 +39,7 @@
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDOMDocument;
|
||||
interface nsIDOMElement;
|
||||
|
||||
/**
|
||||
* Private interface implemented by the instance element.
|
||||
@ -50,6 +51,7 @@ interface nsIInstanceElementPrivate : nsISupports
|
||||
* The document which holds the live instance data.
|
||||
*/
|
||||
attribute nsIDOMDocument document;
|
||||
readonly attribute nsIDOMElement element;
|
||||
void backupOriginalDocument();
|
||||
void restoreOriginalDocument();
|
||||
};
|
||||
|
||||
@ -42,6 +42,11 @@ interface nsIXFormsControl;
|
||||
interface nsISchemaType;
|
||||
interface nsIInstanceElementPrivate;
|
||||
interface nsIDOMNode;
|
||||
%{C++
|
||||
#include "nsCOMArray.h"
|
||||
%}
|
||||
|
||||
[ptr] native nsCOMArrayPtr(nsCOMArray<nsIInstanceElementPrivate>);
|
||||
|
||||
/**
|
||||
* Private interface implemented by the model element for other
|
||||
@ -119,4 +124,21 @@ interface nsIModelElementPrivate : nsIXFormsModelElement
|
||||
* @param aBoundNode The node the control is bound to
|
||||
*/
|
||||
void setStates(in nsIXFormsControl aControl, in nsIDOMNode aBoundNode);
|
||||
|
||||
/**
|
||||
* The list of instance elements held by this model. Includes lazy-authored
|
||||
* instance elements
|
||||
*/
|
||||
readonly attribute nsCOMArrayPtr instanceList;
|
||||
|
||||
/**
|
||||
* Add an instance element to the model's instance list
|
||||
* @param aInstanceElement The instance element to add to the list
|
||||
*/
|
||||
void addInstanceElement(in nsIInstanceElementPrivate aInstanceElement);
|
||||
|
||||
/**
|
||||
* This attribute is set when the model's instance was lazy authored
|
||||
*/
|
||||
readonly attribute boolean lazyAuthored;
|
||||
};
|
||||
|
||||
@ -159,6 +159,19 @@ nsXFormsControlStubBase::ResetBoundNode(const nsString &aBindAttribute,
|
||||
|
||||
if (mBoundNode && mModel) {
|
||||
mModel->SetStates(this, mBoundNode);
|
||||
} else if (mModel) {
|
||||
// we should have been successful. Must be pointing to a node that
|
||||
// doesn't exist in the instance document. Disable the control
|
||||
// per 4.2.2 in the spec
|
||||
|
||||
// Set pseudo class
|
||||
///
|
||||
/// @bug Set via attributes right now. Bug 271720. (XXX)
|
||||
mElement->SetAttribute(NS_LITERAL_STRING("disabled"),
|
||||
NS_LITERAL_STRING("1"));
|
||||
mElement->RemoveAttribute(NS_LITERAL_STRING("enabled"));
|
||||
// Dispatch event
|
||||
nsXFormsUtils::DispatchEvent(mElement, eEvent_Disabled);
|
||||
}
|
||||
|
||||
if (aResult) {
|
||||
|
||||
@ -140,9 +140,9 @@ nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
|
||||
{
|
||||
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
|
||||
nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED |
|
||||
nsIXTFElement::NOTIFY_PARENT_CHANGED |
|
||||
nsIXTFElement::NOTIFY_BEGIN_ADDING_CHILDREN |
|
||||
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
|
||||
// XXX observe nsIXTFElement::NOTIFY_PARENT_CHANGED ??
|
||||
|
||||
nsCOMPtr<nsIDOMElement> node;
|
||||
aWrapper->GetElementNode(getter_AddRefs(node));
|
||||
@ -157,6 +157,23 @@ nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::ParentChanged(nsIDOMElement *aNewParent)
|
||||
{
|
||||
if (!aNewParent)
|
||||
return NS_OK;
|
||||
|
||||
// Once we are set up in the DOM, can find the model and make sure that this
|
||||
// instance is on the list of instance elements that model keeps
|
||||
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
|
||||
NS_ENSURE_TRUE(model, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIInstanceElementPrivate> instance =
|
||||
NS_STATIC_CAST(nsIInstanceElementPrivate*, this);
|
||||
model->AddInstanceElement(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIInterfaceRequestor
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -298,10 +315,11 @@ nsXFormsInstanceElement::RestoreOriginalDocument()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// This is called when xforms-ready is received by the model. By now we know
|
||||
// that the instance document, whether external or inline, is loaded into
|
||||
// mDocument. Get the root node, clone it, and insert it into our copy of
|
||||
// the document. This is the magic behind getting xforms-reset to work.
|
||||
// This is called when xforms-reset is received by the model. We assume
|
||||
// that the backup of the instance document has been populated and is
|
||||
// loaded into mOriginalDocument. Get the backup's root node, clone it, and
|
||||
// insert it into the live copy of the instance document. This is the magic
|
||||
// behind getting xforms-reset to work.
|
||||
if(mDocument && mOriginalDocument) {
|
||||
nsCOMPtr<nsIDOMNode> newNode, instanceRootNode, nodeReturn;
|
||||
nsCOMPtr<nsIDOMElement> instanceRoot;
|
||||
@ -332,6 +350,12 @@ nsXFormsInstanceElement::RestoreOriginalDocument()
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::GetElement(nsIDOMElement **aElement)
|
||||
{
|
||||
NS_IF_ADDREF(*aElement = mElement);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// private methods
|
||||
|
||||
@ -446,7 +470,7 @@ nsXFormsInstanceElement::CreateInstanceDocument()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
|
||||
getter_AddRefs(mDocument));
|
||||
getter_AddRefs(mDocument));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// I don't know if not being able to create a backup document is worth
|
||||
|
||||
@ -78,6 +78,7 @@ public:
|
||||
NS_IMETHOD BeginAddingChildren();
|
||||
NS_IMETHOD DoneAddingChildren();
|
||||
NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper);
|
||||
NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent);
|
||||
|
||||
nsXFormsInstanceElement() NS_HIDDEN;
|
||||
|
||||
|
||||
191
mozilla/extensions/xforms/nsXFormsLazyInstanceElement.cpp
Normal file
191
mozilla/extensions/xforms/nsXFormsLazyInstanceElement.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
/* -*- 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) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Aaron Reed <aaronr@us.ibm.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 "nsXFormsLazyInstanceElement.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDOMImplementation.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsLazyInstanceElement,
|
||||
nsXFormsStubElement,
|
||||
nsIInstanceElementPrivate,
|
||||
nsIInterfaceRequestor)
|
||||
|
||||
nsXFormsLazyInstanceElement::nsXFormsLazyInstanceElement()
|
||||
{
|
||||
}
|
||||
|
||||
// nsIInstanceElementPrivate
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsLazyInstanceElement::GetDocument(nsIDOMDocument **aDocument)
|
||||
{
|
||||
NS_IF_ADDREF(*aDocument = mDocument);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsLazyInstanceElement::SetDocument(nsIDOMDocument *aDocument)
|
||||
{
|
||||
mDocument = aDocument;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsLazyInstanceElement::BackupOriginalDocument()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// This is called when xforms-ready is received by the model. By now we know
|
||||
// that the lazy instance document has been populated and is loaded into
|
||||
// mDocument. Get the root node, clone it, and insert it into our copy of
|
||||
// the document. This is the magic behind getting xforms-reset to work.
|
||||
if(mDocument && mOriginalDocument) {
|
||||
nsCOMPtr<nsIDOMNode> newNode;
|
||||
nsCOMPtr<nsIDOMElement> instanceRoot;
|
||||
rv = mDocument->GetDocumentElement(getter_AddRefs(instanceRoot));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(instanceRoot, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> nodeReturn;
|
||||
rv = instanceRoot->CloneNode(PR_TRUE, getter_AddRefs(newNode));
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
rv = mOriginalDocument->AppendChild(newNode, getter_AddRefs(nodeReturn));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
|
||||
"failed to set up original instance document");
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsLazyInstanceElement::RestoreOriginalDocument()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// This is called when xforms-reset is received by the model. We assume
|
||||
// that the backup of the lazy instance document has been populated and is
|
||||
// loaded into mOriginalDocument. Get the backup's root node, clone it, and
|
||||
// insert it into the live copy of the instance document. This is the magic
|
||||
// behind getting xforms-reset to work.
|
||||
if(mDocument && mOriginalDocument) {
|
||||
nsCOMPtr<nsIDOMNode> newNode, instanceRootNode, nodeReturn;
|
||||
nsCOMPtr<nsIDOMElement> instanceRoot;
|
||||
|
||||
// first remove all the old stuff
|
||||
rv = mDocument->GetDocumentElement(getter_AddRefs(instanceRoot));
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
if(instanceRoot) {
|
||||
rv = mDocument->RemoveChild(instanceRoot, getter_AddRefs(nodeReturn));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
// now all of the garbage is out o' there! Put the original data back
|
||||
// into mDocument
|
||||
rv = mOriginalDocument->GetDocumentElement(getter_AddRefs(instanceRoot));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(instanceRoot, NS_ERROR_FAILURE);
|
||||
instanceRootNode = do_QueryInterface(instanceRoot);
|
||||
|
||||
rv = instanceRootNode->CloneNode(PR_TRUE, getter_AddRefs(newNode));
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
rv = mDocument->AppendChild(newNode, getter_AddRefs(nodeReturn));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
|
||||
"failed to restore original instance document");
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsLazyInstanceElement::GetElement(nsIDOMElement **aElement)
|
||||
{
|
||||
*aElement = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIInterfaceRequestor
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsLazyInstanceElement::GetInterface(const nsIID & aIID, void **aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
return QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsLazyInstanceElement::CreateLazyInstanceDocument(nsIDOMDocument *aXFormsDocument)
|
||||
{
|
||||
NS_ENSURE_ARG(aXFormsDocument);
|
||||
|
||||
// Do not try to load an instance document if the current document is not
|
||||
// associated with a DOM window. This could happen, for example, if some
|
||||
// XForms document loaded itself as instance data (which is what the Forms
|
||||
// 1.0 testsuite does).
|
||||
nsCOMPtr<nsIDocument> d = do_QueryInterface(aXFormsDocument);
|
||||
if (d && !d->GetScriptGlobalObject())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMDOMImplementation> domImpl;
|
||||
nsresult rv = aXFormsDocument->GetImplementation(getter_AddRefs(domImpl));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
|
||||
getter_AddRefs(mDocument));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Lazy authored instance documents have a root named "instanceData"
|
||||
nsCOMPtr<nsIDOMElement> instanceDataElement;
|
||||
nsCOMPtr<nsIDOMNode> childReturn;
|
||||
rv = mDocument->CreateElementNS(EmptyString(),
|
||||
NS_LITERAL_STRING("instanceData"),
|
||||
getter_AddRefs(instanceDataElement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mDocument->AppendChild(instanceDataElement, getter_AddRefs(childReturn));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// I don't know if not being able to create a backup document is worth
|
||||
// failing this function. Since it probably won't be used often, we'll
|
||||
// let it slide. But it probably does mean that things are going south
|
||||
// with the browser.
|
||||
domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
|
||||
getter_AddRefs(mOriginalDocument));
|
||||
return rv;
|
||||
}
|
||||
76
mozilla/extensions/xforms/nsXFormsLazyInstanceElement.h
Normal file
76
mozilla/extensions/xforms/nsXFormsLazyInstanceElement.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* -*- 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) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Aaron Reed <aaronr@us.ibm.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 nsXFormsLazyInstanceElement_h_
|
||||
#define nsXFormsLazyInstanceElement_h_
|
||||
|
||||
#include "nsXFormsStubElement.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIModelElementPrivate.h"
|
||||
#include "nsIInstanceElementPrivate.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
|
||||
class nsIDOMElement;
|
||||
|
||||
/**
|
||||
* Implementation of the XForms \<instance\> element created through lazy
|
||||
* authoring. It creates an instance document by cloning the contained
|
||||
* instance data.
|
||||
*/
|
||||
|
||||
class nsXFormsLazyInstanceElement : public nsXFormsStubElement,
|
||||
public nsIInstanceElementPrivate,
|
||||
public nsIInterfaceRequestor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIINSTANCEELEMENTPRIVATE
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
NS_HIDDEN_(nsresult) CreateLazyInstanceDocument(nsIDOMDocument *aXFormsDocument);
|
||||
|
||||
nsXFormsLazyInstanceElement() NS_HIDDEN;
|
||||
|
||||
private:
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> mDocument;
|
||||
nsCOMPtr<nsIDOMDocument> mOriginalDocument;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -76,6 +76,7 @@
|
||||
#include "nsISchema.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsArray.h"
|
||||
#include "nsXFormsLazyInstanceElement.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
//#define DEBUG_MODEL
|
||||
@ -248,7 +249,9 @@ nsXFormsModelElement::nsXFormsModelElement()
|
||||
mSchemaTotal(0),
|
||||
mPendingInstanceCount(0),
|
||||
mDocumentLoaded(PR_FALSE),
|
||||
mNeedsRefresh(PR_FALSE)
|
||||
mNeedsRefresh(PR_FALSE),
|
||||
mInstanceList(16),
|
||||
mLazyModel(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
@ -268,6 +271,8 @@ nsXFormsModelElement::OnDestroyed()
|
||||
|
||||
mElement = nsnull;
|
||||
mSchemas = nsnull;
|
||||
|
||||
mInstanceList.Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -398,6 +403,22 @@ nsXFormsModelElement::DoneAddingChildren()
|
||||
}
|
||||
}
|
||||
|
||||
// If all of the children are added and there aren't any instance elements,
|
||||
// yet, then we need to make sure that one is ready in case the form author
|
||||
// is using lazy authoring.
|
||||
PRUint32 instCount = mInstanceList.Count();
|
||||
if (!instCount) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||
if (domDoc) {
|
||||
nsXFormsLazyInstanceElement *lazyInstance =
|
||||
new nsXFormsLazyInstanceElement();
|
||||
lazyInstance->CreateLazyInstanceDocument(domDoc);
|
||||
AddInstanceElement(lazyInstance);
|
||||
mLazyModel = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. construct an XPath data model from inline or external initial instance
|
||||
// data. This is done by our child instance elements as they are inserted
|
||||
// into the document, and all of the instances will be processed by this
|
||||
@ -990,32 +1011,34 @@ nsXFormsModelElement::FindInstanceElement(const nsAString &aID,
|
||||
{
|
||||
*aElement = nsnull;
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> children;
|
||||
mElement->GetChildNodes(getter_AddRefs(children));
|
||||
PRUint32 instCount = mInstanceList.Count();
|
||||
if (instCount) {
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
nsAutoString id;
|
||||
for (int i = 0; i < instCount; ++i) {
|
||||
nsIInstanceElementPrivate* instEle = mInstanceList.ObjectAt(i);
|
||||
instEle->GetElement(getter_AddRefs(element));
|
||||
|
||||
if (!children)
|
||||
return NS_OK;
|
||||
|
||||
PRUint32 childCount = 0;
|
||||
children->GetLength(&childCount);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
nsAutoString id;
|
||||
|
||||
for (PRUint32 i = 0; i < childCount; ++i) {
|
||||
children->Item(i, getter_AddRefs(node));
|
||||
NS_ASSERTION(node, "incorrect NodeList length?");
|
||||
|
||||
element = do_QueryInterface(node);
|
||||
if (!element)
|
||||
continue;
|
||||
|
||||
element->GetAttribute(NS_LITERAL_STRING("id"), id);
|
||||
if (aID.IsEmpty() || aID.Equals(id)) {
|
||||
CallQueryInterface(element, aElement);
|
||||
if (*aElement)
|
||||
if (aID.IsEmpty()) {
|
||||
NS_ADDREF(instEle);
|
||||
*aElement = instEle;
|
||||
break;
|
||||
} else if (!element) {
|
||||
// this should only happen if the instance on the list is lazy authored
|
||||
// and as far as I can tell, a lazy authored instance should be the
|
||||
// first (and only) instance in the model and unable to have an ID.
|
||||
// But that isn't clear to me reading the spec, so for now
|
||||
// we'll play it safe in case the WG more clearly defines lazy authoring
|
||||
// in the future.
|
||||
continue;
|
||||
}
|
||||
|
||||
element->GetAttribute(NS_LITERAL_STRING("id"), id);
|
||||
if (aID.Equals(id)) {
|
||||
NS_ADDREF(instEle);
|
||||
*aElement = instEle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1155,6 +1178,12 @@ nsXFormsModelElement::GetContext(nsAString &aModelID,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::GetLazyAuthored(PRBool *aLazyInstance)
|
||||
{
|
||||
*aLazyInstance = mLazyModel;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// internal methods
|
||||
|
||||
@ -1244,40 +1273,23 @@ nsXFormsModelElement::Ready()
|
||||
void
|
||||
nsXFormsModelElement::BackupOrRestoreInstanceData(PRBool restore)
|
||||
{
|
||||
// I imagine that this can be done more elegantly. But in the end, the
|
||||
// bulk of the work is walking the model's children looking for instance
|
||||
// elements. After one is found, just need to ask the instance element to
|
||||
// backup or restore.
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> children;
|
||||
mElement->GetChildNodes(getter_AddRefs(children));
|
||||
PRUint32 instCount = mInstanceList.Count();
|
||||
if (instCount) {
|
||||
for (int i = 0; i < instCount; ++i) {
|
||||
nsIInstanceElementPrivate *instance = mInstanceList.ObjectAt(i);
|
||||
|
||||
if (!children)
|
||||
return;
|
||||
|
||||
PRUint32 childCount = 0;
|
||||
children->GetLength(&childCount);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIInstanceElementPrivate> instance;
|
||||
|
||||
for (PRUint32 i = 0; i < childCount; ++i) {
|
||||
children->Item(i, getter_AddRefs(node));
|
||||
NS_ASSERTION(node, "incorrect NodeList length?");
|
||||
|
||||
instance = do_QueryInterface(node);
|
||||
if (!instance)
|
||||
continue;
|
||||
|
||||
// Don't know what to do with error if we get one.
|
||||
// Restore/BackupOriginalDocument will already output warnings.
|
||||
if(restore) {
|
||||
instance->RestoreOriginalDocument();
|
||||
}
|
||||
else {
|
||||
instance->BackupOriginalDocument();
|
||||
// Don't know what to do with error if we get one.
|
||||
// Restore/BackupOriginalDocument will already output warnings.
|
||||
if(restore) {
|
||||
instance->RestoreOriginalDocument();
|
||||
}
|
||||
else {
|
||||
instance->BackupOriginalDocument();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1614,6 +1626,26 @@ nsXFormsModelElement::SetStates(nsIXFormsControl *aControl, nsIDOMNode *aBoundNo
|
||||
return SetStatesInternal(aControl, aBoundNode, PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::GetInstanceList(nsCOMArray<nsIInstanceElementPrivate> **aInstanceList)
|
||||
{
|
||||
if (aInstanceList) {
|
||||
*aInstanceList = &mInstanceList;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsModelElement::AddInstanceElement(nsIInstanceElementPrivate *aInstEle)
|
||||
{
|
||||
// always append to the end of the list. We need to keep the elements in
|
||||
// document order since the first instance element is the default instance
|
||||
// document for the model.
|
||||
mInstanceList.AppendObject(aInstEle);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsXFormsModelElement::Startup()
|
||||
{
|
||||
|
||||
@ -209,6 +209,15 @@ private:
|
||||
// This flag indicates whether a xforms-rebuild has been called, but no
|
||||
// xforms-revalidate yet
|
||||
PRBool mNeedsRefresh;
|
||||
|
||||
/**
|
||||
* List of instance elements contained by this model, including lazy-authored
|
||||
* instance elements.
|
||||
*/
|
||||
nsCOMArray<nsIInstanceElementPrivate> mInstanceList;
|
||||
|
||||
/** Indicates whether the model's instance was built by lazy authoring */
|
||||
PRBool mLazyModel;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -775,11 +775,20 @@ nsXFormsSubmissionElement::SerializeDataXML(nsIDOMNode *data,
|
||||
|
||||
// add namespaces from the main document to the submission document, but only
|
||||
// if the instance data is local, not remote.
|
||||
PRBool hasSrc = PR_FALSE;
|
||||
PRBool serialize = PR_FALSE;
|
||||
nsCOMPtr<nsIDOMElement> instanceElement(do_QueryInterface(instanceNode));
|
||||
instanceElement->HasAttribute(NS_LITERAL_STRING("src"), &hasSrc);
|
||||
|
||||
if (!hasSrc) {
|
||||
// make sure that this is a DOMElement. It won't be if it was lazy
|
||||
// authored. Lazy authored instance documents don't inherit namespaces
|
||||
// from parent nodes or the original document (in formsPlayer and Novell,
|
||||
// at least).
|
||||
if (instanceElement) {
|
||||
PRBool hasSrc = PR_FALSE;
|
||||
instanceElement->HasAttribute(NS_LITERAL_STRING("src"), &hasSrc);
|
||||
serialize = !hasSrc;
|
||||
}
|
||||
|
||||
if (serialize) {
|
||||
rv = AddNameSpaces(newDocElm, node);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
||||
@ -116,12 +116,10 @@ nsXFormsUtilityService::IsNodeAssocWithModel( nsIDOMNode *aNode,
|
||||
|
||||
if (modelNode && (modelNode == aModel)) {
|
||||
*aModelAssocWithNode = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
*aModelAssocWithNode = PR_FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// We are assuming that if the node coming in isn't a proper XForms element,
|
||||
// then it is an instance element in an instance doc. Now we just have
|
||||
// to determine if the given model contains this instance document.
|
||||
@ -137,26 +135,16 @@ nsXFormsUtilityService::IsNodeAssocWithModel( nsIDOMNode *aNode,
|
||||
// document. If it is equal to the document that contains aNode,
|
||||
// then aNode is associated with this aModel element and we can return
|
||||
// true.
|
||||
nsCOMPtr<nsIDOMNodeList> children;
|
||||
aModel->GetChildNodes(getter_AddRefs(children));
|
||||
|
||||
if (!children)
|
||||
return NS_OK;
|
||||
|
||||
PRUint32 childCount = 0;
|
||||
children->GetLength(&childCount);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIModelElementPrivate>model = do_QueryInterface(modelEle);
|
||||
nsCOMPtr<nsIInstanceElementPrivate> instElement;
|
||||
nsCOMPtr<nsIDOMDocument> instDocument;
|
||||
|
||||
for (PRUint32 i = 0; i < childCount; ++i) {
|
||||
children->Item(i, getter_AddRefs(node));
|
||||
NS_ASSERTION(node, "incorrect NodeList length?");
|
||||
|
||||
instElement = do_QueryInterface(node);
|
||||
if (!instElement)
|
||||
continue;
|
||||
|
||||
nsCOMArray<nsIInstanceElementPrivate> *instList = nsnull;
|
||||
model->GetInstanceList(&instList);
|
||||
NS_ENSURE_TRUE(instList, NS_ERROR_FAILURE);
|
||||
|
||||
for (int i = 0; i < instList->Count(); ++i) {
|
||||
instElement = instList->ObjectAt(i);
|
||||
|
||||
instElement->GetDocument(getter_AddRefs(instDocument));
|
||||
if (instDocument) {
|
||||
|
||||
@ -87,6 +87,7 @@
|
||||
#include "nsIURI.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
#include "nsIDOMNamedNodeMap.h"
|
||||
#include "nsIParserService.h"
|
||||
|
||||
#define CANCELABLE 0x01
|
||||
#define BUBBLES 0x02
|
||||
@ -536,6 +537,73 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement,
|
||||
aDeps,
|
||||
aIndexesUsed);
|
||||
|
||||
// If the evaluation failed because the node wasn't there and we should be
|
||||
// lazy authoring, then create it (if the situation qualifies, of course).
|
||||
// Novell only allows lazy authoring of single bound nodes.
|
||||
if (aResultType == nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE) {
|
||||
if (res) {
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
rv = res->GetSingleNodeValue(getter_AddRefs(node));
|
||||
if (NS_SUCCEEDED(rv) && !node) {
|
||||
PRBool lazy = PR_FALSE;
|
||||
if (*aModel)
|
||||
(*aModel)->GetLazyAuthored(&lazy);
|
||||
if (lazy) {
|
||||
// according to sec 4.2.2 in the spec, "An instance data element node
|
||||
// will be created using the binding expression from the user
|
||||
// interface control as the name. If the name is not a valid QName,
|
||||
// processing halts with an exception (xforms-binding-exception)"
|
||||
nsCOMPtr<nsIParserService> parserService =
|
||||
do_GetService(NS_PARSERSERVICE_CONTRACTID);
|
||||
if (NS_SUCCEEDED(rv) && parserService) {
|
||||
const PRUnichar* colon;
|
||||
rv = parserService->CheckQName(expr, PR_TRUE, &colon);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsAutoString namespaceURI(EmptyString());
|
||||
|
||||
// if we detect a namespace, we'll add it to the node, otherwise
|
||||
// we'll use the empty namespace. If we should have gotten a
|
||||
// namespace and didn't, then we might as well give up.
|
||||
if (colon) {
|
||||
nsCOMPtr<nsIDOM3Node> dom3node = do_QueryInterface(aElement);
|
||||
rv = dom3node->LookupNamespaceURI(Substring(expr.get(), colon),
|
||||
namespaceURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMArray<nsIInstanceElementPrivate> *instList = nsnull;
|
||||
(*aModel)->GetInstanceList(&instList);
|
||||
nsCOMPtr<nsIInstanceElementPrivate> instance =
|
||||
instList->ObjectAt(0);
|
||||
nsCOMPtr<nsIDOMDocument> domdoc;
|
||||
instance->GetDocument(getter_AddRefs(domdoc));
|
||||
nsCOMPtr<nsIDOMElement> instanceDataEle;
|
||||
nsCOMPtr<nsIDOMNode> childReturn;
|
||||
rv = domdoc->CreateElementNS(namespaceURI, expr,
|
||||
getter_AddRefs(instanceDataEle));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIDOMElement> instanceRoot;
|
||||
rv = domdoc->GetDocumentElement(getter_AddRefs(instanceRoot));
|
||||
rv = instanceRoot->AppendChild(instanceDataEle,
|
||||
getter_AddRefs(childReturn));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// now that we inserted the lazy authored node, try to bind
|
||||
// again
|
||||
res = EvaluateXPath(expr, contextNode, aElement, aResultType,
|
||||
contextPosition, contextSize, aDeps,
|
||||
aIndexesUsed);
|
||||
} else {
|
||||
nsXFormsUtils::DispatchEvent(aElement, eEvent_BindingException);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.swap(*aResult); // exchanges ref
|
||||
|
||||
return NS_OK;
|
||||
@ -1116,22 +1184,14 @@ nsXFormsUtils::GetInstanceNodeForData(nsIDOMNode *aInstanceDataNode,
|
||||
instanceDoc = do_QueryInterface(aInstanceDataNode);
|
||||
NS_ENSURE_TRUE(instanceDoc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> modelElem = do_QueryInterface(aModel);
|
||||
NS_ENSURE_STATE(modelElem);
|
||||
nsCOMPtr<nsIDOMNodeList> nodeList;
|
||||
nsresult rv = modelElem->GetElementsByTagNameNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS),
|
||||
NS_LITERAL_STRING("instance"),
|
||||
getter_AddRefs(nodeList));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMArray<nsIInstanceElementPrivate> *instList = nsnull;
|
||||
aModel->GetInstanceList(&instList);
|
||||
NS_ENSURE_TRUE(instList, NS_ERROR_FAILURE);
|
||||
|
||||
PRUint32 childCount = 0;
|
||||
nodeList->GetLength(&childCount);
|
||||
PRUint32 i;
|
||||
PRUint32 childCount = instList->Count();
|
||||
for (i = 0; i < childCount; ++i) {
|
||||
nodeList->Item(i, aInstanceNode);
|
||||
nsCOMPtr<nsIInstanceElementPrivate> instPriv = do_QueryInterface(*aInstanceNode);
|
||||
if (!instPriv)
|
||||
continue;
|
||||
nsCOMPtr<nsIInstanceElementPrivate> instPriv = instList->ObjectAt(i);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> tmpDoc;
|
||||
instPriv->GetDocument(getter_AddRefs(tmpDoc));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user