diff --git a/mozilla/extensions/xforms/Makefile.in b/mozilla/extensions/xforms/Makefile.in index ce2ac8b300a..c7569491280 100644 --- a/mozilla/extensions/xforms/Makefile.in +++ b/mozilla/extensions/xforms/Makefile.in @@ -72,14 +72,16 @@ XPI_PKGNAME = xforms USE_EXTENSION_MANIFEST = 1 NO_JAR_AUTO_REG = 1 INSTALL_EXTENSION_ID = {cf2812dc-6a7c-4402-b639-4d277dac4c36} -PACKAGE_VERSION = 0.4 +PACKAGE_VERSION = 0.5 # We want to strip the XPI STRIP_XPI = 1 XULAPP_DEFINES = \ -DFIREFOX_VERSION=$(FIREFOX_VERSION) \ - -DMOZILLA_VERSION_U=$(MOZILLA_VERSION) \ + -DMOZILLA_VERSION_U=$(MOZILLA_VERSION_U) \ + -DSEAMONKEY_VERSION=$(SEAMONKEY_VERSION) \ + -DBUILD_ID=$(BUILD_ID) \ -DPACKAGE_VERSION=$(PACKAGE_VERSION) \ -DID=${INSTALL_EXTENSION_ID} \ $(NULL) @@ -117,8 +119,9 @@ REQUIRES = \ XPIDLSRCS = \ nsIXFormsModelElement.idl \ nsIXFormsNSModelElement.idl \ - nsIInstanceElementPrivate.idl \ nsIModelElementPrivate.idl \ + nsIXFormsNSInstanceElement.idl \ + nsIInstanceElementPrivate.idl \ nsIXFormsControl.idl \ nsIXFormsContextControl.idl \ nsIXFormsActionElement.idl \ diff --git a/mozilla/extensions/xforms/install.jst b/mozilla/extensions/xforms/install.jst index d26858dae0b..134d77ee19f 100644 --- a/mozilla/extensions/xforms/install.jst +++ b/mozilla/extensions/xforms/install.jst @@ -16,6 +16,8 @@ if (verifyDiskSpace(fProgram, srChrome + srComponents)) "content/xforms/"); registerChrome(LOCALE | DELAYED_CHROME, getFolder("Chrome", "xforms.jar"), "locale/en-US/xforms/"); + registerChrome(SKIN | DELAYED_CHROME, getFolder("Chrome", "xforms.jar"), + "skin/xforms/"); if (err == SUCCESS) { diff --git a/mozilla/extensions/xforms/install.rdf b/mozilla/extensions/xforms/install.rdf index 3c7ad5498ba..ee8a329b59a 100644 --- a/mozilla/extensions/xforms/install.rdf +++ b/mozilla/extensions/xforms/install.rdf @@ -22,8 +22,17 @@ {86c18b42-e466-45a9-ae7a-9b95ba6f5640} - @MOZILLA_VERSION@ - @MOZILLA_VERSION@ + @MOZILLA_VERSION_U@ + @MOZILLA_VERSION_U@ + + + + + + + {92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} + @SEAMONKEY_VERSION@ + @SEAMONKEY_VERSION@ @@ -32,4 +41,3 @@ http://www.mozilla.org/projects/xforms/ - diff --git a/mozilla/extensions/xforms/jar.mn b/mozilla/extensions/xforms/jar.mn index 9ec17b0e1ab..6a5b820bafc 100755 --- a/mozilla/extensions/xforms/jar.mn +++ b/mozilla/extensions/xforms/jar.mn @@ -2,19 +2,30 @@ xforms.jar: % overlay chrome://browser/content/preferences/preferences.xul chrome://xforms/content/xforms-prefs.xul % content xforms %content/xforms/ % locale xforms en-US %locale/en-US/xforms/ +% skin xforms classic/1.0 %skin/xforms/ content/xforms/contents.rdf (resources/content/contents.rdf) * content/xforms/xforms.css (resources/content/xforms.css) * content/xforms/xforms-prefs.xul (resources/content/xforms-prefs.xul) * content/xforms/xforms-prefs-ui.xul (resources/content/xforms-prefs-ui.xul) * content/xforms/xforms-prefs.js (resources/content/xforms-prefs.js) + content/xforms/widgets.xml (resources/content/widgets.xml) + content/xforms/widgets-xhtml.xml (resources/content/widgets-xhtml.xml) content/xforms/xforms.xml (resources/content/xforms.xml) + content/xforms/xforms-xhtml.xml (resources/content/xforms-xhtml.xml) + content/xforms/xforms-xul.xml (resources/content/xforms-xul.xml) + content/xforms/input.xml (resources/content/input.xml) + content/xforms/input-xhtml.xml (resources/content/input-xhtml.xml) + content/xforms/input-xul.xml (resources/content/input-xul.xml) content/xforms/select1.xml (resources/content/select1.xml) content/xforms/range.xml (resources/content/range.xml) content/xforms/select.xml (resources/content/select.xml) + content/xforms/select-xhtml.xml (resources/content/select-xhtml.xml) + content/xforms/select-xul.xml (resources/content/select-xul.xml) content/xforms/bindingex.css (resources/content/bindingex.css) content/xforms/bindingex.xul (resources/content/bindingex.xul) content/xforms/calendar.png (resources/content/calendar.png) * locale/en-US/xforms/contents.rdf (resources/locale/en-US/contents.rdf) locale/en-US/xforms/xforms.properties (resources/locale/en-US/xforms.properties) locale/en-US/xforms/xforms.dtd (resources/locale/en-US/xforms.dtd) +* skin/xforms/contents.rdf (resources/skin/contents.rdf) diff --git a/mozilla/extensions/xforms/nsIInstanceElementPrivate.idl b/mozilla/extensions/xforms/nsIInstanceElementPrivate.idl index c3373046e3a..f0d7498a967 100644 --- a/mozilla/extensions/xforms/nsIInstanceElementPrivate.idl +++ b/mozilla/extensions/xforms/nsIInstanceElementPrivate.idl @@ -36,21 +36,21 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsISupports.idl" +#include "nsIXFormsNSInstanceElement.idl" -interface nsIDOMDocument; interface nsIDOMElement; /** - * Private interface implemented by the instance element. + * Private interface implemented by the \ element. */ -[uuid(debb24ef-7ba1-4e01-9f62-18106b25c993)] -interface nsIInstanceElementPrivate : nsISupports +[uuid(e9a975d7-616c-4c4b-9413-3aa8001cdb08)] +interface nsIInstanceElementPrivate : nsIXFormsNSInstanceElement { /** - * The document which holds the live instance data. + * Set instance document. */ - attribute nsIDOMDocument document; + void setInstanceDocument(in nsIDOMDocument document); + readonly attribute nsIDOMElement element; void backupOriginalDocument(); void restoreOriginalDocument(); diff --git a/mozilla/extensions/xforms/nsIModelElementPrivate.idl b/mozilla/extensions/xforms/nsIModelElementPrivate.idl index abd47088d46..f269b097140 100644 --- a/mozilla/extensions/xforms/nsIModelElementPrivate.idl +++ b/mozilla/extensions/xforms/nsIModelElementPrivate.idl @@ -47,7 +47,7 @@ interface nsIDOMNode; * Private interface implemented by the model element for other * elements to use. */ -[uuid(a6522c1a-a343-4b36-a130-75eb279a667a)] +[uuid(d84caeb1-355f-48ff-9180-a45d8352d26a)] interface nsIModelElementPrivate : nsIXFormsModelElement { /** @@ -55,7 +55,7 @@ interface nsIModelElementPrivate : nsIXFormsModelElement * this model. These form controls will be refreshed when refresh() is * called on the model. */ - void addFormControl(in nsIXFormsControl control); + void addFormControl(in nsIXFormsControl control, in nsIXFormsControl parent); void removeFormControl(in nsIXFormsControl control); /** @@ -75,7 +75,7 @@ interface nsIModelElementPrivate : nsIXFormsModelElement /** * Notification that an instance element has started or finished loading - * its instance data. Model contstruction cannot complete until all of + * its instance data. Model construction cannot complete until all of * the instances have loaded their data. */ void instanceLoadStarted(); @@ -138,18 +138,36 @@ interface nsIModelElementPrivate : nsIXFormsModelElement */ void addInstanceElement(in nsIInstanceElementPrivate aInstanceElement); + /** + * Remove an instance element from the model's instance list + * @param aInstanceElement The instance element to remove from the list + */ + void removeInstanceElement(in nsIInstanceElementPrivate aInstanceElement); + /** * This attribute is set when the model's instance was lazy authored */ readonly attribute boolean lazyAuthored; - - /** - * Retrieves the type for an instance data node - * - * @param aInstanceData The instance data node - * @param aType The type of the node - * @param aNSURI The namespace of the type - */ - void GetTypeFromNode(in nsIDOMNode aInstanceData, out AString aType, - out AString aNSUri); + + /** + * This attribute is set when the model handled xforms-ready event + */ + readonly attribute boolean isReady; + + /** + * Retrieves the type for an instance data node + * + * @param aInstanceData The instance data node + * @param aType The type of the node + * @param aNSURI The namespace of the type + */ + void GetTypeFromNode(in nsIDOMNode aInstanceData, out AString aType, + out AString aNSUri); + + /** + * Notification that all of the external message loads have finished loading. + * Model contstruction cannot complete until all of the external messages + * have loaded their data. + */ + void messageLoadFinished(); }; diff --git a/mozilla/extensions/xforms/nsIXFormsControl.idl b/mozilla/extensions/xforms/nsIXFormsControl.idl index 1c7a6614870..08181e5a514 100644 --- a/mozilla/extensions/xforms/nsIXFormsControl.idl +++ b/mozilla/extensions/xforms/nsIXFormsControl.idl @@ -49,7 +49,7 @@ interface nsIDOMElement; /** * Interface implemented by all XForms form control classes. */ -[uuid(8377c845-5d55-4eee-9a76-0f86751dcbc8)] +[uuid(1bea8750-2133-4a00-986a-04e5cbd129b2)] interface nsIXFormsControl : nsIXFormsContextControl { /** @@ -86,4 +86,10 @@ interface nsIXFormsControl : nsIXFormsContextControl * need to override IsEventTarget() and return PR_FALSE */ boolean isEventTarget(); + + /** + * Is true when the control is getting its instance data node binding from a + * model bind element, ie. it has a |bind| attribute. + */ + readonly attribute boolean usesModelBinding; }; diff --git a/mozilla/extensions/xforms/nsIXFormsNSInstanceElement.idl b/mozilla/extensions/xforms/nsIXFormsNSInstanceElement.idl new file mode 100755 index 00000000000..65757fa074f --- /dev/null +++ b/mozilla/extensions/xforms/nsIXFormsNSInstanceElement.idl @@ -0,0 +1,53 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla XForms support. + * + * The Initial Developer of the Original Code is + * Alexander Surkov. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov + * + * 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 nsIDOMDocument; + +/** + * Defines additional post-spec. functions for the \ element. + */ +[scriptable, uuid(80669b92-8331-4f92-aaf8-06e80e6827b3)] +interface nsIXFormsNSInstanceElement : nsISupports +{ + /** + * Return instance document + */ + nsIDOMDocument getInstanceDocument(); +}; diff --git a/mozilla/extensions/xforms/nsIXFormsRepeatElement.idl b/mozilla/extensions/xforms/nsIXFormsRepeatElement.idl index 0b7e548e57d..200e7060d2a 100644 --- a/mozilla/extensions/xforms/nsIXFormsRepeatElement.idl +++ b/mozilla/extensions/xforms/nsIXFormsRepeatElement.idl @@ -46,7 +46,7 @@ interface nsIXFormsControl; interface nsIDOMNode; -[uuid(419e780d-4f31-4aa4-bae8-a18099d77bb6)] +[uuid(41a0ea05-3fe0-48e8-8c38-96cbb544309c)] interface nsIXFormsRepeatElement : nsISupports { /** @@ -115,5 +115,19 @@ interface nsIXFormsRepeatElement : nsISupports */ void indexHasChanged(); + /** + * Retrieve the starting index for the repeat, that is the index that the + * repeat is initialized to. It is the "startindex" attribute, corrected to + * be a valid index value. + */ unsigned long getStartingIndex(); + + /** + * Handle insertion of a node, ie. eventually adjust index. Note that the + * node might not be influencing the repeat, it is the repeat's + * responsibility to check that. + * + * @param node The node that was inserted + */ + void handleNodeInsert(in nsIDOMNode node); }; diff --git a/mozilla/extensions/xforms/nsIXFormsRepeatItemElement.idl b/mozilla/extensions/xforms/nsIXFormsRepeatItemElement.idl index 0d933952e4c..960274a8d6b 100644 --- a/mozilla/extensions/xforms/nsIXFormsRepeatItemElement.idl +++ b/mozilla/extensions/xforms/nsIXFormsRepeatItemElement.idl @@ -43,7 +43,7 @@ #include "nsISupports.idl" -[uuid(2bd6a7c7-ca59-408b-9a2a-c1bdef919fd5)] +[uuid(a60f5ef2-6c3d-4c57-af19-033734354115)] interface nsIXFormsRepeatItemElement : nsISupports { /** @@ -51,4 +51,9 @@ interface nsIXFormsRepeatItemElement : nsISupports * can set the :repeat-index accordingly. */ attribute boolean indexState; + + /** + * This returns the context position of the repeat item. + */ + readonly attribute long contextPosition; }; diff --git a/mozilla/extensions/xforms/nsIXFormsSwitchElement.idl b/mozilla/extensions/xforms/nsIXFormsSwitchElement.idl index 005532f7ccb..21ff8f8f744 100644 --- a/mozilla/extensions/xforms/nsIXFormsSwitchElement.idl +++ b/mozilla/extensions/xforms/nsIXFormsSwitchElement.idl @@ -43,16 +43,21 @@ interface nsIDOMElement; /** * Interface implemented by the switch element. */ -[uuid(edeb1e48-5d5c-4091-8021-5975310caa66)] +[scriptable, uuid(42af102c-4c96-4534-9ea7-20a23fddbf60)] interface nsIXFormsSwitchElement : nsISupports { /** - * Used by case elements to select or deselect themselves. + * Select or deselect a given case element. * - * @param aCase The case element - * @param aValue The value of the selected attribute. + * @param caseEl The case element + * @param value Select (true) or deselect (false) */ - void setSelected(in nsIDOMElement aCase, in boolean aValue); + void setSelected(in nsIDOMElement caseEl, in boolean value); + + /** + * Retrieve the currently selected case element. + */ + readonly attribute nsIDOMElement selected; }; diff --git a/mozilla/extensions/xforms/nsXFormsAccessors.cpp b/mozilla/extensions/xforms/nsXFormsAccessors.cpp index 366f5ae14b7..53b6f2c793a 100644 --- a/mozilla/extensions/xforms/nsXFormsAccessors.cpp +++ b/mozilla/extensions/xforms/nsXFormsAccessors.cpp @@ -45,6 +45,7 @@ #include "nsIEventStateManager.h" #include "nsIContent.h" #include "nsIXFormsControl.h" +#include "nsIProgrammingLanguage.h" NS_IMPL_ISUPPORTS2(nsXFormsAccessors, nsIXFormsAccessors, nsIClassInfo) diff --git a/mozilla/extensions/xforms/nsXFormsActionElement.cpp b/mozilla/extensions/xforms/nsXFormsActionElement.cpp index 894514173ed..06cdec95b98 100644 --- a/mozilla/extensions/xforms/nsXFormsActionElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsActionElement.cpp @@ -42,68 +42,45 @@ #include "nsIDOMDocument.h" #include "nsIDOMEvent.h" #include "nsIDOMElement.h" -#include "nsIXTFXMLVisualWrapper.h" - -#define ACTION_STYLE_HIDDEN \ - "position:absolute;z-index:2147483647;visibility:hidden;" +#include "nsIXTFBindableElementWrapper.h" #define DEFERRED_REBUILD 0x01 #define DEFERRED_RECALCULATE 0x02 #define DEFERRED_REVALIDATE 0x04 #define DEFERRED_REFRESH 0x08 -nsXFormsActionElement::nsXFormsActionElement() +nsXFormsActionElement::nsXFormsActionElement() : mElement(nsnull) { } -NS_IMPL_ADDREF_INHERITED(nsXFormsActionElement, nsXFormsXMLVisualStub) -NS_IMPL_RELEASE_INHERITED(nsXFormsActionElement, nsXFormsXMLVisualStub) +NS_IMPL_ADDREF_INHERITED(nsXFormsActionElement, nsXFormsBindableStub) +NS_IMPL_RELEASE_INHERITED(nsXFormsActionElement, nsXFormsBindableStub) NS_INTERFACE_MAP_BEGIN(nsXFormsActionElement) NS_INTERFACE_MAP_ENTRY(nsIXFormsActionModuleElement) NS_INTERFACE_MAP_ENTRY(nsIXFormsActionElement) NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) -NS_INTERFACE_MAP_END_INHERITING(nsXFormsXMLVisualStub) +NS_INTERFACE_MAP_END_INHERITING(nsXFormsBindableStub) NS_IMETHODIMP -nsXFormsActionElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper) +nsXFormsActionElement::OnCreated(nsIXTFBindableElementWrapper* aWrapper) { - nsresult rv = nsXFormsXMLVisualStub::OnCreated(aWrapper); + nsresult rv = nsXFormsBindableStub::OnCreated(aWrapper); NS_ENSURE_SUCCESS(rv, rv); - rv = aWrapper->GetElementNode(getter_AddRefs(mElement)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr domDoc; - mElement->GetOwnerDocument(getter_AddRefs(domDoc)); - rv = domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML), - NS_LITERAL_STRING("div"), - getter_AddRefs(mVisualElement)); - NS_ENSURE_SUCCESS(rv, rv); - if (mVisualElement) - mVisualElement->SetAttribute(NS_LITERAL_STRING("style"), - NS_LITERAL_STRING(ACTION_STYLE_HIDDEN)); - return NS_OK; -} - -NS_IMETHODIMP -nsXFormsActionElement::GetVisualContent(nsIDOMElement **aElement) -{ - NS_IF_ADDREF(*aElement = mVisualElement); - return NS_OK; -} - -NS_IMETHODIMP -nsXFormsActionElement::GetInsertionPoint(nsIDOMElement **aElement) -{ - NS_IF_ADDREF(*aElement = mVisualElement); + // 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. + nsCOMPtr node; + aWrapper->GetElementNode(getter_AddRefs(node)); + mElement = node; + NS_ASSERTION(mElement, "Wrapper is not an nsIDOMElement, we'll crash soon"); return NS_OK; } NS_IMETHODIMP nsXFormsActionElement::OnDestroyed() { mParentAction = nsnull; - mVisualElement = nsnull; mElement = nsnull; return NS_OK; } @@ -137,22 +114,23 @@ NS_IMETHODIMP nsXFormsActionElement::HandleAction(nsIDOMEvent* aEvent, nsIXFormsActionElement *aParentAction) { - if (!mElement) + if (!mElement) { return NS_OK; + } if (!mDeferredUpdates.IsInitialized()) { - if (!mDeferredUpdates.Init()) - return NS_ERROR_OUT_OF_MEMORY; - } - else { + NS_ENSURE_TRUE(mDeferredUpdates.Init(), NS_ERROR_OUT_OF_MEMORY); + } else { mDeferredUpdates.Clear(); } mParentAction = aParentAction; nsCOMPtr childNodes; mElement->GetChildNodes(getter_AddRefs(childNodes)); - if (!childNodes) + if (!childNodes) { return NS_OK; + } + PRUint32 count; childNodes->GetLength(&count); nsCOMPtr actionChild; @@ -161,25 +139,30 @@ nsXFormsActionElement::HandleAction(nsIDOMEvent* aEvent, nsCOMPtr child; childNodes->Item(i, getter_AddRefs(child)); actionChild = do_QueryInterface(child); - if (actionChild) + if (actionChild) { actionChild->HandleAction(event, this); + } } - if (!aParentAction) //Otherwise parent will handle deferred updates + if (!aParentAction) { //Otherwise parent will handle deferred updates mDeferredUpdates.EnumerateRead(DoDeferredActions, nsnull); + } return NS_OK; } NS_IMETHODIMP nsXFormsActionElement::SetRebuild(nsIDOMNode* aModel, PRBool aEnable) { - if (mParentAction) + if (mParentAction) { return mParentAction->SetRebuild(aModel, aEnable); + } + PRUint32 deferred = 0; mDeferredUpdates.Get(aModel, &deferred); - if (aEnable) + if (aEnable) { deferred |= DEFERRED_REBUILD; - else + } else { deferred &= ~DEFERRED_REBUILD; + } mDeferredUpdates.Put(aModel, deferred); return NS_OK; } @@ -187,14 +170,17 @@ nsXFormsActionElement::SetRebuild(nsIDOMNode* aModel, PRBool aEnable) NS_IMETHODIMP nsXFormsActionElement::SetRecalculate(nsIDOMNode* aModel, PRBool aEnable) { - if (mParentAction) + if (mParentAction) { return mParentAction->SetRecalculate(aModel, aEnable); + } + PRUint32 deferred = 0; mDeferredUpdates.Get(aModel, &deferred); - if (aEnable) + if (aEnable) { deferred |= DEFERRED_RECALCULATE; - else + } else { deferred &= ~DEFERRED_RECALCULATE; + } mDeferredUpdates.Put(aModel, deferred); return NS_OK; } @@ -202,14 +188,17 @@ nsXFormsActionElement::SetRecalculate(nsIDOMNode* aModel, PRBool aEnable) NS_IMETHODIMP nsXFormsActionElement::SetRevalidate(nsIDOMNode* aModel, PRBool aEnable) { - if (mParentAction) + if (mParentAction) { return mParentAction->SetRevalidate(aModel, aEnable); + } + PRUint32 deferred = 0; mDeferredUpdates.Get(aModel, &deferred); - if (aEnable) + if (aEnable) { deferred |= DEFERRED_REVALIDATE; - else + } else { deferred &= ~DEFERRED_REVALIDATE; + } mDeferredUpdates.Put(aModel, deferred); return NS_OK; } @@ -217,14 +206,17 @@ nsXFormsActionElement::SetRevalidate(nsIDOMNode* aModel, PRBool aEnable) NS_IMETHODIMP nsXFormsActionElement::SetRefresh(nsIDOMNode* aModel, PRBool aEnable) { - if (mParentAction) + if (mParentAction) { return mParentAction->SetRefresh(aModel, aEnable); + } + PRUint32 deferred = 0; mDeferredUpdates.Get(aModel, &deferred); - if (aEnable) + if (aEnable) { deferred |= DEFERRED_REFRESH; - else + } else { deferred &= ~DEFERRED_REFRESH; + } mDeferredUpdates.Put(aModel, deferred); return NS_OK; } @@ -233,8 +225,9 @@ NS_HIDDEN_(nsresult) NS_NewXFormsActionElement(nsIXTFElement **aResult) { *aResult = new nsXFormsActionElement(); - if (!*aResult) + if (!*aResult) { return NS_ERROR_OUT_OF_MEMORY; + } NS_ADDREF(*aResult); return NS_OK; diff --git a/mozilla/extensions/xforms/nsXFormsActionElement.h b/mozilla/extensions/xforms/nsXFormsActionElement.h index 54cf7ec6e87..ee497165661 100644 --- a/mozilla/extensions/xforms/nsXFormsActionElement.h +++ b/mozilla/extensions/xforms/nsXFormsActionElement.h @@ -44,8 +44,10 @@ #include "nsDataHashtable.h" #include "nsXFormsStubElement.h" -class nsXFormsActionElement : public nsIXFormsActionElement, - public nsXFormsXMLVisualStub, +class nsIXTFBindableElementWrapper; + +class nsXFormsActionElement : public nsXFormsBindableStub, + public nsIXFormsActionElement, public nsIXFormsActionModuleElement, public nsIDOMEventListener { @@ -55,15 +57,12 @@ public: NS_DECL_NSIDOMEVENTLISTENER NS_DECL_NSIXFORMSACTIONELEMENT NS_DECL_NSIXFORMSACTIONMODULEELEMENT - NS_IMETHOD OnCreated(nsIXTFXMLVisualWrapper *aWrapper); - NS_IMETHOD GetVisualContent(nsIDOMElement **aElement); - NS_IMETHOD GetInsertionPoint(nsIDOMElement **aElement); + NS_IMETHOD OnCreated(nsIXTFBindableElementWrapper* aWrapper); NS_IMETHOD OnDestroyed(); private: - nsCOMPtr mElement; - nsCOMPtr mVisualElement; - nsCOMPtr mParentAction; - nsDataHashtable mDeferredUpdates; + nsIDOMElement* mElement; + nsCOMPtr mParentAction; + nsDataHashtable mDeferredUpdates; }; #endif diff --git a/mozilla/extensions/xforms/nsXFormsActionModuleBase.cpp b/mozilla/extensions/xforms/nsXFormsActionModuleBase.cpp index f9cd8e236f9..c2e5bb7744c 100644 --- a/mozilla/extensions/xforms/nsXFormsActionModuleBase.cpp +++ b/mozilla/extensions/xforms/nsXFormsActionModuleBase.cpp @@ -49,7 +49,7 @@ #include "nsIDOMDocumentEvent.h" #include "nsIDOMEventTarget.h" -nsXFormsActionModuleBase::nsXFormsActionModuleBase() +nsXFormsActionModuleBase::nsXFormsActionModuleBase() : mElement(nsnull) { } @@ -65,7 +65,13 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsActionModuleBase, NS_IMETHODIMP nsXFormsActionModuleBase::OnCreated(nsIXTFGenericElementWrapper *aWrapper) { - aWrapper->GetElementNode(getter_AddRefs(mElement)); + // 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. + nsCOMPtr node; + aWrapper->GetElementNode(getter_AddRefs(node)); + mElement = node; + NS_ASSERTION(mElement, "Wrapper is not an nsIDOMElement, we'll crash soon"); return NS_OK; } diff --git a/mozilla/extensions/xforms/nsXFormsActionModuleBase.h b/mozilla/extensions/xforms/nsXFormsActionModuleBase.h index 0fd957b1527..2d431fc8faa 100644 --- a/mozilla/extensions/xforms/nsXFormsActionModuleBase.h +++ b/mozilla/extensions/xforms/nsXFormsActionModuleBase.h @@ -58,7 +58,7 @@ public: NS_DECL_NSIDOMEVENTLISTENER NS_IMETHOD OnDestroyed(); protected: - nsCOMPtr mElement; + nsIDOMElement* mElement; }; #endif diff --git a/mozilla/extensions/xforms/nsXFormsAtoms.cpp b/mozilla/extensions/xforms/nsXFormsAtoms.cpp index 177ef1cab60..516db31f4ef 100644 --- a/mozilla/extensions/xforms/nsXFormsAtoms.cpp +++ b/mozilla/extensions/xforms/nsXFormsAtoms.cpp @@ -64,6 +64,7 @@ nsIAtom *nsXFormsAtoms::readyForBindProperty; nsIAtom *nsXFormsAtoms::fatalError; nsIAtom *nsXFormsAtoms::isInstanceDocument; nsIAtom *nsXFormsAtoms::instanceDocumentOwner; +nsIAtom *nsXFormsAtoms::externalMessagesProperty; const nsStaticAtom nsXFormsAtoms::Atoms_info[] = { { "src", &nsXFormsAtoms::src }, @@ -90,7 +91,8 @@ const nsStaticAtom nsXFormsAtoms::Atoms_info[] = { { "ReadyForBindProperty", &nsXFormsAtoms::readyForBindProperty }, { "fatalError", &nsXFormsAtoms::fatalError }, { "isInstanceDocument", &nsXFormsAtoms::isInstanceDocument }, - { "instanceDocumentOwner", &nsXFormsAtoms::instanceDocumentOwner } + { "instanceDocumentOwner", &nsXFormsAtoms::instanceDocumentOwner }, + { "ExternalMessagesProperty", &nsXFormsAtoms::externalMessagesProperty } }; void diff --git a/mozilla/extensions/xforms/nsXFormsAtoms.h b/mozilla/extensions/xforms/nsXFormsAtoms.h index fa8eec4cd2e..a5ab9de6eaa 100644 --- a/mozilla/extensions/xforms/nsXFormsAtoms.h +++ b/mozilla/extensions/xforms/nsXFormsAtoms.h @@ -72,6 +72,7 @@ class nsXFormsAtoms static NS_HIDDEN_(nsIAtom *) fatalError; static NS_HIDDEN_(nsIAtom *) isInstanceDocument; static NS_HIDDEN_(nsIAtom *) instanceDocumentOwner; + static NS_HIDDEN_(nsIAtom *) externalMessagesProperty; static NS_HIDDEN_(void) InitAtoms(); diff --git a/mozilla/extensions/xforms/nsXFormsCaseElement.cpp b/mozilla/extensions/xforms/nsXFormsCaseElement.cpp index 9da9cfcb4d4..31c3fea3cf3 100644 --- a/mozilla/extensions/xforms/nsXFormsCaseElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsCaseElement.cpp @@ -60,6 +60,7 @@ public: NS_IMETHOD OnCreated(nsIXTFBindableElementWrapper *aWrapper); NS_IMETHOD OnDestroyed(); + NS_IMETHOD DoneAddingChildren(); nsXFormsCaseElement() : mElement(nsnull), mSelected(PR_FALSE), mCachedSelectedAttr(PR_FALSE) @@ -82,6 +83,8 @@ nsXFormsCaseElement::OnCreated(nsIXTFBindableElementWrapper *aWrapper) nsresult rv = nsXFormsBindableStub::OnCreated(aWrapper); NS_ENSURE_SUCCESS(rv, rv); + aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN); + nsCOMPtr node; aWrapper->GetElementNode(getter_AddRefs(node)); @@ -101,6 +104,19 @@ nsXFormsCaseElement::OnDestroyed() return NS_OK; } +NS_IMETHODIMP +nsXFormsCaseElement::DoneAddingChildren() +{ + // cache the value of the "selected" attr + nsAutoString value; + mElement->GetAttribute(NS_LITERAL_STRING("selected"), value); + if (value.EqualsLiteral("true") || value.EqualsLiteral("1")) { + mCachedSelectedAttr = PR_TRUE; + } + + return NS_OK; +} + NS_IMETHODIMP nsXFormsCaseElement::GetInitialSelectedState(PRBool *aInitialSelectedState) { @@ -114,24 +130,19 @@ nsXFormsCaseElement::SetSelected(PRBool aEnable) mSelected = aEnable; nsCOMPtr caseUI(do_QueryInterface(mElement)); - if (caseUI) { - caseUI->CaseSelected(mSelected); - } + if (!caseUI) + return NS_ERROR_FAILURE; + caseUI->CaseSelected(mSelected); return NS_OK; } NS_IMETHODIMP nsXFormsCaseElement::WidgetAttached() { - // cache the value of the "selected" attr - nsAutoString value; - mElement->GetAttribute(NS_LITERAL_STRING("selected"), value); - if (value.EqualsLiteral("true") || value.EqualsLiteral("1")) { - mCachedSelectedAttr = PR_TRUE; - } - nsCOMPtr caseUI(do_QueryInterface(mElement)); + NS_WARN_IF_FALSE(caseUI, + "Case element not implementing nsIXFormCaseUIElement?"); if (caseUI) { caseUI->CaseSelected(mSelected); } diff --git a/mozilla/extensions/xforms/nsXFormsContextContainer.cpp b/mozilla/extensions/xforms/nsXFormsContextContainer.cpp index 0ee581ea120..e8f8840d332 100644 --- a/mozilla/extensions/xforms/nsXFormsContextContainer.cpp +++ b/mozilla/extensions/xforms/nsXFormsContextContainer.cpp @@ -45,6 +45,7 @@ #include "nsIDOMDocument.h" #include "nsIDOMElement.h" #include "nsIDOMEvent.h" +#include "nsIDOMNSEvent.h" #include "nsIDOMEventTarget.h" #include "nsIDOMSerializer.h" #include "nsIDOMXPathResult.h" @@ -137,40 +138,70 @@ nsXFormsContextContainer::HandleDefault(nsIDOMEvent *aEvent, nsAutoString type; aEvent->GetType(type); - if (!type.EqualsLiteral("focus")) + // Need to use "DOMFocusIn" here, "focus" doesn't bubble + if (!type.EqualsLiteral("DOMFocusIn")) return nsXFormsBindableControlStub::HandleDefault(aEvent, aHandled); if (!nsXFormsUtils::EventHandlingAllowed(aEvent, mElement)) return NS_OK; - /* - * Either we, or an element we contain, has gotten focus, so we need to set - * the repeat index. This is done through the \ the - * nsXFormsContextContainer belongs to. - * - * Start by finding the \ (our grandparent): - *
-   *  <-- gParent
-   *   
- * <-- this - *
- *
- *
- */ - nsCOMPtr parent; - mElement->GetParentNode(getter_AddRefs(parent)); - NS_ASSERTION(parent, "how can we get focus without a parent?"); - - nsCOMPtr gParent; - parent->GetParentNode(getter_AddRefs(gParent)); - nsCOMPtr repeat = do_QueryInterface(gParent); - if (!repeat) - // Not a child to a \ - return NS_OK; + // Need to explicitly create the parent chain. This ensures that this code + // works both in 1.8, which has the old event dispatching code, and also in + // the later versions of Gecko with the new event dispatching. + // See also Bug 331081. + nsCOMPtr event = do_QueryInterface(aEvent); + NS_ENSURE_STATE(event); + nsCOMPtr target; + event->GetOriginalTarget(getter_AddRefs(target)); + nsCOMPtr currentNode = do_QueryInterface(target); - // Tell \ about the new index position - PRUint32 tmp = mContextPosition; - return repeat->SetIndex(&tmp, PR_FALSE); + nsCOMArray containerStack(4); + while (currentNode) { + nsCOMPtr repeatItem = + do_QueryInterface(currentNode); + if (repeatItem) { + containerStack.AppendObject(currentNode); + } + nsCOMPtr parent; + currentNode->GetParentNode(getter_AddRefs(parent)); + currentNode.swap(parent); + } + + for (PRInt32 i = containerStack.Count() - 1; i >= 0; --i) { + nsCOMPtr node = containerStack[i]; + if (node) { + // Either we, or an element we contain, has gotten focus, so we need to + // set the repeat index. This is done through the the + // nsXFormsContextContainer belongs to. + // + // Start by finding the (our grandparent): + // <-- gParent + //
+ // <-- this + //
+ //
+ nsCOMPtr parent; + node->GetParentNode(getter_AddRefs(parent)); + if (parent) { + nsCOMPtr grandParent; + parent->GetParentNode(getter_AddRefs(grandParent)); + nsCOMPtr repeat = + do_QueryInterface(grandParent); + nsCOMPtr repeatItem = + do_QueryInterface(node); + if (repeat && repeatItem) { + PRInt32 position = 1; + repeatItem->GetContextPosition(&position); + // Tell about the new index position + PRUint32 tmp = position; + repeat->SetIndex(&tmp, PR_FALSE); + } + } + } + } + + *aHandled = PR_TRUE; + return NS_OK; } NS_IMETHODIMP @@ -200,19 +231,7 @@ nsXFormsContextContainer::SetContext(nsIDOMNode *aContextNode, mContextPosition = aContextPosition; mContextSize = aContextSize; - // Remove from old model (if any) - if (mModel) { - mModel->RemoveFormControl(this); - } - - // Add to new model - mModel = nsXFormsUtils::GetModel(mElement); - if (mModel) { - mModel->AddFormControl(this); - mModel->SetStates(this, mBoundNode); - } - - return NS_OK; + return Bind(); } NS_IMETHODIMP @@ -238,6 +257,14 @@ nsXFormsContextContainer::GetContext(nsAString &aModelID, NS_IMETHODIMP nsXFormsContextContainer::Bind() { + + nsresult rv = BindToModel(); + NS_ENSURE_SUCCESS(rv, rv); + + if (mModel) { + mModel->SetStates(this, mBoundNode); + } + return NS_OK; } @@ -283,6 +310,13 @@ nsXFormsContextContainer::GetIndexState(PRBool *aHasIndex) return NS_OK; } +NS_IMETHODIMP +nsXFormsContextContainer::GetContextPosition(PRInt32 *aContextPosition) +{ + *aContextPosition = mContextPosition; + return NS_OK; +} + // Factory NS_HIDDEN_(nsresult) NS_NewXFormsContextContainer(nsIXTFElement **aResult) diff --git a/mozilla/extensions/xforms/nsXFormsControlStub.cpp b/mozilla/extensions/xforms/nsXFormsControlStub.cpp index 7f4243d87f4..2faee0fe9e1 100644 --- a/mozilla/extensions/xforms/nsXFormsControlStub.cpp +++ b/mozilla/extensions/xforms/nsXFormsControlStub.cpp @@ -51,10 +51,10 @@ #include "nsXFormsModelElement.h" #include "nsPIDOMWindow.h" #include "nsIFocusController.h" -#include "nsIScriptGlobalObject.h" #include "nsIServiceManager.h" #include "nsIEventStateManager.h" #include "nsIContent.h" +#include "nsIDOM3Node.h" /** This class is used to generate xforms-hint and xforms-help events.*/ class nsXFormsHintHelpListener : public nsIDOMEventListener { @@ -147,6 +147,7 @@ nsXFormsControlStubBase::ResetBoundNode(const nsString &aBindAttribute, { // Clear existing bound node, etc. mBoundNode = nsnull; + mUsesModelBinding = PR_FALSE; mDependencies.Clear(); RemoveIndexListeners(); @@ -167,8 +168,13 @@ nsXFormsControlStubBase::ResetBoundNode(const nsString &aBindAttribute, if (!result) return NS_OK; - // Get context node, if any - result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); + // Get context node, if any + if (mUsesModelBinding) { + // When bound via @bind, we'll get a snapshot back + result->SnapshotItem(0, getter_AddRefs(mBoundNode)); + } else { + result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); + } if (mBoundNode && mModel) { mModel->SetStates(this, mBoundNode); @@ -177,12 +183,10 @@ nsXFormsControlStubBase::ResetBoundNode(const nsString &aBindAttribute, // 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")); + nsCOMPtr xtfWrap(do_QueryInterface(mElement)); + NS_ENSURE_STATE(xtfWrap); + xtfWrap->SetIntrinsicState(NS_EVENT_STATE_DISABLED); + // Dispatch event nsXFormsUtils::DispatchEvent(mElement, eEvent_Disabled); } @@ -215,13 +219,42 @@ nsXFormsControlStubBase::IsEventTarget(PRBool *aOK) *aOK = PR_TRUE; return NS_OK; } - + +NS_IMETHODIMP +nsXFormsControlStubBase::GetUsesModelBinding(PRBool *aRes) +{ + *aRes = mUsesModelBinding; + return NS_OK; +} + +nsresult +nsXFormsControlStubBase::MaybeAddToModel(nsIModelElementPrivate *aOldModel, + nsIXFormsControl *aParent) +{ + // XXX: just doing pointer comparison would be nice.... + PRBool sameModel = PR_FALSE; + nsCOMPtr n3Model(do_QueryInterface(mModel)); + nsCOMPtr nOldModel(do_QueryInterface(aOldModel)); + NS_ASSERTION(n3Model, "model element not supporting nsIDOM3Node?!"); + nsresult rv = n3Model->IsSameNode(nOldModel, &sameModel); + NS_ENSURE_SUCCESS(rv, rv); + if (!sameModel) { + if (aOldModel) { + rv = aOldModel->RemoveFormControl(this); + NS_ENSURE_SUCCESS(rv, rv); + } + rv = mModel->AddFormControl(this, aParent); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; +} + nsresult nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAttr, - PRUint16 aResultType, - nsIDOMXPathResult **aResult, - nsIModelElementPrivate **aModel) + PRUint16 aResultType, + nsIDOMXPathResult **aResult, + nsIModelElementPrivate **aModel) { nsStringArray indexesUsed; @@ -240,6 +273,9 @@ nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAtt } nsresult rv; + PRBool usesModelBinding; + nsCOMPtr oldModel(mModel); + nsCOMPtr parentControl; rv = nsXFormsUtils::EvaluateNodeBinding(mElement, kElementFlags, aBindingAttr, @@ -247,17 +283,22 @@ nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAtt aResultType, getter_AddRefs(mModel), aResult, + &usesModelBinding, + getter_AddRefs(parentControl), &mDependencies, &indexesUsed); NS_ENSURE_STATE(mModel); - - mModel->AddFormControl(this); + + rv = MaybeAddToModel(oldModel, parentControl); + NS_ENSURE_SUCCESS(rv, rv); + if (aModel) NS_ADDREF(*aModel = mModel); + mUsesModelBinding = usesModelBinding; if (NS_SUCCEEDED(rv) && indexesUsed.Count()) { // add index listeners on repeat elements - + for (PRInt32 i = 0; i < indexesUsed.Count(); ++i) { // Find the repeat element and add |this| as a listener nsCOMPtr repElem; @@ -278,6 +319,23 @@ nsXFormsControlStubBase::ProcessNodeBinding(const nsString &aBindingAtt return rv; } +nsresult +nsXFormsControlStubBase::BindToModel(PRBool aSetBoundNode) +{ + nsCOMPtr oldModel(mModel); + + nsCOMPtr parentControl; + nsCOMPtr boundNode; + mModel = nsXFormsUtils::GetModel(mElement, getter_AddRefs(parentControl), + kElementFlags, + getter_AddRefs(boundNode)); + if (aSetBoundNode) { + mBoundNode.swap(boundNode); + } + + return MaybeAddToModel(oldModel, parentControl); +} + void nsXFormsControlStubBase::ResetHelpAndHint(PRBool aInitialize) { @@ -397,15 +455,13 @@ nsXFormsControlStubBase::HandleDefault(nsIDOMEvent *aEvent, // element isn't in a document, yet? Odd, indeed. Well, if not in // document, these two events have no meaning. NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED); - nsCOMPtr win = - do_QueryInterface(doc->GetScriptGlobalObject()); - // An inelegant way to retrieve this to be sure, but we are // guaranteed that the focus controller outlives us, so it // is safe to hold on to it (since we can't die until it has // died). - nsIFocusController *focusController = win->GetRootFocusController(); + nsIFocusController *focusController = + doc->GetWindow()->GetRootFocusController(); if (focusController && type.EqualsASCII(sXFormsEventsEntries[eEvent_Next].name)) { focusController->MoveFocus(PR_TRUE, nsnull); @@ -413,7 +469,8 @@ nsXFormsControlStubBase::HandleDefault(nsIDOMEvent *aEvent, focusController->MoveFocus(PR_FALSE, nsnull); } } else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_BindingException].name)) { - *aHandled = nsXFormsUtils::HandleBindingException(mElement); + *aHandled = nsXFormsUtils::HandleFatalError(mElement, + NS_LITERAL_STRING("XFormsBindingException")); } } @@ -461,9 +518,6 @@ nsXFormsControlStubBase::Create(nsIXTFElementWrapper *aWrapper) ResetHelpAndHint(PR_TRUE); - // enabled is on pr. default - aWrapper->SetIntrinsicState(NS_EVENT_STATE_ENABLED); - #ifdef DEBUG_smaug sControlList->AppendElement(this); #endif @@ -476,6 +530,7 @@ nsXFormsControlStubBase::OnDestroyed() { ResetHelpAndHint(PR_FALSE); RemoveIndexListeners(); + mDependencies.Clear(); if (mModel) { mModel->RemoveFormControl(this); @@ -490,14 +545,32 @@ nsXFormsControlStubBase::OnDestroyed() return NS_OK; } +nsresult +nsXFormsControlStubBase::ForceModelRebind() +{ + if (mModel) { + // Remove from model, so Bind() will be forced to reattach + mModel->RemoveFormControl(this); + mModel = nsnull; + } + nsresult rv = Bind(); + NS_ENSURE_SUCCESS(rv, rv); + return Refresh(); +} + + nsresult nsXFormsControlStubBase::DocumentChanged(nsIDOMDocument *aNewDocument) { // We need to re-evaluate our instance data binding when our document // changes, since our context can change + if (aNewDocument) { - Bind(); - Refresh(); + // The intrinsic state needs to be initialized here since + // SetIntrinsicState will do nothing until the element lives in a document. + ResetProperties(); + + return ForceModelRebind(); } return NS_OK; @@ -509,39 +582,34 @@ nsXFormsControlStubBase::ParentChanged(nsIDOMElement *aNewParent) mHasParent = aNewParent != nsnull; // We need to re-evaluate our instance data binding when our parent changes, // since xmlns declarations or our context could have changed. - if (mHasParent) { - Bind(); - Refresh(); - } - - return NS_OK; + return mHasParent ? ForceModelRebind() : NS_OK; } nsresult nsXFormsControlStubBase::WillSetAttribute(nsIAtom *aName, const nsAString &aValue) { - MaybeRemoveFromModel(aName, aValue); + BeforeSetAttribute(aName, aValue); return NS_OK; } nsresult nsXFormsControlStubBase::AttributeSet(nsIAtom *aName, const nsAString &aValue) { - MaybeBindAndRefresh(aName); + AfterSetAttribute(aName); return NS_OK; } nsresult nsXFormsControlStubBase::WillRemoveAttribute(nsIAtom *aName) { - MaybeRemoveFromModel(aName, EmptyString()); + BeforeSetAttribute(aName, EmptyString()); return NS_OK; } nsresult nsXFormsControlStubBase::AttributeRemoved(nsIAtom *aName) { - MaybeBindAndRefresh(aName); + AfterSetAttribute(aName); return NS_OK; } @@ -570,8 +638,7 @@ nsXFormsControlStubBase::GetContext(nsAString &aModelID, if (aContextNode) { if (mBoundNode) { // We are bound to a node: This is the context node - CallQueryInterface(mBoundNode, aContextNode); // addrefs - NS_ASSERTION(*aContextNode, "could not QI context node from bound node?"); + NS_ADDREF(*aContextNode = mBoundNode); } else if (mModel) { // We are bound to a model: The document element of its default instance // document is the context node @@ -630,13 +697,22 @@ nsXFormsControlStubBase::AddRemoveSNBAttr(nsIAtom *aName, const nsAString &aValu } } -void -nsXFormsControlStubBase::MaybeBindAndRefresh(nsIAtom *aName) +PRBool +nsXFormsControlStubBase::IsBindingAttribute(const nsIAtom *aAttr) const { - if (aName == nsXFormsAtoms::bind || - aName == nsXFormsAtoms::ref || - aName == nsXFormsAtoms::model) { + if (aAttr == nsXFormsAtoms::bind || + aAttr == nsXFormsAtoms::ref || + aAttr == nsXFormsAtoms::model) { + return PR_TRUE; + } + + return PR_FALSE; +} +void +nsXFormsControlStubBase::AfterSetAttribute(nsIAtom *aName) +{ + if (IsBindingAttribute(aName)) { Bind(); Refresh(); } @@ -644,15 +720,10 @@ nsXFormsControlStubBase::MaybeBindAndRefresh(nsIAtom *aName) } void -nsXFormsControlStubBase::MaybeRemoveFromModel(nsIAtom *aName, - const nsAString &aValue) +nsXFormsControlStubBase::BeforeSetAttribute(nsIAtom *aName, + const nsAString &aValue) { - if (aName == nsXFormsAtoms::model || - aName == nsXFormsAtoms::bind || - aName == nsXFormsAtoms::ref) { - if (mModel) - mModel->RemoveFormControl(this); - + if (IsBindingAttribute(aName)) { AddRemoveSNBAttr(aName, aValue); } } diff --git a/mozilla/extensions/xforms/nsXFormsControlStub.h b/mozilla/extensions/xforms/nsXFormsControlStub.h index 5cd440b1dce..f0fd11f70c6 100644 --- a/mozilla/extensions/xforms/nsXFormsControlStub.h +++ b/mozilla/extensions/xforms/nsXFormsControlStub.h @@ -89,6 +89,7 @@ public: NS_IMETHOD Bind(); NS_IMETHOD TryFocus(PRBool* aOK); NS_IMETHOD IsEventTarget(PRBool *aOK); + NS_IMETHOD GetUsesModelBinding(PRBool *aRes); nsresult Create(nsIXTFElementWrapper *aWrapper); // for nsIXTFElement @@ -140,6 +141,7 @@ public: kElementFlags(nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR), mHasParent(PR_FALSE), mPreventLoop(PR_FALSE), + mUsesModelBinding(PR_FALSE), mBindAttrsCount(0) {}; @@ -160,12 +162,17 @@ protected: nsCOMPtr mEventListener; /** State that tells whether control has a parent or not */ - PRBool mHasParent; + PRPackedBool mHasParent; /** State to prevent infinite loop when generating and handling xforms-next * and xforms-previous events */ - PRBool mPreventLoop; + PRPackedBool mPreventLoop; + + /** + * Does the control use a model bind? That is, does it have a @bind. + */ + PRPackedBool mUsesModelBinding; /** * Array of repeat-elements of which the control uses repeat-index. @@ -203,12 +210,21 @@ protected: */ void ResetProperties(); + /** + * Checks whether an attribute is a binding attribute for the control. This + * should be overriden by controls that have "non-standard" binding + * attributes. + * + * @param aAttr The attribute to check. + */ + virtual PRBool IsBindingAttribute(const nsIAtom *aAttr) const; + /** * Causes Bind() and Refresh() to be called if aName is the atom of a * single node binding attribute for this control. Called by AttributeSet * and AttributeRemoved. */ - void MaybeBindAndRefresh(nsIAtom *aName); + void AfterSetAttribute(nsIAtom *aName); /** * Removes this control from its model's list of controls if a single node @@ -218,10 +234,35 @@ protected: * @param aName - atom of the attribute being changed * @param aValue - value that the attribute is being changed to. */ - void MaybeRemoveFromModel(nsIAtom *aName, const nsAString &aValue); + void BeforeSetAttribute(nsIAtom *aName, const nsAString &aValue); /** Removes the index change event listeners */ void RemoveIndexListeners(); + + /** + * Binds the control to the model. Just sets mModel, and handle attaching to + * the model (including reattaching from any old model). + * + * @note It can also set the mBoundNode, but does not do a proper node + * binding, as in setting up dependencies, attaching index() listeners, etc. + * + * @param aSetBoundNode Set mBoundNode too? + */ + nsresult BindToModel(PRBool aSetBoundNode = PR_FALSE); + + /** + * Forces a rebinding to the model. + */ + nsresult ForceModelRebind(); + + /** + * Adds the form control to the model, if the model has changed. + * + * @param aOldModel The previous model the control was bound to + * @param aParent The parent XForms control + */ + nsresult MaybeAddToModel(nsIModelElementPrivate *aOldModel, + nsIXFormsControl *aParent); }; diff --git a/mozilla/extensions/xforms/nsXFormsCopyElement.cpp b/mozilla/extensions/xforms/nsXFormsCopyElement.cpp index 8429991c4db..f139932d075 100644 --- a/mozilla/extensions/xforms/nsXFormsCopyElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsCopyElement.cpp @@ -157,24 +157,15 @@ nsXFormsCopyElement::GetCopyNode(nsIDOMNode **aNode) NS_ENSURE_ARG_POINTER(aNode); *aNode = nsnull; + nsCOMPtr singleNode; nsCOMPtr model; - nsCOMPtr result; - nsresult rv = - nsXFormsUtils::EvaluateNodeBinding(mElement, - nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, - NS_LITERAL_STRING("ref"), EmptyString(), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, - getter_AddRefs(model), - getter_AddRefs(result)); + PRBool succeeded = + nsXFormsUtils::GetSingleNodeBinding(mElement, + getter_AddRefs(singleNode), + getter_AddRefs(model)); - NS_ENSURE_SUCCESS(rv, rv); - - if (result) { - nsCOMPtr singleNode; - result->GetSingleNodeValue(getter_AddRefs(singleNode)); - - NS_IF_ADDREF(*aNode = singleNode); - } + if (succeeded && singleNode) + NS_ADDREF(*aNode = singleNode); return NS_OK; } diff --git a/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp b/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp index bee04c1eb5f..e1dd8925b97 100644 --- a/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp +++ b/mozilla/extensions/xforms/nsXFormsDelegateStub.cpp @@ -102,19 +102,19 @@ NS_IMETHODIMP nsXFormsDelegateStub::Refresh() { if (mRepeatState == eType_Template) - return NS_OK; + return NS_OK_XFORMS_NOREFRESH; const nsVoidArray* list = nsPostRefresh::PostRefreshList(); if (list && list->IndexOf(this) >= 0) { // This control will be refreshed later. - return NS_OK; + return NS_OK_XFORMS_NOREFRESH; } SetMozTypeAttribute(); nsCOMPtr widget = do_QueryInterface(mElement); if (!widget) - return NS_OK; + return NS_ERROR_FAILURE; return widget->Refresh(); } @@ -190,9 +190,20 @@ nsXFormsDelegateStub::ReportError(const nsAString& aErrorMsg) NS_IMETHODIMP nsXFormsDelegateStub::WidgetAttached() { - if (UpdateRepeatState() != eType_Template) - nsXFormsModelElement::NeedsPostRefresh(this); + if (UpdateRepeatState() == eType_Template) + return NS_OK; + if (mBindAttrsCount) { + // If control is bounded to instance data then we should ask for refresh + // only when model is loaded entirely. The reason is control is refreshed + // by model when it get loaded. + nsCOMPtr domDoc; + mElement->GetOwnerDocument(getter_AddRefs(domDoc)); + if (!nsXFormsUtils::IsDocumentReadyForBind(domDoc)) + return NS_OK; + } + + nsXFormsModelElement::NeedsPostRefresh(this); return NS_OK; } @@ -213,6 +224,10 @@ nsXFormsDelegateStub::UpdateRepeatState() mRepeatState = eType_Template; break; } + if (nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("itemset"))) { + mRepeatState = eType_Template; + break; + } nsCOMPtr tmp; parent->GetParentNode(getter_AddRefs(tmp)); parent = tmp; diff --git a/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp b/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp index 1315d32d2ce..badcc3e623c 100644 --- a/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp @@ -41,6 +41,8 @@ #include "nsIDOMElement.h" #include "nsIDOMDocument.h" #include "nsIDOMNodeList.h" +#include "nsIXFormsRepeatElement.h" +#include "nsIXFormsControl.h" #include "nsString.h" @@ -48,6 +50,7 @@ #include "nsXFormsActionModuleBase.h" #include "nsXFormsActionElement.h" #include "nsXFormsUtils.h" +#include "nsIDOM3Node.h" #include "math.h" @@ -65,14 +68,14 @@ * @see http://www.w3.org/TR/xforms/slice4.html#evt-insert * @see https://bugzilla.mozilla.org/show_bug.cgi?id=280423 * - * @todo Any \ elements need to set their repeat-indexes properly if - * they are bound to the same nodeset. (XXX) */ class nsXFormsInsertDeleteElement : public nsXFormsActionModuleBase { private: PRBool mIsInsert; - + + nsresult RefreshRepeats(nsIDOMNode *aNode); + public: NS_DECL_NSIXFORMSACTIONMODULEELEMENT @@ -97,13 +100,15 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, nsresult rv; nsCOMPtr model; nsCOMPtr nodeset; + PRBool usesModelBinding; rv = nsXFormsUtils::EvaluateNodeBinding(mElement, - 0, + nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, NS_LITERAL_STRING("nodeset"), EmptyString(), nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, getter_AddRefs(model), - getter_AddRefs(nodeset)); + getter_AddRefs(nodeset), + &usesModelBinding); NS_ENSURE_SUCCESS(rv, rv); if (!model || !nodeset) @@ -169,7 +174,7 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, #ifdef DEBUG_XF_INSERTDELETE if (mIsInsert) { printf("Will try to INSERT node _%s_ index %d (set size: %d)\n", - NS_ConvertUCS2toUTF8(position).get(), + NS_ConvertUTF16toUTF8(position).get(), atInt, setSize); } else { @@ -198,7 +203,6 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, nsCOMPtr resNode; if (mIsInsert) { - // // Get prototype and clone it (last member of nodeset) nsCOMPtr prototype; nodeset->SnapshotItem(setSize - 1, getter_AddRefs(prototype)); @@ -212,6 +216,11 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, location, getter_AddRefs(resNode)); NS_ENSURE_STATE(resNode); + + // Set indexes for repeats + rv = RefreshRepeats(resNode); + NS_ENSURE_SUCCESS(rv, rv); + } else { rv = parent->RemoveChild(location, getter_AddRefs(resNode)); NS_ENSURE_SUCCESS(rv, rv); @@ -219,9 +228,6 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, // Dispatch xforms-insert/delete event to the instance node we have modified // data for - nsCOMPtr modelElem = do_QueryInterface(model); - NS_ENSURE_STATE(modelElem); - nsCOMPtr instNode; rv = nsXFormsUtils::GetInstanceNodeForData(resNode, getter_AddRefs(instNode)); NS_ENSURE_SUCCESS(rv, rv); @@ -231,6 +237,8 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, NS_ENSURE_SUCCESS(rv, rv); // Dispatch refreshing events to the model + nsCOMPtr modelElem(do_QueryInterface(model)); + NS_ASSERTION(modelElem, "Model not implementing nsIDOMElement?!"); if (aParentAction) { aParentAction->SetRebuild(modelElem, PR_TRUE); aParentAction->SetRecalculate(modelElem, PR_TRUE); @@ -246,6 +254,46 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, return NS_OK; } + +nsresult +nsXFormsInsertDeleteElement::RefreshRepeats(nsIDOMNode *aNode) +{ + // XXXbeaufour: only check repeats belonging to the same model... + // possibly use mFormControls? Should be quicker than searching through + // entire document!! mModel->GetControls("repeat"); Would also possibly + // save a QI? + + nsCOMPtr document; + + nsresult rv = mElement->GetOwnerDocument(getter_AddRefs(document)); + NS_ENSURE_STATE(document); + + nsCOMPtr repeatNodes; + document->GetElementsByTagNameNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS), + NS_LITERAL_STRING("repeat"), + getter_AddRefs(repeatNodes)); + NS_ENSURE_STATE(repeatNodes); + + // work over each node and if the node contains the inserted element + PRUint32 nodeCount; + rv = repeatNodes->GetLength(&nodeCount); + NS_ENSURE_SUCCESS(rv, rv); + + for (PRUint32 node = 0; node < nodeCount; ++node) { + nsCOMPtr repeatNode; + + rv = repeatNodes->Item(node, getter_AddRefs(repeatNode)); + nsCOMPtr repeatEl(do_QueryInterface(repeatNode)); + NS_ENSURE_STATE(repeatEl); + + rv = repeatEl->HandleNodeInsert(aNode); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} + + NS_HIDDEN_(nsresult) NS_NewXFormsInsertElement(nsIXTFElement **aResult) { diff --git a/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp b/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp index e3a01fed7b1..a9ace90b5dc 100644 --- a/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp @@ -53,8 +53,9 @@ static const char* kLoadAsData = "loadAsData"; -NS_IMPL_ISUPPORTS_INHERITED5(nsXFormsInstanceElement, +NS_IMPL_ISUPPORTS_INHERITED6(nsXFormsInstanceElement, nsXFormsStubElement, + nsIXFormsNSInstanceElement, nsIInstanceElementPrivate, nsIStreamListener, nsIRequestObserver, @@ -78,7 +79,7 @@ nsXFormsInstanceElement::OnDestroyed() mChannel = nsnull; } mListener = nsnull; - SetDocument(nsnull); + SetInstanceDocument(nsnull); mElement = nsnull; return NS_OK; } @@ -139,7 +140,9 @@ NS_IMETHODIMP nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper) { aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_ATTRIBUTE_SET | - nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED); + nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED | + nsIXTFElement::NOTIFY_WILL_CHANGE_PARENT | + nsIXTFElement::NOTIFY_PARENT_CHANGED); nsCOMPtr node; aWrapper->GetElementNode(getter_AddRefs(node)); @@ -184,7 +187,9 @@ nsXFormsInstanceElement::OnChannelRedirect(nsIChannel *OldChannel, NS_ENSURE_STATE(doc); if (!nsXFormsUtils::CheckSameOrigin(doc, newURI)) { - nsXFormsUtils::ReportError(NS_LITERAL_STRING("instanceLoadOrigin"), domDoc); + const PRUnichar *strings[] = { NS_LITERAL_STRING("instance").get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLinkLoadOrigin"), + strings, 1, mElement, mElement); return NS_ERROR_ABORT; } @@ -244,7 +249,7 @@ nsXFormsInstanceElement::OnStopRequest(nsIRequest *request, nsISupports *ctx, PRBool succeeded = NS_SUCCEEDED(status); if (!succeeded) { - SetDocument(nsnull); + SetInstanceDocument(nsnull); } if (mDocument) { @@ -259,7 +264,7 @@ nsXFormsInstanceElement::OnStopRequest(nsIRequest *request, nsISupports *ctx, namespaceURI.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) { NS_WARNING("resulting instance document could not be parsed"); succeeded = PR_FALSE; - SetDocument(nsnull); + SetInstanceDocument(nsnull); } } } @@ -273,17 +278,19 @@ nsXFormsInstanceElement::OnStopRequest(nsIRequest *request, nsISupports *ctx, return NS_OK; } -// nsIInstanceElementPrivate +// nsIXFormsNSInstanceElement NS_IMETHODIMP -nsXFormsInstanceElement::GetDocument(nsIDOMDocument **aDocument) +nsXFormsInstanceElement::GetInstanceDocument(nsIDOMDocument **aDocument) { NS_IF_ADDREF(*aDocument = mDocument); return NS_OK; } +// nsIInstanceElementPrivate + NS_IMETHODIMP -nsXFormsInstanceElement::SetDocument(nsIDOMDocument *aDocument) +nsXFormsInstanceElement::SetInstanceDocument(nsIDOMDocument *aDocument) { nsCOMPtr doc(do_QueryInterface(mDocument)); if (doc) { @@ -389,74 +396,81 @@ nsXFormsInstanceElement::GetElement(nsIDOMElement **aElement) } NS_IMETHODIMP -nsXFormsInstanceElement::Initialize() +nsXFormsInstanceElement::WillChangeParent(nsIDOMElement *aNewParent) { + if (!aNewParent) { + nsCOMPtr model = GetModel(); + if (model) { + model->RemoveInstanceElement(this); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsXFormsInstanceElement::ParentChanged(nsIDOMElement *aNewParent) +{ + nsCOMPtr model = GetModel(); + if (!model) return NS_OK; + if (mInitialized || !mElement) { return NS_OK; } mInitialized = PR_TRUE; - - nsCOMPtr model = GetModel(); - NS_ENSURE_TRUE(model, NS_ERROR_FAILURE); model->AddInstanceElement(this); + // If model isn't loaded entirely (It means xforms-ready event hasn't been + // fired) then the instance will be initialized by model and will be backed up + // when xforms-ready event is fired. + PRBool isready; + model->GetIsReady(&isready); + if (!isready) + return NS_OK; + + // If the model is loaded and ready then the instance is inserted dynamically. + // The instance should create instance document and back it up. + + // Probably dynamic instances should be handled too when model isn't loaded + // entirely (for more information see a comment 29 of bug 320081 + // https://bugzilla.mozilla.org/show_bug.cgi?id=320081#c29). + + nsAutoString src; + mElement->GetAttribute(NS_LITERAL_STRING("src"), src); + + if (!src.IsEmpty()) { + // XXX: external dynamic instances isn't handled (see a bug 325684 + // https://bugzilla.mozilla.org/show_bug.cgi?id=325684) + return NS_OK; + } + + // If we don't have a linked external instance, use our inline data. + nsresult rv = CloneInlineInstance(); + if (NS_FAILED(rv)) + return rv; + return BackupOriginalDocument(); +} + +NS_IMETHODIMP +nsXFormsInstanceElement::Initialize() +{ mElement->HasAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_MOZ_XFORMS_LAZY), NS_LITERAL_STRING("lazy"), &mLazy); - // Lazy instance - if (mLazy) { - nsCOMPtr domDoc; - mElement->GetOwnerDocument(getter_AddRefs(domDoc)); - NS_ENSURE_STATE(domDoc); - - nsCOMPtr domImpl; - nsresult rv = domDoc->GetImplementation(getter_AddRefs(domImpl)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr newDoc; - rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull, - getter_AddRefs(newDoc)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = SetDocument(newDoc); - NS_ENSURE_SUCCESS(rv, rv); - - // Lazy authored instance documents have a root named "instanceData" - nsCOMPtr instanceDataElement; - nsCOMPtr 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)); - NS_WARN_IF_FALSE(mOriginalDocument, "Couldn't create mOriginalDocument!!"); - } else { - // Normal instance - - // By the time this is called, we should be inserted in the document and - // have all of our child elements, so this is our first opportunity to - // create the instance document. - - nsAutoString src; - mElement->GetAttribute(NS_LITERAL_STRING("src"), src); - - if (src.IsEmpty()) { - // If we don't have a linked external instance, use our inline data. - CloneInlineInstance(); - } else { - LoadExternalInstance(src); - } + if (mLazy) { // Lazy instance + return CreateInstanceDocument(NS_LITERAL_STRING("instanceData")); } + // Normal instance + nsAutoString src; + mElement->GetAttribute(NS_LITERAL_STRING("src"), src); + + if (src.IsEmpty()) { + return CloneInlineInstance(); + } + + LoadExternalInstance(src); return NS_OK; } @@ -466,7 +480,7 @@ nsresult nsXFormsInstanceElement::CloneInlineInstance() { // Clear out our existing instance data - nsresult rv = CreateInstanceDocument(); + nsresult rv = CreateInstanceDocument(EmptyString()); if (NS_FAILED(rv)) return rv; // don't warn, we might just not be in the document yet @@ -519,9 +533,7 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc) mElement->GetOwnerDocument(getter_AddRefs(domDoc)); nsCOMPtr doc(do_QueryInterface(domDoc)); if (doc) { - nsresult tmp; - doc->GetProperty(nsXFormsAtoms::isInstanceDocument, &tmp); - if (NS_SUCCEEDED(tmp)) { + if (doc->GetProperty(nsXFormsAtoms::isInstanceDocument)) { /// Property exists, which means we are an instance document trying /// to load an external instance document. We do not allow that. const nsPromiseFlatString& flat = PromiseFlatString(aSrc); @@ -530,7 +542,7 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc) strings, 1, mElement, mElement); } else { // Clear out our existing instance data - if (NS_SUCCEEDED(CreateInstanceDocument())) { + if (NS_SUCCEEDED(CreateInstanceDocument(EmptyString()))) { nsCOMPtr newDoc = do_QueryInterface(mDocument); nsCOMPtr uri; @@ -559,8 +571,9 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc) } } } else { - nsXFormsUtils::ReportError(NS_LITERAL_STRING("instanceLoadOrigin"), - domDoc); + const PRUnichar *strings[] = {NS_LITERAL_STRING("instance").get()}; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLinkLoadOrigin"), + strings, 1, mElement, mElement); } } } @@ -583,7 +596,7 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc) } nsresult -nsXFormsInstanceElement::CreateInstanceDocument() +nsXFormsInstanceElement::CreateInstanceDocument(const nsAString &aQualifiedName) { nsCOMPtr doc; nsresult rv = mElement->GetOwnerDocument(getter_AddRefs(doc)); @@ -597,18 +610,18 @@ nsXFormsInstanceElement::CreateInstanceDocument() NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr newDoc; - rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull, + rv = domImpl->CreateDocument(EmptyString(), aQualifiedName, nsnull, getter_AddRefs(newDoc)); NS_ENSURE_SUCCESS(rv, rv); - rv = SetDocument(newDoc); + rv = SetInstanceDocument(newDoc); 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, + domImpl->CreateDocument(EmptyString(), aQualifiedName, nsnull, getter_AddRefs(mOriginalDocument)); return rv; } diff --git a/mozilla/extensions/xforms/nsXFormsInstanceElement.h b/mozilla/extensions/xforms/nsXFormsInstanceElement.h index 81a2e364c38..a37f32ef2ef 100644 --- a/mozilla/extensions/xforms/nsXFormsInstanceElement.h +++ b/mozilla/extensions/xforms/nsXFormsInstanceElement.h @@ -66,6 +66,7 @@ class nsXFormsInstanceElement : public nsXFormsStubElement, public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSIXFORMSNSINSTANCEELEMENT NS_DECL_NSIINSTANCEELEMENTPRIVATE NS_DECL_NSISTREAMLISTENER NS_DECL_NSICHANNELEVENTSINK @@ -75,6 +76,8 @@ public: NS_IMETHOD OnDestroyed(); NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aNewValue); NS_IMETHOD AttributeRemoved(nsIAtom *aName); + NS_IMETHOD WillChangeParent(nsIDOMElement *aNewParent); + NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent); NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper); nsXFormsInstanceElement() NS_HIDDEN; @@ -82,7 +85,7 @@ public: private: NS_HIDDEN_(nsresult) CloneInlineInstance(); NS_HIDDEN_(void) LoadExternalInstance(const nsAString &aSrc); - NS_HIDDEN_(nsresult) CreateInstanceDocument(); + NS_HIDDEN_(nsresult) CreateInstanceDocument(const nsAString &aQualifiedName); NS_HIDDEN_(already_AddRefed) GetModel(); nsCOMPtr mDocument; diff --git a/mozilla/extensions/xforms/nsXFormsItemElement.cpp b/mozilla/extensions/xforms/nsXFormsItemElement.cpp index 442864441cc..e93a0b0a47e 100644 --- a/mozilla/extensions/xforms/nsXFormsItemElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsItemElement.cpp @@ -94,6 +94,7 @@ public: // nsIXFormsSelectChild NS_DECL_NSIXFORMSSELECTCHILD + private: nsIDOMElement* mElement; PRBool mDoneAddingChildren; @@ -101,9 +102,6 @@ private: // If true, indicates that this item contains a xf:copy element (via // xf:itemset) rather than a xf:value element PRBool mIsCopyItem; - - // context node (used by itemset in select) - nsCOMPtr mContextNode; }; NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsItemElement, diff --git a/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp b/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp index a2ecfd487d7..a3d04307875 100644 --- a/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsItemSetElement.cpp @@ -225,12 +225,7 @@ nsXFormsItemSetElement::SelectItemByNode(nsIDOMNode *aNode, NS_IMETHODIMP nsXFormsItemSetElement::Bind() { - mModel = nsXFormsUtils::GetModel(mElement); - if (mModel) { - mModel->AddFormControl(this); - } - - return NS_OK; + return BindToModel(); } NS_IMETHODIMP @@ -337,11 +332,11 @@ nsXFormsItemSetElement::Refresh() anonContent->AppendChild(itemNode, getter_AddRefs(tmpNode)); } - // tell parent we appended a child + // refresh parent we if (parent) { - nsCOMPtr stub = do_QueryInterface(parent); - if (stub) { - stub->ChildAppended(parent); + nsCOMPtr control = do_QueryInterface(parent); + if (control) { + control->Refresh(); } } diff --git a/mozilla/extensions/xforms/nsXFormsLabelElement.cpp b/mozilla/extensions/xforms/nsXFormsLabelElement.cpp index ed5760729c8..281e780a6a7 100644 --- a/mozilla/extensions/xforms/nsXFormsLabelElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsLabelElement.cpp @@ -233,12 +233,11 @@ nsXFormsLabelElement::LoadExternalLabel(const nsAString& aSrc) // URI doesn't exist; report error. mChannel = nsnull; - // XXX Passing |mElement| as |aContext| param to ReportError leads - // to an infinite loop. Avoid for now. const nsPromiseFlatString& flat = PromiseFlatString(aSrc); - const PRUnichar *strings[] = { flat.get() }; - nsXFormsUtils::ReportError(NS_LITERAL_STRING("labelLink1Error"), - strings, 1, mElement, nsnull); + const PRUnichar *strings[] = { flat.get(), + NS_LITERAL_STRING("label").get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink1Error"), + strings, 2, mElement, mElement); nsCOMPtr modelPriv = nsXFormsUtils::GetModel(mElement); @@ -247,8 +246,9 @@ nsXFormsLabelElement::LoadExternalLabel(const nsAString& aSrc) } } } else { - nsXFormsUtils::ReportError(NS_LITERAL_STRING("labelLinkLoadOrigin"), - domDoc); + const PRUnichar *strings[] = { NS_LITERAL_STRING("label").get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLinkLoadOrigin"), + strings, 1, mElement, mElement); } } } @@ -259,7 +259,10 @@ nsXFormsLabelElement::LoadExternalLabel(const nsAString& aSrc) NS_IMETHODIMP nsXFormsLabelElement::Refresh() { - nsXFormsDelegateStub::Refresh(); + nsresult rv = nsXFormsDelegateStub::Refresh(); + if (NS_FAILED(rv) || rv == NS_OK_XFORMS_NOREFRESH) + return rv; + nsCOMPtr parent; mElement->GetParentNode(getter_AddRefs(parent)); @@ -375,13 +378,12 @@ nsXFormsLabelElement::OnStopRequest(nsIRequest *aRequest, if (aStatusCode == NS_BINDING_ABORTED) return NS_OK; - // XXX Passing |mElement| as |aContext| param to ReportError leads - // to an infinite loop. Avoid for now. nsAutoString src; mElement->GetAttribute(NS_LITERAL_STRING("src"), src); - const PRUnichar *strings[] = { src.get() }; - nsXFormsUtils::ReportError(NS_LITERAL_STRING("labelLink2Error"), - strings, 1, mElement, nsnull); + const PRUnichar *strings[] = { NS_LITERAL_STRING("label").get(), + src.get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink2Error"), + strings, 2, mElement, mElement); nsCOMPtr modelPriv = nsXFormsUtils::GetModel(mElement); diff --git a/mozilla/extensions/xforms/nsXFormsMDGEngine.cpp b/mozilla/extensions/xforms/nsXFormsMDGEngine.cpp index 66209a358ef..d17faf82504 100644 --- a/mozilla/extensions/xforms/nsXFormsMDGEngine.cpp +++ b/mozilla/extensions/xforms/nsXFormsMDGEngine.cpp @@ -45,9 +45,10 @@ #include "nsIDOMNSXPathExpression.h" #include "nsIDOMXPathResult.h" #include "nsDeque.h" -#include "nsIModelElementPrivate.h" #include "nsXFormsUtils.h" #include "nsDOMError.h" +#include "nsIDOMElement.h" +#include "nsXFormsModelElement.h" #ifdef DEBUG //# define DEBUG_XF_MDG @@ -64,7 +65,6 @@ /* ------------------------------------ */ /* --------- nsXFormsMDGNode ---------- */ /* ------------------------------------ */ -MOZ_DECL_CTOR_COUNTER(nsXFormsMDGNode) nsXFormsMDGNode::nsXFormsMDGNode(nsIDOMNode *aNode, const ModelItemPropName aType) @@ -122,7 +122,6 @@ nsXFormsMDGNode::MarkClean() /* ------------------------------------ */ /* -------- nsXFormsMDGEngine --------- */ /* ------------------------------------ */ -MOZ_DECL_CTOR_COUNTER(nsXFormsMDGEngine) nsXFormsMDGEngine::nsXFormsMDGEngine() : mNodesInGraph(0) @@ -138,7 +137,7 @@ nsXFormsMDGEngine::~nsXFormsMDGEngine() } nsresult -nsXFormsMDGEngine::Init(nsIModelElementPrivate *aModel) +nsXFormsMDGEngine::Init(nsXFormsModelElement *aModel) { nsresult rv = NS_ERROR_FAILURE; if (mNodeStates.Init() && mNodeToMDG.Init()) { @@ -165,7 +164,7 @@ nsXFormsMDGEngine::AddMIP(ModelItemPropName aType, nsAutoString nodename; aContextNode->GetNodeName(nodename); printf("nsXFormsMDGEngine::AddMIP(aContextNode=%s, aExpression=%p, aDependencies=|%d|,\n", - NS_ConvertUCS2toUTF8(nodename).get(), + NS_ConvertUTF16toUTF8(nodename).get(), (void*) aExpression, aDependencies ? aDependencies->Count() : 0); printf(" aContextPos=%d, aContextSize=%d, aType=%s, aDynFunc=%d)\n", @@ -275,7 +274,7 @@ nsXFormsMDGEngine::PrintDot(const char* aFile) if (g->IsDirty()) { fprintf(FD, "\t%s [color=red];\n", - NS_ConvertUCS2toUTF8(domNodeName).get()); + NS_ConvertUTF16toUTF8(domNodeName).get()); } for (PRInt32 j = 0; j < g->mSuc.Count(); ++j) { @@ -285,8 +284,8 @@ nsXFormsMDGEngine::PrintDot(const char* aFile) nsAutoString sucName; sucnode->mContextNode->GetNodeName(sucName); fprintf(FD, "\t%s -> %s [label=\"%s\"];\n", - NS_ConvertUCS2toUTF8(sucName).get(), - NS_ConvertUCS2toUTF8(domNodeName).get(), + NS_ConvertUTF16toUTF8(sucName).get(), + NS_ConvertUTF16toUTF8(domNodeName).get(), gMIPNames[sucnode->mType]); } } @@ -345,7 +344,7 @@ nsXFormsMDGEngine::Recalculate(nsCOMArray *aChangedNodes) printf("\tNode #%d: This=%p, Dirty=%d, DynFunc=%d, Type=%d, Count=%d, Suc=%d, CSize=%d, CPos=%d, Next=%p, domnode=%s\n", i, (void*) g, g->IsDirty(), g->mDynFunc, g->mType, g->mCount, g->mSuc.Count(), g->mContextSize, g->mContextPosition, - (void*) g->mNext, NS_ConvertUCS2toUTF8(domNodeName).get()); + (void*) g->mNext, NS_ConvertUTF16toUTF8(domNodeName).get()); #endif // Ignore node if it is not dirty @@ -557,7 +556,11 @@ nsXFormsMDGEngine::Rebuild() #endif if (mGraph.Count() != mNodesInGraph) { - NS_WARNING("XForms: There are loops in the MDG\n"); + nsCOMPtr modelElement; + if (mModel) { + modelElement = mModel->GetDOMElement(); + } + nsXFormsUtils::ReportError(NS_LITERAL_STRING("MDGLoopError"), modelElement); rv = NS_ERROR_ABORT; } diff --git a/mozilla/extensions/xforms/nsXFormsMDGEngine.h b/mozilla/extensions/xforms/nsXFormsMDGEngine.h index c16821b4065..64785ce030f 100644 --- a/mozilla/extensions/xforms/nsXFormsMDGEngine.h +++ b/mozilla/extensions/xforms/nsXFormsMDGEngine.h @@ -50,9 +50,9 @@ #include "nsXFormsTypes.h" #include "nsXFormsNodeState.h" -#include "nsIModelElementPrivate.h" class nsIDOMNSXPathExpression; +class nsXFormsModelElement; /** * Data structure for nodes in the graph. @@ -174,7 +174,7 @@ protected: nsVoidArray mGraph; /** The model that created the MDG */ - nsIModelElementPrivate *mModel; + nsXFormsModelElement *mModel; /** * Nodes that are marked as changed, and should be included in recalculation @@ -343,7 +343,7 @@ public: * * @param aModel The model that created this MDGEngine instance. */ - nsresult Init(nsIModelElementPrivate *aModel); + nsresult Init(nsXFormsModelElement *aModel); /** * Insert new MIP (Model Item Property) into graph. diff --git a/mozilla/extensions/xforms/nsXFormsMessageElement.cpp b/mozilla/extensions/xforms/nsXFormsMessageElement.cpp index c4482aaa535..d8215b9ce97 100644 --- a/mozilla/extensions/xforms/nsXFormsMessageElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsMessageElement.cpp @@ -78,6 +78,9 @@ #include "nsIDOMSerializer.h" #include "nsIServiceManager.h" #include "nsIDelegateInternal.h" +#include "nsNetUtil.h" +#include "nsIDOMDocumentEvent.h" +#include "nsIChannelEventSink.h" #define EPHEMERAL_STYLE \ "position:absolute;z-index:2147483647; \ @@ -98,8 +101,15 @@ \ " + +#define MESSAGE_WINDOW_UI_PART1_WITHOUT_SRC \ + "onload='window.sizeToContent(); \ + document.documentElement.lastChild.previousSibling \ .firstChild.nextSibling.focus();'>" #define MESSAGE_WINDOW_UI_PART2 \ @@ -121,7 +131,10 @@ class nsXFormsEventListener; */ class nsXFormsMessageElement : public nsXFormsXMLVisualStub, public nsIDOMEventListener, - public nsIXFormsActionModuleElement + public nsIXFormsActionModuleElement, + public nsIStreamListener, + public nsIInterfaceRequestor, + public nsIChannelEventSink { public: NS_DECL_ISUPPORTS_INHERITED @@ -138,7 +151,13 @@ public: NS_IMETHOD GetInsertionPoint(nsIDOMElement **aElement); NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent); NS_IMETHOD WillChangeParent(nsIDOMElement *aNewParent); + NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aSrc); + NS_IMETHOD AttributeRemoved(nsIAtom *aName); + NS_DECL_NSICHANNELEVENTSINK + NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIDOMEVENTLISTENER NS_DECL_NSIXFORMSACTIONMODULEELEMENT @@ -161,18 +180,41 @@ public: eType_Alert }; + enum StopType { + eStopType_None, + eStopType_Security, + eStopType_LinkError + }; + + nsXFormsMessageElement(MessageType aType) : - mType(aType), mElement(nsnull), mPosX(-1), mPosY(-1) {} + mType(aType), mElement(nsnull), mPosX(-1), mPosY(-1), + mStopType(eStopType_None) {} private: nsresult HandleEphemeralMessage(nsIDOMDocument* aDoc, nsIDOMEvent* aEvent); nsresult HandleModalAndModelessMessage(nsIDOMDocument* aDoc, nsAString& aLevel); void CloneNode(nsIDOMNode* aSrc, nsIDOMNode** aTarget); - void AppendCSSOptions(nsIDOMViewCSS* aViewCSS, nsAString& aOptions); PRBool HandleInlineAlert(nsIDOMEvent* aEvent); nsresult ConstructMessageWindowURL(nsAString& aData, PRBool aIsLink, /*out*/ nsAString& aURL); + /** + * Begin the process of testing to see if this message element could get held + * up later by linking to an external resource. Run this when the element is + * set up and it will try to access any external resource that this message + * may later try to access. If we can't get to it by the time the message + * is triggered, then throw a xforms-link-error. + */ + nsresult TestExternalFile(); + + /** + * Either add or subtract from the number of messages with external resources + * currently loading in this document. aAdd == PR_TRUE will add to the total + * otherwise we will subtract from the total (as long as it isn't already 0). + */ + void AddRemoveExternalResource(PRBool aAdd); + MessageType mType; nsCOMPtr mVisualElement; @@ -184,12 +226,17 @@ private: nsCOMPtr mEphemeralTimer; nsCOMPtr mDocument; + nsCOMPtr mChannel; + StopType mStopType; }; NS_IMPL_ADDREF_INHERITED(nsXFormsMessageElement, nsXFormsXMLVisualStub) NS_IMPL_RELEASE_INHERITED(nsXFormsMessageElement, nsXFormsXMLVisualStub) NS_INTERFACE_MAP_BEGIN(nsXFormsMessageElement) + NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + NS_INTERFACE_MAP_ENTRY(nsIStreamListener) NS_INTERFACE_MAP_ENTRY(nsIXFormsActionModuleElement) NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) NS_INTERFACE_MAP_END_INHERITING(nsXFormsXMLVisualStub) @@ -203,7 +250,9 @@ nsXFormsMessageElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper) NS_ENSURE_SUCCESS(rv, rv); aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT | - nsIXTFElement::NOTIFY_PARENT_CHANGED); + nsIXTFElement::NOTIFY_PARENT_CHANGED | + nsIXTFElement::NOTIFY_ATTRIBUTE_SET | + nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED); nsCOMPtr node; rv = aWrapper->GetElementNode(getter_AddRefs(node)); @@ -261,6 +310,12 @@ nsXFormsMessageElement::WillChangeDocument(nsIDOMDocument *aNewDocument) if (msg == this) doc->UnsetProperty(nsXFormsAtoms::messageProperty); } + + // If we are currently trying to load an external message, cancel the + // request. + if (mChannel) { + mChannel->Cancel(NS_BINDING_ABORTED); + } } mDocument = aNewDocument; @@ -272,6 +327,7 @@ nsXFormsMessageElement::OnDestroyed() { mElement = nsnull; mVisualElement = nsnull; + mChannel = nsnull; return NS_OK; } @@ -391,6 +447,39 @@ nsXFormsMessageElement::ParentChanged(nsIDOMElement *aNewParent) return NS_OK; } +NS_IMETHODIMP +nsXFormsMessageElement::AttributeSet(nsIAtom *aName, const nsAString &aValue) +{ + if (aName == nsXFormsAtoms::src) { + // If we are currently trying to load an external message, cancel the + // request. + if (mChannel) { + mChannel->Cancel(NS_BINDING_ABORTED); + } + + mStopType = eStopType_None; + TestExternalFile(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsXFormsMessageElement::AttributeRemoved(nsIAtom *aName) +{ + if (aName == nsXFormsAtoms::src) { + // If we are currently trying to test an external resource, cancel the + // request. + if (mChannel) { + mChannel->Cancel(NS_BINDING_ABORTED); + } + + mStopType = eStopType_None; + } + + return NS_OK; +} + NS_IMETHODIMP nsXFormsMessageElement::HandleAction(nsIDOMEvent* aEvent, nsIXFormsActionElement *aParentAction) @@ -398,6 +487,35 @@ nsXFormsMessageElement::HandleAction(nsIDOMEvent* aEvent, if (!mElement) return NS_OK; + // If TestExternalFile fails, then there is an external link that we need + // to use that we can't reach right now. If it won't load, then might as + // well stop here. We don't want to be popping up empty windows + // or windows that will just end up showing 404 messages. + if (mStopType == eStopType_LinkError) { + // we couldn't successfully link to our external resource. Better throw + // the xforms-link-error event + nsCOMPtr modelPriv = + nsXFormsUtils::GetModel(mElement); + nsCOMPtr model = do_QueryInterface(modelPriv); + nsXFormsUtils::DispatchEvent(model, eEvent_LinkError); + return NS_OK; + } + + // If we couldn't test the external link due to it not living in an + // acceptable domain, then no sense going any further down this path. + if (mStopType == eStopType_Security) { + return NS_OK; + } + + // If there is still a channel, then someone must have changed the value of + // the src attribute since the document finished loading and we haven't yet + // determined whether the new link is valid or not. For now we'll assume + // that the value is good rather than returning a link error. Also + // canceling the channel since it is too late now. + if (mChannel) { + mChannel->Cancel(NS_BINDING_ABORTED); + } + if (mType != eType_Normal) { nsCOMPtr target; @@ -604,16 +722,13 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc, instanceData); nsAutoString options; - options.AppendLiteral(MESSAGE_WINDOW_PROPERTIES); + options.AssignLiteral(MESSAGE_WINDOW_PROPERTIES); nsAutoString src; if (!hasBinding) { mElement->GetAttribute(NS_LITERAL_STRING("src"), src); } - nsCOMPtr cssView(do_QueryInterface(internal)); - AppendCSSOptions(cssView, options); - // order of precedence is single-node binding, linking attribute then // inline text nsresult rv; @@ -625,7 +740,7 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc, } else { // Cloning the content of the xf:message and creating a // dialog for it. - options.AppendLiteral(",dialog,chrome,dependent"); + options.AppendLiteral(",dialog,chrome,dependent,width=200,height=200"); nsCOMPtr ddoc; nsCOMPtr domImpl; rv = aDoc->GetImplementation(getter_AddRefs(domImpl)); @@ -644,14 +759,14 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc, getter_AddRefs(htmlEl)); NS_ENSURE_SUCCESS(rv, rv); ddoc->AppendChild(htmlEl, getter_AddRefs(tmp)); - + nsCOMPtr bodyEl; rv = ddoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML), NS_LITERAL_STRING("body"), getter_AddRefs(bodyEl)); NS_ENSURE_SUCCESS(rv, rv); htmlEl->AppendChild(bodyEl, getter_AddRefs(tmp)); - + // If we have a binding, it is enough to show a simple message if (hasBinding) { nsCOMPtr body3(do_QueryInterface(bodyEl)); @@ -680,7 +795,7 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc, } } } - + nsCOMPtr serializer = do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); @@ -688,11 +803,11 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc, nsAutoString docString; rv = serializer->SerializeToString(ddoc, docString); NS_ENSURE_SUCCESS(rv, rv); - + rv = ConstructMessageWindowURL(docString, PR_FALSE, src); NS_ENSURE_SUCCESS(rv, rv); } - + nsCOMPtr arg; PRBool isModal = aLevel.EqualsLiteral("modal"); if (isModal) { @@ -702,71 +817,15 @@ nsXFormsMessageElement::HandleModalAndModelessMessage(nsIDOMDocument* aDoc, // cycles between the windows. arg = nsXFormsAtoms::messageProperty; } - - //XXX Add support for xforms-link-error. + nsCOMPtr messageWindow; - internal->OpenDialog(src, aLevel, options, arg, getter_AddRefs(messageWindow)); - if (!isModal) { - nsCOMPtr msgWinInternal = - do_QueryInterface(messageWindow); - if (msgWinInternal) - msgWinInternal->Focus(); - } + // The 2nd argument is the window name, and if a window with the name exists, + // it gets reused. Using "_blank" makes sure we get a new window each time. + internal->OpenDialog(src, NS_LITERAL_STRING("_blank"), options, arg, + getter_AddRefs(messageWindow)); return NS_OK; } -void -nsXFormsMessageElement::AppendCSSOptions(nsIDOMViewCSS* aViewCSS, nsAString& aOptions) -{ - if (!aViewCSS) - return; - // Try to get the calculated size of the message element. It will - // be used for the new window. - //XXX This could be extended also for 'top', 'left' etc. properties. - PRInt32 computedWidth = 0; - PRInt32 computedHeight = 0; - - nsAutoString tmp; - nsCOMPtr styles; - aViewCSS->GetComputedStyle(mElement, tmp, getter_AddRefs(styles)); - if (styles) { - nsCOMPtr cssWidth; - styles->GetPropertyCSSValue(NS_LITERAL_STRING("width"), - getter_AddRefs(cssWidth)); - nsCOMPtr pvalueWidth(do_QueryInterface(cssWidth)); - float width = 0; - if (pvalueWidth) { - PRUint16 type; - pvalueWidth->GetPrimitiveType(&type); - if (type == nsIDOMCSSPrimitiveValue::CSS_PX) - pvalueWidth->GetFloatValue(type, &width); - } - - nsCOMPtr cssHeight; - styles->GetPropertyCSSValue(NS_LITERAL_STRING("height"), - getter_AddRefs(cssHeight)); - nsCOMPtr pvalueHeight(do_QueryInterface(cssHeight)); - float height = 0; - if (pvalueHeight) { - PRUint16 type; - pvalueHeight->GetPrimitiveType(&type); - if (type == nsIDOMCSSPrimitiveValue::CSS_PX) - pvalueHeight->GetFloatValue(type, &height); - } - computedWidth = NS_STATIC_CAST(PRInt32, width); - computedHeight = NS_STATIC_CAST(PRInt32, height); - } - - if (computedWidth > 0 && computedHeight > 0) { - nsAutoString options; - options.AppendLiteral(",innerWidth="); - options.AppendInt(computedWidth); - options.AppendLiteral(",innerHeight="); - options.AppendInt(computedHeight); - aOptions.Append(options); - } -} - nsresult nsXFormsMessageElement::ConstructMessageWindowURL(nsAString& aData, PRBool aIsLink, @@ -789,8 +848,12 @@ nsXFormsMessageElement::ConstructMessageWindowURL(nsAString& aData, nsAutoString xul; xul.AssignLiteral(MESSAGE_WINDOW_UI_PART1); - if (aIsLink) + if (aIsLink) { + xul.AppendLiteral(MESSAGE_WINDOW_UI_PART1_WITH_SRC); xul.AppendLiteral("GetAttribute(NS_LITERAL_STRING("bind"), snb); + if (!snb.IsEmpty()) { + return NS_OK; + } + mElement->GetAttribute(NS_LITERAL_STRING("ref"), snb); + if (!snb.IsEmpty()) { + return NS_OK; + } + + // if no linking attribute, no need to go on + nsAutoString src; + mElement->GetAttribute(NS_LITERAL_STRING("src"), src); + if (src.IsEmpty()) { + return NS_OK; + } + + nsCOMPtr domDoc; + mElement->GetOwnerDocument(getter_AddRefs(domDoc)); + nsCOMPtr doc(do_QueryInterface(domDoc)); + NS_ENSURE_STATE(doc); + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), src, doc->GetDocumentCharacterSet().get(), + doc->GetDocumentURI()); + NS_ENSURE_STATE(uri); + + if (!nsXFormsUtils::CheckSameOrigin(doc, uri)) { + nsAutoString tagName; + mElement->GetLocalName(tagName); + const PRUnichar *strings[] = { tagName.get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLinkLoadOrigin"), + strings, 1, mElement, mElement); + // Keep the the dialog from popping up. Won't be able to reach the + // resource anyhow. + mStopType = eStopType_Security; + return NS_ERROR_FAILURE; + } + + nsCOMPtr loadGroup = doc->GetDocumentLoadGroup(); + NS_WARN_IF_FALSE(loadGroup, "No load group!"); + + // Using the same load group as the main document and creating + // the channel with LOAD_NORMAL flag delays the dispatching of + // the 'load' event until message data document has been loaded. + nsresult rv = NS_NewChannel(getter_AddRefs(mChannel), uri, nsnull, loadGroup, + this, nsIRequest::LOAD_NORMAL); + NS_ENSURE_TRUE(mChannel, rv); + + // See if it's an http channel. We'll look at the http status code more + // closely and only request the "HEAD" to keep the response small. + // Especially since we are requesting this for every message in the document + // and in most cases we pass off the URL to another browser service to + // get and display the message so no good to try to look at the contents + // anyway. + + // XXX ephemeral messages should probably get their full contents here once + // they are set up to handle external resources. + nsCOMPtr httpChannel = do_QueryInterface(mChannel); + if (httpChannel) { + PRBool isReallyHTTP = PR_FALSE; + uri->SchemeIs("http", &isReallyHTTP); + if (!isReallyHTTP) { + uri->SchemeIs("https", &isReallyHTTP); + } + if (isReallyHTTP) { + httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("HEAD")); + } + } + + rv = mChannel->AsyncOpen(this, nsnull); + if (NS_FAILED(rv)) { + mChannel = nsnull; + + // URI doesn't exist; report error. + // set up the error strings + nsAutoString tagName; + mElement->GetLocalName(tagName); + const PRUnichar *strings[] = { src.get(), tagName.get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink1Error"), + strings, 2, mElement, mElement); + mStopType = eStopType_LinkError; + return NS_ERROR_FAILURE; + } + + // channel should be running along smoothly, increment the count + AddRemoveExternalResource(PR_TRUE); + return NS_OK; +} + +// nsIInterfaceRequestor + +NS_IMETHODIMP +nsXFormsMessageElement::GetInterface(const nsIID &aIID, void **aResult) +{ + *aResult = nsnull; + return QueryInterface(aIID, aResult); +} + +// nsIChannelEventSink + +NS_IMETHODIMP +nsXFormsMessageElement::OnChannelRedirect(nsIChannel *OldChannel, + nsIChannel *aNewChannel, + PRUint32 aFlags) +{ + NS_PRECONDITION(aNewChannel, "Redirect without a channel?"); + + nsCOMPtr newURI; + nsresult rv = aNewChannel->GetURI(getter_AddRefs(newURI)); + NS_ENSURE_SUCCESS(rv, rv); + + NS_ENSURE_STATE(mElement); + nsCOMPtr domDoc; + mElement->GetOwnerDocument(getter_AddRefs(domDoc)); + nsCOMPtr doc(do_QueryInterface(domDoc)); + NS_ENSURE_STATE(doc); + + if (!nsXFormsUtils::CheckSameOrigin(doc, newURI)) { + nsAutoString tagName; + mElement->GetLocalName(tagName); + const PRUnichar *strings[] = { tagName.get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLinkLoadOrigin"), + strings, 1, mElement, mElement); + return NS_ERROR_ABORT; + } + + return NS_OK; +} + +// nsIStreamListener + +NS_IMETHODIMP +nsXFormsMessageElement::OnStartRequest(nsIRequest *aRequest, + nsISupports *aContext) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXFormsMessageElement::OnDataAvailable(nsIRequest *aRequest, + nsISupports *aContext, + nsIInputStream *aInputStream, + PRUint32 aOffset, + PRUint32 aCount) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXFormsMessageElement::OnStopRequest(nsIRequest *aRequest, + nsISupports *aContext, + nsresult aStatusCode) +{ + + // We are done with the load request, whatever the result, so make sure to + // null out mChannel before we return. Keep in mind that if this is the last + // message channel to be loaded for the xforms document then when + // AddRemoveExternalResource is called, it may result in xforms-ready firing. + // Should there be a message acting as a handler for xforms-ready, it will + // start the logic to display itself (HandleAction()). So we can't call + // AddRemoveExternalResource to remove this channel from the count until we've + // set the mStopType to be the proper value. Entering this function, + // mStopType will be eStopType_None, so if we need mStopType to be any other + // value (like in an error condition), please make sure it is set before + // AddRemoveExternalResource is called. + + if (NS_FAILED(aStatusCode)) { + // NS_BINDING_ABORTED means that we have been cancelled by a later + // AttributeSet() call (which will also reset mStopType). So don't treat + // like an error. + if (aStatusCode != NS_BINDING_ABORTED) { + nsAutoString src, tagName; + mElement->GetLocalName(tagName); + mElement->GetAttribute(NS_LITERAL_STRING("src"), src); + const PRUnichar *strings[] = { tagName.get(), src.get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink2Error"), + strings, 2, mElement, mElement); + mStopType = eStopType_LinkError; + AddRemoveExternalResource(PR_FALSE); + mChannel = nsnull; + + return NS_OK; + } + } + + PRUint32 responseStatus; + nsCOMPtr httpChannel = do_QueryInterface(mChannel); + if (NS_SUCCEEDED(aStatusCode) && httpChannel) { + nsresult rv = httpChannel->GetResponseStatus(&responseStatus); + + // If responseStatus is 4xx or 5xx, it is an error. 2xx is success. + // 3xx (various flavors of redirection) COULD be successful. Can't really + // follow those to conclusion so we'll assume they were successful. + if (NS_FAILED(rv) || (responseStatus >= 400)) { + nsAutoString src, tagName; + mElement->GetLocalName(tagName); + mElement->GetAttribute(NS_LITERAL_STRING("src"), src); + const PRUnichar *strings[] = { tagName.get(), src.get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("externalLink2Error"), + strings, 2, mElement, mElement); + mStopType = eStopType_LinkError; + } + } + + AddRemoveExternalResource(PR_FALSE); + mChannel = nsnull; + + return NS_OK; +} + +void +nsXFormsMessageElement::AddRemoveExternalResource(PRBool aAdd) +{ + // if this message doesn't have a channel established already or it has + // already returned, then no sense bumping the counter. + if (!mChannel) { + return; + } + + nsCOMPtr domDoc; + mElement->GetOwnerDocument(getter_AddRefs(domDoc)); + if (!domDoc) { + return; + } + + nsCOMPtr doc = do_QueryInterface(domDoc); + PRUint32 loadingMessages = NS_PTR_TO_UINT32( + doc->GetProperty(nsXFormsAtoms::externalMessagesProperty)); + if (aAdd) { + loadingMessages++; + } else { + if (loadingMessages) { + loadingMessages--; + } + } + doc->SetProperty(nsXFormsAtoms::externalMessagesProperty, + NS_REINTERPRET_CAST(void *, loadingMessages), nsnull); + + if (!loadingMessages) { + // no outstanding loads left, let the model in the document know in case + // the models are waiting to send out the xforms-ready event + + nsCOMPtr modelPriv = + nsXFormsUtils::GetModel(mElement); + if (modelPriv) { + // if there are no more messages loading then it is probably the case + // that my mChannel is going to get nulled out as soon as this function + // returns. If the model is waiting for this notification, then it may + // kick off the message right away and we should probably ensure that + // mChannel is gone before HandleAction is called. So...if the channel + // isn't pending, let's null it out right here. + PRBool isPending = PR_TRUE; + mChannel->IsPending(&isPending); + if (!isPending) { + mChannel = nsnull; + } + modelPriv->MessageLoadFinished(); + } + } +} + NS_HIDDEN_(nsresult) NS_NewXFormsMessageElement(nsIXTFElement **aResult) { diff --git a/mozilla/extensions/xforms/nsXFormsModelElement.cpp b/mozilla/extensions/xforms/nsXFormsModelElement.cpp index 7093edc24fd..10f6483a336 100644 --- a/mozilla/extensions/xforms/nsXFormsModelElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsModelElement.cpp @@ -50,7 +50,6 @@ #include "nsXFormsAtoms.h" #include "nsINameSpaceManager.h" #include "nsIServiceManager.h" -#include "nsINodeInfo.h" #include "nsIDOMEvent.h" #include "nsIDOMDOMImplementation.h" #include "nsIDOMXMLDocument.h" @@ -59,7 +58,6 @@ #include "nsIXFormsXPathEvaluator.h" #include "nsIDOMXPathNSResolver.h" #include "nsIDOMNSXPathExpression.h" -#include "nsIScriptGlobalObject.h" #include "nsIContent.h" #include "nsIURL.h" #include "nsNetUtil.h" @@ -76,10 +74,13 @@ #include "nsISchema.h" #include "nsAutoPtr.h" #include "nsArray.h" -#include "nsIEventStateManager.h" #include "nsIDOMDocumentXBL.h" +#include "nsIProgrammingLanguage.h" +#include "nsDOMError.h" +#include "nsIDOMXPathException.h" + #define XFORMS_LAZY_INSTANCE_BINDING \ - "chrome://xforms/content/xforms.xml#xforms-lazy-instance" + "chrome://xforms/content/xforms.xml#xforms-lazy-instance" #ifdef DEBUG //#define DEBUG_MODEL @@ -170,6 +171,321 @@ GetModelList(nsIDOMDocument *domDoc) doc->GetProperty(nsXFormsAtoms::modelListProperty)); } +static void +SupportsDtorFunc(void *aObject, nsIAtom *aPropertyName, + void *aPropertyValue, void *aData) +{ + nsISupports *propertyValue = NS_STATIC_CAST(nsISupports*, aPropertyValue); + NS_IF_RELEASE(propertyValue); +} + + +//------------------------------------------------------------------------------ +// --- nsXFormsControlListItem --- + + +nsXFormsControlListItem::iterator::iterator() + : mCur(0) +{ +} + +nsXFormsControlListItem::iterator::iterator(const nsXFormsControlListItem::iterator& aCopy) + : mCur(aCopy.mCur) +{ + mStack = aCopy.mStack; +} + +nsXFormsControlListItem::iterator +nsXFormsControlListItem::iterator::operator=(nsXFormsControlListItem* aCnt) +{ + mCur = aCnt; + return *this; +} + +bool +nsXFormsControlListItem::iterator::operator!=(const nsXFormsControlListItem* aCnt) +{ + return mCur != aCnt; +} + +nsXFormsControlListItem::iterator +nsXFormsControlListItem::iterator::operator++() +{ + if (!mCur) + return *this; + + if (mCur->mFirstChild) { + if (!mCur->mNextSibling) { + mCur = mCur->mFirstChild; + return *this; + } + mStack.AppendElement(mCur->mFirstChild); + } + + if (mCur->mNextSibling) { + mCur = mCur->mNextSibling; + } else if (mStack.Count()) { + mCur = (nsXFormsControlListItem*) mStack[mStack.Count() - 1]; + mStack.RemoveElementAt(mStack.Count() - 1); + } else { + mCur = nsnull; + } + + return *this; +} + +nsXFormsControlListItem* +nsXFormsControlListItem::iterator::operator*() +{ + return mCur; +} + +nsXFormsControlListItem::nsXFormsControlListItem(nsIXFormsControl* aControl) + : mNode(aControl), + mNextSibling(nsnull), + mFirstChild(nsnull) +{ + +} + +nsXFormsControlListItem::~nsXFormsControlListItem() +{ + Clear(); +} + +nsXFormsControlListItem::nsXFormsControlListItem(const nsXFormsControlListItem& aCopy) + : mNode(aCopy.mNode) +{ + if (aCopy.mNextSibling) { + mNextSibling = new nsXFormsControlListItem(*aCopy.mNextSibling); + NS_WARN_IF_FALSE(mNextSibling, "could not new?!"); + } else { + mNextSibling = nsnull; + } + + if (aCopy.mFirstChild) { + mFirstChild = new nsXFormsControlListItem(*aCopy.mFirstChild); + NS_WARN_IF_FALSE(mFirstChild, "could not new?!"); + } else { + mFirstChild = nsnull; + } +} + +void +nsXFormsControlListItem::Clear() +{ + if (mFirstChild) { + mFirstChild->Clear(); + NS_ASSERTION(!(mFirstChild->mFirstChild || mFirstChild->mNextSibling), + "child did not clear members!!"); + delete mFirstChild; + mFirstChild = nsnull; + } + if (mNextSibling) { + mNextSibling->Clear(); + NS_ASSERTION(!(mNextSibling->mFirstChild || mNextSibling->mNextSibling), + "sibling did not clear members!!"); + delete mNextSibling; + mNextSibling = nsnull; + } + if (mNode) + mNode = nsnull; +} + +nsresult +nsXFormsControlListItem::AddControl(nsIXFormsControl *aControl, + nsIXFormsControl *aParent) +{ + // Four insertion posibilities: + + // 1) Delegate to first child from root node + if (!mNode && mFirstChild) { + return mFirstChild->AddControl(aControl, aParent); + } + + // 2) control with no parent + if (!aParent) { + nsXFormsControlListItem* newNode = new nsXFormsControlListItem(aControl); + NS_ENSURE_STATE(newNode); + + // Empty tree (we have already checked mFirstChild) + if (!mNode) { + mFirstChild = newNode; + return NS_OK; + } + + if (mNextSibling) { + newNode->mNextSibling = mNextSibling; + } + mNextSibling = newNode; +#ifdef DEBUG + nsXFormsControlListItem* next = newNode->mNextSibling; + while (next) { + NS_ASSERTION(aControl != next->mNode, + "Node already in tree!!"); + next = next->mNextSibling; + } +#endif + + return NS_OK; + } + + // Locate parent + nsXFormsControlListItem* parentControl = FindControl(aParent); + NS_ASSERTION(parentControl, "Parent not found?!"); + + // 3) parentControl has a first child, insert as sibling to that + if (parentControl->mFirstChild) { + return parentControl->mFirstChild->AddControl(aControl, nsnull); + } + + // 4) first child for parentControl + nsXFormsControlListItem* newNode = new nsXFormsControlListItem(aControl); + NS_ENSURE_STATE(newNode); + parentControl->mFirstChild = newNode; + + return NS_OK; +} + +nsresult +nsXFormsControlListItem::RemoveControl(nsIXFormsControl *aControl, + PRBool &aRemoved) +{ + nsXFormsControlListItem* deleteMe = nsnull; + aRemoved = PR_FALSE; + + // Try children + if (mFirstChild) { + // The control to remove is our first child + if (mFirstChild->mNode == aControl) { + deleteMe = mFirstChild; + + // Fix siblings + if (deleteMe->mNextSibling) { + mFirstChild = deleteMe->mNextSibling; + deleteMe->mNextSibling = nsnull; + } else { + mFirstChild = nsnull; + } + + // Fix children + if (deleteMe->mFirstChild) { + if (!mFirstChild) { + mFirstChild = deleteMe->mFirstChild; + } else { + nsXFormsControlListItem *insertPos = mFirstChild; + while (insertPos->mNextSibling) { + insertPos = insertPos->mNextSibling; + } + insertPos->mNextSibling = deleteMe->mFirstChild; + } + deleteMe->mFirstChild = nsnull; + } + } else { + // Run through children + nsresult rv = mFirstChild->RemoveControl(aControl, aRemoved); + NS_ENSURE_SUCCESS(rv, rv); + if (aRemoved) + return rv; + } + } + + // Try siblings + if (!deleteMe && mNextSibling) { + if (mNextSibling->mNode == aControl) { + deleteMe = mNextSibling; + // Fix siblings + if (deleteMe->mNextSibling) { + mNextSibling = deleteMe->mNextSibling; + deleteMe->mNextSibling = nsnull; + } else { + mNextSibling = nsnull; + } + // Fix children + if (deleteMe->mFirstChild) { + if (!mNextSibling) { + mNextSibling = deleteMe->mFirstChild; + } else { + nsXFormsControlListItem *insertPos = mNextSibling; + while (insertPos->mNextSibling) { + insertPos = insertPos->mNextSibling; + } + insertPos->mNextSibling = deleteMe->mFirstChild; + } + deleteMe->mFirstChild = nsnull; + } + } else { + // run through siblings + return mNextSibling->RemoveControl(aControl, aRemoved); + } + } + + if (deleteMe) { + NS_ASSERTION(!(deleteMe->mNextSibling), + "Deleted control should not have siblings!"); + NS_ASSERTION(!(deleteMe->mFirstChild), + "Deleted control should not have children!"); + delete deleteMe; + aRemoved = PR_TRUE; + } + + return NS_OK; +} + +nsXFormsControlListItem* +nsXFormsControlListItem::FindControl(nsIXFormsControl *aControl) +{ + if (!aControl) + return nsnull; + + // this should only be false for the root + if (mNode) { + // XXX: *sigh* pointer comparision of nsIXFormsControl would be nice... + nsCOMPtr el1, el2; + aControl->GetElement(getter_AddRefs(el1)); + mNode->GetElement(getter_AddRefs(el2)); + + if (el1 == el2) + return this; + } + + nsXFormsControlListItem* cur = nsnull; + if (mFirstChild) { + cur = mFirstChild->FindControl(aControl); + } + if (!cur && mNextSibling) { + cur = mNextSibling->FindControl(aControl); + } + return cur; +} + +already_AddRefed +nsXFormsControlListItem::Control() +{ + nsIXFormsControl* res = nsnull; + if (mNode) + NS_ADDREF(res = mNode); + NS_WARN_IF_FALSE(res, "Returning nsnull for a control. Bad sign."); + return res; +} + +nsXFormsControlListItem* +nsXFormsControlListItem::begin() +{ + // handle root + if (!mNode) + return mFirstChild; + + return this; +} + +nsXFormsControlListItem* +nsXFormsControlListItem::end() +{ + return nsnull; +} + + //------------------------------------------------------------------------------ static const nsIID sScriptingIIDs[] = { @@ -255,14 +571,17 @@ nsXFormsModelElement::CancelPostRefresh(nsIXFormsControl* aControl) nsXFormsModelElement::nsXFormsModelElement() : mElement(nsnull), + mFormControls(nsnull), mSchemaCount(0), mSchemaTotal(0), mPendingInstanceCount(0), mDocumentLoaded(PR_FALSE), mNeedsRefresh(PR_FALSE), mInstancesInitialized(PR_FALSE), + mReadyHandled(PR_FALSE), mInstanceDocuments(nsnull), - mLazyModel(PR_FALSE) + mLazyModel(PR_FALSE), + mConstructDoneHandled(PR_FALSE) { } @@ -290,6 +609,8 @@ nsXFormsModelElement::OnDestroyed() if (mInstanceDocuments) mInstanceDocuments->DropReferences(); + mFormControls.Clear(); + return NS_OK; } @@ -401,6 +722,8 @@ nsXFormsModelElement::InitializeInstances() // Parse the whitespace-separated list. nsCOMPtr content = do_QueryInterface(mElement); nsRefPtr baseURI = content->GetBaseURI(); + nsRefPtr docURI = content->GetOwnerDoc() ? + content->GetOwnerDoc()->GetDocumentURI() : nsnull; nsCStringArray schemas; schemas.ParseString(NS_ConvertUTF16toUTF8(schemaList).get(), " \t\r\n"); @@ -422,7 +745,7 @@ nsXFormsModelElement::InitializeInstances() newURL->GetRef(ref); newURL->SetRef(EmptyCString()); PRBool equals = PR_FALSE; - newURL->Equals(baseURI, &equals); + newURL->Equals(docURI, &equals); if (equals) { // We will not be able to locate the element using the // getElementById function defined on our document when @@ -454,10 +777,15 @@ nsXFormsModelElement::InitializeInstances() } } if (NS_FAILED(rv)) { - // this is a fatal error (XXX) + // this is a fatal error nsXFormsUtils::ReportError(NS_LITERAL_STRING("schemaLoadError"), mElement); nsXFormsUtils::DispatchEvent(mElement, eEvent_LinkException); - return NS_OK; + rv = NS_OK; + if (!nsXFormsUtils::HandleFatalError(mElement, + NS_LITERAL_STRING("XFormsLinkException"))) { + rv = NS_ERROR_FAILURE; + } + return rv; } } } @@ -465,6 +793,7 @@ nsXFormsModelElement::InitializeInstances() // 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. + // Lazy element is created in anonymous content using XBL. NS_ENSURE_STATE(mInstanceDocuments); PRUint32 instCount; mInstanceDocuments->GetLength(&instCount); @@ -549,20 +878,18 @@ nsXFormsModelElement::HandleDefault(nsIDOMEvent *aEvent, PRBool *aHandled) rv = Rebuild(); } else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_ModelConstructDone].name)) { rv = ConstructDone(); - } else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_Ready].name)) { - Ready(); + mConstructDoneHandled = PR_TRUE; } else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_Reset].name)) { Reset(); } else if (type.EqualsASCII(sXFormsEventsEntries[eEvent_BindingException].name)) { - *aHandled = nsXFormsUtils::HandleBindingException(mElement); + *aHandled = nsXFormsUtils::HandleFatalError(mElement, + NS_LITERAL_STRING("XFormsBindingException")); } else { *aHandled = PR_FALSE; } -#ifdef DEBUG - if (NS_FAILED(rv)) - printf("nsXFormsModelElement::HandleDefault() failed!\n"); -#endif + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), + "nsXFormsModelElement::HandleDefault() failed!\n"); return rv; } @@ -597,7 +924,7 @@ nsXFormsModelElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper) nsresult rv = mMDG.Init(this); NS_ENSURE_SUCCESS(rv, rv); - mSchemas = do_GetService(NS_SCHEMALOADER_CONTRACTID); + mSchemas = do_CreateInstance(NS_SCHEMALOADER_CONTRACTID); mInstanceDocuments = new nsXFormsModelInstanceDocuments(); NS_ASSERTION(mInstanceDocuments, "could not create mInstanceDocuments?!"); @@ -627,7 +954,18 @@ nsXFormsModelElement::GetInstanceDocument(const nsAString& aInstanceID, NS_ENSURE_ARG_POINTER(aDocument); *aDocument = FindInstanceDocument(aInstanceID).get(); // transfer reference - return *aDocument ? NS_OK : NS_ERROR_FAILURE; + + if (*aDocument) { + return NS_OK; + } + + const nsPromiseFlatString& flat = PromiseFlatString(aInstanceID); + const PRUnichar *strings[] = { flat.get() }; + nsXFormsUtils::ReportError(aInstanceID.IsEmpty() ? + NS_LITERAL_STRING("defInstanceNotFound") : + NS_LITERAL_STRING("instanceNotFound"), + strings, 1, mElement, nsnull); + return NS_ERROR_DOM_NOT_FOUND_ERR; } NS_IMETHODIMP @@ -648,45 +986,26 @@ nsXFormsModelElement::Rebuild() mNodeToType.Clear(); mNodeToP3PType.Clear(); - // 2. Re-attach all elements + // 2. Process bind elements + rv = ProcessBindElements(); + NS_ENSURE_SUCCESS(rv, rv); + + // 3. Re-attach all elements if (mDocumentLoaded) { // if it's not during initializing phase - // Copy the form control list as it stands right now. - nsVoidArray *oldFormList = new nsVoidArray(); - NS_ENSURE_TRUE(oldFormList, NS_ERROR_OUT_OF_MEMORY); - *oldFormList = mFormControls; - - // Clear out mFormControls so that we can rebuild the list. We'll go control - // by control over the old list and rebind the controls. - mFormControls.Clear(); // if this happens on a documentchange + nsXFormsControlListItem::iterator it; + for (it = mFormControls.begin(); it != mFormControls.end(); ++it) { + nsCOMPtr control = (*it)->Control(); + NS_ASSERTION(control, "mFormControls has null control?!"); - PRInt32 controlCount = oldFormList->Count(); - for (PRInt32 i = 0; i < controlCount; ++i) { - nsIXFormsControl* control = NS_STATIC_CAST(nsIXFormsControl*, - (*oldFormList)[i]); - /// @todo If a control is removed because of previous control has been - /// refreshed, we do, obviously, not need to refresh it. So mFormControls - /// should have weak bindings to the controls I guess? (XXX) - /// - /// This could happen for \s for example. - if (!control) { - continue; - } - - // run bind to reset mBoundNode for all of these controls and also, in the - // process, they will be added to the model that they should be bound to. + // run bind to reset mBoundNode for all of the model's controls control->Bind(); } - - delete oldFormList; // Triggers a refresh of all controls mNeedsRefresh = PR_TRUE; } - // 3. Rebuild graph - rv = ProcessBindElements(); - NS_ENSURE_SUCCESS(rv, rv); - + // 4. Rebuild graph return mMDG.Rebuild(); } @@ -714,7 +1033,7 @@ nsXFormsModelElement::SetSingleState(nsIDOMElement *aElement, nsresult nsXFormsModelElement::SetStatesInternal(nsIXFormsControl *aControl, nsIDOMNode *aNode, - PRBool aAllStates) + PRBool aDispatchEvents) { NS_ENSURE_ARG(aControl); if (!aNode) @@ -730,32 +1049,25 @@ nsXFormsModelElement::SetStatesInternal(nsIXFormsControl *aControl, const nsXFormsNodeState *ns = mMDG.GetNodeState(aNode); NS_ENSURE_STATE(ns); - // XXX nsXFormsNodeState could expose a bitmask using NS_EVENTs, to avoid - // most of this... - PRBool tmp = ns->IsValid(); - PRUint32 state = tmp ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID; - if (aAllStates || ns->ShouldDispatchValid()) { - SetSingleState(element, tmp, eEvent_Valid); - } - tmp = ns->IsReadonly(); - state |= tmp ? NS_EVENT_STATE_MOZ_READONLY : NS_EVENT_STATE_MOZ_READWRITE; - if (aAllStates || ns->ShouldDispatchReadonly()) { - SetSingleState(element, tmp, eEvent_Readonly); - } - tmp = ns->IsRequired(); - state |= tmp ? NS_EVENT_STATE_REQUIRED : NS_EVENT_STATE_OPTIONAL; - if (aAllStates || ns->ShouldDispatchRequired()) { - SetSingleState(element, tmp, eEvent_Required); - } - tmp = ns->IsRelevant(); - state |= tmp ? NS_EVENT_STATE_ENABLED : NS_EVENT_STATE_DISABLED; - if (aAllStates || ns->ShouldDispatchRelevant()) { - SetSingleState(element, tmp, eEvent_Enabled); - } - - nsresult rv = xtfWrap->SetIntrinsicState(state); + nsresult rv = xtfWrap->SetIntrinsicState(ns->GetIntrinsicState()); NS_ENSURE_SUCCESS(rv, rv); + if (!aDispatchEvents) + return NS_OK; + + if (ns->ShouldDispatchValid()) { + SetSingleState(element, ns->IsValid(), eEvent_Valid); + } + if (ns->ShouldDispatchReadonly()) { + SetSingleState(element, ns->IsReadonly(), eEvent_Readonly); + } + if (ns->ShouldDispatchRequired()) { + SetSingleState(element, ns->IsRequired(), eEvent_Required); + } + if (ns->ShouldDispatchRelevant()) { + SetSingleState(element, ns->IsRelevant(), eEvent_Enabled); + } + if (ns->ShouldDispatchValueChanged()) { nsXFormsUtils::DispatchEvent(element, eEvent_ValueChanged); } @@ -777,7 +1089,7 @@ nsXFormsModelElement::Revalidate() nsAutoString name; node->GetNodeName(name); printf("\t%s [%p]\n", - NS_ConvertUCS2toUTF8(name).get(), + NS_ConvertUTF16toUTF8(name).get(), (void*) node); } #endif @@ -788,6 +1100,159 @@ nsXFormsModelElement::Revalidate() return NS_OK; } +nsresult +nsXFormsModelElement::RefreshSubTree(nsXFormsControlListItem *aCurrent, + PRBool aForceRebind) +{ + nsresult rv; + + while (aCurrent) { + nsCOMPtr control(aCurrent->Control()); + NS_ASSERTION(control, "A tree node without a control?!"); + + // Get bound node + nsCOMPtr boundNode; + control->GetBoundNode(getter_AddRefs(boundNode)); + + PRBool rebind = aForceRebind; + PRBool refresh = PR_FALSE; + PRBool rebindChildren = PR_FALSE; + +#ifdef DEBUG_MODEL + nsCOMPtr controlElement; + control->GetElement(getter_AddRefs(controlElement)); + printf("rebind: %d, mNeedsRefresh: %d, rebindChildren: %d\n", + rebind, mNeedsRefresh, rebindChildren); + if (controlElement) { + printf("Checking control: "); + //DBG_TAGINFO(controlElement); + } +#endif + + if (mNeedsRefresh || rebind) { + refresh = PR_TRUE; + } else { + PRBool usesModelBinding = PR_FALSE; + control->GetUsesModelBinding(&usesModelBinding); + +#ifdef DEBUG_MODEL + printf("usesModelBinding: %d\n", usesModelBinding); +#endif + + nsCOMArray *deps = nsnull; + if (usesModelBinding) { + if (!boundNode) { + // If a control uses a model binding, but has no bound node a + // rebuild is the only thing that'll (eventually) change it + aCurrent = aCurrent->NextSibling(); + continue; + } + } else { + // Get dependencies + control->GetDependencies(&deps); + } + PRUint32 depCount = deps ? deps->Count() : 0; + +#ifdef DEBUG_MODEL + nsAutoString boundName; + if (boundNode) + boundNode->GetNodeName(boundName); + printf("\tDependencies: %d, Bound to: '%s' [%p]\n", + depCount, + NS_ConvertUTF16toUTF8(boundName).get(), + (void*) boundNode); + + nsAutoString depNodeName; + for (PRUint32 t = 0; t < depCount; ++t) { + nsCOMPtr tmpdep = deps->ObjectAt(t); + if (tmpdep) { + tmpdep->GetNodeName(depNodeName); + printf("\t\t%s [%p]\n", + NS_ConvertUTF16toUTF8(depNodeName).get(), + (void*) tmpdep); + } + } +#endif + + nsCOMPtr curChanged; + + // Iterator over changed nodes. Checking for rebind, too. If it ever + // becomes true due to some condition below, we can stop this testing + // since any control that needs to rebind will also refresh. + for (PRInt32 j = 0; j < mChangedNodes.Count() && !rebind; ++j) { + curChanged = do_QueryInterface(mChangedNodes[j]); + + // Check whether the bound node is dirty. If so, we need to refresh the + // control (get updated node value from the bound node) + if (!refresh && boundNode) { + curChanged->IsSameNode(boundNode, &refresh); + + // Two ways to go here. Keep in mind that controls using model + // binding expressions never needs to have dependencies checked as + // they only rebind on xforms-rebuild + if (refresh && usesModelBinding) { + // 1) If the control needs a refresh, and uses model bindings, + // we can stop checking here + break; + } + if (refresh || usesModelBinding) { + // 2) If either the control needs a refresh or it uses a model + // binding we can continue to next changed node + continue; + } + } + + // Check whether any dependencies are dirty. If so, we need to rebind + // the control (re-evaluate it's binding expression) + for (PRUint32 k = 0; k < depCount; ++k) { + /// @note beaufour: I'm not too happy about this ... + /// O(mChangedNodes.Count() * deps->Count()), but using the pointers + /// for sorting and comparing does not work... + curChanged->IsSameNode(deps->ObjectAt(k), &rebind); + if (rebind) + // We need to rebind the control, no need to check any more + break; + } + } +#ifdef DEBUG_MODEL + printf("\trebind: %d, refresh: %d\n", rebind, refresh); +#endif + } + + // Handle rebinding + if (rebind) { + nsCOMPtr oldBoundNode; + control->GetBoundNode(getter_AddRefs(oldBoundNode)); + rv = control->Bind(); + NS_ENSURE_SUCCESS(rv, rv); + control->GetBoundNode(getter_AddRefs(boundNode)); + rebindChildren = (oldBoundNode != boundNode); + } + + // Handle refreshing + if (rebind || refresh) { + rv = SetStatesInternal(control, boundNode); + NS_ENSURE_SUCCESS(rv, rv); + control->Refresh(); + // XXX: we should really check the return result, but f.x. select1 + // returns error because of no widget...? so we should ensure that an + // error is only returned when there actually is an error, and we should + // report that on the console... possibly we should then continue, + // instead of bailing totally. + // NS_ENSURE_SUCCESS(rv, rv); + } + + // Refresh children + rv = RefreshSubTree(aCurrent->FirstChild(), rebindChildren); + NS_ENSURE_SUCCESS(rv, rv); + + aCurrent = aCurrent->NextSibling(); + } + + return NS_OK; +} + + NS_IMETHODIMP nsXFormsModelElement::Refresh() { @@ -796,111 +1261,17 @@ nsXFormsModelElement::Refresh() #endif nsPostRefresh postRefresh = nsPostRefresh(); - // Iterate over all form controls if not during initialization phase (then - // this is handled in InitializeControls()) - if (mDocumentLoaded) { - PRInt32 controlCount = mFormControls.Count(); - for (PRInt32 i = 0; i < controlCount; ++i) { - nsIXFormsControl* control = NS_STATIC_CAST(nsIXFormsControl*, mFormControls[i]); - /// @todo If a control is removed because of previous control has been - /// refreshed, we do, obviously, not need to refresh it. So mFormControls - /// should have weak bindings to the controls I guess? (XXX) - /// - /// This could happen for \s for example. - if (!control) { - continue; - } - - // Get bound node - nsCOMPtr boundNode; - control->GetBoundNode(getter_AddRefs(boundNode)); - - PRBool rebind = PR_FALSE; - PRBool refresh = PR_FALSE; - - if (mNeedsRefresh) { - refresh = PR_TRUE; - } else { - // Get dependencies - nsCOMArray *deps = nsnull; - control->GetDependencies(&deps); - -#ifdef DEBUG_MODEL - PRUint32 depCount = deps ? deps->Count() : 0; - nsCOMPtr controlElement; - control->GetElement(getter_AddRefs(controlElement)); - if (controlElement) { - printf("Checking control: "); - //DBG_TAGINFO(controlElement); - nsAutoString boundName; - if (boundNode) - boundNode->GetNodeName(boundName); - printf("\tDependencies: %d, Bound to: '%s' [%p]\n", - depCount, - NS_ConvertUCS2toUTF8(boundName).get(), - (void*) boundNode); - - nsAutoString depNodeName; - for (PRUint32 t = 0; t < depCount; ++t) { - nsCOMPtr tmpdep = deps->ObjectAt(t); - if (tmpdep) { - tmpdep->GetNodeName(depNodeName); - printf("\t\t%s [%p]\n", - NS_ConvertUCS2toUTF8(depNodeName).get(), - (void*) tmpdep); - } - } - } -#endif - - nsCOMPtr curChanged; - - for (PRInt32 j = 0; j < mChangedNodes.Count(); ++j) { - curChanged = do_QueryInterface(mChangedNodes[j]); - - // Check whether the bound node is dirty. If so, we need to refresh the - // control (get updated node value from the bound node) - if (!refresh && boundNode) { - curChanged->IsSameNode(boundNode, &refresh); - - if (refresh) - // We need to refresh the control. We cannot break out of the loop - // as we need to check dependencies - continue; - } - - // Check whether any dependencies are dirty. If so, we need to rebind - // the control (re-evaluate it's binding expression) - for (PRInt32 k = 0; k < deps->Count(); ++k) { - /// @note beaufour: I'm not to happy about this ... - /// O(mChangedNodes.Count() * deps->Count()), but using the pointers - /// for sorting and comparing does not work... - curChanged->IsSameNode(deps->ObjectAt(k), &rebind); - if (rebind) - // We need to rebind the control, no need to check any more - break; - } - } -#ifdef DEBUG_MODEL - printf("\trebind: %d, refresh: %d\n", rebind, refresh); -#endif - } - - if (rebind) { - control->Bind(); - control->GetBoundNode(getter_AddRefs(boundNode)); - } - if (rebind || refresh) { - nsresult rv = SetStatesInternal(control, boundNode); - NS_ENSURE_SUCCESS(rv, rv); - control->Refresh(); - } - } - - mChangedNodes.Clear(); - mNeedsRefresh = PR_FALSE; + if (!mDocumentLoaded) { + return NS_OK; } - + + // Kick off refreshing on root node + nsresult rv = RefreshSubTree(mFormControls.FirstChild(), PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + + // Clear refresh structures + mChangedNodes.Clear(); + mNeedsRefresh = PR_FALSE; mMDG.ClearDispatchFlags(); return NS_OK; @@ -917,8 +1288,6 @@ nsXFormsModelElement::OnLoad(nsISchema* aSchema) nsresult rv = FinishConstruction(); NS_ENSURE_SUCCESS(rv, rv); - nsXFormsUtils::DispatchEvent(mElement, eEvent_Refresh); - MaybeNotifyCompletion(); } @@ -959,18 +1328,22 @@ nsXFormsModelElement::HandleEvent(nsIDOMEvent* aEvent) // nsIModelElementPrivate NS_IMETHODIMP -nsXFormsModelElement::AddFormControl(nsIXFormsControl *aControl) +nsXFormsModelElement::AddFormControl(nsIXFormsControl *aControl, + nsIXFormsControl *aParent) { - if (mFormControls.IndexOf(aControl) == -1) - mFormControls.AppendElement(aControl); - return NS_OK; + NS_ENSURE_ARG(aControl); + return mFormControls.AddControl(aControl, aParent); } NS_IMETHODIMP nsXFormsModelElement::RemoveFormControl(nsIXFormsControl *aControl) { - mFormControls.RemoveElement(aControl); - return NS_OK; + NS_ENSURE_ARG(aControl); + PRBool removed; + nsresult rv = mFormControls.RemoveControl(aControl, removed); + NS_WARN_IF_FALSE(removed, + "Tried to remove control that was not in the model"); + return rv; } NS_IMETHODIMP @@ -1034,14 +1407,20 @@ nsXFormsModelElement::InstanceLoadStarted() NS_IMETHODIMP nsXFormsModelElement::InstanceLoadFinished(PRBool aSuccess) { - --mPendingInstanceCount; if (!aSuccess) { + // This will leave mPendingInstanceCount in an invalid state, which is + // exactly what we want, because this is a fatal error, and processing + // should stop. If we decrease mPendingInstanceCount, the model would + // finish construction, which is wrong. nsXFormsUtils::ReportError(NS_LITERAL_STRING("instanceLoadError"), mElement); nsXFormsUtils::DispatchEvent(mElement, eEvent_LinkException); - } else if (IsComplete()) { + return NS_OK; + } + + --mPendingInstanceCount; + if (IsComplete()) { nsresult rv = FinishConstruction(); if (NS_SUCCEEDED(rv)) { - nsXFormsUtils::DispatchEvent(mElement, eEvent_Refresh); MaybeNotifyCompletion(); } } @@ -1147,6 +1526,62 @@ nsXFormsModelElement::ValidateNode(nsIDOMNode *aInstanceNode, PRBool *aResult) return NS_OK; } +nsresult +nsXFormsModelElement::ValidateDocument(nsIDOMDocument *aInstanceDocument, + PRBool *aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + NS_ENSURE_ARG(aInstanceDocument); + + /* + This will process the instance document and check for schema validity. It + will mark nodes in the document with their schema types using nsIProperty + until it hits a structural schema validation error. So if the instance + document's XML structure is invalid, don't expect type properties to be + set. + + Note that if the structure is fine but some simple types nodes (nodes + that contain text only) are invalid (say one has a empty nodeValue but + should be a date), the schema validator will continue processing and add + the type properties. Schema validation will return false at the end. + */ + + nsCOMPtr element; + nsresult rv = aInstanceDocument->GetDocumentElement(getter_AddRefs(element)); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool isValid = PR_FALSE; + + // get namespace from node + nsAutoString nsuri; + element->GetNamespaceURI(nsuri); + + nsCOMPtr schemaColl = do_QueryInterface(mSchemas); + NS_ENSURE_STATE(schemaColl); + + nsCOMPtr schema; + schemaColl->GetSchema(nsuri, getter_AddRefs(schema)); + if (schema) { + nsXFormsSchemaValidator validator; + validator.LoadSchema(schema); + // Validate will validate the node and its subtree, as per the schema + // specification. + isValid = validator.Validate(element); + } else { + // no schema found for the instance document's namespace. + nsCOMPtr instanceElement; + nsXFormsUtils::GetInstanceNodeForData(element, + getter_AddRefs(instanceElement)); + const PRUnichar *strings[] = { nsuri.get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("noSchemaForInstance"), + strings, 1, instanceElement, nsnull); + rv = NS_ERROR_UNEXPECTED; + } + + *aResult = isValid; + return rv; +} + /* * SUBMIT_SERIALIZE_NODE - node is to be serialized * SUBMIT_SKIP_NODE - node is not to be serialized @@ -1179,6 +1614,20 @@ nsXFormsModelElement::HandleInstanceDataNode(nsIDOMNode *aInstanceDataNode, unsi return NS_OK; } +NS_IMETHODIMP +nsXFormsModelElement::GetLazyAuthored(PRBool *aLazyInstance) +{ + *aLazyInstance = mLazyModel; + return NS_OK; +} + +NS_IMETHODIMP +nsXFormsModelElement::GetIsReady(PRBool *aIsReady) +{ + *aIsReady = mReadyHandled; + return NS_OK; +} + NS_IMETHODIMP nsXFormsModelElement::GetTypeFromNode(nsIDOMNode *aInstanceData, nsAString &aType, @@ -1203,6 +1652,21 @@ nsXFormsModelElement::GetTypeFromNode(nsIDOMNode *aInstanceData, // If there was no type information on the node itself, check for a type // bound to the node via \ if (!typeVal && !mNodeToType.Get(aInstanceData, &typeVal)) { + // check if schema validation left us a nsISchemaType* + nsCOMPtr content = do_QueryInterface(aInstanceData); + + if (content) { + nsISchemaType *type; + nsCOMPtr myAtom = do_GetAtom("xsdtype"); + + type = NS_STATIC_CAST(nsISchemaType *, content->GetProperty(myAtom)); + if (type) { + type->GetName(aType); + type->GetTargetNamespace(aNSUri); + return NS_OK; + } + } + // No type information found return NS_ERROR_NOT_AVAILABLE; } @@ -1252,7 +1716,6 @@ nsXFormsModelElement::GetTypeFromNode(nsIDOMNode *aInstanceData, return rv; } - // nsIXFormsContextControl NS_IMETHODIMP @@ -1308,13 +1771,6 @@ nsXFormsModelElement::GetContext(nsAString &aModelID, return NS_OK; } -NS_IMETHODIMP -nsXFormsModelElement::GetLazyAuthored(PRBool *aLazyInstance) -{ - *aLazyInstance = mLazyModel; - return NS_OK; -} - // internal methods already_AddRefed @@ -1324,8 +1780,9 @@ nsXFormsModelElement::FindInstanceDocument(const nsAString &aID) nsXFormsModelElement::FindInstanceElement(aID, getter_AddRefs(instance)); nsIDOMDocument *doc = nsnull; - if (instance) - instance->GetDocument(&doc); // addrefs + if (instance) { + instance->GetInstanceDocument(&doc); // addrefs + } return doc; } @@ -1370,7 +1827,8 @@ nsXFormsModelElement::ProcessBindElements() child->GetNamespaceURI(namespaceURI); if (namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) { rv = ProcessBind(xpath, firstInstanceRoot, 1, 1, - nsCOMPtr(do_QueryInterface(child))); + nsCOMPtr(do_QueryInterface(child)), + PR_TRUE); if (NS_FAILED(rv)) { return NS_OK; } @@ -1391,12 +1849,6 @@ nsXFormsModelElement::Reset() nsXFormsUtils::DispatchEvent(mElement, eEvent_Refresh); } -void -nsXFormsModelElement::Ready() -{ - BackupOrRestoreInstanceData(PR_FALSE); -} - // This function will restore all of the model's instance data to it's original // state if the supplied boolean is PR_TRUE. If it is PR_FALSE, this function // will cause this model's instance data to be backed up. @@ -1492,15 +1944,19 @@ nsXFormsModelElement::InitializeControls() #endif nsPostRefresh postRefresh = nsPostRefresh(); - PRInt32 controlCount = mFormControls.Count(); + nsXFormsControlListItem::iterator it; nsresult rv; - for (PRInt32 i = 0; i < controlCount; ++i) { + for (it = mFormControls.begin(); it != mFormControls.end(); ++it) { // Get control - nsIXFormsControl *control = NS_STATIC_CAST(nsIXFormsControl*, - mFormControls[i]); - if (!control) - continue; + nsCOMPtr control = (*it)->Control(); + NS_ASSERTION(control, "mFormControls has null control?!"); +#ifdef DEBUG_MODEL + printf("\tControl (%p): ", (void*) control); + nsCOMPtr controlElement; + control->GetElement(getter_AddRefs(controlElement)); + // DBG_TAGINFO(controlElement); +#endif // Rebind rv = control->Bind(); NS_ENSURE_SUCCESS(rv, rv); @@ -1511,7 +1967,7 @@ nsXFormsModelElement::InitializeControls() NS_ENSURE_SUCCESS(rv, rv); // Set MIP states on control - rv = SetStatesInternal(control, boundNode, PR_TRUE); + rv = SetStatesInternal(control, boundNode, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); // Refresh controls @@ -1519,6 +1975,8 @@ nsXFormsModelElement::InitializeControls() NS_ENSURE_SUCCESS(rv, rv); } + mChangedNodes.Clear(); + return NS_OK; } @@ -1553,12 +2011,58 @@ nsXFormsModelElement::MaybeNotifyCompletion() nsXFormsUtils::DispatchEvent(model->mElement, eEvent_ModelConstructDone); } + // validate the instance documents becauar we want schemaValidation to add + // schema type properties from the schema file unto our instance document + // elements. We don't care about the validation results. + if (mInstanceDocuments) { + PRUint32 instCount; + mInstanceDocuments->GetLength(&instCount); + if (instCount) { + nsCOMPtr document; + + for (PRUint32 i = 0; i < instCount; ++i) { + nsIInstanceElementPrivate* instEle = mInstanceDocuments->GetInstanceAt(i); + nsCOMPtr NSInstEle(instEle); + NSInstEle->GetInstanceDocument(getter_AddRefs(document)); + NS_ASSERTION(document, "nsIXFormsNSInstanceElement::GetInstanceDocument returned null?!"); + + if (document) { + PRBool isValid = PR_FALSE; + ValidateDocument(document, &isValid); + + if (!isValid) { + nsCOMPtr instanceElement; + instEle->GetElement(getter_AddRefs(instanceElement)); + + nsXFormsUtils::ReportError(NS_LITERAL_STRING("instDocumentInvalid"), + instanceElement); + } + } + } + } + } + nsXFormsModelElement::ProcessDeferredBinds(domDoc); + nsCOMPtr doc = do_QueryInterface(domDoc); + if (doc) { + PRUint32 loadingMessages = NS_PTR_TO_UINT32( + doc->GetProperty(nsXFormsAtoms::externalMessagesProperty)); + if (loadingMessages) { + // if we are still waiting for external messages to load, then put off + // the xforms-ready until a model in the document is notified that they + // are finished loading + + return; + } + } + for (i = 0; i < models->Count(); ++i) { nsXFormsModelElement *model = NS_STATIC_CAST(nsXFormsModelElement *, models->ElementAt(i)); - nsXFormsUtils::DispatchEvent(model->mElement, eEvent_Ready); + model->BackupOrRestoreInstanceData(PR_FALSE); + model->mReadyHandled = PR_TRUE; + nsXFormsUtils::DispatchEvent(model->mElement, eEvent_Ready); } } @@ -1567,7 +2071,8 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator, nsIDOMNode *aContextNode, PRInt32 aContextPosition, PRInt32 aContextSize, - nsIDOMElement *aBindElement) + nsIDOMElement *aBindElement, + PRBool aIsOuter) { // Get the model item properties specified by this \. nsCOMPtr props[eModel__count]; @@ -1602,22 +2107,45 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator, if (expr.IsEmpty()) { expr = NS_LITERAL_STRING("."); } - rv = aEvaluator->Evaluate(expr, aContextNode, aContextSize, aContextPosition, + rv = aEvaluator->Evaluate(expr, aContextNode, aContextPosition, aContextSize, aBindElement, nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nsnull, getter_AddRefs(result)); if (NS_FAILED(rv)) { + if (rv == nsIDOMXPathException::INVALID_EXPRESSION_ERR) { + // the xpath expression isn't valid xpath + + const nsPromiseFlatString& flat = PromiseFlatString(expr); + const PRUnichar *strings[] = { flat.get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("exprParseError"), + strings, 1, aBindElement, nsnull); + nsXFormsUtils::DispatchEvent(mElement, eEvent_ComputeException); + } else { #ifdef DEBUG - printf("xforms-binding-exception: XPath Evaluation failed\n"); + printf("xforms-binding-exception: XPath Evaluation failed\n"); #endif - const PRUnichar *strings[] = { expr.get() }; - nsXFormsUtils::ReportError(NS_LITERAL_STRING("nodesetEvaluateError"), - strings, 1, aBindElement, aBindElement); - nsXFormsUtils::DispatchEvent(mElement, eEvent_BindingException); + const PRUnichar *strings[] = { expr.get() }; + nsXFormsUtils::ReportError(NS_LITERAL_STRING("nodesetEvaluateError"), + strings, 1, aBindElement, aBindElement); + nsXFormsUtils::DispatchEvent(mElement, eEvent_BindingException); + } return rv; } NS_ENSURE_STATE(result); + + // If this is an outer bind, store the nodeset, as controls binding to this + // bind will need this. + if (aIsOuter) { + nsCOMPtr content(do_QueryInterface(aBindElement)); + NS_ASSERTION(content, "nsIDOMElement not implementing nsIContent?!"); + rv = content->SetProperty(nsXFormsAtoms::bind, result, + SupportsDtorFunc); + NS_ENSURE_SUCCESS(rv, rv); + + // addref, circumventing nsDerivedSave + NS_ADDREF(NS_STATIC_CAST(nsIDOMXPathResult*, result)); + } PRUint32 snapLen; rv = result->GetSnapshotLength(&snapLen); @@ -1681,7 +2209,7 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator, nsAutoPtr xNode(parser.Parse(propStrings[j])); deps.Clear(); rv = analyzer.Analyze(node, xNode, expr, &propStrings[j], &deps, - snapItem + 1, snapLen); + snapItem + 1, snapLen, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); // Insert into MDG @@ -1754,7 +2282,7 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator, NS_IMETHODIMP nsXFormsModelElement::SetStates(nsIXFormsControl *aControl, nsIDOMNode *aBoundNode) { - return SetStatesInternal(aControl, aBoundNode, PR_TRUE); + return SetStatesInternal(aControl, aBoundNode, PR_FALSE); } nsresult @@ -1766,6 +2294,60 @@ nsXFormsModelElement::AddInstanceElement(nsIInstanceElementPrivate *aInstEle) return NS_OK; } +nsresult +nsXFormsModelElement::RemoveInstanceElement(nsIInstanceElementPrivate *aInstEle) +{ + NS_ENSURE_STATE(mInstanceDocuments); + mInstanceDocuments->RemoveInstance(aInstEle); + + return NS_OK; +} + +nsresult +nsXFormsModelElement::MessageLoadFinished() +{ + // This is our signal that all external message links have been tested. If + // we were waiting for this to send out xforms-ready, then now is the time. + + // if this document hasn't processed xforms-model-construct-done, yet (which + // must precede xforms-ready), then we'll send out the xforms-ready later + // as part of our normal handling. If we've already become ready, then this + // event was probably generated by a change in the src attribute on the + // message element. Ignore it in that case. + if (!mConstructDoneHandled || mReadyHandled) { + return NS_OK; + } + + nsCOMPtr domDoc; + mElement->GetOwnerDocument(getter_AddRefs(domDoc)); + const nsVoidArray *models = GetModelList(domDoc); + nsCOMPtrdoc = do_QueryInterface(domDoc); + nsCOMArray *deferredBindList = + NS_STATIC_CAST(nsCOMArray *, + doc->GetProperty(nsXFormsAtoms::deferredBindListProperty)); + + // if we've already gotten the xforms-model-construct-done event and not + // yet the xforms-ready, we've hit a window where we may still be + // processing the deferred control binding. If so, we'll leave now and + // leave it to MaybeNotifyCompletion to generate the xforms-ready event. + if (deferredBindList) { + return NS_OK; + } + + + // if we reached here, then we had to wait on sending out the xforms-ready + // events until the external messages were tested. Now we are finally + // ready to send out xforms-ready to all of the models. + for (int i = 0; i < models->Count(); ++i) { + nsXFormsModelElement *model = + NS_STATIC_CAST(nsXFormsModelElement *, models->ElementAt(i)); + model->mReadyHandled = PR_TRUE; + nsXFormsUtils::DispatchEvent(model->mElement, eEvent_Ready); + } + + return NS_OK; +} + /* static */ void nsXFormsModelElement::Startup() { @@ -1778,6 +2360,14 @@ nsXFormsModelElement::Startup() sModelPropsList[eModel_p3ptype] = nsXFormsAtoms::p3ptype; } +already_AddRefed +nsXFormsModelElement::GetDOMElement() +{ + nsIDOMElement* element = nsnull; + NS_IF_ADDREF(element = mElement); + return element; +} + static void DeleteBindList(void *aObject, nsIAtom *aPropertyName, @@ -1897,7 +2487,6 @@ nsXFormsModelElement::HandleLoad(nsIDOMEvent* aEvent) if (IsComplete()) { rv = FinishConstruction(); NS_ENSURE_SUCCESS(rv, rv); - nsXFormsUtils::DispatchEvent(mElement, eEvent_Refresh); } mPendingInlineSchemas.Clear(); } @@ -1954,7 +2543,7 @@ nsXFormsModelInstanceDocuments::Item(PRUint32 aIndex, nsIDOMNode** aReturn) nsIInstanceElementPrivate* instance = mInstanceList.SafeObjectAt(aIndex); if (instance) { nsCOMPtr doc; - if (NS_SUCCEEDED(instance->GetDocument(getter_AddRefs(doc))) && doc) { + if (NS_SUCCEEDED(instance->GetInstanceDocument(getter_AddRefs(doc))) && doc) { NS_ADDREF(*aReturn = doc); } } @@ -1977,6 +2566,12 @@ nsXFormsModelInstanceDocuments::AddInstance(nsIInstanceElementPrivate *aInst) mInstanceList.AppendObject(aInst); } +void +nsXFormsModelInstanceDocuments::RemoveInstance(nsIInstanceElementPrivate *aInst) +{ + mInstanceList.RemoveObject(aInst); +} + void nsXFormsModelInstanceDocuments::DropReferences() { diff --git a/mozilla/extensions/xforms/nsXFormsModelElement.h b/mozilla/extensions/xforms/nsXFormsModelElement.h index ec1041eb7c2..20d20847396 100644 --- a/mozilla/extensions/xforms/nsXFormsModelElement.h +++ b/mozilla/extensions/xforms/nsXFormsModelElement.h @@ -89,6 +89,13 @@ public: */ void AddInstance(nsIInstanceElementPrivate *aInstance); + /** + * Remove an instance element + * + * @param aInstance The instance element + */ + void RemoveInstance(nsIInstanceElementPrivate *aInstance); + /** * Get the instance document at a given index * @@ -109,6 +116,101 @@ protected: nsCOMArray mInstanceList; }; +/** + * A class for storing pointers to XForms controls added to an XForms + * model. Organized as a tree, with pointers to first child and next sibling. + * + * Notes: + * 1) The root node is special; only has children and a nsnull mNode. + * 2) All functions operate on the node they are called on, and its + * subtree. Functions will never go up (as in: nearer the root) in the tree. + */ +class nsXFormsControlListItem +{ + /** The XForms control itself */ + nsCOMPtr mNode; + + /** The next sibling of the node */ + nsXFormsControlListItem *mNextSibling; + + /** The first child of the node */ + nsXFormsControlListItem *mFirstChild; + +public: + nsXFormsControlListItem(nsIXFormsControl* aControl); + ~nsXFormsControlListItem(); + nsXFormsControlListItem(const nsXFormsControlListItem& aCopy); + + /** Clear contents of current node, all siblings, and all children */ + void Clear(); + + /** + * Remove a control from the current (sub-) tree. Will search from that node + * and down in the tree for the node. + * + * @param aControl The control to remove + * @param aRemoved Was the control found and removed? + */ + nsresult RemoveControl(nsIXFormsControl *aControl, PRBool &aRemoved); + + /** + * Add a control to the (sub-) tree as a child to the given |aParent|. If + * there is no |aParent|, it will insert it as a sibling to |this|. If + * |aParent| is not found, it will bail. + * + * @param aControl The control to insert + * @param aParent The (eventual) parent to insert it under + */ + nsresult AddControl(nsIXFormsControl *aControl, + nsIXFormsControl *aParent); + + /** + * Find a control in the (sub-) tree. + * + * @param aControl The control to find + */ + nsXFormsControlListItem* FindControl(nsIXFormsControl *aControl); + + /** + * Return the nsIXFormsControl that this node contains. + */ + already_AddRefed Control(); + + /** Return the first child of the node */ + nsXFormsControlListItem* FirstChild() { return mFirstChild; }; + + /** Return the next sibling of the node */ + nsXFormsControlListItem* NextSibling() { return mNextSibling; }; + + /** + * An iterator implementation for the class. + */ + class iterator + { + private: + /** The control the iterator is currently pointing at */ + nsXFormsControlListItem *mCur; + + /** A stack of non-visited nodes */ + nsVoidArray mStack; + + public: + iterator(); + iterator(const iterator&); + iterator operator=(nsXFormsControlListItem*); + bool operator!=(const nsXFormsControlListItem*); + iterator operator++(); + nsXFormsControlListItem* operator*(); + }; + friend class nsXFormsControlListItem::iterator; + + /** The begining position for the node (itself) */ + nsXFormsControlListItem* begin(); + + /** The end position for the node (nsnull) */ + nsXFormsControlListItem* end(); +}; + /** * Implementation of the XForms \ element. * @@ -167,12 +269,17 @@ public: static nsresult NeedsPostRefresh(nsIXFormsControl* aControl); static void CancelPostRefresh(nsIXFormsControl* aControl); + + /** + * Returns the DOM element for the model. + */ + already_AddRefed GetDOMElement(); + private: NS_HIDDEN_(already_AddRefed) FindInstanceDocument(const nsAString &aID); NS_HIDDEN_(void) Reset(); - NS_HIDDEN_(void) Ready(); NS_HIDDEN_(void) BackupOrRestoreInstanceData(PRBool restore); /** Initializes the MIPs on all form controls */ @@ -189,7 +296,8 @@ private: nsIDOMNode *aContextNode, PRInt32 aContextPosition, PRInt32 aContextSize, - nsIDOMElement *aBindElement); + nsIDOMElement *aBindElement, + PRBool aIsOuter = PR_FALSE); NS_HIDDEN_(void) RemoveModelFromDocument(); @@ -205,7 +313,7 @@ private: */ NS_HIDDEN_(nsresult) SetStatesInternal(nsIXFormsControl *aControl, nsIDOMNode *aNode, - PRBool aAllStates = PR_FALSE); + PRBool aDispatchEvents = PR_TRUE); /** * Sets the state of a specific state. @@ -240,10 +348,16 @@ private: */ NS_HIDDEN_(nsresult) HandleUnload(nsIDOMEvent *aEvent); + NS_HIDDEN_(nsresult) RefreshSubTree(nsXFormsControlListItem *aCurrent, + PRBool aForceRebind); + + NS_HIDDEN_(nsresult) ValidateDocument(nsIDOMDocument *aInstanceDocument, + PRBool *aResult); + nsIDOMElement *mElement; nsCOMPtr mSchemas; nsStringArray mPendingInlineSchemas; - nsVoidArray mFormControls; + nsXFormsControlListItem mFormControls; PRInt32 mSchemaCount; PRInt32 mSchemaTotal; @@ -268,13 +382,18 @@ private: // This flag indicates whether instance elements have been initialized PRBool mInstancesInitialized; + /** + * Indicates whether the model has handled the xforms-ready event + */ + PRBool mReadyHandled; + /** * All instance documents contained by this model, including lazy-authored * instance documents. */ nsRefPtr mInstanceDocuments; - /** Indicates whether the model's instance was built by lazy authoring */ + // Indicates whether the model's instance was built by lazy authoring PRBool mLazyModel; /** @@ -291,6 +410,12 @@ private: * @see http://www.w3.org/TR/xforms/slice6.html#model-prop-p3ptype */ nsClassHashtable mNodeToP3PType; + + /** + * Indicates whether the model has handled the xforms-model-construct-done + * event + */ + PRBool mConstructDoneHandled; }; /** diff --git a/mozilla/extensions/xforms/nsXFormsNodeState.cpp b/mozilla/extensions/xforms/nsXFormsNodeState.cpp index 738a7ade28b..b523e797d58 100644 --- a/mozilla/extensions/xforms/nsXFormsNodeState.cpp +++ b/mozilla/extensions/xforms/nsXFormsNodeState.cpp @@ -38,6 +38,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsXFormsNodeState.h" +#include "nsIEventStateManager.h" void nsXFormsNodeState::Set(PRUint16 aFlags, PRBool aVal) @@ -70,27 +71,31 @@ nsXFormsNodeState::TestAndClear(eFlag_t aFlag) return test ? PR_TRUE : PR_FALSE; } -PRBool -nsXFormsNodeState::TestAndSet(eFlag_t aFlag) -{ - PRUint16 test = mState & aFlag; - mState |= aFlag; - return test ? PR_TRUE : PR_FALSE; -} - PRBool nsXFormsNodeState::Test(eFlag_t aFlag) const { return (mState & aFlag) ? PR_TRUE : PR_FALSE; } +PRUint32 +nsXFormsNodeState::GetIntrinsicState() const +{ + PRUint32 state = + (IsValid() ? NS_EVENT_STATE_VALID : NS_EVENT_STATE_INVALID) | + (IsReadonly() ? NS_EVENT_STATE_MOZ_READONLY + : NS_EVENT_STATE_MOZ_READWRITE) | + (IsRequired() ? NS_EVENT_STATE_REQUIRED : NS_EVENT_STATE_OPTIONAL) | + (IsRelevant() ? NS_EVENT_STATE_ENABLED : NS_EVENT_STATE_DISABLED); + + return state; +} + #ifdef DEBUG_XF_NODESTATE const char* flagnames[] = {0, "eFlag_READONLY", "eFlag_CONSTRAINT", "eFlag_RELEVANT", "eFlag_REQUIRED", - "eFlag_SCHEMA_VALID", "eFlag_VALID", "eFlag_INHERITED_RELEVANT", "eFlag_INHERITED_READONLY", diff --git a/mozilla/extensions/xforms/nsXFormsNodeState.h b/mozilla/extensions/xforms/nsXFormsNodeState.h index 26387f248ce..94773e85991 100644 --- a/mozilla/extensions/xforms/nsXFormsNodeState.h +++ b/mozilla/extensions/xforms/nsXFormsNodeState.h @@ -54,16 +54,15 @@ enum eFlag_t { eFlag_CONSTRAINT_SCHEMA = 1 << 3, eFlag_RELEVANT = 1 << 4, eFlag_REQUIRED = 1 << 5, - eFlag_SCHEMA_VALID = 1 << 6, - eFlag_INHERITED_RELEVANT = 1 << 7, - eFlag_INHERITED_READONLY = 1 << 8, + eFlag_INHERITED_RELEVANT = 1 << 6, + eFlag_INHERITED_READONLY = 1 << 7, // Events to be dispatched - eFlag_DISPATCH_VALUE_CHANGED = 1 << 9, - eFlag_DISPATCH_READONLY_CHANGED = 1 << 10, - eFlag_DISPATCH_VALID_CHANGED = 1 << 11, - eFlag_DISPATCH_RELEVANT_CHANGED = 1 << 12, - eFlag_DISPATCH_REQUIRED_CHANGED = 1 << 13, - eFlag_DISPATCH_CONSTRAINT_CHANGED = 1 << 14 + eFlag_DISPATCH_VALUE_CHANGED = 1 << 8, + eFlag_DISPATCH_READONLY_CHANGED = 1 << 9, + eFlag_DISPATCH_VALID_CHANGED = 1 << 10, + eFlag_DISPATCH_RELEVANT_CHANGED = 1 << 11, + eFlag_DISPATCH_REQUIRED_CHANGED = 1 << 12, + eFlag_DISPATCH_CONSTRAINT_CHANGED = 1 << 13 }; // Default flags set for new states @@ -147,14 +146,6 @@ public: */ PRBool TestAndClear(eFlag_t aFlag); - /** - * Get flag state and set flag. - * - * @param aFlag The flag - * @return The flag state - */ - PRBool TestAndSet(eFlag_t aFlag); - /** * Get flag state * @@ -192,6 +183,8 @@ public: PRBool ShouldDispatchValueChanged() const { return Test(eFlag_DISPATCH_VALUE_CHANGED); }; + PRUint32 GetIntrinsicState() const; + #ifdef DEBUG_XF_NODESTATE /** Print the flags currently set to stdout */ void PrintFlags() const; diff --git a/mozilla/extensions/xforms/nsXFormsOutputElement.cpp b/mozilla/extensions/xforms/nsXFormsOutputElement.cpp index 4800ec298e8..76a011bd131 100755 --- a/mozilla/extensions/xforms/nsXFormsOutputElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsOutputElement.cpp @@ -61,6 +61,7 @@ #include "nsXFormsAtoms.h" #include "nsXFormsUtils.h" #include "nsIXFormsUIWidget.h" +#include "nsXFormsModelElement.h" /** @@ -74,19 +75,26 @@ public: // nsIXFormsControl NS_IMETHOD Bind(); NS_IMETHOD Refresh(); + NS_IMETHOD GetBoundNode(nsIDOMNode **aBoundNode); // nsIXFormsDelegate NS_IMETHOD GetValue(nsAString& aValue); + NS_IMETHOD GetHasBoundNode(PRBool *aHasBoundNode); - nsXFormsOutputElement() : - nsXFormsDelegateStub(NS_LITERAL_STRING("output")) {} - + nsXFormsOutputElement(); private: - PRBool mHasBinding; - nsString mValue; + PRPackedBool mHasBinding; + PRPackedBool mValueIsDirty; + nsString mValue; }; +nsXFormsOutputElement::nsXFormsOutputElement() + : nsXFormsDelegateStub(NS_LITERAL_STRING("output")), + mHasBinding(PR_FALSE), mValueIsDirty(PR_TRUE) +{ +} + // nsIXFormsControl nsresult @@ -99,24 +107,39 @@ nsXFormsOutputElement::Bind() if (!mHasParent) return NS_OK; - - nsresult rv = mElement->HasAttribute(NS_LITERAL_STRING("ref"), &mHasBinding); + + PRBool tmp; + nsresult rv = mElement->HasAttribute(NS_LITERAL_STRING("ref"), &tmp); NS_ENSURE_SUCCESS(rv, rv); + mHasBinding = tmp; if (!mHasBinding) { - rv = mElement->HasAttribute(NS_LITERAL_STRING("bind"), &mHasBinding); + rv = mElement->HasAttribute(NS_LITERAL_STRING("bind"), &tmp); NS_ENSURE_SUCCESS(rv, rv); + mHasBinding = tmp; + + if (!mHasBinding) { + // If output only has a value attribute, it can't have a proper single + // node binding. In an effort to streamline this a bit, we'll just bind + // to the model here and add output to the deferred bind list if + // necessary. This should be all that we need from the services that + // ProcessNodeBinding provides. ProcessNodeBinding is called during + // ::Refresh (via GetValue) so we just need a few things set up before + // ::Refresh gets called (usually right after ::Bind) + + nsCOMPtr domDoc; + mElement->GetOwnerDocument(getter_AddRefs(domDoc)); + if (!nsXFormsUtils::IsDocumentReadyForBind(domDoc)) { + nsXFormsModelElement::DeferElementBind(domDoc, this); + } + + return BindToModel(PR_TRUE); + } } nsCOMPtr result; - if (mHasBinding) { - rv = ProcessNodeBinding(NS_LITERAL_STRING("ref"), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, - getter_AddRefs(result)); - } else { - rv = ProcessNodeBinding(NS_LITERAL_STRING("value"), - nsIDOMXPathResult::STRING_TYPE, - getter_AddRefs(result)); - } + rv = ProcessNodeBinding(NS_LITERAL_STRING("ref"), + nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, + getter_AddRefs(result)); if (NS_FAILED(rv)) { nsXFormsUtils::ReportError(NS_LITERAL_STRING("controlBindError"), mElement); @@ -124,7 +147,12 @@ nsXFormsOutputElement::Bind() } if (result) { - result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); + if (mUsesModelBinding) { + // When bound via @bind, we'll get a snapshot back + result->SnapshotItem(0, getter_AddRefs(mBoundNode)); + } else { + result->GetSingleNodeValue(getter_AddRefs(mBoundNode)); + } } if (mBoundNode && mModel) { @@ -137,43 +165,49 @@ nsXFormsOutputElement::Bind() NS_IMETHODIMP nsXFormsOutputElement::Refresh() { - if (mRepeatState == eType_Template) - return NS_OK; + mValueIsDirty = PR_TRUE; + return nsXFormsDelegateStub::Refresh(); +} - nsresult rv = NS_OK; - SetDOMStringToNull(mValue); +NS_IMETHODIMP +nsXFormsOutputElement::GetBoundNode(nsIDOMNode **aBoundNode) +{ + return mHasBinding ? nsXFormsDelegateStub::GetBoundNode(aBoundNode) : NS_OK; +} - if (mModel) { - if (mHasBinding) { - if (mBoundNode) { - nsXFormsUtils::GetNodeValue(mBoundNode, mValue); - } - } else { - nsCOMPtr result; - rv = ProcessNodeBinding(NS_LITERAL_STRING("value"), - nsIDOMXPathResult::STRING_TYPE, - getter_AddRefs(result)); - NS_ENSURE_SUCCESS(rv, rv); - - if (result) { - rv = result->GetStringValue(mValue); - NS_ENSURE_SUCCESS(rv, rv); - } - } - } - - SetMozTypeAttribute(); - - nsCOMPtr widget = do_QueryInterface(mElement); - if (widget) - widget->Refresh(); - - return rv; +NS_IMETHODIMP +nsXFormsOutputElement::GetHasBoundNode(PRBool *aHasBoundNode) +{ + NS_ENSURE_ARG_POINTER(aHasBoundNode); + *aHasBoundNode = (mBoundNode && mHasBinding) ? PR_TRUE : PR_FALSE; + return NS_OK; } NS_IMETHODIMP nsXFormsOutputElement::GetValue(nsAString& aValue) { + NS_ENSURE_STATE(mModel); + + if (mValueIsDirty) { + if (mHasBinding) { + NS_ENSURE_STATE(mBoundNode); + nsXFormsUtils::GetNodeValue(mBoundNode, mValue); + } else { + nsCOMPtr result; + nsresult rv = ProcessNodeBinding(NS_LITERAL_STRING("value"), + nsIDOMXPathResult::STRING_TYPE, + getter_AddRefs(result)); + NS_ENSURE_SUCCESS(rv, rv); + + if (result) { + SetDOMStringToNull(mValue); + rv = result->GetStringValue(mValue); + NS_ENSURE_SUCCESS(rv, rv); + } + } + mValueIsDirty = PR_FALSE; + } + aValue = mValue; return NS_OK; } diff --git a/mozilla/extensions/xforms/nsXFormsRangeAccessors.cpp b/mozilla/extensions/xforms/nsXFormsRangeAccessors.cpp index abae6142851..dc0c046b143 100644 --- a/mozilla/extensions/xforms/nsXFormsRangeAccessors.cpp +++ b/mozilla/extensions/xforms/nsXFormsRangeAccessors.cpp @@ -95,8 +95,7 @@ nsXFormsRangeAccessors::GetRangeStep(nsAString &aStep) static const nsIID sScriptingIIDs[] = { NS_IXFORMSACCESSORS_IID, - NS_IXFORMSRANGEACCESSORS_IID, - + NS_IXFORMSRANGEACCESSORS_IID }; NS_IMETHODIMP diff --git a/mozilla/extensions/xforms/nsXFormsRangeAccessors.h b/mozilla/extensions/xforms/nsXFormsRangeAccessors.h index 23ff0a7dca9..ceb22f36f45 100644 --- a/mozilla/extensions/xforms/nsXFormsRangeAccessors.h +++ b/mozilla/extensions/xforms/nsXFormsRangeAccessors.h @@ -45,8 +45,8 @@ * * @todo Support out-of/in-range events (XXX) */ -class nsXFormsRangeAccessors : public nsIXFormsRangeAccessors, - public nsXFormsAccessors +class nsXFormsRangeAccessors : public nsXFormsAccessors, + public nsIXFormsRangeAccessors { public: NS_DECL_ISUPPORTS_INHERITED diff --git a/mozilla/extensions/xforms/nsXFormsRepeatElement.cpp b/mozilla/extensions/xforms/nsXFormsRepeatElement.cpp index 0bcb54f7c40..ca2e92c0267 100644 --- a/mozilla/extensions/xforms/nsXFormsRepeatElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsRepeatElement.cpp @@ -281,18 +281,15 @@ protected: */ nsresult CloneNode(nsIDOMNode *aSrc, nsIDOMNode **aTarget); - /** - * If this attribute name is bind, model or nodeset, then remove the repeat - * control from the list of controls that the model keeps. - */ - void MaybeRemoveFromModel(nsIAtom *aName); + PRBool IsBindingAttribute(const nsIAtom *aAttr) const; /** - * If this attribute name is bind, model or nodeset, then try to Bind and - * Refresh to keep the repeat element current + * Make sure that an index value is inside the valid index range. + * + * @param aIndex The index value to sanitize + * @param aIsScroll Send scroll events if first or last index? */ - void MaybeBindAndRefresh(nsIAtom *aName); - + void SanitizeIndex(PRUint32 *aIndex, PRBool aIsScroll = PR_FALSE); public: NS_DECL_ISUPPORTS_INHERITED @@ -305,10 +302,6 @@ public: // nsIXTFElement overrides NS_IMETHOD OnDestroyed(); - NS_IMETHOD WillSetAttribute(nsIAtom *aName, const nsAString &aValue); - NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue); - NS_IMETHOD WillRemoveAttribute(nsIAtom *aName); - NS_IMETHOD AttributeRemoved(nsIAtom *aName); NS_IMETHOD BeginAddingChildren(); NS_IMETHOD DoneAddingChildren(); @@ -383,34 +376,6 @@ nsXFormsRepeatElement::OnDestroyed() return nsXFormsControlStub::OnDestroyed(); } -NS_IMETHODIMP -nsXFormsRepeatElement::WillSetAttribute(nsIAtom *aName, const nsAString &aValue) -{ - MaybeRemoveFromModel(aName); - return NS_OK; -} - -NS_IMETHODIMP -nsXFormsRepeatElement::AttributeSet(nsIAtom *aName, const nsAString &aValue) -{ - MaybeBindAndRefresh(aName); - return NS_OK; -} - -NS_IMETHODIMP -nsXFormsRepeatElement::WillRemoveAttribute(nsIAtom *aName) -{ - MaybeRemoveFromModel(aName); - return NS_OK; -} - -NS_IMETHODIMP -nsXFormsRepeatElement::AttributeRemoved(nsIAtom *aName) -{ - MaybeBindAndRefresh(aName); - return NS_OK; -} - NS_IMETHODIMP nsXFormsRepeatElement::BeginAddingChildren() { @@ -445,32 +410,32 @@ nsXFormsRepeatElement::SetIndex(PRUint32 *aIndex, // Set repeat-index if (mIsParent) { - NS_ASSERTION(mCurrentRepeat, "How can we be a repeat parent without a child?"); + NS_ASSERTION(mCurrentRepeat, + "How can we be a repeat parent without a child?"); // We're the parent of nested repeats, set through the correct repeat return mCurrentRepeat->SetIndex(aIndex, aIsRefresh); } // Do nothing if we are not showing anything - if (mMaxIndex == 0) + if (mMaxIndex == 0) { + // 9.3.6 states that the index position becomes 0 if there are + // no elements in the repeat. + mCurrentIndex = 0; + + // XXXbeaufour: handle scroll-first/last return NS_OK; + } if (aIsRefresh && !mCurrentIndex) { // If we are refreshing, get existing index value from parent - NS_ASSERTION(mParent, "SetIndex with aIsRefresh == PR_TRUE for a non-nested repeat?!"); + NS_ASSERTION(mParent, + "SetIndex with aIsRefresh == PR_TRUE for a non-nested repeat?!"); rv = mParent->GetIndex(aIndex); NS_ENSURE_SUCCESS(rv, rv); } // Check min. and max. value - if (*aIndex < 1) { - *aIndex = 1; - if (!aIsRefresh) - nsXFormsUtils::DispatchEvent(mElement, eEvent_ScrollFirst); - } else if (*aIndex > mMaxIndex) { - *aIndex = mMaxIndex; - if (!aIsRefresh) - nsXFormsUtils::DispatchEvent(mElement, eEvent_ScrollLast); - } + SanitizeIndex(aIndex, PR_TRUE); // Do nothing if setting to existing value if (!aIsRefresh && mCurrentIndex && *aIndex == mCurrentIndex) @@ -490,7 +455,9 @@ nsXFormsRepeatElement::SetIndex(PRUint32 *aIndex, if (mCurrentIndex) { // We had the previous selection, unset directly SetChildIndex(mCurrentIndex, PR_FALSE, aIsRefresh); - } if (mParent) { + } + + if (mParent) { // Selection is in another repeat, inform parent (it will inform the // previous owner of its new state) rv = mParent->SetCurrentRepeat(this, *aIndex); @@ -534,17 +501,16 @@ nsXFormsRepeatElement::Deselect(void) NS_IMETHODIMP nsXFormsRepeatElement::GetStartingIndex(PRUint32 *aRes) { + NS_ENSURE_ARG(aRes); + nsresult rv = GetIntAttr(NS_LITERAL_STRING("startindex"), (PRInt32*) aRes, nsISchemaBuiltinType::BUILTIN_TYPE_POSITIVEINTEGER); if (NS_FAILED(rv)) { *aRes = 1; } - if (*aRes < 1) { - *aRes = 1; - } else if (*aRes > mMaxIndex) { - *aRes = mMaxIndex; - } + SanitizeIndex(aRes); + return NS_OK; } @@ -628,6 +594,7 @@ nsXFormsRepeatElement::IndexHasChanged() NS_IMETHODIMP nsXFormsRepeatElement::GetIsParent(PRBool *aIsParent) { + NS_ENSURE_ARG(aIsParent); *aIsParent = mIsParent; return NS_OK; } @@ -674,6 +641,58 @@ nsXFormsRepeatElement::GetLevel(PRUint32 *aLevel) return NS_OK; } +NS_IMETHODIMP +nsXFormsRepeatElement::HandleNodeInsert(nsIDOMNode *aNode) +{ + NS_ENSURE_STATE(mHTMLElement); + + nsCOMPtr node(do_QueryInterface(aNode)); + NS_ENSURE_STATE(node); + + // XXX, badness^2: If it is a insert we have to refresh before we can + // figure out whether the node is in our nodeset... refactor this so + // repeat actually gets the nodeset in Bind() and then uses it refresh, + // then we can "just" re-evaluate the nodeset, and only refresh if the + // node actually hits this repeat + + // XXX, moreover it is also wrong to refresh at this point. It will happen + // in insert processing (and possibly deferred...) + nsresult rv = Refresh(); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr child; + mHTMLElement->GetFirstChild(getter_AddRefs(child)); + + PRUint32 index = 1; + while (child) { + nsCOMPtr context(do_QueryInterface(child)); + NS_ASSERTION(context, + "repeat child not implementing nsIXFormsContextControl?!"); + + nsAutoString modelID; + PRInt32 position, size; + nsCOMPtr boundNode; + rv = context->GetContext(modelID, getter_AddRefs(boundNode), &position, + &size); + NS_ENSURE_SUCCESS(rv, rv); + PRBool sameNode = PR_FALSE; + node->IsSameNode(boundNode, &sameNode); + if (sameNode) { + rv = SetIndex(&index, PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + + break; + } + + nsCOMPtr tmp; + child->GetNextSibling(getter_AddRefs(tmp)); + child.swap(tmp); + ++index; + } + + return NS_OK; +} + // nsXFormsControl NS_IMETHODIMP @@ -682,11 +701,7 @@ nsXFormsRepeatElement::Bind() if (mAddingChildren) return NS_OK; - mModel = nsXFormsUtils::GetModel(mElement); - if (mModel) - mModel->AddFormControl(this); - - return NS_OK; + return BindToModel(); } NS_IMETHODIMP @@ -717,7 +732,7 @@ nsXFormsRepeatElement::Refresh() if (NS_FAILED(rv) | !result | !model) return rv; - + /// @todo The spec says: "This node-set must consist of contiguous child /// element nodes, with the same local name and namespace name of a common /// parent node. The behavior of element repeat with respect to @@ -725,14 +740,14 @@ nsXFormsRepeatElement::Refresh() /// @see http://www.w3.org/TR/xforms/slice9.html#ui-repeat /// /// Can/should we check this somehow? (XXX) - + PRUint32 contextSize; rv = result->GetSnapshotLength(&contextSize); NS_ENSURE_SUCCESS(rv, rv); if (!contextSize) return NS_OK; - + // Get model ID nsCOMPtr modelElement = do_QueryInterface(model); NS_ENSURE_TRUE(modelElement, NS_ERROR_FAILURE); @@ -748,15 +763,18 @@ nsXFormsRepeatElement::Refresh() for (PRUint32 i = 1; i < mMaxIndex + 1; ++i) { // Create nsCOMPtr riElement; - rv = domDoc->CreateElementNS(NS_LITERAL_STRING("http://www.w3.org/2002/xforms"), + rv = domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS), NS_LITERAL_STRING("contextcontainer"), getter_AddRefs(riElement)); NS_ENSURE_SUCCESS(rv, rv); - + + riElement->SetAttribute(NS_LITERAL_STRING("class"), + NS_LITERAL_STRING("xf-repeat-item")); + // Set model as attribute if (!modelID.IsEmpty()) { riElement->SetAttribute(NS_LITERAL_STRING("model"), modelID); - } + } // Get context node nsCOMPtr riContext = do_QueryInterface(riElement); @@ -765,7 +783,7 @@ nsXFormsRepeatElement::Refresh() nsCOMPtr contextNode; rv = result->SnapshotItem(i - 1, getter_AddRefs(contextNode)); NS_ENSURE_SUCCESS(rv, rv); - + // Set context node, position, and size rv = riContext->SetContext(contextNode, i, contextSize); NS_ENSURE_SUCCESS(rv, rv); @@ -776,7 +794,8 @@ nsXFormsRepeatElement::Refresh() rv = mHTMLElement->AppendChild(riElement, getter_AddRefs(domNode)); NS_ENSURE_SUCCESS(rv, rv); - // Iterate over template children, clone them, and append them to + // Iterate over template children, clone them, and append them to + // \ nsCOMPtr child; rv = mElement->GetFirstChild(getter_AddRefs(child)); NS_ENSURE_SUCCESS(rv, rv); @@ -786,18 +805,23 @@ nsXFormsRepeatElement::Refresh() nsCOMPtr childClone; rv = CloneNode(child, getter_AddRefs(childClone)); NS_ENSURE_SUCCESS(rv, rv); - + nsCOMPtr newNode; rv = riElement->AppendChild(childClone, getter_AddRefs(newNode)); NS_ENSURE_SUCCESS(rv, rv); - + rv = child->GetNextSibling(getter_AddRefs(newNode)); NS_ENSURE_SUCCESS(rv, rv); child = newNode; } } - if (!mParent && !mCurrentIndex && mMaxIndex) { + if (mCurrentIndex) { + // somebody might have been fooling around with our children since last + // refresh (either using delete or through script, so check the index + // value + SanitizeIndex(&mCurrentIndex); + } else if (!mParent && mMaxIndex) { // repeat-index has not been initialized, set it. GetStartingIndex(&mCurrentIndex); } @@ -829,11 +853,14 @@ nsXFormsRepeatElement::SetChildIndex(PRUint32 aPosition, mHTMLElement->GetChildNodes(getter_AddRefs(children)); NS_ENSURE_STATE(children); + PRUint32 index = aPosition - 1; // Indexes are 1-based, the DOM is 0-based; + nsCOMPtr child; - children->Item(aPosition - 1, // Indexes are 1-based, the DOM is 0-based + children->Item(index, getter_AddRefs(child)); - nsCOMPtr repeatItem = do_QueryInterface(child); - NS_ENSURE_STATE(repeatItem); + nsCOMPtr repeatItem(do_QueryInterface(child)); + NS_ASSERTION(repeatItem, + "repeat child not implementing nsIXFormsRepeatItemElement?!"); nsresult rv; PRBool curState; @@ -854,6 +881,23 @@ nsXFormsRepeatElement::SetChildIndex(PRUint32 aPosition, return NS_OK; } +void +nsXFormsRepeatElement::SanitizeIndex(PRUint32 *aIndex, PRBool aIsScroll) +{ + if (!aIndex) + return; + + if (*aIndex < 1) { + *aIndex = 1; + if (aIsScroll) + nsXFormsUtils::DispatchEvent(mElement, eEvent_ScrollFirst); + } else if (*aIndex > mMaxIndex) { + *aIndex = mMaxIndex; + if (aIsScroll) + nsXFormsUtils::DispatchEvent(mElement, eEvent_ScrollLast); + } +} + nsresult nsXFormsRepeatElement::ResetInnerRepeats(nsIDOMNode *aNode, PRBool aIsRefresh) @@ -1055,29 +1099,18 @@ nsXFormsRepeatElement::GetIntAttr(const nsAString &aName, return rv; } -void nsXFormsRepeatElement::MaybeBindAndRefresh(nsIAtom *aName) +PRBool +nsXFormsRepeatElement::IsBindingAttribute(const nsIAtom *aAttr) const { - if (aName == nsXFormsAtoms::bind || - aName == nsXFormsAtoms::nodeset || - aName == nsXFormsAtoms::model) { - - Bind(); - Refresh(); + if (aAttr == nsXFormsAtoms::bind || + aAttr == nsXFormsAtoms::nodeset || + aAttr == nsXFormsAtoms::model) { + return PR_TRUE; } + + return PR_FALSE; } -void nsXFormsRepeatElement::MaybeRemoveFromModel(nsIAtom *aName) -{ - if (aName == nsXFormsAtoms::bind || - aName == nsXFormsAtoms::nodeset || - aName == nsXFormsAtoms::model) { - if (mModel) { - mModel->RemoveFormControl(this); - } - } -} - - // Factory NS_HIDDEN_(nsresult) NS_NewXFormsRepeatElement(nsIXTFElement **aResult) diff --git a/mozilla/extensions/xforms/nsXFormsSchemaValidator.cpp b/mozilla/extensions/xforms/nsXFormsSchemaValidator.cpp index e03860b33b5..144fff24fcf 100644 --- a/mozilla/extensions/xforms/nsXFormsSchemaValidator.cpp +++ b/mozilla/extensions/xforms/nsXFormsSchemaValidator.cpp @@ -51,7 +51,7 @@ nsXFormsSchemaValidator::nsXFormsSchemaValidator() { - mSchemaValidator = do_GetService(NS_SCHEMAVALIDATOR_CONTRACTID); + mSchemaValidator = do_CreateInstance(NS_SCHEMAVALIDATOR_CONTRACTID); } nsresult @@ -83,28 +83,12 @@ nsXFormsSchemaValidator::ValidateString(const nsAString & aValue, } PRBool -nsXFormsSchemaValidator::ValidateNode(nsIDOMNode* aElement, - const nsAString & aType, - const nsAString & aNamespace) +nsXFormsSchemaValidator::Validate(nsIDOMNode* aElement) { PRBool isValid = PR_FALSE; NS_ENSURE_TRUE(mSchemaValidator, isValid); - if (aNamespace.EqualsLiteral(NS_NAMESPACE_XFORMS)) { - // XXX: currently, we will only support validating a lone node. When - // we get complex type support, we should load the schema for the xforms - // types and use ValidateAgainstType like below. - nsAutoString nodeValue; - nsCOMPtr domNode3 = do_QueryInterface(aElement); - domNode3->GetTextContent(nodeValue); - - isValid = ValidateString(nodeValue, aType, aNamespace); - } else { - nsCOMPtr type; - if (GetType(aType, aNamespace, getter_AddRefs(type))) { - mSchemaValidator->ValidateAgainstType(aElement, type, &isValid); - } - } + mSchemaValidator->Validate(aElement, &isValid); return isValid; } diff --git a/mozilla/extensions/xforms/nsXFormsSchemaValidator.h b/mozilla/extensions/xforms/nsXFormsSchemaValidator.h index b1ddf0ebfe3..aaebe121586 100644 --- a/mozilla/extensions/xforms/nsXFormsSchemaValidator.h +++ b/mozilla/extensions/xforms/nsXFormsSchemaValidator.h @@ -64,15 +64,12 @@ public: const nsAString & aNamespace); /** - * Validates a node against a namespace and schema type + * Validates a node and its subtree against the loaded schema(s) * * @param aElement Node to validate - * @param aType Type - * @param aNamespace Namespace * @return Whether the string is valid or not */ - PRBool ValidateNode(nsIDOMNode* aElement, const nsAString & aType, - const nsAString & aNamespace); + PRBool Validate(nsIDOMNode* aElement); /** * Returns a nsISchemaType given an type and namespace diff --git a/mozilla/extensions/xforms/nsXFormsSelectElement.cpp b/mozilla/extensions/xforms/nsXFormsSelectElement.cpp index c7409ec949e..8820920c6d0 100644 --- a/mozilla/extensions/xforms/nsXFormsSelectElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsSelectElement.cpp @@ -65,8 +65,6 @@ public: NS_IMETHOD ChildAppended(nsIDOMNode *aChild); NS_IMETHOD ChildRemoved(PRUint32 aIndex); - // nsIXFormsDelegate - NS_IMETHOD SetValue(const nsAString& aValue); #ifdef DEBUG_smaug virtual const char* Name() { return "select"; } #endif @@ -109,31 +107,6 @@ nsXFormsSelectElement::ChildRemoved(PRUint32 aIndex) return NS_OK; } -NS_IMETHODIMP -nsXFormsSelectElement::SetValue(const nsAString& aValue) -{ - if (!mBoundNode || !mModel) - return NS_OK; - - PRBool changed; - nsresult rv = mModel->SetNodeValue(mBoundNode, aValue, &changed); - NS_ENSURE_SUCCESS(rv, rv); - if (changed) { - nsCOMPtr model = do_QueryInterface(mModel); - - if (model) { - rv = nsXFormsUtils::DispatchEvent(model, eEvent_Recalculate); - NS_ENSURE_SUCCESS(rv, rv); - rv = nsXFormsUtils::DispatchEvent(model, eEvent_Revalidate); - NS_ENSURE_SUCCESS(rv, rv); - rv = nsXFormsUtils::DispatchEvent(model, eEvent_Refresh); - NS_ENSURE_SUCCESS(rv, rv); - } - } - - return NS_OK; -} - NS_HIDDEN_(nsresult) NS_NewXFormsSelectElement(nsIXTFElement **aResult) { diff --git a/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp b/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp index 11e3e991bbd..5075fc5fa39 100644 --- a/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp @@ -91,13 +91,15 @@ nsXFormsSetIndexElement::HandleAction(nsIDOMEvent *aEvent, nsCOMPtr result; // EvaluateNodeBinding uses @bind if @index is not present, but we have // checked that @index is present above + PRBool usesModelBinding; rv = nsXFormsUtils::EvaluateNodeBinding(mElement, 0, indexStr, EmptyString(), nsIDOMXPathResult::NUMBER_TYPE, getter_AddRefs(model), - getter_AddRefs(result)); + getter_AddRefs(result), + &usesModelBinding); NS_ENSURE_SUCCESS(rv, rv); if (!result) { nsXFormsUtils::ReportError(NS_LITERAL_STRING("indexEvalError"), @@ -116,7 +118,7 @@ nsXFormsSetIndexElement::HandleAction(nsIDOMEvent *aEvent, #ifdef DEBUG_XF_SETINDEX printf(": Setting index '%s' to '%d'\n", - NS_ConvertUCS2toUTF8(id).get(), + NS_ConvertUTF16toUTF8(id).get(), indexInt); #endif nsCOMPtr repeatElem; diff --git a/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp b/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp index b1733fd811a..39582adb5a2 100644 --- a/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp @@ -66,23 +66,13 @@ nsXFormsSetValueElement::HandleAction(nsIDOMEvent* aEvent, return NS_OK; nsCOMPtr modelPriv; - nsCOMPtr result; - nsresult rv = - nsXFormsUtils:: EvaluateNodeBinding(mElement, - nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, - NS_LITERAL_STRING("ref"), - EmptyString(), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, - getter_AddRefs(modelPriv), - getter_AddRefs(result)); - NS_ENSURE_SUCCESS(rv, rv); - - if (!result | !modelPriv) - return NS_OK; - nsCOMPtr singleNode; - result->GetSingleNodeValue(getter_AddRefs(singleNode)); - if (!singleNode) + PRBool succeeded = + nsXFormsUtils::GetSingleNodeBinding(mElement, + getter_AddRefs(singleNode), + getter_AddRefs(modelPriv)); + + if (!succeeded | !modelPriv | !singleNode) return NS_OK; nsAutoString value; @@ -105,7 +95,8 @@ nsXFormsSetValueElement::HandleAction(nsIDOMEvent* aEvent, } PRBool changed; - rv = modelPriv->SetNodeValue(singleNode, value, &changed); + nsresult rv = + modelPriv->SetNodeValue(singleNode, value, &changed); NS_ENSURE_SUCCESS(rv, rv); if (changed) { diff --git a/mozilla/extensions/xforms/nsXFormsSubmissionElement.cpp b/mozilla/extensions/xforms/nsXFormsSubmissionElement.cpp index d4dae50af42..b497c45ec06 100644 --- a/mozilla/extensions/xforms/nsXFormsSubmissionElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsSubmissionElement.cpp @@ -67,8 +67,8 @@ #include "nsIDOMProcessingInstruction.h" #include "nsIDOMParser.h" #include "nsComponentManagerUtils.h" +#include "nsStringStream.h" #include "nsIDocShell.h" -#include "nsIStringStream.h" #include "nsIInputStream.h" #include "nsIStorageStream.h" #include "nsIMultiplexInputStream.h" @@ -515,48 +515,48 @@ nsXFormsSubmissionElement::LoadReplaceInstance(nsIChannel *channel) nsCOMPtr instanceElement; nsAutoString value; mElement->GetAttribute(NS_LITERAL_STRING("instance"), value); - if (!value.IsEmpty()){ + if (!value.IsEmpty()) { rv = GetSelectedInstanceElement(value, model, getter_AddRefs(instanceElement)); } else { nsCOMPtr data; rv = GetBoundInstanceData(getter_AddRefs(data)); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr instanceNode; - rv = nsXFormsUtils::GetInstanceNodeForData(data, - getter_AddRefs(instanceNode)); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr instanceNode; + rv = nsXFormsUtils::GetInstanceNodeForData(data, + getter_AddRefs(instanceNode)); + NS_ENSURE_SUCCESS(rv, rv); instanceElement = do_QueryInterface(instanceNode); } } - // replace the document referenced by this instance element with the info - // returned back from the submission + // replace the document referenced by this instance element with the info + // returned back from the submission if (NS_SUCCEEDED(rv) && instanceElement) { - instanceElement->SetDocument(newDoc); + instanceElement->SetInstanceDocument(newDoc); - // refresh everything - model->Rebuild(); - model->Recalculate(); - model->Revalidate(); - model->Refresh(); - } + // refresh everything + model->Rebuild(); + model->Recalculate(); + model->Revalidate(); + model->Refresh(); + } return NS_OK; - } +} nsresult nsXFormsSubmissionElement::GetSelectedInstanceElement( - const nsString &aInstanceID, + const nsAString &aInstanceID, nsIModelElementPrivate *aModel, nsIInstanceElementPrivate **aResult) { aModel->FindInstanceElement(aInstanceID, aResult); if (*aResult == nsnull) { // if failed to get desired instance, dispatch binding exception - const PRUnichar *strings[] = { aInstanceID.get() }; + const PRUnichar *strings[] = { PromiseFlatString(aInstanceID).get() }; nsXFormsUtils::ReportError(NS_LITERAL_STRING("instanceBindError"), strings, 1, mElement, mElement); nsXFormsUtils::DispatchEvent(mElement, eEvent_BindingException); @@ -636,8 +636,7 @@ nsXFormsSubmissionElement::Submit() // 3. revalidate selected instance data (only for namespaces considered for // serialization) - // XXX call nsISchemaValidator::validate on each node - + // This is handled by the SerializeData() method // 4. serialize instance data // Checking the format only before starting the submission. @@ -663,18 +662,21 @@ nsXFormsSubmissionElement::GetBoundInstanceData(nsIDOMNode **result) { nsCOMPtr model; nsCOMPtr xpRes; + PRBool usesModelBind; nsresult rv = nsXFormsUtils::EvaluateNodeBinding(mElement, 0, NS_LITERAL_STRING("ref"), NS_LITERAL_STRING("/"), nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, getter_AddRefs(model), - getter_AddRefs(xpRes)); + getter_AddRefs(xpRes), + &usesModelBind); if (NS_FAILED(rv) || !xpRes) return NS_ERROR_UNEXPECTED; - return xpRes->GetSingleNodeValue(result); + return usesModelBind ? xpRes->SnapshotItem(0, result) + : xpRes->GetSingleNodeValue(result); } PRBool @@ -751,6 +753,13 @@ nsXFormsSubmissionElement::SerializeData(nsIDOMNode *data, if (mFormat & ENCODING_XML) return SerializeDataXML(data, stream, contentType, nsnull); + // Ensure the data is valid and required nodes are non-empty + // This is handled directly within SerializeDataXML() + nsCOMPtr model = GetModel(); + NS_ENSURE_STATE(model); + nsresult rv = CanSubmit(data, model, PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + if (mFormat & ENCODING_URL) return SerializeDataURLEncoded(data, uri, stream, contentType); @@ -792,49 +801,35 @@ nsXFormsSubmissionElement::SerializeDataXML(nsIDOMNode *data, nsCOMPtr serializer = do_GetService("@mozilla.org/xmlextras/xmlserializer;1"); - NS_ENSURE_TRUE(serializer, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(serializer); - nsCOMPtr doc, newDoc; - data->GetOwnerDocument(getter_AddRefs(doc)); + nsCOMPtr instDoc, submDoc; + data->GetOwnerDocument(getter_AddRefs(instDoc)); - nsresult rv; // XXX: We can't simply pass in data if !doc, since it crashes - if (!doc) { + nsresult rv; + if (!instDoc) { // owner doc is null when the data node is the document (e.g., ref="/") // so we can just get the document via QI. - doc = do_QueryInterface(data); - NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED); + instDoc = do_QueryInterface(data); + NS_ENSURE_STATE(instDoc); - rv = CreateSubmissionDoc(doc, encoding, attachments, - getter_AddRefs(newDoc)); + rv = CreateSubmissionDoc(instDoc, encoding, attachments, + getter_AddRefs(submDoc)); } else { // if we got a document, we need to create a new rv = CreateSubmissionDoc(data, encoding, attachments, - getter_AddRefs(newDoc)); + getter_AddRefs(submDoc)); } // clone and possibly modify the document for submission NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(newDoc, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(submDoc); // We now need to add namespaces to the submission document. We get them // from 3 sources - the main document's documentElement, the model and the // xforms:instance that contains the submitted instance data node. - // first handle the main document - nsCOMPtr mainDoc; - mElement->GetOwnerDocument(getter_AddRefs(mainDoc)); - NS_ENSURE_TRUE(mainDoc, NS_ERROR_UNEXPECTED); - - nsCOMPtr docElm; - mainDoc->GetDocumentElement(getter_AddRefs(docElm)); - nsCOMPtr node(do_QueryInterface(docElm)); - NS_ENSURE_TRUE(node, NS_ERROR_UNEXPECTED); - - // get the document element of the document we are going to submit - nsCOMPtr newDocElm; - newDoc->GetDocumentElement(getter_AddRefs(newDocElm)); - nsCOMPtr instanceNode; rv = nsXFormsUtils::GetInstanceNodeForData(data, getter_AddRefs(instanceNode)); NS_ENSURE_SUCCESS(rv, rv); @@ -864,24 +859,54 @@ nsXFormsSubmissionElement::SerializeDataXML(nsIDOMNode *data, NS_ENSURE_SUCCESS(rv, rv); } - // handle namespace on main document - rv = AddNameSpaces(newDocElm, node, prefixHash); + // get the document element of the document we are going to submit + nsCOMPtr submDocElm; + submDoc->GetDocumentElement(getter_AddRefs(submDocElm)); + NS_ENSURE_STATE(submDocElm); + + // if submission document has empty default namespace attribute and if + // @includenamespaceprefixes attribute doesn't contain "#default" value then + // we should remove default namespace attribute (see the specs 11.3). + nsAutoString XMLNSAttrValue; + submDocElm->GetAttributeNS(kXMLNSNameSpaceURI, NS_LITERAL_STRING("xmlns"), + XMLNSAttrValue); + + if (XMLNSAttrValue.IsEmpty() && (!prefixHash || + !prefixHash->Contains(NS_LITERAL_STRING("#default")))) { + submDocElm->RemoveAttributeNS(kXMLNSNameSpaceURI, + NS_LITERAL_STRING("xmlns")); + } + + // handle namespaces on the root element of the instance document + nsCOMPtr instDocElm; + instDoc->GetDocumentElement(getter_AddRefs(instDocElm)); + nsCOMPtr instDocNode(do_QueryInterface(instDocElm)); + NS_ENSURE_STATE(instDocNode); + rv = AddNameSpaces(submDocElm, instDocNode, prefixHash); + NS_ENSURE_SUCCESS(rv, rv); + + // handle namespaces on the xforms:instance + rv = AddNameSpaces(submDocElm, instanceNode, prefixHash); NS_ENSURE_SUCCESS(rv, rv); // handle namespaces on the model nsCOMPtr model = GetModel(); - node = do_QueryInterface(model); - NS_ENSURE_STATE(node); - rv = AddNameSpaces(newDocElm, node, prefixHash); + nsCOMPtr modelNode(do_QueryInterface(model)); + NS_ENSURE_STATE(modelNode); + rv = AddNameSpaces(submDocElm, modelNode, prefixHash); NS_ENSURE_SUCCESS(rv, rv); - // handle namespaces on the xforms:instance - rv = AddNameSpaces(newDocElm, instanceNode, prefixHash); - NS_ENSURE_SUCCESS(rv, rv); + // handle namespace on main document + nsCOMPtr mainDoc; + mElement->GetOwnerDocument(getter_AddRefs(mainDoc)); + NS_ENSURE_STATE(mainDoc); - // handle namespaces on the root element of the instance document - doc->GetDocumentElement(getter_AddRefs(docElm)); - rv = AddNameSpaces(newDocElm, docElm, prefixHash); + nsCOMPtr mainDocElm; + mainDoc->GetDocumentElement(getter_AddRefs(mainDocElm)); + nsCOMPtr mainDocNode(do_QueryInterface(mainDocElm)); + NS_ENSURE_STATE(mainDocNode); + + rv = AddNameSpaces(submDocElm, mainDocNode, prefixHash); NS_ENSURE_SUCCESS(rv, rv); if (prefixHash) @@ -889,7 +914,7 @@ nsXFormsSubmissionElement::SerializeDataXML(nsIDOMNode *data, } // Serialize content - rv = serializer->SerializeToStream(newDoc, sink, + rv = serializer->SerializeToStream(submDoc, sink, NS_LossyConvertUTF16toASCII(encoding)); NS_ENSURE_SUCCESS(rv, rv); @@ -991,10 +1016,10 @@ nsXFormsSubmissionElement::AddNameSpaces(nsIDOMElement* aTarget, { nsCOMPtr attrMap; nsCOMPtr attrNode; - nsAutoString nsURI, localName, value, attrName; + nsAutoString nsURI, localName, value; aSource->GetAttributes(getter_AddRefs(attrMap)); - NS_ENSURE_TRUE(attrMap, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(attrMap); PRUint32 length; attrMap->GetLength(&length); @@ -1007,18 +1032,26 @@ nsXFormsSubmissionElement::AddNameSpaces(nsIDOMElement* aTarget, attrNode->GetLocalName(localName); attrNode->GetNodeValue(value); - attrName.AssignLiteral("xmlns"); - // xmlns:foo, not xmlns= if (!localName.EqualsLiteral("xmlns")) { - // If "includenamespaceprefixes" attribute is present, don't add - // namespace unless it appears in hash - if (aPrefixHash && !aPrefixHash->Contains(localName)) - continue; - attrName.AppendLiteral(":"); - attrName.Append(localName); - } + if (!aPrefixHash || aPrefixHash->Contains(localName)) { + nsAutoString attrName(NS_LITERAL_STRING("xmlns:")); + attrName.Append(localName); + aTarget->SetAttributeNS(kXMLNSNameSpaceURI, attrName, value); + } + } else if (!value.IsEmpty()) { + PRBool hasDefaultNSAttr; + aTarget->HasAttributeNS(kXMLNSNameSpaceURI, + NS_LITERAL_STRING("xmlns"), &hasDefaultNSAttr); - aTarget->SetAttribute(attrName, value); + if (!hasDefaultNSAttr) { + aTarget->GetNamespaceURI(nsURI); + if (!nsURI.IsEmpty()) { + // if aTarget default namespace uri isn't empty and it hasn't + // default namespace attribute then we should add it. + aTarget->SetAttributeNS(kXMLNSNameSpaceURI, localName, value); + } + } + } } } @@ -1097,12 +1130,12 @@ nsXFormsSubmissionElement::CreateSubmissionDoc(nsIDOMNode *source, source->GetOwnerDocument(getter_AddRefs(tmpDoc)); tmpDoc->GetImplementation(getter_AddRefs(impl)); } - NS_ENSURE_TRUE(impl, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(impl); nsCOMPtr doc; impl->CreateDocument(EmptyString(), EmptyString(), nsnull, getter_AddRefs(doc)); - NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(doc); if (!omit_xml_declaration) { @@ -1129,8 +1162,10 @@ nsXFormsSubmissionElement::CreateSubmissionDoc(nsIDOMNode *source, startNode = source; } - nsresult rv = CopyChildren(startNode, doc, doc, attachments, cdataElements, - indent, 0); + nsCOMPtr model = GetModel(); + NS_ENSURE_STATE(model); + nsresult rv = CopyChildren(model, startNode, doc, doc, attachments, + cdataElements, indent, 0); NS_ENSURE_SUCCESS(rv, rv); NS_ADDREF(*result = doc); @@ -1138,14 +1173,14 @@ nsXFormsSubmissionElement::CreateSubmissionDoc(nsIDOMNode *source, } nsresult -nsXFormsSubmissionElement::CopyChildren(nsIDOMNode *source, nsIDOMNode *dest, +nsXFormsSubmissionElement::CopyChildren(nsIModelElementPrivate* model, + nsIDOMNode *source, nsIDOMNode *dest, nsIDOMDocument *destDoc, SubmissionAttachmentArray *attachments, const nsString &cdataElements, PRBool indent, PRUint32 depth) { nsCOMPtr currentNode(source), node, destChild; - nsCOMPtr model = GetModel(); while (currentNode) { @@ -1156,14 +1191,14 @@ nsXFormsSubmissionElement::CopyChildren(nsIDOMNode *source, nsIDOMNode *dest, // (remains to be determined) reference external entities. destDoc->ImportNode(currentNode, PR_FALSE, getter_AddRefs(destChild)); - NS_ENSURE_TRUE(destChild, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(destChild); PRUint16 type; destChild->GetNodeType(&type); if (type == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) { nsCOMPtr pi = do_QueryInterface(destChild); - NS_ENSURE_TRUE(pi, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(pi); // ignore "" since we would have already inserted this. @@ -1256,7 +1291,7 @@ nsXFormsSubmissionElement::CopyChildren(nsIDOMNode *source, nsIDOMNode *dest, nsCOMPtr text; destDoc->CreateTextNode(cidURI, getter_AddRefs(text)); - NS_ENSURE_TRUE(text, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(text); destChild->AppendChild(text, getter_AddRefs(node)); dest->AppendChild(destChild, getter_AddRefs(node)); @@ -1271,18 +1306,73 @@ nsXFormsSubmissionElement::CopyChildren(nsIDOMNode *source, nsIDOMNode *dest, nsCOMPtr startNode; currentNode->GetFirstChild(getter_AddRefs(startNode)); - nsresult rv = CopyChildren(startNode, destChild, destDoc, attachments, - cdataElements, indent, depth + 1); + nsresult rv = CopyChildren(model, startNode, destChild, destDoc, + attachments, cdataElements, indent, + depth + 1); NS_ENSURE_SUCCESS(rv, rv); } } + if (!depth) { + break; + } + currentNode->GetNextSibling(getter_AddRefs(node)); currentNode.swap(node); } return NS_OK; } +nsresult +nsXFormsSubmissionElement::CanSubmit(nsIDOMNode *aTopNode, + nsIModelElementPrivate *aModel, + PRBool aCheckSiblings) +{ + nsCOMPtr currentNode(aTopNode), node; + + while (currentNode) { + PRUint16 handleNodeResult; + aModel->HandleInstanceDataNode(currentNode, &handleNodeResult); + + /* + * SUBMIT_SERIALIZE_NODE - node is to be serialized + * SUBMIT_SKIP_NODE - node is not to be serialized + * SUBMIT_ABORT_SUBMISSION - abort submission + * (invalid node or empty required node) + */ + if (handleNodeResult == nsIModelElementPrivate::SUBMIT_SKIP_NODE) { + // skip node and subtree + currentNode->GetNextSibling(getter_AddRefs(node)); + currentNode.swap(node); + continue; + } else if (handleNodeResult == + nsIModelElementPrivate::SUBMIT_ABORT_SUBMISSION) { + + // abort + return NS_ERROR_ABORT; + } + NS_ASSERTION( + handleNodeResult == nsIModelElementPrivate::SUBMIT_SERIALIZE_NODE, + "unexpected node type"); + + // recurse + nsCOMPtr firstChild; + currentNode->GetFirstChild(getter_AddRefs(firstChild)); + + nsresult rv = CanSubmit(firstChild, aModel); + NS_ENSURE_SUCCESS(rv, rv); + + if (!aCheckSiblings) { + break; + } + + currentNode->GetNextSibling(getter_AddRefs(node)); + currentNode.swap(node); + } + + return NS_OK; +} + nsresult nsXFormsSubmissionElement::SerializeDataURLEncoded(nsIDOMNode *data, nsCString &uri, @@ -1331,7 +1421,7 @@ nsXFormsSubmissionElement::SerializeDataURLEncoded(nsIDOMNode *data, // make new stream NS_NewCStringInputStream(stream, buf); - NS_ENSURE_TRUE(*stream, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(*stream); contentType.AssignLiteral("application/x-www-form-urlencoded"); } @@ -1431,7 +1521,7 @@ nsXFormsSubmissionElement::SerializeDataMultipartRelated(nsIDOMNode *data, nsCOMPtr multiStream = do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1"); - NS_ENSURE_TRUE(multiStream, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(multiStream); nsCAutoString type, start; @@ -1536,7 +1626,7 @@ nsXFormsSubmissionElement::SerializeDataMultipartFormData(nsIDOMNode *data, nsCOMPtr multiStream = do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1"); - NS_ENSURE_TRUE(multiStream, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(multiStream); nsCString postDataChunk; nsresult rv = AppendMultipartFormData(data, boundary, postDataChunk, multiStream); @@ -1706,7 +1796,7 @@ nsXFormsSubmissionElement::GetElementEncodingType(nsIDOMNode *node, *encType = ELEMENT_ENCTYPE_STRING; // default nsCOMPtr element = do_QueryInterface(node); - NS_ENSURE_TRUE(element, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(element); // check for 'xsd:base64Binary', 'xsd:hexBinary', or 'xsd:anyURI' nsAutoString type, nsuri; @@ -1743,20 +1833,20 @@ nsXFormsSubmissionElement::CreateFileStream(const nsString &absURI, nsCOMPtr uri; NS_NewURI(getter_AddRefs(uri), absURI); - NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(uri); // restrict to file:// -- XXX is this correct? PRBool schemeIsFile = PR_FALSE; uri->SchemeIs("file", &schemeIsFile); - NS_ENSURE_TRUE(schemeIsFile, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(schemeIsFile); // NOTE: QI to nsIFileURL just means that the URL corresponds to a // local file resource, which is not restricted to file:// nsCOMPtr fileURL = do_QueryInterface(uri); - NS_ENSURE_TRUE(fileURL, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(fileURL); fileURL->GetFile(resultFile); - NS_ENSURE_TRUE(*resultFile, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(*resultFile); return NS_NewLocalFileInputStream(resultStream, *resultFile); } @@ -1828,8 +1918,13 @@ nsXFormsSubmissionElement::SendData(const nsCString &uriSpec, // get the stream contents PRUint32 len, read, numReadIn = 1; - stream->Available(&len); + rv = stream->Available(&len); + NS_ENSURE_SUCCESS(rv, rv); + char *buf = new char[len+1]; + if (buf == NULL) { + return NS_ERROR_OUT_OF_MEMORY; + } memset(buf, 0, len+1); // Read returns 0 if eos @@ -1885,7 +1980,7 @@ nsXFormsSubmissionElement::SendData(const nsCString &uriSpec, if (stream) { NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream, 4096); - NS_ENSURE_TRUE(bufferedStream, NS_ERROR_UNEXPECTED); + NS_ENSURE_STATE(bufferedStream); } nsCOMPtr channel; @@ -1916,6 +2011,12 @@ nsXFormsSubmissionElement::SendData(const nsCString &uriSpec, nsCOMPtr loadGroup = doc->GetDocumentLoadGroup(); channel->SetLoadGroup(loadGroup); + // set LOAD_DOCUMENT_URI so throbber works during submit + nsLoadFlags loadFlags = 0; + channel->GetLoadFlags(&loadFlags); + loadFlags |= nsIChannel::LOAD_DOCUMENT_URI; + channel->SetLoadFlags(loadFlags); + // create a pipe in which to store the response (yeah, this kind of // sucks since we'll use a lot of memory if the response is large). // @@ -1926,7 +2027,7 @@ nsXFormsSubmissionElement::SendData(const nsCString &uriSpec, nsCOMPtr pipeOut; rv = NS_NewPipe(getter_AddRefs(mPipeIn), getter_AddRefs(pipeOut), - 0, PR_UINT32_MAX, PR_TRUE, PR_TRUE); + 4096, PR_UINT32_MAX, PR_TRUE, PR_TRUE); NS_ENSURE_SUCCESS(rv, rv); // use a simple stream listener to tee our data into the pipe, and diff --git a/mozilla/extensions/xforms/nsXFormsSubmissionElement.h b/mozilla/extensions/xforms/nsXFormsSubmissionElement.h index 7191a4d1222..aa72bce977f 100644 --- a/mozilla/extensions/xforms/nsXFormsSubmissionElement.h +++ b/mozilla/extensions/xforms/nsXFormsSubmissionElement.h @@ -81,10 +81,10 @@ public: NS_DECL_NSIINTERFACEREQUESTOR nsXFormsSubmissionElement() - : mElement(nsnull) - , mSubmissionActive(PR_FALSE) - , mIsReplaceInstance(PR_FALSE) - , mFormat(0) + : mElement(nsnull), + mSubmissionActive(PR_FALSE), + mIsReplaceInstance(PR_FALSE), + mFormat(0) {} // nsIXTFGenericElement overrides @@ -97,33 +97,65 @@ public: NS_HIDDEN_(nsresult) LoadReplaceInstance(nsIChannel *); NS_HIDDEN_(nsresult) LoadReplaceAll(nsIChannel *); NS_HIDDEN_(nsresult) Submit(); - NS_HIDDEN_(PRBool) GetBooleanAttr(const nsAString &attrName, PRBool defaultVal = PR_FALSE); + NS_HIDDEN_(PRBool) GetBooleanAttr(const nsAString &attrName, + PRBool defaultVal = PR_FALSE); NS_HIDDEN_(void) GetDefaultInstanceData(nsIDOMNode **result); NS_HIDDEN_(nsresult) GetBoundInstanceData(nsIDOMNode **result); - NS_HIDDEN_(nsresult) GetSelectedInstanceElement(const nsString &aInstance, nsIModelElementPrivate *aModel, nsIInstanceElementPrivate **result); - NS_HIDDEN_(nsresult) SerializeData(nsIDOMNode *data, nsCString &uri, nsIInputStream **, nsCString &contentType); - NS_HIDDEN_(nsresult) SerializeDataXML(nsIDOMNode *data, nsIInputStream **, nsCString &contentType, SubmissionAttachmentArray *); - NS_HIDDEN_(nsresult) CreateSubmissionDoc(nsIDOMNode *source, const nsString &encoding, SubmissionAttachmentArray *, nsIDOMDocument **result); - NS_HIDDEN_(nsresult) CopyChildren(nsIDOMNode *source, nsIDOMNode *dest, nsIDOMDocument *destDoc, SubmissionAttachmentArray *, const nsString &cdataElements, PRBool indent, PRUint32 depth); - NS_HIDDEN_(nsresult) SerializeDataURLEncoded(nsIDOMNode *data, nsCString &uri, nsIInputStream **, nsCString &contentType); - NS_HIDDEN_(void) AppendURLEncodedData(nsIDOMNode *data, const nsCString &sep, nsCString &buf); - NS_HIDDEN_(nsresult) SerializeDataMultipartRelated(nsIDOMNode *data, nsIInputStream **, nsCString &contentType); - NS_HIDDEN_(nsresult) SerializeDataMultipartFormData(nsIDOMNode *data, nsIInputStream **, nsCString &contentType); - NS_HIDDEN_(nsresult) AppendMultipartFormData(nsIDOMNode *data, const nsCString &boundary, nsCString &buf, nsIMultiplexInputStream *); - NS_HIDDEN_(nsresult) AppendPostDataChunk(nsCString &postDataChunk, nsIMultiplexInputStream *multiStream); - NS_HIDDEN_(nsresult) GetElementEncodingType(nsIDOMNode *data, PRUint32 *encType, nsIModelElementPrivate* aModel = nsnull); - NS_HIDDEN_(nsresult) CreateFileStream(const nsString &absURI, nsIFile **file, nsIInputStream **stream); - NS_HIDDEN_(nsresult) SendData(const nsCString &uri, nsIInputStream *stream, const nsCString &contentType); + NS_HIDDEN_(nsresult) GetSelectedInstanceElement(const nsAString &aInstance, + nsIModelElementPrivate *aModel, + nsIInstanceElementPrivate **result); + NS_HIDDEN_(nsresult) SerializeData(nsIDOMNode *data, nsCString &uri, + nsIInputStream **, nsCString &contentType); + NS_HIDDEN_(nsresult) SerializeDataXML(nsIDOMNode *data, nsIInputStream **, + nsCString &contentType, + SubmissionAttachmentArray *); + NS_HIDDEN_(nsresult) CreateSubmissionDoc(nsIDOMNode *source, + const nsString &encoding, + SubmissionAttachmentArray *, + nsIDOMDocument **result); + NS_HIDDEN_(nsresult) CopyChildren(nsIModelElementPrivate* model, + nsIDOMNode *source, nsIDOMNode *dest, + nsIDOMDocument *destDoc, + SubmissionAttachmentArray *, + const nsString &cdataElements, + PRBool indent, PRUint32 depth); + NS_HIDDEN_(nsresult) SerializeDataURLEncoded(nsIDOMNode *data, nsCString &uri, + nsIInputStream **, + nsCString &contentType); + NS_HIDDEN_(void) AppendURLEncodedData(nsIDOMNode *data, + const nsCString &sep, + nsCString &buf); + NS_HIDDEN_(nsresult) SerializeDataMultipartRelated(nsIDOMNode *data, + nsIInputStream **, + nsCString &contentType); + NS_HIDDEN_(nsresult) SerializeDataMultipartFormData(nsIDOMNode *data, + nsIInputStream **, + nsCString &contentType); + NS_HIDDEN_(nsresult) AppendMultipartFormData(nsIDOMNode *data, + const nsCString &boundary, + nsCString &buf, + nsIMultiplexInputStream *); + NS_HIDDEN_(nsresult) AppendPostDataChunk(nsCString &postDataChunk, + nsIMultiplexInputStream *multiStream); + NS_HIDDEN_(nsresult) GetElementEncodingType(nsIDOMNode *data, + PRUint32 *encType, + nsIModelElementPrivate* aModel = nsnull); + NS_HIDDEN_(nsresult) CreateFileStream(const nsString &absURI, nsIFile **file, + nsIInputStream **stream); + NS_HIDDEN_(nsresult) SendData(const nsCString &uri, nsIInputStream *stream, + const nsCString &contentType); private: - nsIDOMElement *mElement; - PRPackedBool mSubmissionActive; - PRPackedBool mIsReplaceInstance; // Valid when mSubmissionActive == PR_TRUE - PRUint32 mFormat; // Valid when mSubmissionActive == PR_TRUE + nsIDOMElement* mElement; + PRPackedBool mSubmissionActive; + // Valid when mSubmissionActive == PR_TRUE + PRPackedBool mIsReplaceInstance; + // Valid when mSubmissionActive == PR_TRUE + PRUint32 mFormat; nsCOMPtr mActivator; // input end of pipe, which contains response data. - nsCOMPtr mPipeIn; + nsCOMPtr mPipeIn; /** * @return true if aTestURI has the same origin as aBaseURI or if @@ -135,6 +167,21 @@ private: nsStringHashSet* aPrefixHash); nsresult GetIncludeNSPrefixesAttr(nsStringHashSet** aHash); + /** + * This walks the DOM tree, starting at aTopNode and invokes + * model->HandleInstanceDataNode()that ensures that the instance is valid, + * required conditions met...if so, then can submit. + * + * @param aTopNode Root instance node of tree to be evaluated + * @param aModel The model for the submission + * @param aCheckSiblings Check siblings too? + * @return NS_ERROR_ABORT if instance is not valid and empty + * required nodes, otherwise return NS_OK. + * + */ + nsresult CanSubmit(nsIDOMNode *aTopNode, nsIModelElementPrivate *aModel, + PRBool aCheckSiblings = PR_TRUE); + /** * Send xforms-submit-done/-error, depending on |aSucceeded| * diff --git a/mozilla/extensions/xforms/nsXFormsSwitchElement.cpp b/mozilla/extensions/xforms/nsXFormsSwitchElement.cpp index 9987bc2a701..2d845cfa941 100644 --- a/mozilla/extensions/xforms/nsXFormsSwitchElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsSwitchElement.cpp @@ -46,7 +46,6 @@ // For focus control #include "nsPIDOMWindow.h" #include "nsIFocusController.h" -#include "nsIScriptGlobalObject.h" #include "nsIXTFXMLVisualWrapper.h" @@ -193,8 +192,10 @@ nsXFormsSwitchElement::Init(nsIDOMElement* aDeselected) nsCOMPtr firstCase = FindFirstSelectedCase(aDeselected); mSelected = firstCase; nsCOMPtr selected(do_QueryInterface(mSelected)); - if (selected) - selected->SetSelected(PR_TRUE); + if (selected) { + nsresult rv = selected->SetSelected(PR_TRUE); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to select case"); + } } already_AddRefed @@ -205,7 +206,7 @@ nsXFormsSwitchElement::FindFirstSelectedCase(nsIDOMElement* aDeselected) nsCOMPtr firstCase; while (child) { nsCOMPtr childElement(do_QueryInterface(child)); - if (childElement && childElement != aDeselected) { + if (childElement && childElement != aDeselected) { if (nsXFormsUtils::IsXFormsElement(child, NS_LITERAL_STRING("case"))) { if (!firstCase) firstCase = childElement; @@ -231,6 +232,17 @@ nsXFormsSwitchElement::FindFirstSelectedCase(nsIDOMElement* aDeselected) return result; } +// nsIXFormsSwitchElement + +NS_IMETHODIMP +nsXFormsSwitchElement::GetSelected(nsIDOMElement **aCase) +{ + NS_ENSURE_ARG_POINTER(aCase); + NS_IF_ADDREF(*aCase = mSelected); + return NS_OK; +} + + NS_IMETHODIMP nsXFormsSwitchElement::SetSelected(nsIDOMElement *aCase, PRBool aValue) { @@ -291,6 +303,8 @@ nsXFormsSwitchElement::SetSelected(nsIDOMElement *aCase, PRBool aValue) return NS_OK; } +// nsXFormsSwitchElement + void nsXFormsSwitchElement::SetFocus(nsIDOMElement* aDeselected, nsIDOMElement* aSelected) @@ -304,7 +318,7 @@ nsXFormsSwitchElement::SetFocus(nsIDOMElement* aDeselected, if (!doc) return; - nsCOMPtr win = do_QueryInterface(doc->GetScriptGlobalObject()); + nsCOMPtr win = doc->GetWindow(); if (!win) return; @@ -379,6 +393,8 @@ nsXFormsSwitchElement::CaseChanged(nsIDOMNode* aCase, PRBool aRemoved) } } +// nsIXFormsControl + NS_IMETHODIMP nsXFormsSwitchElement::IsEventTarget(PRBool *aOK) { diff --git a/mozilla/extensions/xforms/nsXFormsUploadElement.cpp b/mozilla/extensions/xforms/nsXFormsUploadElement.cpp index 81bd480b721..fd646324178 100644 --- a/mozilla/extensions/xforms/nsXFormsUploadElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsUploadElement.cpp @@ -121,7 +121,8 @@ nsXFormsUploadElement::Refresh() // type 'anyURI', 'base64Binary', or 'hexBinary'. nsresult rv = nsXFormsDelegateStub::Refresh(); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_FAILED(rv) || rv == NS_OK_XFORMS_NOREFRESH) + return rv; if (!mBoundNode) return NS_OK; diff --git a/mozilla/extensions/xforms/nsXFormsUtils.cpp b/mozilla/extensions/xforms/nsXFormsUtils.cpp index c085a314e89..1116d617abd 100644 --- a/mozilla/extensions/xforms/nsXFormsUtils.cpp +++ b/mozilla/extensions/xforms/nsXFormsUtils.cpp @@ -44,7 +44,6 @@ #include "nsIDOMNSHTMLElement.h" #include "nsIDocument.h" #include "nsINameSpaceManager.h" -#include "nsINodeInfo.h" #include "nsIDOMNodeList.h" #include "nsIXFormsXPathEvaluator.h" #include "nsIDOMXPathResult.h" @@ -265,6 +264,7 @@ nsXFormsUtils::GetNodeContext(nsIDOMElement *aElement, nsIModelElementPrivate **aModel, nsIDOMElement **aBindElement, PRBool *aOuterBind, + nsIXFormsControl **aParentControl, nsIDOMNode **aContextNode, PRInt32 *aContextPosition, PRInt32 *aContextSize) @@ -274,6 +274,8 @@ nsXFormsUtils::GetNodeContext(nsIDOMElement *aElement, NS_ENSURE_ARG_POINTER(aContextNode); NS_ENSURE_ARG_POINTER(aBindElement); *aBindElement = nsnull; + if (aParentControl) + *aParentControl = nsnull; // Set default context size and position if (aContextSize) @@ -331,6 +333,7 @@ nsXFormsUtils::GetNodeContext(nsIDOMElement *aElement, // Search for a parent setting context for us nsresult rv = FindParentContext(aElement, aModel, + aParentControl, aContextNode, aContextPosition, aContextSize); @@ -362,8 +365,10 @@ nsXFormsUtils::GetNodeContext(nsIDOMElement *aElement, } /* static */ already_AddRefed -nsXFormsUtils::GetModel(nsIDOMElement *aElement, - PRUint32 aElementFlags) +nsXFormsUtils::GetModel(nsIDOMElement *aElement, + nsIXFormsControl **aParentControl, + PRUint32 aElementFlags, + nsIDOMNode **aContextNode) { nsCOMPtr model; @@ -376,13 +381,18 @@ nsXFormsUtils::GetModel(nsIDOMElement *aElement, getter_AddRefs(model), getter_AddRefs(bind), &outerbind, + aParentControl, getter_AddRefs(contextNode)); NS_ENSURE_TRUE(model, nsnull); + if (aContextNode) { + NS_IF_ADDREF(*aContextNode = contextNode); + } + nsIModelElementPrivate *result = nsnull; if (model) - CallQueryInterface(model, &result); // addrefs + NS_ADDREF(result = model); return result; } @@ -436,7 +446,8 @@ nsXFormsUtils::EvaluateXPath(const nsAString &aExpression, &aExpression, aSet, aContextPosition, - aContextSize); + aContextSize, + aResultType == nsIDOMXPathResult::STRING_TYPE); NS_ENSURE_SUCCESS(rv, nsnull); if (aIndexesUsed) @@ -471,15 +482,18 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, PRUint16 aResultType, nsIModelElementPrivate **aModel, nsIDOMXPathResult **aResult, + PRBool *aUsesModelBind, + nsIXFormsControl **aParentControl, nsCOMArray *aDeps, nsStringArray *aIndexesUsed) { - if (!aElement || !aModel || !aResult) { - return NS_OK; + if (!aElement || !aModel || !aResult || !aUsesModelBind) { + return NS_ERROR_FAILURE; } *aModel = nsnull; *aResult = nsnull; + *aUsesModelBind = PR_FALSE; nsCOMPtr contextNode; nsCOMPtr bindElement; @@ -491,6 +505,7 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, aModel, getter_AddRefs(bindElement), &outerBind, + aParentControl, getter_AddRefs(contextNode), &contextPosition, &contextSize); @@ -501,30 +516,44 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, return NS_OK; // this will happen if the doc is still loading } - nsAutoString expr; + //////////////////// + // STEP 1: Handle @bind'ings if (bindElement) { - if (!outerBind) { + if (outerBind) { + // If there is an outer bind element, we retrieve its nodeset. + nsCOMPtr content(do_QueryInterface(bindElement)); + NS_ASSERTION(content, "nsIDOMElement not implementing nsIContent?!"); + + NS_IF_ADDREF(*aResult = + NS_STATIC_CAST(nsIDOMXPathResult*, + content->GetProperty(nsXFormsAtoms::bind))); + *aUsesModelBind = PR_TRUE; + } else { + // References to inner binds are not defined. // "When you refer to @id on a nested bind it returns an emtpy nodeset // because it has no meaning. The XForms WG will assign meaning in the // future." // @see http://www.w3.org/MarkUp/Group/2004/11/f2f/2004Nov11#resolution6 + nsXFormsUtils::ReportError(NS_LITERAL_STRING("innerBindRefError"), + aElement); + } + return NS_OK; + } + + + //////////////////// + // STEP 2: No bind attribute + // If there's no bind attribute, we expect there to be a |aBindingAttr| + // attribute. + nsAutoString expr; + aElement->GetAttribute(aBindingAttr, expr); + if (expr.IsEmpty()) { + // if there's no default binding, bail out + if (aDefaultRef.IsEmpty()) return NS_OK; - } else { - // If there is a (outer) bind element, we retrieve its nodeset. - bindElement->GetAttribute(NS_LITERAL_STRING("nodeset"), expr); - } - } else { - // If there's no bind element, we expect there to be a |aBindingAttr| attribute. - aElement->GetAttribute(aBindingAttr, expr); - if (expr.IsEmpty()) - { - if (aDefaultRef.IsEmpty()) - return NS_OK; - - expr.Assign(aDefaultRef); - } + expr.Assign(aDefaultRef); } // Evaluate |expr| @@ -537,6 +566,9 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, aDeps, aIndexesUsed); + //////////////////// + // STEP 3: Check for lazy binding + // 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. @@ -577,7 +609,7 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement, getter_AddRefs(instance)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr domdoc; - instance->GetDocument(getter_AddRefs(domdoc)); + instance->GetInstanceDocument(getter_AddRefs(domdoc)); nsCOMPtr instanceDataEle; nsCOMPtr childReturn; rv = domdoc->CreateElementNS(namespaceURI, expr, @@ -773,6 +805,7 @@ nsXFormsUtils::GetSingleNodeBinding(nsIDOMElement* aElement, return PR_FALSE; nsCOMPtr model; nsCOMPtr result; + PRBool usesModelBind; nsresult rv = EvaluateNodeBinding(aElement, nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, @@ -780,13 +813,18 @@ nsXFormsUtils::GetSingleNodeBinding(nsIDOMElement* aElement, EmptyString(), nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, getter_AddRefs(model), - getter_AddRefs(result)); + getter_AddRefs(result), + &usesModelBind); if (NS_FAILED(rv) || !result) return PR_FALSE; nsCOMPtr singleNode; - result->GetSingleNodeValue(getter_AddRefs(singleNode)); + if (usesModelBind) { + result->SnapshotItem(0, getter_AddRefs(singleNode)); + } else { + result->GetSingleNodeValue(getter_AddRefs(singleNode)); + } if (!singleNode) return PR_FALSE; @@ -953,7 +991,7 @@ nsXFormsUtils::EventHandlingAllowed(nsIDOMEvent* aEvent, nsIDOMNode* aTarget) } } } - NS_WARN_IF_FALSE(allow, "Event handling not allowed!"); + NS_ASSERTION(allow, "Event handling not allowed!"); return allow; } @@ -1014,6 +1052,7 @@ nsXFormsUtils::CloneScriptingInterfaces(const nsIID *aIIDList, /* static */ nsresult nsXFormsUtils::FindParentContext(nsIDOMElement *aElement, nsIModelElementPrivate **aModel, + nsIXFormsControl **aParentControl, nsIDOMNode **aContextNode, PRInt32 *aContextPosition, PRInt32 *aContextSize) @@ -1062,6 +1101,15 @@ nsXFormsUtils::FindParentContext(nsIDOMElement *aElement, *aContextSize = cSize; if (aContextPosition) *aContextPosition = cPosition; + // We QI from nsIXFormsContextControl to nsIXFormsControl here. This + // will always suceed when needed, as the only element not + // implementing both is the model element, and no children of model + // need to register with the model (which is what aParentControl is + // needed for). + if (aParentControl) { + CallQueryInterface(contextControl, aParentControl); // addrefs + } + break; } } @@ -1127,19 +1175,18 @@ nsXFormsUtils::CheckSameOrigin(nsIDocument *aBaseDocument, nsIURI *aTestURI) return PR_TRUE; // check the security manager and do a same original check on the principal - nsCOMPtr secMan = + nsCOMPtr secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); - if (secMan) { + if (secMan) { // get a principal for the uri we are testing nsCOMPtr testPrincipal; rv = secMan->GetCodebasePrincipal(aTestURI, getter_AddRefs(testPrincipal)); if (NS_SUCCEEDED(rv)) { - rv = secMan->CheckSameOriginPrincipal(aBaseDocument->GetPrincipal(), - testPrincipal); - if (NS_SUCCEEDED(rv)) - return PR_TRUE; - } + rv = secMan->CheckSameOriginPrincipal(basePrincipal, testPrincipal); + if (NS_SUCCEEDED(rv)) + return PR_TRUE; + } } } @@ -1270,20 +1317,20 @@ nsXFormsUtils::ParseTypeFromNode(nsIDOMNode *aInstanceData, nsAString &aNSUri) { nsresult rv; - + // Find the model for the instance data node nsCOMPtr instanceNode; rv = nsXFormsUtils::GetInstanceNodeForData(aInstanceData, getter_AddRefs(instanceNode)); NS_ENSURE_SUCCESS(rv, rv); - + nsCOMPtr modelNode; rv = instanceNode->GetParentNode(getter_AddRefs(modelNode)); NS_ENSURE_SUCCESS(rv, rv); - + nsCOMPtr model(do_QueryInterface(modelNode)); NS_ENSURE_STATE(model); - + return model->GetTypeFromNode(aInstanceData, aType, aNSUri); } @@ -1325,7 +1372,7 @@ nsXFormsUtils::ReportError(const nsString& aMessageName, const PRUnichar **aPara if (msg.IsEmpty()) { #ifdef DEBUG printf("nsXFormsUtils::ReportError() Failed to get message string for message id '%s'!\n", - NS_ConvertUCS2toUTF8(aMessageName).get()); + NS_ConvertUTF16toUTF8(aMessageName).get()); #endif return; } @@ -1390,7 +1437,7 @@ nsXFormsUtils::ReportError(const nsString& aMessageName, const PRUnichar **aPara // Log the message to JavaScript Console #ifdef DEBUG - printf("ERR: %s\n", NS_ConvertUCS2toUTF8(msg).get()); + printf("ERR: %s\n", NS_ConvertUTF16toUTF8(msg).get()); #endif nsresult rv = errorObject->Init(msg.get(), srcFile.get(), srcLine.get(), 0, 0, aErrorFlag, "XForms"); @@ -1546,7 +1593,8 @@ nsXFormsUtils::GetElementById(nsIDOMDocument *aDoc, /* static */ PRBool -nsXFormsUtils::HandleBindingException(nsIDOMElement *aElement) +nsXFormsUtils::HandleFatalError(nsIDOMElement *aElement, + const nsAString &aName) { if (!aElement) { return PR_FALSE; @@ -1589,13 +1637,15 @@ nsXFormsUtils::HandleBindingException(nsIDOMElement *aElement) // Show popup nsCOMPtr messageWindow; rv = internal->OpenDialog(NS_LITERAL_STRING("chrome://xforms/content/bindingex.xul"), - NS_LITERAL_STRING("XFormsBindingException"), + aName, NS_LITERAL_STRING("modal,dialog,chrome,dependent"), - nsnull, getter_AddRefs(messageWindow)); + nsnull, + getter_AddRefs(messageWindow)); return NS_SUCCEEDED(rv); } -/* static */ PRBool +/* static */ +PRBool nsXFormsUtils::AreEntitiesEqual(nsIDOMNamedNodeMap *aEntities1, nsIDOMNamedNodeMap *aEntities2) { diff --git a/mozilla/extensions/xforms/nsXFormsUtils.h b/mozilla/extensions/xforms/nsXFormsUtils.h index 46612f1d3f3..edd1191c431 100644 --- a/mozilla/extensions/xforms/nsXFormsUtils.h +++ b/mozilla/extensions/xforms/nsXFormsUtils.h @@ -65,6 +65,13 @@ class nsIDOMEvent; #define NS_NAMESPACE_MOZ_XFORMS_TYPE "http://www.mozilla.org/projects/xforms/2005/type" #define NS_NAMESPACE_MOZ_XFORMS_LAZY "http://www.mozilla.org/projects/xforms/2005/lazy" +/** + * Error codes + */ + +#define NS_OK_XFORMS_NOREFRESH \ +NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_GENERAL, 1) + /** * XForms event types * @@ -175,6 +182,7 @@ public: * @param aModel The \ for the element * @param aBindElement The \ the element is bound to (if any) * @param aOuterBind Whether the \ is an outermost bind + * @param aParentControl The parent control, ie the one setting the context * @param aContextNode The context node for the element * @param aContextPosition The context position for the element * @param aContextSize The context size for the element @@ -185,6 +193,7 @@ public: nsIModelElementPrivate **aModel, nsIDOMElement **aBindElement, PRBool *aOuterBind, + nsIXFormsControl **aParentControl, nsIDOMNode **aContextNode, PRInt32 *aContextPosition = nsnull, PRInt32 *aContextSize = nsnull); @@ -195,12 +204,17 @@ public: * @note Actually it is just a shortcut for GetNodeContext(). * * @param aElement The element + * @param aParentControl The parent control setting the context * @param aElementFlags Flags describing characteristics of aElement + * @param aContextNode The context node * @return The model */ static NS_HIDDEN_(already_AddRefed) - GetModel(nsIDOMElement *aElement, - PRUint32 aElementFlags = ELEMENT_WITH_MODEL_ATTR); + GetModel(nsIDOMElement *aElement, + nsIXFormsControl **aParentControl = nsnull, + PRUint32 aElementFlags = ELEMENT_WITH_MODEL_ATTR, + nsIDOMNode **aContextNode = nsnull); + /** * Evaluate a 'bind' or |aBindingAttr| attribute on |aElement|. @@ -220,6 +234,8 @@ public: PRUint16 aResultType, nsIModelElementPrivate **aModel, nsIDOMXPathResult **aResult, + PRBool *aUsesModelBind, + nsIXFormsControl **aParentControl = nsnull, nsCOMArray *aDeps = nsnull, nsStringArray *aIndexesUsed = nsnull); @@ -336,16 +352,19 @@ public: /** * Returns the context for the element, if set by a parent node. * - * Controls inheriting from nsIXFormsContextControl sets the context for its children. + * 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 aParentControl The parent control setting the context * @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, nsIModelElementPrivate **aModel, + nsIXFormsControl **aParentControl, nsIDOMNode **aContextNode, PRInt32 *aContextPosition, PRInt32 *aContextSize); @@ -454,18 +473,18 @@ public: const PRBool aOnlyXForms, nsIDOMElement *aCaller, nsIDOMElement **aElement); - - + /** - * Shows an error dialog for the user the first time an - * xforms-binding-exception event is received by the control. + * Shows an error dialog for fatal errors. * * The dialog can be disabled via the |xforms.disablePopup| preference. * * @param aElement Element the exception occured at + * @param aName The name to use for the new window * @return Whether handling was successful */ - static PRBool HandleBindingException(nsIDOMElement *aElement); + static NS_HIDDEN_(PRBool) HandleFatalError(nsIDOMElement *aElement, + const nsAString &aName); /** * Returns whether the given NamedNodeMaps of Entities are equal diff --git a/mozilla/extensions/xforms/nsXFormsValueElement.cpp b/mozilla/extensions/xforms/nsXFormsValueElement.cpp index 96322a951c0..2e8095c7d83 100644 --- a/mozilla/extensions/xforms/nsXFormsValueElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsValueElement.cpp @@ -94,26 +94,12 @@ nsXFormsValueElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper) NS_IMETHODIMP nsXFormsValueElement::GetValue(nsAString &aValue) { - nsCOMPtr model; - nsCOMPtr result; - nsXFormsUtils::EvaluateNodeBinding(mElement, - nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, - NS_LITERAL_STRING("ref"), - EmptyString(), - nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE, - getter_AddRefs(model), - getter_AddRefs(result)); - - if (result) { - nsCOMPtr singleNode; - result->GetSingleNodeValue(getter_AddRefs(singleNode)); - - if (singleNode) { - nsString value; - nsXFormsUtils::GetNodeValue(singleNode, value); - aValue.Assign(value); - return NS_OK; - } + nsString value; + PRBool singleNodeVal = + nsXFormsUtils::GetSingleNodeBindingValue(mElement, value); + if (singleNodeVal) { + aValue.Assign(value); + return NS_OK; } nsCOMPtr node3 = do_QueryInterface(mElement); diff --git a/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.cpp b/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.cpp index 677b9e5b5d3..04ed9d373a6 100644 --- a/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.cpp +++ b/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.cpp @@ -45,8 +45,6 @@ //#define DEBUG_XF_ANALYZER #endif -MOZ_DECL_CTOR_COUNTER(nsXFormsXPathAnalyzer) - nsXFormsXPathAnalyzer::nsXFormsXPathAnalyzer(nsIXFormsXPathEvaluator *aEvaluator, nsIDOMNode *aResolver) : mEvaluator(aEvaluator), mResolver(aResolver) @@ -66,7 +64,8 @@ nsXFormsXPathAnalyzer::Analyze(nsIDOMNode *aContextNode, const nsAString *aExprString, nsCOMArray *aSet, PRUint32 aPosition, - PRUint32 aSize) + PRUint32 aSize, + PRBool aIncludeRoot) { NS_ENSURE_ARG(aContextNode); NS_ENSURE_ARG(aNode); @@ -82,11 +81,12 @@ nsXFormsXPathAnalyzer::Analyze(nsIDOMNode *aContextNode, #ifdef DEBUG_XF_ANALYZER printf("=====================================\n"); - printf("Analyzing: %s\n", NS_ConvertUCS2toUTF8(*mCurExprString).get()); + printf("Analyzing: %s\n", NS_ConvertUTF16toUTF8(*mCurExprString).get()); printf("=====================================\n"); #endif - nsresult rv = AnalyzeRecursively(aContextNode, aNode->mChild, 0); + nsresult rv = AnalyzeRecursively(aContextNode, aNode->mChild, 0, + aIncludeRoot); #ifdef DEBUG_XF_ANALYZER printf("-------------------------------------\n"); #endif @@ -102,15 +102,18 @@ nsXFormsXPathAnalyzer::Analyze(nsIDOMNode *aContextNode, nsresult nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode, const nsXFormsXPathNode *aNode, - PRUint32 aIndent) + PRUint32 aIndent, + PRBool aCollect) { nsXFormsXPathNode* t; nsAutoString xp; nsresult rv; nsCOMPtr result; nsCOMPtr node; +#ifdef DEBUG_XF_ANALYZER char strbuf[100]; char* strpos; +#endif #ifdef DEBUG_beaufour_xxx printf("nsXFormsXPathParser::AnalyzeRecursively(%p)\n", (void*) aNode); @@ -129,8 +132,6 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode, } PRBool hasContinue = PR_FALSE; - strpos = strbuf; - *strpos = '\0'; // hasContinue == whether we have a child with a mCon t = aNode->mChild; @@ -140,6 +141,8 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode, } #ifdef DEBUG_XF_ANALYZER + strpos = strbuf; + *strpos = '\0'; for (PRUint32 j = 0; j < aIndent; ++j) { strpos += sprintf(strpos, " "); } @@ -214,13 +217,13 @@ nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode *aContextNode, #ifdef DEBUG_XF_ANALYZER printf(strbuf); #endif - if (aNode->mChild || (!aNode->mChild && hasContinue)) { + if (!aCollect && (aNode->mChild || (!aNode->mChild && hasContinue))) { #ifdef DEBUG_XF_ANALYZER - printf("iterating '%s'\n", NS_ConvertUCS2toUTF8(xp).get()); + printf("iterating '%s'\n", NS_ConvertUTF16toUTF8(xp).get()); #endif } else { #ifdef DEBUG_XF_ANALYZER - printf("collecting '%s'\n", NS_ConvertUCS2toUTF8(xp).get()); + printf("collecting '%s'\n", NS_ConvertUTF16toUTF8(xp).get()); #endif mCurSet->AppendObject(node); } diff --git a/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.h b/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.h index 20c9e0a9a73..b379f63bbf7 100644 --- a/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.h +++ b/mozilla/extensions/xforms/nsXFormsXPathAnalyzer.h @@ -70,7 +70,8 @@ private: nsresult AnalyzeRecursively(nsIDOMNode *aContextNode, const nsXFormsXPathNode *aNode, - PRUint32 aIndent); + PRUint32 aIndent, + PRBool aCollect = PR_FALSE); public: nsXFormsXPathAnalyzer(nsIXFormsXPathEvaluator *aEvaluator, @@ -83,7 +84,8 @@ public: const nsAString *aExprString, nsCOMArray *aSet, PRUint32 aSize, - PRUint32 aPosition); + PRUint32 aPosition, + PRBool aIncludeRoot); const nsStringArray& IndexesUsed() const; }; diff --git a/mozilla/extensions/xforms/nsXFormsXPathNode.cpp b/mozilla/extensions/xforms/nsXFormsXPathNode.cpp index 00340e73591..15682ceeea3 100644 --- a/mozilla/extensions/xforms/nsXFormsXPathNode.cpp +++ b/mozilla/extensions/xforms/nsXFormsXPathNode.cpp @@ -40,8 +40,6 @@ #include "nsXFormsXPathNode.h" #include "nsCOMPtr.h" -MOZ_DECL_CTOR_COUNTER(nsXFormsXPathNode) - nsXFormsXPathNode::nsXFormsXPathNode(nsXFormsXPathNode* aParent, PRBool aContinue) : mChild(nsnull), mEndIndex(-100), mCon(aContinue), mIsIndex(PR_FALSE) { diff --git a/mozilla/extensions/xforms/nsXFormsXPathParser.cpp b/mozilla/extensions/xforms/nsXFormsXPathParser.cpp index b058a6c351f..1e94d1cf7ca 100644 --- a/mozilla/extensions/xforms/nsXFormsXPathParser.cpp +++ b/mozilla/extensions/xforms/nsXFormsXPathParser.cpp @@ -45,22 +45,20 @@ * that was to overdo it a bit, when the code probably does not survive... (XXX) */ void -XPathCompilerException(const char *aMsg, - nsAString &aExpression, - PRInt32 aOffset = -1, - PRInt32 aLength = -1) +XPathCompilerException(const char *aMsg, + const nsAString &aExpression, + PRInt32 aOffset = -1, + PRInt32 aLength = -1) { printf("XPathCompilerException: %s, %s [o: %d, l: %d]\n", aMsg, - NS_ConvertUCS2toUTF8(aExpression).get(), aOffset, aLength); - + NS_ConvertUTF16toUTF8(aExpression).get(), aOffset, aLength); + printf("WARNING: Houston we have a problem, and unlike Apollo 13, we're not going to make it!\n"); NS_ABORT(); } -MOZ_DECL_CTOR_COUNTER(nsXFormsXPathParser) - nsXFormsXPathParser::nsXFormsXPathParser() : mUsesDynamicFunc(PR_FALSE), mHead(nsnull), mAnalyzeStackPointer(nsnull) { @@ -561,8 +559,7 @@ nsXFormsXPathParser::PathExpr() if (DoRelative()) { RelativeLocationPath(); } else { - nsAutoString nullstr; - XPathCompilerException("After / in a filter expression it is required to have a reletive path expression", nullstr); + XPathCompilerException("After / in a filter expression it is required to have a reletive path expression", EmptyString()); } } @@ -858,7 +855,7 @@ nsXFormsXPathParser::Parse(const nsAString& aExpression) { #ifdef DEBUG_XF_PARSER printf("=====================================\n"); - printf("Parsing: %s\n", NS_ConvertUCS2toUTF8(aExpression).get()); + printf("Parsing: %s\n", NS_ConvertUTF16toUTF8(aExpression).get()); printf("=====================================\n"); #endif @@ -917,6 +914,6 @@ void nsXFormsXPathParser::OutputSubExpression(PRInt32 aOffset, PRInt32 aEndOffset) { const nsDependentSubstring expr = Substring(mScanner.Expression(), aOffset, aEndOffset - aOffset); - printf("%s\n", NS_ConvertUCS2toUTF8(expr).get()); + printf("%s\n", NS_ConvertUTF16toUTF8(expr).get()); } #endif diff --git a/mozilla/extensions/xforms/nsXFormsXPathScanner.cpp b/mozilla/extensions/xforms/nsXFormsXPathScanner.cpp index c467f29bf98..f99581d728b 100644 --- a/mozilla/extensions/xforms/nsXFormsXPathScanner.cpp +++ b/mozilla/extensions/xforms/nsXFormsXPathScanner.cpp @@ -40,8 +40,6 @@ #include "nsXFormsXPathScanner.h" #include "nsXFormsXPathXMLUtil.h" -MOZ_DECL_CTOR_COUNTER(nsXFormsXPathScanner) - nsXFormsXPathScanner::nsXFormsXPathScanner() { MOZ_COUNT_CTOR(nsXFormsXPathScanner); diff --git a/mozilla/extensions/xforms/resources/content/bindingex.xul b/mozilla/extensions/xforms/resources/content/bindingex.xul index 6b85c296c63..93a94706935 100644 --- a/mozilla/extensions/xforms/resources/content/bindingex.xul +++ b/mozilla/extensions/xforms/resources/content/bindingex.xul @@ -15,7 +15,7 @@ - The Original Code is Mozilla XForms Support. - - The Initial Developer of the Original Code is - - IBM Corportation. + - IBM Corporation. - Portions created by the Initial Developer are Copyright (C) 2005 - the Initial Developer. All Rights Reserved. - diff --git a/mozilla/extensions/xforms/resources/content/input-xhtml.xml b/mozilla/extensions/xforms/resources/content/input-xhtml.xml new file mode 100644 index 00000000000..46851967385 --- /dev/null +++ b/mozilla/extensions/xforms/resources/content/input-xhtml.xml @@ -0,0 +1,378 @@ + + + + + + + + + %xformsDTD; +]> + + + + + + + + + + + + + + + + return { + __proto__: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'), + + set readonly(val) { + if (val) { + this.setAttribute('readonly', 'readonly'); + } else { + this.removeAttribute('readonly'); + } + } + }; + + + + + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMFocusIn"); + } + + + + if (event.originalTarget == this.control) { + this.updateInstanceData(); + this.dispatchDOMUIEvent("DOMFocusOut"); + } + + + + + + + + + + + + + + + + + + + + + + + + + return { + __proto__: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'), + + get value() { + return this.checked; + }, + set value(val) { + this.checked = val; + }, + set readonly(val) { + if (val) { + this.setAttribute('disabled', 'disabled'); + } else { + this.removeAttribute('disabled'); + } + } + }; + + + + + + + if (event.originalTarget == this.control) + this.updateInstanceData(true); + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMFocusIn"); + } + + + + if (event.originalTarget == this.control) { + this.updateInstanceData(); + this.dispatchDOMUIEvent("DOMFocusOut"); + } + + + + + + + + + + + + + + + + + + + + + return this.ownerDocument. + getAnonymousElementByAttribute(this, "anonid", "control"); + + + + + var changeHandler = { + inputControl: this, + handleEvent: function() { + this.inputControl.updateInstanceData(false); + } + }; + this.addEventListener("change", changeHandler, false); + + + + + + + + + + + + + + + + + + + return { + __proto__: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'), + + XHTML_NS: 'http://www.w3.org/1999/xhtml', + + set readonly(val) { + this.disabled = val; + }, + appendMonth: function(name, value) { + var option = this.ownerDocument. + createElementNS(this.XHTML_NS, 'option'); + option.textContent = name; + option.setAttribute('value', value); + this.appendChild(option); + } + }; + + + + + + + if (event.originalTarget == this.control) + this.updateInstanceData(false); + + + + if (event.originalTarget == this.control) + this.updateInstanceData(true); + + + + + + + + + + + + + + + + + + + return { + __proto__: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'), + + XHTML_NS: 'http://www.w3.org/1999/xhtml', + + set readonly(val) { + this.disabled = val; + }, + appendDay: function(name, value) { + var option = this.ownerDocument. + createElementNS(this.XHTML_NS, 'option'); + option.textContent = name; + option.setAttribute('value', value); + this.appendChild(option); + } + }; + + + + + + + if (event.originalTarget == this.control) + this.updateInstanceData(false); + + + + if (event.originalTarget == this.control) + this.updateInstanceData(true); + + + + + + + + + + + + + + + + + + + + + + + + + + + return { + __proto__: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'), + + set readonly(val) { + if (val) { + this.setAttribute('readonly', 'readonly'); + } else { + this.removeAttribute('readonly'); + } + } + }; + + + + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMFocusIn"); + } + + + + if (event.originalTarget == this.control) { + this.updateInstanceData(); + this.dispatchDOMUIEvent("DOMFocusOut"); + } + + + + + + + + + diff --git a/mozilla/extensions/xforms/resources/content/input-xul.xml b/mozilla/extensions/xforms/resources/content/input-xul.xml new file mode 100644 index 00000000000..bc91d75521e --- /dev/null +++ b/mozilla/extensions/xforms/resources/content/input-xul.xml @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + var control = this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'); + + return { + control: control, + + __proto__: control.inputField, + + set readonly(val) { + this.control.readonly = val; + } + }; + + + + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMFocusIn"); + } + + + + if (event.originalTarget == this.control) { + this.updateInstanceData(); + this.dispatchDOMUIEvent("DOMFocusOut"); + } + + + + if (event.originalTarget == this.control) { + this.updateInstanceData(true); + } + + + + + + + + + + + + + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMActivate"); + } + + + + + + + + + + + + + + + + + return { + __proto__: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'), + + get value() { + return this.checked; + }, + set value(val) { + this.checked = val; + }, + set readonly(val) { + this.disabled = val; + } + }; + + + + + + + if (event.originalTarget == this.control) + this.updateInstanceData(true); + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMFocusIn"); + } + + + + if (event.originalTarget == this.control) { + this.updateInstanceData(); + this.dispatchDOMUIEvent("DOMFocusOut"); + } + + + + + + + + + + + + + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMActivate"); + } + + + + + + + + + + + + + + + diff --git a/mozilla/extensions/xforms/resources/content/input.xml b/mozilla/extensions/xforms/resources/content/input.xml new file mode 100644 index 00000000000..e68b8792625 --- /dev/null +++ b/mozilla/extensions/xforms/resources/content/input.xml @@ -0,0 +1,879 @@ + + + + + + + + + %xformsDTD; +]> + + + + + + + + + + + + this.control.readonly = this.accessors.isReadonly(); + // If the value has not changed, no need to update the + // value of the control, because f.x. that makes the textarea widget + // to scroll up. + if (this.control.value != this.stringValue) { + this.control.value = this.stringValue; + } + + return true; + + + + + + this.control.focus(); + return true; + + + + + + + if (!aIncremental || this.getAttribute("incremental") == "true") + this.accessors.setValue(this.control.value); + + + + + + + + + + + + + + var value = this.stringValue; + if (value == "true" || value == "1") { + this.control.value = true; + } else { + this.control.value = false; + } + + this.control.readonly = this.accessors.isReadonly(); + return true; + + + + + + this.control.focus(); + return true; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + this.inputField.value = this.stringValue; + if (this.accessors.isReadonly()) { + this.inputField.setAttribute("readonly", "readonly"); + this.dropmarker.setAttribute("disabled", "true"); + } else { + this.inputField.removeAttribute("readonly"); + this.dropmarker.removeAttribute("disabled"); + } + return true; + + + + + + if (this.getAttribute("incremental") == "true") { + this.accessors.setValue(this.inputField.value); + } + return true; + + + + null + + + if (!this._inputField) { + this._inputField = + document.getAnonymousElementByAttribute(this, "anonid", "control"); + } + return this._inputField; + + + + null + + + if (!this._picker) { + this._picker = + document.getAnonymousElementByAttribute(this, "anonid", "picker"); + } + return this._picker; + + + + null + + + if (!this._dropmarker) { + this._dropmarker = + document.getAnonymousElementByAttribute(this, "anonid", "dropmarker"); + } + return this._dropmarker; + + + + null + + + if (!this._dateField) { + this._dateField = + document.getAnonymousElementByAttribute(this, "anonid", "date"); + } + return this._dateField; + + + + false + false + null + null + + -1 + + + + + + + + + + window.innerWidth) { + // we use window.innerWidth because XHTML documents are not always + // 100% width, and innerWidth will always give use the browser size. + position = window.innerWidth - width; + } + + picker.style.left = position + "px"; + + this._refreshCells(this._date, this._date.getDate()); + ]]> + + + + + + + + + + + + + + + + + + + + + + + = (firstDay + totaldays)) { + // either previous or next month + if (i < firstDay) { + // previous month + var prevyear = prevDate.getFullYear(); + var prevmonth = prevDate.getMonth(); + + var maxprev = this._getDaysInMonth(prevmonth, prevyear); + this._cells[i].node.textContent = maxprev - firstDay + i + 1; + + this._cells[i].node.className = "prevMonth"; + showsPrevDays++; + } else { + // next month + this._cells[i].node.textContent = i - (firstDay + totaldays) + 1; + this._cells[i].node.className = "nextMonth"; + } + } else { + // current month + // this._cells add one since the first day is 1, not 0! + this._cells[i].node.textContent = i - firstDay + 1; + this._cells[i].node.className = "currentMonth"; + } + + this._cells[i].node.setAttribute("tabindex", "-1"); + } + + // first time + if (this._currentCellIndex == -1) { + // select the current day + this._currentCellIndex = aDate.getDate() + showsPrevDays - 1; + } else { + // if the day is larger that the total days in this month + if (aDayToSelect > totaldays) + aDayToSelect = totaldays; + + this._currentCellIndex = aDayToSelect + showsPrevDays - 1; + } + + this._cells[this._currentCellIndex].node.setAttribute("tabindex", "0"); + + if (!aSkipFocus) + this._cells[this._currentCellIndex].node.focus(); + + // update the month year heading + this.dateField.textContent = this._date.toLocaleFormat("%B %Y"); + ]]> + + + + + + + + var month, year = aYear; + + if (aMonth == 0) { + month = 11; + year--; + } else { + month = aMonth - 1; + } + + return new Date(year, month); + + + + + + + + var month, year = aYear; + + if (aMonth == 11) { + month = 0; + year++; + } else { + month = aMonth + 1; + } + + return new Date(year, month); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + = 0) { + this.selectCell(index - 7); + } else { + // focus the back button + document.getAnonymousElementByAttribute(this, "anonid", "back-button").focus(); + } + } else if (event.keyCode == event.DOM_VK_LEFT) { + // ctrl-left goes back a month + if (event.ctrlKey) { + this.goBack(); + } else if (currentElement.localName == "input") { + // input means we are on one of the back/fwd buttons + document.getAnonymousElementByAttribute(this, "anonid", "back-button").focus(); + } else if ((index - 1) >= 0) { + this.selectCell(index - 1); + } + } else if (event.keyCode == event.DOM_VK_RIGHT) { + // ctrl-right goes forward a month + if (event.ctrlKey) { + this.goForward(); + } else if (currentElement.localName == "input") { + // input means we are on one of the back/fwd buttons + document.getAnonymousElementByAttribute(this, "anonid", "fwd-button").focus(); + } else if ((index + 1) < this._cells.length) { + this.selectCell(index + 1); + } + } else if (event.keyCode == event.DOM_VK_RETURN && + event.originalTarget.localName == "td") { + var type = event.originalTarget.className; + if (type == "currentMonth") { + this.selectCell(event.originalTarget.getAttribute("num")); + this._valueSet(); + } else if (type == "prevMonth") { + this.goBack(); + } else if (type == "nextMonth") { + this.goForward(); + } + } else if (event.keyCode == event.DOM_VK_ESCAPE) { + this._hidePicker(true); + } + } else { + // pressing down if the picker is hidden will show it + if (event.keyCode == event.DOM_VK_DOWN) { + // first set the accessor value, since the input's value hasn't + // been validated yet, and forcing this will. + this.accessors.setValue(this.inputField.value); + + this._showPicker(); + } else { + // check if something changed + this._change(); + } + } + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + this.control.focus(); + return true; + + + + + + + if (!aIncremental || this.getAttribute("incremental") == "true") { + if (this.control.value != "") { + this.accessors.setValue("--" + this.control.value); + } else { + this.accessors.setValue(""); + } + } + + + + + + + + + + + + + + + + + + + + + + this.control.focus(); + return true; + + + + + + + if (!aIncremental || this.getAttribute("incremental") == "true") { + if (this.control.value != "") { + this.accessors.setValue("---" + this.control.value); + } else { + this.accessors.setValue(""); + } + } + + + + + + + + + + + + + + + diff --git a/mozilla/extensions/xforms/resources/content/select-xhtml.xml b/mozilla/extensions/xforms/resources/content/select-xhtml.xml new file mode 100644 index 00000000000..0e621622a02 --- /dev/null +++ b/mozilla/extensions/xforms/resources/content/select-xhtml.xml @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + for (var i = this.control.childNodes.length; i > 0; i--) { + this.control.removeChild(this.control.childNodes[i-1]); + } + + + + + + + + + var item = document.createElementNS(this.XHTML_NS, "option"); + item.setAttribute("value", aValue); + + if (aLabel) { + item.appendChild(aLabel.cloneNode(true)); + } + + if (aGroup) { + aGroup.appendChild(item); + } else { + this.control.appendChild(item); + } + return item; + + + + + + + + var item = document.createElementNS(this.XHTML_NS, "optgroup"); + if (aLabel) { + item.appendChild(aLabel.cloneNode(true)); + } + if (aGroup) { + aGroup.appendChild(item); + } else { + this.control.appendChild(item); + } + return item; + + + + + + + aItem.selected = true; + + + + + + + aItem.selected = false; + + + + + + + return aItem.selected; + + + + + + + this.dispatchDOMUIEvent("DOMFocusIn"); + + + + this.updateInstanceData(false); + this.dispatchDOMUIEvent("DOMFocusOut"); + + + + this.updateInstanceData(true); + + + + + + + + + + + + + + + + + + + + + + : 'selectedIndex' property isn't implemented." + ]]> + + + + + for (var i = this.control.childNodes.length; i > 0; i--) { + this.control.removeChild(this.control.childNodes[i-1]); + } + + + + + + + + + var div = document.createElementNS(this.XHTML_NS, "div"); + var input = document.createElementNS(this.XHTML_NS, "input"); + input.setAttribute("type", "checkbox"); + input.setAttribute("value", aValue); + input.setAttribute("anonid", "wcontrol"); + if (this.readonly) + input.setAttribute("disabled", "true"); + + div.appendChild(input); + if (aLabel) + div.appendChild(aLabel.cloneNode(true)); + + if (aGroup) { + aGroup.appendChild(div); + } else { + this.control.appendChild(div); + } + return div; + + + + + + + + var mainDiv = document.createElementNS(this.XHTML_NS, "div"); + + var labelDiv = document.createElementNS(this.XHTML_NS, "div"); + if (aLabel) { + labelDiv.className = "select-choice-label"; + labelDiv.appendChild(aLabel.cloneNode(true)); + } + mainDiv.appendChild(labelDiv); + + var contentDiv = document.createElementNS(this.XHTML_NS, "div"); + contentDiv.className = "select-choice-content"; + mainDiv.appendChild(contentDiv); + + if (aGroup) { + aGroup.appendChild(mainDiv); + } else { + this.control.appendChild(mainDiv); + } + + return contentDiv; + + + + + + + aItem.firstChild.checked = true; + + + + + + + aItem.firstChild.checked = false; + + + + + + + return aItem.firstChild.checked; + + + + + + + if (event.originalTarget.getAttribute("anonid") == "wcontrol") + this.updateInstanceData(true); + + + + if (event.originalTarget.getAttribute("anonid") == "wcontrol") + this.updateInstanceData(false); + + + + + + + + diff --git a/mozilla/extensions/xforms/resources/content/select-xul.xml b/mozilla/extensions/xforms/resources/content/select-xul.xml new file mode 100644 index 00000000000..8c4ece6f525 --- /dev/null +++ b/mozilla/extensions/xforms/resources/content/select-xul.xml @@ -0,0 +1,619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // removeItemAt fires 'select' event event if 'suppressonselect' + // attribute is specified, we shouldn't listen the event (bug 312149) + + this.suppress = true; + for (var i = this.control.childNodes.length-1; i >= 0; i--) { + this.control.removeItemAt(i); + } + this.suppress = false; + + + false + + + + + + + var item = this.ownerDocument.createElementNS(this.XUL_NS, "listitem"); + item.setAttribute("value", aValue); + if (aLabel) { + // since label node can contains textnodes then we use + // 'description' element as container for label node. + var description = this.ownerDocument. + createElementNS(this.XUL_NS, "description"); + description.appendChild(aLabel.cloneNode(true)); + item.appendChild(description); + } + + // XXX: Group supporting isn't implemented + this.control.appendChild(item); + + return item; + + + + + + + + // XXX: Group supporting isn't implemented + return null; + + + + + + + // there are cases when 'listitem' binding isn't created yet, + // therefore we use setTimeout + + window.setTimeout( + function(list, item) { + list.setAttribute("suppressonselect", "true"); + list.addItemToSelection(item); + list.removeAttribute("suppressonselect"); + }, + 0, + this.control, aItem + ); + + + + + + + this.control.setAttribute("suppressonselect", "true"); + this.control.removeItemFromSelection(aItem); + this.control.removeAttribute("suppressonselect"); + + + + + + + return aItem.selected; + + + + + // 'select' event is not always handled when handler is added by using + // xbl:handler element. + var selectHandler = { + control: this, + handleEvent: function() { + if (!this.control.suppress) { + this.control.updateInstanceData(true); + } + } + }; + this.addEventListener("select", selectHandler, false); + + + + + + this.dispatchDOMUIEvent("DOMFocusIn"); + + + + this.updateInstanceData(false); + this.dispatchDOMUIEvent("DOMFocusOut"); + + + + + + + + + + + + + + + + + + + + : 'selectedIndex' property isn't implemented." + ]]> + + + + + for (var i = this.control.childNodes.length; i > 0; i--) { + this.control.removeChild(this.control.childNodes[i-1]); + } + + + + + + + + + var box = this.ownerDocument.createElementNS(this.XUL_NS, "hbox"); + box.setAttribute("align", "center"); + + var checkbox = this.ownerDocument.createElementNS(this.XUL_NS, "checkbox"); + checkbox.setAttribute("value", aValue); + checkbox.setAttribute("anonid", "wcontrol"); + if (this.readonly) + checkbox.setAttribute("disabled", "true"); + + box.appendChild(checkbox); + if (aLabel) { + // since label node can contains textnodes then we use + // 'description' element as container for label node. + var description = this.ownerDocument. + createElementNS(this.XUL_NS, "description"); + description.appendChild(aLabel.cloneNode(true)); + box.appendChild(description); + } + + if (aGroup) { + aGroup.appendChild(box); + } else { + this.control.appendChild(box); + } + + return box; + + + + + + + + var mainBox = this.ownerDocument.createElementNS(this.XUL_NS, "vbox"); + + var labelBox = this.ownerDocument.createElementNS(this.XUL_NS, "hbox"); + if (aLabel) { + labelBox.className = "select-choice-label"; + labelBox.appendChild(aLabel.cloneNode(true)); + } + mainBox.appendChild(labelBox); + + var contentBox = this.ownerDocument.createElementNS(this.XUL_NS, "vbox"); + contentBox.className = "select-choice-content"; + mainBox.appendChild(contentBox); + + if (aGroup) { + aGroup.appendChild(mainBox); + } else { + this.control.appendChild(mainBox); + } + + return contentBox; + + + + + + + aItem.firstChild.checked = true; + + + + + + + aItem.firstChild.checked = false; + + + + + + + return aItem.firstChild.checked; + + + + + + + if (event.originalTarget.getAttribute("anonid") == "wcontrol") + this.updateInstanceData(true); + + + + if (event.originalTarget.getAttribute("anonid") == "wcontrol") + this.updateInstanceData(false); + + + + + + + + + + + + + + + + + + + + + + + + + var popup = this.control.menupopup; + while (popup.hasChildNodes()) { + popup.removeChild(popup.lastChild); + } + + + + + + + + + var item = this.ownerDocument.createElementNS(this.XUL_NS, "menuitem"); + item.setAttribute("value", aValue); + if (aLabel) { + // XXX: We should use node instead of its text content to add a + // label. But we cannot put node into menuitem, therefore we now + // use label text and set @label for menulist. + item.setAttribute("label", aLabel.textContent); + } + + // XXX: Group supporting isn't implemented + this.control.menupopup.appendChild(item); + return item; + + + + + + + + // XXX: Group supporting isn't implemented + return null; + + + + + + + this.control.selectedItem = aItem; + + + + + + + if (this.control.selectedItem == aItem) + this.control.selectedItem = null; + + + + + + + return aItem.getAttribute("selected") == "true"; + + + + + + + this.dispatchDOMUIEvent("DOMFocusIn"); + + + + this.updateInstanceData(false); + this.dispatchDOMUIEvent("DOMFocusOut"); + + + + this.updateInstanceData(true); + + + + + + + + + + + + + + + + + + + + + + + + + + + + : 'selectedIndex' property isn't implemented." + ]]> + + + + + for (var i = this.control.childNodes.length; i > 0; i--) { + this.control.removeChild(this.control.childNodes[i-1]); + } + + + + + + + + + var box = this.ownerDocument.createElementNS(this.XUL_NS, "hbox"); + box.setAttribute("align", "center"); + + var radio = this.ownerDocument.createElementNS(this.XUL_NS, "radio"); + radio.setAttribute("value", aValue); + radio.setAttribute("anonid", "wcontrol"); + if (this.readonly) + radio.setAttribute("disabled", "true"); + + box.appendChild(radio); + if (aLabel) { + // since label node can contains textnodes then we use + // 'description' element as container for label node. + var description = this.ownerDocument. + createElementNS(this.XUL_NS, "description"); + description.appendChild(aLabel.cloneNode(true)); + box.appendChild(description); + } + + if (aGroup) { + aGroup.appendChild(box); + } else { + this.control.appendChild(box); + } + + return box; + + + + + + + + var mainBox = this.ownerDocument.createElementNS(this.XUL_NS, "vbox"); + + var labelBox = this.ownerDocument.createElementNS(this.XUL_NS, "hbox"); + if (aLabel) { + labelBox.className = "select-choice-label"; + labelBox.appendChild(aLabel.cloneNode(true)); + } + mainBox.appendChild(labelBox); + + var contentBox = this.ownerDocument.createElementNS(this.XUL_NS, "vbox"); + contentBox.className = "select-choice-content"; + mainBox.appendChild(contentBox); + + if (aGroup) { + aGroup.appendChild(mainBox); + } else { + this.control.appendChild(mainBox); + } + + return contentBox; + + + + + + + // there are a cases when 'radio' binding isn't created yet, therefore + // we use setTimeout. + window.setTimeout( + function(list, item) { + list.selectedItem = item; + }, + 0, + this.control, aItem.firstChild + ); + + + + + + + if (aItem.firstChild.selected) + this.control.selectedItem = null; + + + + + + + return aItem.firstChild.selected; + + + + + + + if (event.originalTarget.getAttribute("anonid") == "wcontrol") + this.updateInstanceData(true); + + + + if (event.originalTarget.getAttribute("anonid") == "control") + this.updateInstanceData(false); + + + + + + diff --git a/mozilla/extensions/xforms/resources/content/select.xml b/mozilla/extensions/xforms/resources/content/select.xml index a9589f85195..9a48ddefcb8 100644 --- a/mozilla/extensions/xforms/resources/content/select.xml +++ b/mozilla/extensions/xforms/resources/content/select.xml @@ -22,6 +22,7 @@ - - Contributor(s): - Doron Rosenberg + - Olli Pettay - - 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 @@ -38,102 +39,68 @@ - ***** END LICENSE BLOCK ***** --> - + xmlns:xbl="http://www.mozilla.org/xbl"> - - + - - - - - - - - - - - - - null - - - if (!this._uiElement) { - this._uiElement = - document.getAnonymousElementByAttribute(this, "anonid", "select"); - } - - return this._uiElement; - - - - - - this.uiElement.selectedIndex = val; - - - - null + + false - + ]]> - 0 - new Array() - 0 - new Array() - null + + + + + + + + + + + + + - - + + + + + + 0; i--) { - this.uiElement.removeChild(this.uiElement.childNodes[i-1]); - } - - // create children - var child, option; - var childNodes = this.childNodes; - - // these hold an array of generated HTML controls - this._controlArraySize = 0; - this._controlArray = new Array(); - - for (var i = 0; i < childNodes.length; i++) { - child = childNodes[i]; - - // we only care about element nodes in the XForms namespace. - if (child.nodeType == child.ELEMENT_NODE && - child.namespaceURI == this.XFORMS_NS) { - if (child.localName == "item") { - // cache the item's label/value - var itemElement = - child.QueryInterface(Components.interfaces.nsIXFormsItemElement); - var value = itemElement.value; - var label = itemElement.labelText; - - this._addSelectItem(label, value, child); - - // check if we should pre-select this option - this.preselectItem(value); - } else if (child.localName == "choices") { - var optGroup = this._handleChoices(child); - this.uiElement.appendChild(optGroup); - } else if (child.localName == "itemset") { - var uiElement = - child.QueryInterface(Components.interfaces.nsIXFormsItemSetUIElement); - var containers = uiElement.anonymousItemSetContent.childNodes; - - // go through each item in the itemset and add it to the - // html:select. Select any of the items that contain a value - // that also appears under the bound node. - for (var y = 0; y < containers.length; y++) { - if (containers[y].nodeType == containers[y].ELEMENT_NODE) { - this._addItemSetItem(containers[y]); - } - } - } - } - } - - // check if any default values were not found - for (var index in this._defaultHash) { - if (this._defaultHash[index].hits == 0) { - // XXX: some of default values not found, we need to throw an - // xforms-out-of-range event, but only if the select is 'closed'. - // If the select is open, the missing elements should be added - // and selected per 8.1.10 in the spec. - } - } - - // check if any default elements were not found - for (var j = 0; j < this._selectedElementSize; j++) { - if (this._selectedElementArray[j].hits == 0) { - // XXX: some of default values not found, we need to throw an - // xforms-out-of-range event, but only if the select is 'closed'. - // If the select is open, the missing elements should be added - // and selected per 8.1.10 in the spec. - } - } - - - - return true; - ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0) { - var item = aItemElement.QueryInterface(Components.interfaces.nsIXFormsSelectChild); - for (var j = 0; j < this._selectedElementSize; j++ ) { - var selectedItem = - item.selectItemByNode(this._selectedElementArray[j].element); - if (selectedItem) { - this._selectedElementArray[j].hits++; - option.selected = true; - // XXX It is possible that two identical elements are under the - // bound node. I guess we shouldn't mark one and not the other - // if there is an item in the select that matches it. So we'll - // go through the whole list. But this is quite an edge case - // and will cause more inefficiency just to prevent an errant - // xforms-out-of-range. - } - } - } - - // add to the control array - this._controlArray[this._controlArraySize] = - {control: aItemElement, option: option, type: "item", wasSelected: option.selected} - this._controlArraySize++; - - this.uiElement.appendChild(option); - - if (!copyItem) { - // if this item contains a value element, then make sure to select - // this item if its value exists under the bound node. - this.preselectItem(itemValue); - } - - return itemValue; - ]]> - - - - - - - - - - - - - + + + + + + + // cache the item's label/value + aItem = aItem.QueryInterface(Components.interfaces.nsIXFormsItemElement); + var labels = aItem.getElementsByTagNameNS(this.XFORMS_NS, "label"); + + var controlitem; + if (labels[0]) { + controlitem = this.control. + appendItem(labels[0].nodeValue, aItem.value, aParentGroup); + } else { + controlitem = this.control. + appendItem(null, aItem.value, aParentGroup); + } + + var selected = false; + if (aItem.value in this._defaultHash) { + selected = true; + this.control.addItemToSelection(controlitem); + this._defaultHash[aItem.value].hits++; + } + + this._controlArray.push( + {control: aItem, option: controlitem, wasSelected: selected} + ); + + + + + + + + + + + + + + + 0) { + item = item.QueryInterface(Components.interfaces.nsIXFormsSelectChild); + + for (var j = 0; j < this._selectedElementArray.length; j++ ) { + var selectedItem = + item.selectItemByNode(this._selectedElementArray[j].element); + if (selectedItem) { + this.control.addItemToSelection(controlitem); + selected = true; + this._selectedElementArray[j].hits++; + // XXX It is possible that two identical elements are under the + // bound node. I guess we shouldn't mark one and not the other + // if there is an item in the select that matches it. So we'll + // go through the whole list. But this is quite an edge case + // and will cause more inefficiency just to prevent an errant + // xforms-out-of-range. + } + } + } + + if (!copyItem) { + if (item.value in this._defaultHash) { + this.control.addItemToSelection(controlitem); + selected = true; + this._defaultHash[item.value].hits++; + } + } + + this._controlArray.push( + {control: item, option: controlitem, wasSelected: selected} + ); + } + ]]> + + + + + + + + + + + + + + + + + + + ]]> @@ -582,7 +589,6 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - + ]]> @@ -832,228 +737,131 @@ var ev = document.createEvent("Events"); ev.initEvent(aName, true, false); - var elm = aElement; - // per http://www.w3.org/TR/2005/PER-xforms-20051006/index-all.html#evt-select // we send the event to the itemset if it is a parent. if (elm.parentNode.localName == "itemset") elm = elm.parentNode; - elm.dispatchEvent(ev); return true; + + new Array() + new Array() + null + null + + + + return document.getAnonymousElementByAttribute(this, "anonid", "control"); + + + + - - - - - - - - - - - - - - - - - + + + + + - + return this._parentControl; + ]]> + null - - - - - - - + + + if (!this._control) { + this._control = + document.getAnonymousElementByAttribute(this, "anonid", "control"); + } + return this._control; + + + null - var labelSpan = document.createElementNS("http://www.w3.org/1999/xhtml", - "span"); - - if (aUseLabelValue) { - labelSpan.textContent = aLabel; + + + + return this.getAttribute("readonly") == "true" ? true : false; + + + if (val) { + this.setAttribute("readonly", "true"); } else { - // label can contain other elements such as html, so we clone it - var label = aControl.getElementsByTagName("label")[0]; - var newLabel = label.cloneNode(true); - labelSpan.appendChild(newLabel); + this.removeAttribute("readonly"); } + + - var input = document.createElementNS("http://www.w3.org/1999/xhtml", - "input"); - input.setAttribute("type", "checkbox"); - input.setAttribute("value", aValue); - input.setAttribute("optionid", this._controlArraySize); - - div.appendChild(input); - div.appendChild(labelSpan); - - return div; - ]]> - - - - - - - + + + - - - - - - - - - - - - - - - - - - + + + - 0) { - var item = aItemElement.QueryInterface(Components.interfaces.nsIXFormsSelectChild); - for (var j = 0; j < this._selectedElementSize; j++ ) { - var selectedItem = - item.selectItemByNode(this._selectedElementArray[j].element); - if (selectedItem) { - this._selectedElementArray[j].hits++; - item.firstChild.checked = true; - - this._controlArray[this._controlArraySize - 1].wasSelected = true; - // XXX It is possible that two identical elements are under the - // bound node. I guess we shouldn't mark one and not the other - // if there is an item in the select that matches it. So we'll - // go through the whole list. But this is quite an edge case - // and will cause more inefficiency just to prevent an errant - // xforms-out-of-range. - } - } - } else if (!copyItem) { - // if this item contains a value element, then make sure to select - // this item if its value exists under the bound node. - this.preselectItem(itemValue); - } - - return itemValue; - ]]> + this.parentControl.dispatchDOMUIEvent(aType); + + + + + + + + + diff --git a/mozilla/extensions/xforms/resources/content/select1.xml b/mozilla/extensions/xforms/resources/content/select1.xml index 9c55cca22f6..625d84e1fc5 100644 --- a/mozilla/extensions/xforms/resources/content/select1.xml +++ b/mozilla/extensions/xforms/resources/content/select1.xml @@ -138,6 +138,21 @@ + + + + + + + - Alexander Surkov + - + - 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 ***** --> + + + %xformsDTD; +]> + + + + + + + + + + + + + + + + + + + + + + if (this.currentDayIndex != -1) + this._dayElements[this.currentDayIndex].focus(); + + + + + + + + + this.refreshInternal(aCurrentDay, aDaysRefreshOnly); + + + + + + + this.daysCount) + return -1; + return day; + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + if (this._currentDayIndex == aIndex) + return; + + var dayElm = null; + if (this._currentDayIndex != -1) { + dayElm = this._dayElements[this._currentDayIndex]; + dayElm.setAttribute("tabindex", "-1"); + } + + dayElm = this._dayElements[aIndex]; + dayElm.setAttribute("tabindex", "0"); + + this._currentDayIndex = aIndex; + + + + + + + + + + + + + + + + + + + + + + + + if (aNode.localName != "td" || aNode.namespaceURI != this.XHTML_NS) + return false; + return true; + + + + + + + new Array() + + + -1 + + + -1 + + + false + + + + + if (!this._dayContainer) + this._dayContainer = this.ownerDocument. + getAnonymousElementByAttribute(this, "anonid", "dayContainer"); + return this._dayContainer; + + + null + + + + + = 0) { + this.currentDayIndex--; + this.focus(); + } + ]]> + + + + + + = 0) { + this.currentDayIndex -= 7; + this.focus(); + } + ]]> + + + + + + + var target = event.originalTarget; + if (this.isDayControl(target)) + this.processAction(target.getAttribute("class"), target.textContent); + + + var target = event.originalTarget; + if (this.isDayControl(target)) + this.processAction(target.getAttribute("class"), target.textContent); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + this.refreshInternal(aCurrentDay, aDaysRefreshOnly); + var dateLabel = + new Date(this.year, this.month - 1).toLocaleFormat("%B %Y"); + this.dateLabel.textContent = dateLabel; + + + + + + + if (!this._dateLabel) { + this._dateLabel = this.ownerDocument. + getAnonymousElementByAttribute(this, "anonid", "date-label"); + } + return this._dateLabel; + + + null + + + + if (!this._backButton) { + this._backButton = this.ownerDocument. + getAnonymousElementByAttribute(this, "anonid", "back-button"); + } + return this._backButton; + + + null + + + + if (!this._fwdButton) { + this._fwdButton = this.ownerDocument. + getAnonymousElementByAttribute(this, "anonid", "fwd-button"); + } + return this._fwdButton; + + + null + + + + + + + + + switch (event.originalTarget) { + case this.backButton: + this.processAction("prevMonth", null, true); + break; + case this.fwdButton: + this.processAction("nextMonth", null, true); + break; + } + + + + diff --git a/mozilla/extensions/xforms/resources/content/widgets.xml b/mozilla/extensions/xforms/resources/content/widgets.xml new file mode 100644 index 00000000000..41a76f12463 --- /dev/null +++ b/mozilla/extensions/xforms/resources/content/widgets.xml @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + return this.hasAttribute("readonly"); + + + if (val) + this.setAttribute("readonly", "readonly"); + else + this.removeAttribute("readonly"); + + + + + + + + + + + + + + + + + + + + + + + + + if (this.focusedDay == -1) + return null; + return new Date(this.year, this.month - 1, this.currentDay); + + + + + + + + + + + + + + + + + + + + + return this._selectedDate; + + + // if passed date is empty or invalid then we use today date. + if (!val || String(val) == this.invalidDate) + val = new Date(); + + this._selectedDate = val; + if (!this.isSelectedDate()) + this.setDate(this.selectedYear, this.selectedMonth, this.selectedDay); + else + this.refresh(this.selectedDay, true); + + + + + + + + + + + + + + + + return new Date(this.year, this.month - 1, 1).getDay(); + + + + + + + + + + + + + + + + + + + + + + + + var event = this.ownerDocument.createEvent("Events"); + event.initEvent("change", true, false); + this.dispatchEvent(event); + + + + + + + + + + + + + + null + + + String(new Date(undefined)) + + + diff --git a/mozilla/extensions/xforms/resources/content/xforms-prefs-ui.xul b/mozilla/extensions/xforms/resources/content/xforms-prefs-ui.xul index 3da7e53a274..c1bffe59f8c 100644 --- a/mozilla/extensions/xforms/resources/content/xforms-prefs-ui.xul +++ b/mozilla/extensions/xforms/resources/content/xforms-prefs-ui.xul @@ -15,7 +15,7 @@ - The Original Code is Mozilla XForms Support. - - The Initial Developer of the Original Code is - - IBM Corportation. + - IBM Corporation. - Portions created by the Initial Developer are Copyright (C) 2005 - the Initial Developer. All Rights Reserved. - diff --git a/mozilla/extensions/xforms/resources/content/xforms-prefs.js b/mozilla/extensions/xforms/resources/content/xforms-prefs.js index ceaf84a2e9f..104032e51c5 100644 --- a/mozilla/extensions/xforms/resources/content/xforms-prefs.js +++ b/mozilla/extensions/xforms/resources/content/xforms-prefs.js @@ -14,7 +14,7 @@ * The Original Code is Mozilla XForms Support. * * The Initial Developer of the Original Code is - * IBM Corportation. + * IBM Corporation. * Portions created by the Initial Developer are Copyright (C) 2005 * the Initial Developer. All Rights Reserved. * diff --git a/mozilla/extensions/xforms/resources/content/xforms-prefs.xul b/mozilla/extensions/xforms/resources/content/xforms-prefs.xul index 27b0c243586..642cb2c8e53 100644 --- a/mozilla/extensions/xforms/resources/content/xforms-prefs.xul +++ b/mozilla/extensions/xforms/resources/content/xforms-prefs.xul @@ -15,7 +15,7 @@ - The Original Code is Mozilla XForms Support. - - The Initial Developer of the Original Code is - - IBM Corportation. + - IBM Corporation. - Portions created by the Initial Developer are Copyright (C) 2005 - the Initial Developer. All Rights Reserved. - diff --git a/mozilla/extensions/xforms/resources/content/xforms-xhtml.xml b/mozilla/extensions/xforms/resources/content/xforms-xhtml.xml new file mode 100644 index 00000000000..bc805824b8c --- /dev/null +++ b/mozilla/extensions/xforms/resources/content/xforms-xhtml.xml @@ -0,0 +1,441 @@ + + + + + + + + + %xformsDTD; +]> + + + + + + + + + + + + + + + + + return { + __proto__: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'), + + // XXX changing from setting textContent to setting nodeValue of + // first child (text node created by space character initializer + // above). Workaround for bug 322975. Probably should be changed + // back after repeat is xbl-ized + + set value(val) { + this.firstChild.nodeValue = val; + } + }; + + + + + + + + + + + + + + + + + + return this.ownerDocument. + getAnonymousElementByAttribute(this, "anonid", "control"); + + + + + + + + + + + + + + + + + return { + _implicitContent: this.ownerDocument. + getAnonymousElementByAttribute(this, "anonid", 'implicitcontent'), + _explicitContent: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'explicitcontent'), + __proto__: this, + + set value(val) { + if (val != null) { + this._implicitContent.textContent = val; + this._explicitContent.style.display = 'none'; + } else { + this._implicitContent.textContent = ''; + this._explicitContent.style.display = 'inline'; + } + }, + + get textValue() { + if (this._explicitContent.style.display == 'none') + return this._implicitContent.textContent; + return this.textContent; + }, + get nodeValue() { + var fragment = this.ownerDocument.createDocumentFragment(); + + var container = null; + if (this._explicitContent.style.display == 'none') + container = this._implicitContent; + else + container = this; + + for (var node = container.firstChild; node; node = node.nextSibling) { + fragment.appendChild(node.cloneNode(true)); + } + return fragment; + } + }; + + + + + + + + + + + + + + + + + + -1) { + // we create a range around the character we want and surround + // it with an + var range = this._ownerDocument.createRange(); + range.setStart(aTextNode, location); + range.setEnd(aTextNode, location + 1); + + var u = this._ownerDocument. + createElementNS("http://www.w3.org/1999/xhtml", "u"); + range.surroundContents(u); + } else { + // if we didn't find the accesskey, append it to the end + aTextNode.nodeValue += "(" + aAccesskey + ")"; + } + } + }; + ]]> + + + + + + + + + + + + + + + + + + return { + __proto__: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'), + + set disabled(val) { + if (val) { + this.setAttribute('disabled', 'disabled'); + } else { + this.removeAttribute('disabled'); + } + } + }; + + + + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMFocusIn"); + } + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMFocusOut"); + } + + + + + + + + + + + + + + + + + + return { + __proto__: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'), + + set disabled(val) { + this.isDisabled = val; + }, + isDisabled: false + }; + + + + + + + + if (!this.control.isDisabled) + this.dispatchDOMUIEvent("DOMActivate"); + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMFocusIn"); + } + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMFocusOut"); + } + + + + + + + + + + + + + &xforms.upload.browsetext; + + + &xforms.upload.cleartext; + + + + + + + + return { + set value(val) { + this._textControl.value = val; + }, + set readonly(val) { + if (val) { + this._browseButton.setAttribute('disabled', 'disabled'); + this._clearButton.setAttribute('disabled', 'disabled'); + } else { + this._browseButton.removeAttribute('disabled'); + this._clearButton.removeAttribute('disabled'); + } + }, + focus: function() { + this._browseButton.focus(); + }, + + _browseButton: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'browse_button'), + _clearButton: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'clear_button'), + _textControl: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'text_control'), + }; + + + + + + + switch (event.originalTarget.getAttribute("anonid")) { + case "browse_button": + this.uploadElement.pickFile(); + break; + case "clear_button": + this.uploadElement.clearFile(); + break; + } + + + + switch (event.originalTarget.getAttribute("anonid")) { + case "browse_button": + case "clear_button": + this.dispatchDOMUIEvent('DOMActivate'); + break; + } + + + + + + + + + + + + &xforms.upload.browsetext; + + + &xforms.upload.cleartext; + + + + + + + + return { + set value(val){}, + set readonly(val){}, + focus: function(){} + }; + + + + + diff --git a/mozilla/extensions/xforms/resources/content/xforms-xul.xml b/mozilla/extensions/xforms/resources/content/xforms-xul.xml new file mode 100644 index 00000000000..66563b9aef4 --- /dev/null +++ b/mozilla/extensions/xforms/resources/content/xforms-xul.xml @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + return { + __proto__: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'), + + set value(val) { + this.textContent = val; + } + }; + + + + + + + + + + + + + + + + + + + return { + _contentSwitcher: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'contentswitcher'), + _implicitContent: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'implicitcontent'), + __proto__: this, + + set value(val) { + if (val != null) { + this._implicitContent.textContent = val; + this._contentSwitcher.selectedIndex = 0; + } else { + this._implicitContent.textContent = ''; + this._contentSwitcher.selectedIndex = 1; + } + }, + + get textValue() { + if (this._contentSwitcher.selectedIndex == '0') + return this._implicitContent.textContent; + return this.textContent; + }, + get nodeValue() { + var fragment = this.ownerDocument.createDocumentFragment(); + + var container = null; + if (this._contentSwitcher.selectedIndex == '0') + container = this._implicitContent; + else + container = this; + + for (var node = container.firstChild; node; node = node.nextSibling) { + fragment.appendChild(node.cloneNode(true)); + } + var rep = new XMLSerializer().serializeToString(fragment); + return fragment; + } + }; + + + + + + + + + + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMFocusIn"); + } + + + + if (event.originalTarget == this.control) { + this.dispatchDOMUIEvent("DOMFocusOut"); + } + + + + + + + + + + + + + + + + + + return this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'); + + + + + + + // XXX: we need to fire 'DOMActivate' event to get xforms:submit to + // work, since xul:button do not do it (see a bug 323005 + // https://bugzilla.mozilla.org/show_bug.cgi?id=323005). + this.dispatchDOMUIEvent("DOMActivate"); + + + + + + + + + + + + + + + + + return { + __proto__: this.ownerDocument. + getAnonymousElementByAttribute(this, 'anonid', 'control'), + + set disabled(val) { + this.isDisabled = val; + }, + isDisabled: false + } + + + + + + + if (!this.control.isDisabled) + this.dispatchDOMUIEvent("DOMActivate"); + + + + + diff --git a/mozilla/extensions/xforms/resources/content/xforms.css b/mozilla/extensions/xforms/resources/content/xforms.css index 574be598b39..97cc84ad1bf 100755 --- a/mozilla/extensions/xforms/resources/content/xforms.css +++ b/mozilla/extensions/xforms/resources/content/xforms.css @@ -38,20 +38,43 @@ @namespace url(http://www.w3.org/2002/xforms); @namespace html url(http://www.w3.org/1999/xhtml); +@namespace xul url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul); @namespace mozType url(http://www.mozilla.org/projects/xforms/2005/type); -repeat, -repeatitem, -contextcontainer, -group, -switch, -case, -select1 item, -select1 itemset, -select1 choices { +html|*:root repeat, +html|*:root repeatitem, +html|*:root contextcontainer, +html|*:root group, +html|*:root switch, +html|*:root case, +html|*:root select1 item, +html|*:root select1 itemset, +html|*:root select1 choices { display: block; } +xul|*:root output, +xul|*:root label, +xul|*:root input, +xul|*:root secret, +xul|*:root textarea, +xul|*:root trigger, +xul|*:root submit, +xul|*:root repeat, +xul|*:root repeatitem, +xul|*:root contextcontainer, +xul|*:root group, +xul|*:root switch, +xul|*:root case { + display: -moz-box; +} + +xul|*:root select1 item, +xul|*:root select1 itemset, +xul|*:root select1 choices { + display: none; +} + contextcontainer-inline { display: inline; } @@ -72,28 +95,74 @@ message[level="ephemeral"], hint { position: absolute !important; } +action { + position: absolute; + z-index: 2147481647; + visibility: hidden; + top: 0px; + left: 0px; + width: 0px; + height: 0px; +} + alert { display: none; } -output { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-output'); +/* group */ +group { + -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-base'); } +/* output widgets */ +html|*:root output { + -moz-binding: url('chrome://xforms/content/xforms-xhtml.xml#xformswidget-output'); +} + +html|*:root output[mozType|type="http://www.w3.org/2001/XMLSchema#date"][appearance="full"] { + -moz-binding: url('chrome://xforms/content/xforms-xhtml.xml#xformswidget-output-date-full'); +} +html|*:root output[mozType|type="http://www.w3.org/2001/XMLSchema#date"][appearance="full"] + html|span[mozType|calendar] { + -moz-binding: url('chrome://xforms/content/widgets-xhtml.xml#calendar-full'); +} + +xul|*:root output { + -moz-binding: url('chrome://xforms/content/xforms-xul.xml#xformswidget-output'); +} + +/* range widgets */ range { -moz-binding: url('chrome://xforms/content/range.xml#xformswidget-range'); } -input { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-input'); +/* input widgets */ +html|*:root input { + -moz-binding: url('chrome://xforms/content/input-xhtml.xml#xformswidget-input'); } -input[mozType|type="http://www.w3.org/2001/XMLSchema#boolean"] { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-input-boolean'); +xul|*:root input { + -moz-binding: url('chrome://xforms/content/input-xul.xml#xformswidget-input'); +} + +html|*:root input[mozType|type="http://www.w3.org/2001/XMLSchema#boolean"] { + -moz-binding: url('chrome://xforms/content/input-xhtml.xml#xformswidget-input-boolean'); +} + +xul|*:root input[mozType|type="http://www.w3.org/2001/XMLSchema#boolean"] { + -moz-binding: url('chrome://xforms/content/input-xul.xml#xformswidget-input-boolean'); } input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-input-date'); + -moz-binding: url('chrome://xforms/content/input.xml#xformswidget-input-date'); +} + +input[mozType|type="http://www.w3.org/2001/XMLSchema#date"][appearance="full"] { + -moz-binding: url('chrome://xforms/content/input-xhtml.xml#xformswidget-input-date-full'); +} +input[mozType|type="http://www.w3.org/2001/XMLSchema#date"][appearance="full"] + html|span[mozType|calendar] { + -moz-binding: url('chrome://xforms/content/widgets-xhtml.xml#calendar-full'); } input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|input[anonid="dropmarker"] { @@ -104,40 +173,49 @@ input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|input[anonid="d background-repeat: no-repeat !important; } -input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|div[anonid="picker"] { +input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|div[anonid="picker"], +html|span[mozType|calendar] html|table { border: 1px outset black !important; background-color: -moz-Field; font: -moz-list; text-align: start; } -input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td { +input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td, +html|span[mozType|calendar] html|td { border: 1px solid transparent; text-align: center; } input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td.prevMonth, -input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td.nextMonth { +input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td.nextMonth, +html|span[mozType|calendar] html|td.prevMonth, +html|span[mozType|calendar] html|td.nextMonth { color: GrayText; } input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td.prevMonth:hover, -input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td.nextMonth:hover { +input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td.nextMonth:hover, +html|span[mozType|calendar] html|td.prevMonth:hover, +html|span[mozType|calendar] html|td.nextMonth:hover { background-color: grey; cursor: pointer; } -input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td.currentMonth { +input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td.currentMonth, +html|span[mozType|calendar] html|td.currentMonth { color: black; } -input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td.currentMonth:hover { +input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td.currentMonth:hover, +html|span[mozType|calendar] html|td.currentMonth:hover{ color: HighlightText; background-color: Highlight; cursor: pointer; } -input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|td[tabindex="0"] { +input[mozType|type="http://www.w3.org/2001/XMLSchema#date"] html|div[anonid="picker"] html|td[tabindex="0"], +html|span[mozType|calendar] html|td[selected] { border: 1px solid black; } @@ -155,72 +233,169 @@ html|input.-moz-date-fwd-button { background-position: center !important; } -input[mozType|type="http://www.w3.org/2001/XMLSchema#gMonth"] { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-input-month'); +html|*:root input[mozType|type="http://www.w3.org/2001/XMLSchema#gMonth"] { + -moz-binding: url('chrome://xforms/content/input-xhtml.xml#xformswidget-input-month'); } -input[mozType|type="http://www.w3.org/2001/XMLSchema#gDay"] { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-input-day'); +html|*:root input[mozType|type="http://www.w3.org/2001/XMLSchema#gDay"] { + -moz-binding: url('chrome://xforms/content/input-xhtml.xml#xformswidget-input-day'); } -input[mozType|type="http://www.w3.org/2001/XMLSchema#gYear"] { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-input-year'); +html|*:root input[mozType|type="http://www.w3.org/2001/XMLSchema#gYear"] { + -moz-binding: url('chrome://xforms/content/input-xhtml.xml#xformswidget-input-year'); } -secret { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-secret'); +/* secret widgets */ +html|*:root secret { + -moz-binding: url('chrome://xforms/content/input-xhtml.xml#xformswidget-secret'); } -textarea { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-textarea'); +xul|*:root secret { + -moz-binding: url('chrome://xforms/content/input-xul.xml#xformswidget-secret'); } -trigger, submit { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-trigger'); +/* textarea widgets */ +html|*:root textarea { + -moz-binding: url('chrome://xforms/content/input-xhtml.xml#xformswidget-textarea'); } -trigger[appearance="minimal"], submit[appearance="minimal"] { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-trigger-minimal'); +xul|*:root textarea { + -moz-binding: url('chrome://xforms/content/input-xul.xml#xformswidget-textarea'); +} + +/* trigger and submit widgets */ +html|*:root trigger, html|*:root submit { + -moz-binding: url('chrome://xforms/content/xforms-xhtml.xml#xformswidget-trigger'); +} + +xul|*:root trigger, xul|*:root submit { + -moz-binding: url('chrome://xforms/content/xforms-xul.xml#xformswidget-trigger'); +} + +html|*:root trigger[appearance="minimal"], html|*:root submit[appearance="minimal"] { + -moz-binding: url('chrome://xforms/content/xforms-xhtml.xml#xformswidget-trigger-minimal'); +} + +xul|*:root trigger[appearance="minimal"], xul|*:root submit[appearance="minimal"] { + -moz-binding: url('chrome://xforms/content/xforms-xul.xml#xformswidget-trigger-minimal'); } trigger[appearance="minimal"]:hover, submit[appearance="minimal"]:hover { cursor: pointer; } -label { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-label'); +/* Most of the trigger[appearance="minimal"] specific CSS is copied from toolbarbutton.css */ +xul|*:root trigger[appearance="minimal"] { + -moz-appearance: toolbarbutton; + -moz-box-align: center; + -moz-box-pack: center; + margin: 0; + border: 1px solid transparent; + padding: 3px; + background-color: transparent; + color: -moz-DialogText; + cursor: default; +} +xul|*:root trigger[appearance="minimal"]:focus { + -moz-appearance: toolbarbutton; + outline: 1px dotted -moz-DialogText; + -moz-outline-offset: -2px; +} +xul|*:root trigger[appearance="minimal"]:hover { + border-color: ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight; +} +xul|*:root trigger[appearance="minimal"]:hover:active { + border-color: ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow; + padding-top: 4px; + padding-bottom: 2px; + -moz-padding-start: 4px; + -moz-padding-end: 2px; +} +xul|*:root trigger[appearance="minimal"][disabled], +xul|*:root trigger[appearance="minimal"][disabled]:hover, +xul|*:root trigger[appearance="minimal"][disabled]:hover:active { + border-color: transparent; + padding: 3px; + color: GrayText !important; } -input > label, -secret > label, -textarea > label, -trigger > label, -submit > label, -select > label, -select1 > label, -upload > label { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-label-accesskey'); +/* label widgets */ +html|*:root input[accesskey] > label, +html|*:root secret[accesskey] > label, +html|*:root textarea[accesskey] > label, +html|*:root trigger[accesskey] > label, +html|*:root submit[accesskey] > label, +html|*:root select[accesskey] > label, +html|*:root select1[accesskey] > label, +html|*:root upload[accesskey] > label { + -moz-binding: url('chrome://xforms/content/xforms-xhtml.xml#xformswidget-label-accesskey'); } -select1 { - -moz-binding: url('chrome://xforms/content/select1.xml#xformswidget-select1'); +html|*:root label { + -moz-binding: url('chrome://xforms/content/xforms-xhtml.xml#xformswidget-label'); } -select1 itemset, -select itemset { +xul|*:root label { + -moz-binding: url('chrome://xforms/content/xforms-xul.xml#xformswidget-label'); +} +xul|*:root input label, xul|*:root secret label, xul|*:root textarea label, +xul|*:root select > label, xul|*:root select1 > label { + padding-top: 4px; +} + +/* case widgets */ +case { + -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-case'); +} + +case > html|div.-moz-xforms-case-container { + display: inherit; +} + +/* select, select1 widgets */ + + /* itemset widget */ +select1 itemset, select itemset { -moz-binding: url('chrome://xforms/content/select1.xml#xformswidget-itemset'); } -/* Most of the select1 specific CSS is copied from forms.css */ - -select1 item { + /* select1 appearance='minimal' (default) */ +html|*:root select1 { + -moz-binding: url('chrome://xforms/content/select1.xml#xformswidget-select1'); +} +html|*:root select1 item { -moz-binding: url('chrome://xforms/content/select1.xml#xformswidget-select1-item'); white-space : nowrap; } +xul|*:root select1 { + -moz-binding: url('chrome://xforms/content/select-xul.xml#xformswidget-select-minimal'); +} +xul|*:root select1 xul|box { + -moz-binding: url('chrome://xforms/content/select-xul.xml#controlwidget-select1-minimal'); +} -html|input.-moz-xforms-date-dropdown, -html|input.-moz-xforms-select1-dropdown { + /* select1 appearance='compact' */ +xul|*:root select1[appearance="compact"] { + -moz-binding: url('chrome://xforms/content/select-xul.xml#xformswidget-select-compact'); +} +xul|*:root select1[appearance="compact"] xul|box{ + -moz-binding: url('chrome://xforms/content/select-xul.xml#controlwidget-select1-compact'); +} + + /* select1 appearance='full' */ +xul|*:root select1[appearance="full"] { + -moz-binding: url('chrome://xforms/content/select-xul.xml#xformswidget-select-full'); +} +xul|*:root select1[appearance="full"] xul|box { + -moz-binding: url('chrome://xforms/content/select-xul.xml#controlwidget-select1-full'); +} + +/* select1[appearance='minimal'] for xhtml styles (most of the select1 specific +CSS is copied from forms.css) */ + +html|*:root html|input.-moz-xforms-date-dropdown, +html|*:root html|input.-moz-xforms-select1-dropdown { width: 12px; height: 1.3em; white-space: nowrap; @@ -237,15 +412,15 @@ html|input.-moz-xforms-select1-dropdown { margin-top: -1px !important; } -html|input.-moz-xforms-select1-dropdown::-moz-focus-inner { +html|*:root html|input.-moz-xforms-select1-dropdown::-moz-focus-inner { border: 0 !important; } -html|input.-moz-xforms-select1-dropdown:active:hover { +html|*:root html|input.-moz-xforms-select1-dropdown:active:hover { border-style: outset; } -html|input.-moz-xforms-select1-input { +html|*:root html|input.-moz-xforms-select1-input { border: 1px dotted transparent; margin-right: 0px; padding: 0px; @@ -255,12 +430,12 @@ html|input.-moz-xforms-select1-input { line-height: normal !important; } -html|input.-moz-xforms-select1-input:focus { +html|*:root html|input.-moz-xforms-select1-input:focus { border: 1px dotted black; } -html|span.-moz-date-container, -html|span.-moz-select1-container { +html|*:root html|span.-moz-date-container, +html|*:root html|span.-moz-select1-container { margin: 0px; margin-bottom: 1px; border-color: ThreeDFace; @@ -282,7 +457,7 @@ html|span.-moz-select1-container { padding-top: 1px; } -html|div.-moz-xforms-select1-popup { +html|*:root html|div.-moz-xforms-select1-popup { border-width: 1px; top: 0px; left: 0px; @@ -299,12 +474,12 @@ html|div.-moz-xforms-select1-popup { cursor: default; } -item[_moz_active] { +html|*:root item[_moz_active] { color: HighlightText; background: Highlight; } -choices > label { +html|*:root select1[appearance='minimal'] choices > label { display: block; font: -moz-list; line-height: normal !important; @@ -315,53 +490,74 @@ choices > label { text-indent: 0; } -choices > item, choices > itemset, choices > choices{ +html|*:root select1[appearance='minimal'] choices > item, +html|*:root select1[appearance='minimal'] choices > itemset, +html|*:root select1[appearance='minimal'] choices > choices { padding-left: 20px; font-style: normal; font-weight: normal; } -case { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-case'); + /* select appearance="compact" (default) */ +html|*:root select { + -moz-binding: url('chrome://xforms/content/select-xhtml.xml#xformswidget-select-compact'); +} +html|*:root select html|span[anonid="control"] { + -moz-binding: url('chrome://xforms/content/select-xhtml.xml#controlwidget-select-compact'); } -case > html|div.-moz-xforms-case-container { - display: inherit; +xul|*:root select { + -moz-binding: url('chrome://xforms/content/select-xul.xml#xformswidget-select-compact'); +} +xul|*:root select xul|box[anonid="control"] { + -moz-binding: url('chrome://xforms/content/select-xul.xml#controlwidget-select-compact'); } -/* select */ -select { - -moz-binding: url('chrome://xforms/content/select.xml#xformswidget-select'); + /* select appearance="full" */ +html|*:root select[appearance="full"] { + -moz-binding: url('chrome://xforms/content/select-xhtml.xml#xformswidget-select-full'); +} +html|*:root select[appearance="full"] html|span[anonid="control"] { + -moz-binding: url('chrome://xforms/content/select-xhtml.xml#controlwidget-select-full'); } -select[appearance="full"] { - -moz-binding: url('chrome://xforms/content/select.xml#xformswidget-select-full'); +xul|*:root select[appearance="full"] { + -moz-binding: url('chrome://xforms/content/select-xul.xml#xformswidget-select-full'); +} +xul|*:root select[appearance="full"] xul|box { + -moz-binding: url('chrome://xforms/content/select-xul.xml#controlwidget-select-full'); } -select html|div.select-choice-label { + /* select, select1 styles*/ +select *|*.select-choice-label, select1 *|*.select-choice-label { font: -moz-list; font-style: italic; font-weight: bold; } -select html|div.select-choice-content { +select *|*.select-choice-content, select1 *|*.select-choice-content { padding-left: 10px; } -upload { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-upload-disabled'); +xul|*:root select1[appearance="full"] xul|box xul|radiogroup:focus xul|radio[selected] + label, +xul|*:root select[appearance="full"] xul|box xul|checkbox:focus + label { + outline: 1px dotted invert; } -upload[mozType|type="http://www.w3.org/2001/XMLSchema#anyURI"] { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-upload'); +xul|*:root select, xul|*:root select1 { + display: -moz-box; + margin: 2px 4px; } -upload[mozType|type="http://www.w3.org/2001/XMLSchema#base64Binary"] { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-upload'); +/* upload widgets */ +html|*:root upload { + -moz-binding: url('chrome://xforms/content/xforms-xhtml.xml#xformswidget-upload-disabled'); } -upload[mozType|type="http://www.w3.org/2001/XMLSchema#hexBinary"] { - -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-upload'); +html|*:root upload[mozType|type="http://www.w3.org/2001/XMLSchema#anyURI"], +html|*:root upload[mozType|type="http://www.w3.org/2001/XMLSchema#base64Binary"], +html|*:root upload[mozType|type="http://www.w3.org/2001/XMLSchema#hexBinary"] { + -moz-binding: url('chrome://xforms/content/xforms-xhtml.xml#xformswidget-upload'); } /* default MIP styling */ diff --git a/mozilla/extensions/xforms/resources/content/xforms.xml b/mozilla/extensions/xforms/resources/content/xforms.xml index 0f6a3b1eb6f..1afab952f92 100644 --- a/mozilla/extensions/xforms/resources/content/xforms.xml +++ b/mozilla/extensions/xforms/resources/content/xforms.xml @@ -38,71 +38,40 @@ - - ***** END LICENSE BLOCK ***** --> + + + %xformsDTD; ]> + xmlns="http://www.mozilla.org/xbl" + xmlns:html="http://www.w3.org/1999/xhtml" + xmlns:xbl="http://www.mozilla.org/xbl" + xmlns:xforms="http://www.w3.org/2002/xforms" + xmlns:lazy="http://www.mozilla.org/projects/xforms/2005/lazy"> + + + - + - - this.delegate.widgetAttached(); - - - - this._delegate = null; - this._accessors = null; - - - - - return "http://www.w3.org/2002/xforms"; - - - - null - - - - if (!this._delegate) - this._delegate = this.QueryInterface(Components.interfaces.nsIXFormsDelegate); - return this._delegate; - - - - null - - - - - - - - - - var value = this.accessors.getValue(); - return value != null ? value : ""; - - + return true; @@ -122,6 +91,30 @@ + + + + return "http://www.w3.org/2002/xforms"; + + + + + + + + + + + + var value = this.accessors.getValue(); + return value != null ? value : ""; + + + @@ -147,1033 +140,129 @@ return true; - - - - - - - - - - - - - - - - // XXX changing from setting textContent to setting nodeValue of - // first child (text node created by space character initializer - // above). Workaround for bug 322975. Probably should be changed - // back after repeat is xbl-ized - document.getAnonymousElementByAttribute(this, "anonid", "content").firstChild.nodeValue = - this.stringValue; - - return true; - - - - - - - - - - - - - - - - - var anoncontent = - document.getAnonymousElementByAttribute(this, "anonid", "anoncontent"); - - if (this.accessors.hasBoundNode() || this.accessors.getValue() != null) { - anoncontent.setAttribute("style", "display:none;"); - } else { - anoncontent.removeAttribute("style"); - } - - document.getAnonymousElementByAttribute(this, "anonid", "content").textContent = - this.stringValue; - return true; - - - - - - - - - - - - - - - - - content in XBL1, so we switch to - // always cloning the content into the content span. - var content = - document.getAnonymousElementByAttribute(this, "anonid", "content"); - - var hasElementChildren = false; - var hasBoundValue = false; - - if (this.accessors.hasBoundNode() || this.accessors.getValue() != null) { - content.textContent = this.stringValue; - hasBoundValue = true; - } else { - // clone the contents child by child - var node; - for (var i = 0; i < this.childNodes.length; i++) { - if (!hasElementChildren && this.childNodes[i].nodeType == Node.ELEMENT_NODE) - hasElementChildren = true; - - content.appendChild(this.childNodes[i].cloneNode(true)); - } - } - - // XXX: if label has element node children, we skip accesskey underlining - if (!hasElementChildren && this.parentNode.hasAttribute("accesskey")) { - var accesskey = this.parentNode.getAttribute("accesskey"); - - // bail if no accesskey or accesskey is longer than 1 character - if (!accesskey || accesskey.length != 1) - return true; - - var str = content.textContent; - var location = str.indexOf(accesskey); - - if (location > -1) { - // we create a range around the character we want and surround it - // with an - var range = document.createRange(); - range.setStart(content.firstChild, location) - range.setEnd(content.firstChild, location+1) - - var u = document.createElementNS("http://www.w3.org/1999/xhtml", "u"); - range.surroundContents(u); - } else { - // if we didn't find the accesskey, append it to the end - content.textContent += "(" + accesskey + ")"; - } - } - - return true; - ]]> - - - - - - - - - - - - - - - null - - + - if (!this._inputField) { - this._inputField = - document.getAnonymousElementByAttribute(this, "anonid", "control"); - } - return this._inputField; + if (!this._control) + this._control = this.getControlElement(); + return this._control; - + + - if (this.getAttribute("incremental") == "true") { - this.accessors.setValue(this.inputField.value); - } - return true; + throw Error("getControlElement() method isn't implemented."); - - - this.inputField.value = this.stringValue; - if (this.accessors.isReadonly()) { - this.inputField.setAttribute("readonly", "readonly"); - } else { - this.inputField.removeAttribute("readonly"); - } - return true; - - - - - - this.inputField.focus(); - return true; - - - - - - - - - - - this.inputField.setAttribute("type","checkbox"); - var value = this.stringValue; - if (value == "true" || value == "1") { - this.inputField.setAttribute("checked", "checked"); - } else { - this.inputField.removeAttribute("checked"); - } - - this.inputField.value = value; - if (this.accessors.isReadonly()) { - this.inputField.setAttribute("readonly", "readonly"); - } else { - this.inputField.removeAttribute("readonly"); - } - - - this.inputField.removeAttribute("onkeypress"); - - return true; - - - - - - if (this.getAttribute("incremental") != "false") { - if (this.inputField.checked) { - this.accessors.setValue("true"); - } else { - this.accessors.setValue("false"); - } - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - return true; - - - - null - - - if (!this._picker) { - this._picker = - document.getAnonymousElementByAttribute(this, "anonid", "picker"); - } - return this._picker; - - - - null - - - - if (!this._dateField) { - this._dateField = - document.getAnonymousElementByAttribute(this, "anonid", "date"); - } - return this._dateField; - - - - false - false - null - null - - -1 - - - - - - - - - - - window.innerWidth) { - // we use window.innerWidth because XHTML documents are not always - // 100% width, and innerWidth will always give use the browser size. - position = window.innerWidth - width; - } - - picker.style.left = position + "px"; - - this._refreshCells(this._date, this._date.getDate()); - ]]> - - - - - - - - - - - - - - - - - - - - - - - = (firstDay + totaldays)) { - // either previous or next month - if (i < firstDay) { - // previous month - var prevyear = prevDate.getFullYear(); - var prevmonth = prevDate.getMonth(); - - var maxprev = this._getDaysInMonth(prevmonth, prevyear); - this._cells[i].node.textContent = maxprev - firstDay + i + 1; - - this._cells[i].node.className = "prevMonth" - showsPrevDays++; - } else { - // next month - this._cells[i].node.textContent = i - (firstDay + totaldays) + 1; - this._cells[i].node.className = "nextMonth" - } - } else { - // current month - // this._cells add one since the first day is 1, not 0! - this._cells[i].node.textContent = i - firstDay + 1; - this._cells[i].node.className = "currentMonth"; - } - - this._cells[i].node.setAttribute("tabindex", "-1"); - } - - // first time - if (this._currentCellIndex == -1) { - // select the current day - this._currentCellIndex = aDate.getDate() + showsPrevDays - 1; - } else { - // if the day is larger that the total days in this month - if (aDayToSelect > totaldays) - aDayToSelect = totaldays; - - this._currentCellIndex = aDayToSelect + showsPrevDays - 1; - } - - this._cells[this._currentCellIndex].node.setAttribute("tabindex", "0"); - - if (!aSkipFocus) - this._cells[this._currentCellIndex].node.focus(); - - // update the month year heading - this.dateField.textContent = this._date.toLocaleFormat("%B %Y"); - ]]> - - - - - - - - var month, year = aYear; - - if (aMonth == 0) { - month = 11 - year--; - } else { - month = aMonth - 1; - } - - return new Date(year, month); - - - - - - - - var month, year = aYear; - - if (aMonth == 11) { - month = 0 - year++; - } else { - month = aMonth + 1; - } - - return new Date(year, month); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - = 0) { - this.selectCell(index - 7); - } else { - // focus the back button - document.getAnonymousElementByAttribute(this, "anonid", "back-button").focus(); - } - } else if (event.keyCode == event.DOM_VK_LEFT) { - // ctrl-left goes back a month - if (event.ctrlKey) { - this.goBack(); - } else if (currentElement.localName == "input") { - // input means we are on one of the back/fwd buttons - document.getAnonymousElementByAttribute(this, "anonid", "back-button").focus(); - } else if ((index - 1) >= 0) { - this.selectCell(index - 1); - } - } else if (event.keyCode == event.DOM_VK_RIGHT) { - // ctrl-right goes forward a month - if (event.ctrlKey) { - this.goForward(); - } else if (currentElement.localName == "input") { - // input means we are on one of the back/fwd buttons - document.getAnonymousElementByAttribute(this, "anonid", "fwd-button").focus(); - } else if ((index + 1) < this._cells.length) { - this.selectCell(index + 1); - } - } else if (event.keyCode == event.DOM_VK_RETURN && - event.originalTarget.localName == "td") { - var type = event.originalTarget.className; - if (type == "currentMonth") { - this.selectCell(event.originalTarget.getAttribute("num")); - this._valueSet(); - } else if (type == "prevMonth") { - this.goBack(); - } else if (type == "nextMonth") { - this.goForward(); - } - } else if (event.keyCode == event.DOM_VK_ESCAPE) { - this._hidePicker(true); - } - } else { - // pressing down if the picker is hidden will show it - if (event.keyCode == event.DOM_VK_DOWN) - // first set the accessor value, since the input's value hasn't - // been validated yet, and forcing this will. - this.accessors.setValue(this.inputField.value); - - this._showPicker(); - } - } - ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + this.delegate.widgetAttached(); - - - + this._delegate = null; + this._accessors = null; + this._control = null; + - if (this.accessors.isValid()) - this.select.value = this.stringValue.substr(2,2) - else - this.select.value = ""; - - return true; - ]]> - - - - - - - - - - - - if (this.getAttribute("incremental") == "true") { - this._setValue(); - } - - - - - - if (this.select.value != "") - this.accessors.setValue("--" + this.select.value); - else - this.accessors.setValue(""); - - - - null - + - if (!this._select) { - this._select = - document.getAnonymousElementByAttribute(this, "anonid", "control"); + if (!this._delegate) { + this._delegate = + this.QueryInterface(Components.interfaces.nsIXFormsDelegate); } - return this._select; + return this._delegate; + + null + null + null + - - + The output widget assumes successors bindings implement getElementControl() + method what returns the object: + { + set value(); // set "string" value + } + --> + + + + + this.control.value = this.stringValue; + return true; + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - if (this.getAttribute("incremental") == "true") { - this._setValue(); - } - - - - - - if (this.select.value != "") - this.accessors.setValue("---" + this.select.value); - else - this.accessors.setValue(""); - - - - null - - - if (!this._select) { - this._select = - document.getAnonymousElementByAttribute(this, "anonid", "control"); - } - return this._select; - - - - - - - - - - - this.inputField.setAttribute("type","password"); - this.inputField.value = this.stringValue; - this.inputField.readonly = this.accessors.isReadonly(); + this.control.value = this.accessors.getValue(); return true; + + + + - - + The trigger widget assumes successors bindings implement getElementControl() + method what returns the object: + { + set disabled(); // set disabled state + focus(); // set focus + } + --> + - - - - - - - - null - - - - if (!this._controlField) { - this._controlField = - document.getAnonymousElementByAttribute(this, "anonid", "control"); - } - return this._controlField; - - - - - - if (this.accessors.isReadonly()) { - this.controlField.setAttribute("readonly", "readonly"); - } else { - this.controlField.removeAttribute("readonly"); - } - // If the value has not changed, no need to update the - // value of the control, because that makes the textarea widget - // to scroll up. - if (this.controlField.value != this.stringValue) { - this.controlField.value = this.stringValue; - } - return true; - - - - - - if (this.getAttribute("incremental") == "true") { - this.accessors.setValue(this.controlField.value); - } - return true; - - - - - - this.controlField.focus(); - return true; - - - - - - - - - - - - - var control = - document.getAnonymousElementByAttribute(this, "anonid", "thebutton"); - if (aDisable) { - control.setAttribute("disabled", "disabled"); - } else { - control.removeAttribute("disabled"); - } + this.control.disabled = aDisable; - document.getAnonymousElementByAttribute(this, "anonid", "thebutton").focus(); + this.control.focus(); return true; @@ -1181,36 +270,13 @@ - - - - - - - - - false + - - - - this._disabled = aDisable; - - - - - - document.getAnonymousElementByAttribute(this, "anonid", "thespan").focus(); - return true; - - - - @@ -1222,15 +288,16 @@ - this.QueryInterface(Components.interfaces.nsIXFormsCaseElement).widgetAttached(); + this.QueryInterface(Components.interfaces.nsIXFormsCaseElement). + widgetAttached(); null if (!this._container) { - this._container = - document.getAnonymousElementByAttribute(this, "anonid", "container"); + this._container = document. + getAnonymousElementByAttribute(this, "anonid", "container"); } return this._container; @@ -1248,114 +315,53 @@ return true; + - - - - - - &xforms.upload.browsetext; - &xforms.upload.cleartext; - - + + + - - this._uploadElem = null; - this._textControl = null; - this._browseButton = null; - this._clearButton = null; - + + + this.control.readonly = this.accessors.isReadonly(); + + - null + + + this.control.focus(); + return true; + + - + - if (!this._uploadElem) { - this._uploadElem = + if (!this._uploadElement) { + this._uploadElement = this.QueryInterface(Components.interfaces.nsIXFormsUploadElement); } - return this._uploadElem; - - - - null - - - - if (!this._textControl) { - this._textControl = - document.getAnonymousElementByAttribute(this, "anonid", - "upload_text_control"); - } - return this._textControl; - - - - null - - - - if (!this._browseButton) { - this._browseButton = - document.getAnonymousElementByAttribute(this, "anonid", - "upload_browse_button"); - } - return this._browseButton; - - - - null - - - - if (!this._clearButton) { - this._clearButton = - document.getAnonymousElementByAttribute(this, "anonid", - "upload_clear_button"); - } - return this._clearButton; + return this._uploadElement; + null - this.textControl.value = aString; + this.control.value = aString; - - - - - - - &xforms.upload.browsetext; - &xforms.upload.cleartext; - - - - diff --git a/mozilla/extensions/xforms/resources/locale/en-US/xforms.dtd b/mozilla/extensions/xforms/resources/locale/en-US/xforms.dtd index 39bed4dceec..91e4a60595e 100644 --- a/mozilla/extensions/xforms/resources/locale/en-US/xforms.dtd +++ b/mozilla/extensions/xforms/resources/locale/en-US/xforms.dtd @@ -14,7 +14,7 @@ - The Original Code is Mozilla XForms Support. - - The Initial Developer of the Original Code is - - IBM Corportation. + - IBM Corporation. - Portions created by the Initial Developer are Copyright (C) 2005 - the Initial Developer. All Rights Reserved. - @@ -48,3 +48,5 @@ + + diff --git a/mozilla/extensions/xforms/resources/locale/en-US/xforms.properties b/mozilla/extensions/xforms/resources/locale/en-US/xforms.properties index 2c85a0ebb58..88c4f23300a 100644 --- a/mozilla/extensions/xforms/resources/locale/en-US/xforms.properties +++ b/mozilla/extensions/xforms/resources/locale/en-US/xforms.properties @@ -50,29 +50,33 @@ exprEvaluateError = XForms Error (11): Error evaluating XPath expression: %S noModelError = XForms Error (12): Could not find model for element instanceParseError = XForms Error (13): Could not parse new instance data submitSendOrigin = XForms Error (14): Security check failed! Trying to submit data to a different domain than document -instanceLoadOrigin = XForms Error (15): Security check failed! Trying to load instance data from a different domain than document -controlBindError = XForms Error (16): Could not bind control to instance data -labelLinkLoadOrigin = XForms Error (17): Security check failed! Trying to load label data from a different domain than document -labelLink1Error = XForms Error (18): External file (%S) for Label element not found -labelLink2Error = XForms Error (19): Failed to load Label element from external file: %S -invalidSeparator = XForms Error (20): Submission separator may only be either "&" or ";", but found "%S". -instanceBindError = XForms Error (21): Submission failed trying to replace instance document '%S'. Instance document doesn't exist in same model as submission element. -instanceInstanceLoad = XForms Error (22): Instance document trying to load external instance: %S -rangeSetSliderNaN = XForms Error (23): NaN passed to setSlider() -rangeNullObjects = XForms Error (24): One or more of the passed objects were null -rangeNullInit = XForms Error (25): One or more init() parameters is NaN -rangeBeginEndError = XForms Error (26): Begin is higher than end? -encodingMemoryError = XForms Error (27): Not enough available memory to encode file %S, size = %S. -uploadBoundTypeError = XForms Error (28): Upload element not bound to valid datatype. Must be bound to datatype 'xsd:anyURI', 'xsd:base64Binary', or 'xsd:hexBinary'. -copyError = XForms Error (29): A copy element was found whose parent is not an itemset element -submitMailtoInit = XForms Error (30): No mailto: handler found -submitMailtoFailed = XForms Error (31): Failed to load a mail client for a mailto: submission -invalidQName = XForms Error (32): Failed to create node. %S is not a valid QName. +controlBindError = XForms Error (15): Could not bind control to instance data +invalidSeparator = XForms Error (16): Submission separator may only be either "&" or ";", but found "%S". +instanceBindError = XForms Error (17): Submission failed trying to replace instance document '%S'. Instance document doesn't exist in same model as submission element. +instanceInstanceLoad = XForms Error (18): Instance document not allowed to load external instance: %S +rangeSetSliderNaN = XForms Error (19): NaN passed to setSlider() +rangeNullObjects = XForms Error (20): One or more of the passed objects were null +rangeNullInit = XForms Error (21): One or more init() parameters is NaN +rangeBeginEndError = XForms Error (22): Begin is higher than end? +encodingMemoryError = XForms Error (23): Not enough available memory to encode file %S, size = %S. +uploadBoundTypeError = XForms Error (24): Upload element not bound to valid datatype. Must be bound to datatype 'xsd:anyURI', 'xsd:base64Binary', or 'xsd:hexBinary'. +copyError = XForms Error (25): A copy element was found whose parent is not an itemset element +submitMailtoInit = XForms Error (26): No mailto: handler found +submitMailtoFailed = XForms Error (27): Failed to load a mail client for a mailto: submission +invalidQName = XForms Error (28): Failed to create node. %S is not a valid QName. +innerBindRefError = XForms Error (29): You are refering to an inner bind, which is undefined in XForms 1.0 +externalLink1Error = XForms Error (30): External file (%S) for %S element not found +externalLink2Error = XForms Error (31): Failed to load %S element from external file: %S +externalLinkLoadOrigin = XForms Error (32): Security check failed! Trying to load %S data from a different domain than document +instanceNotFound = XForms Error (33): Could not find instance with id == '%S' +defInstanceNotFound = XForms Error (34): Could not find default instance +MDGLoopError = XForms Error (35): There are loops in the bindings of the model! +noSchemaForInstance = XForms Error (36): Could not find a schema for validating the instance document (namespace=%S) # Warning Messages: -warnMailtoBodyParam = XForms Warning (1): The submission action uri already contains a body parameter. +warnMailtoBodyParam = XForms Warning (2): The submission action uri already contains a body parameter. +instDocumentInvalid = XForms Warning (3): Instance document did not validate. # XForms Permission Messages: xformsXDPermissionDialogTitle = Allowed Sites - XForms Cross Domain Access xformsXDPermissionDialogIntro = You can specify which web sites containing XForms may submit data to other domains. Type the exact address of the site you want to allow and then press Allow. - diff --git a/mozilla/extensions/xforms/resources/skin/contents.rdf b/mozilla/extensions/xforms/resources/skin/contents.rdf new file mode 100644 index 00000000000..6c645566c2a --- /dev/null +++ b/mozilla/extensions/xforms/resources/skin/contents.rdf @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + +