NS_IMETHODIMP nsXFormsControlStub::ResetBoundNode(const nsString &aBindAttribute, PRUint16 aResultType, PRBool *aContextChanged) { NS_ENSURE_ARG(aContextChanged); // Clear existing bound node, etc. *aContextChanged = mBoundNode ? PR_TRUE : PR_FALSE; nsCOMPtr<nsIDOMNode> oldBoundNode; oldBoundNode.swap(mBoundNode); mUsesModelBinding = PR_FALSE; mAppearDisabled = PR_FALSE; mDependencies.Clear(); RemoveIndexListeners(); if (!mHasParent || !mHasDoc || !HasBindingAttribute()) return NS_OK_XFORMS_NOTREADY; nsCOMPtr<nsIDOMXPathResult> result; nsresult rv = ProcessNodeBinding(aBindAttribute, aResultType, getter_AddRefs(result)); if (NS_FAILED(rv)) { nsXFormsUtils::ReportError(NS_LITERAL_STRING("controlBindError"), mElement); return rv; } if (rv == NS_OK_XFORMS_DEFERRED || rv == NS_OK_XFORMS_NOTREADY || !result) { // Binding was deferred, or not bound return rv; } // 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)); } *aContextChanged = (oldBoundNode != mBoundNode); // Some controls may not be bound to certain types of content. If the content // is a disallowed type, report the error and dispatch a binding exception // event. PRBool isAllowed = IsContentAllowed(); if (!mBoundNode || !isAllowed) { // If there's no result (ie, no instance node) returned by the above, it // means that the binding is not pointing to an instance data node, so we // should disable the control. mAppearDisabled = PR_TRUE; if (!isAllowed) { // build the error string that we want output to the ErrorConsole nsAutoString localName; mElement->GetLocalName(localName); const PRUnichar *strings[] = { localName.get() }; nsXFormsUtils::ReportError( NS_LITERAL_STRING("boundTypeErrorComplexContent"), strings, 1, mElement, mElement); nsXFormsUtils::DispatchEvent(mElement, eEvent_BindingException); } nsCOMPtr<nsIXTFElementWrapper> wrapper(do_QueryInterface(mElement)); NS_ENSURE_STATE(wrapper); PRInt32 iState; GetDisabledIntrinsicState(&iState); return wrapper->SetIntrinsicState(iState); } // Check for presence of @xsi:type on bound node and add as a dependency nsCOMPtr<nsIDOMElement> boundEl(do_QueryInterface(mBoundNode)); if (boundEl) { nsCOMPtr<nsIDOMAttr> attrNode; rv = boundEl->GetAttributeNodeNS(NS_LITERAL_STRING(NS_NAMESPACE_XML_SCHEMA_INSTANCE), NS_LITERAL_STRING("type"), getter_AddRefs(attrNode)); if (NS_SUCCEEDED(rv) && attrNode) { mDependencies.AppendObject(attrNode); } } return NS_OK; }
NS_IMETHODIMP nsXFormsRepeatElement::Refresh() { #ifdef DEBUG_XF_REPEAT printf("nsXFormsRepeatElement::Refresh()\n"); #endif if (mAddingChildren || mIsParent) return NS_OK; nsPostRefresh postRefresh = nsPostRefresh(); PRUint32 oldIndex = mCurrentIndex; /// @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 /// non-homogeneous node-sets is undefined." /// @see http://www.w3.org/TR/xforms/slice9.html#ui-repeat /// /// Can/should we check this somehow? (XXX) // Get the nodeset we are bound to nsresult rv; nsCOMPtr<nsIDOMXPathResult> result; rv = ProcessNodeBinding(NS_LITERAL_STRING("nodeset"), nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, getter_AddRefs(result)); NS_ENSURE_SUCCESS(rv, rv); // Unroll the repeat rows rv = UnrollRows(result); NS_ENSURE_SUCCESS(rv, rv); // Maintain the index if (mCurrentIndex || !mMaxIndex) { // Somebody might have been fooling around with our children since last // refresh (either using delete or through script). Or we might have an // empty nodeset. So fix the index value. SanitizeIndex(&mCurrentIndex); } else if (mMaxIndex) { // repeat-index has not been initialized, set it. if (!mParent) { GetStartingIndex(&mCurrentIndex); // Inform listeners of initial index value IndexHasChanged(); } else if (mLevel > 1) { // Set repeat-index for inner repeats. If parent <contextcontainer/> // element is selected then mCurrentIndex is setted on starting index. nsCOMPtr<nsIDOMNode> temp = mElement; nsCOMPtr<nsIDOMNode> parent; nsCOMPtr<nsIXFormsRepeatItemElement> context; while (!context) { rv = temp->GetParentNode(getter_AddRefs(parent)); NS_ENSURE_SUCCESS(rv, rv); if (!parent) break; context = do_QueryInterface(parent); temp.swap(parent); } if (context) { PRBool hasIndex = PR_FALSE; context->GetIndexState(&hasIndex); if (hasIndex) { PRUint32 index = 0; GetStartingIndex(&index); SetIndex(&index, PR_FALSE); } } return NS_OK; } } // If we have the repeat-index, set it. if (mCurrentIndex) { SetChildIndex(mCurrentIndex, PR_TRUE, PR_TRUE); } if (mCurrentIndex != oldIndex) { mParent ? mParent->IndexHasChanged() : IndexHasChanged(); } return NS_OK; }
NS_IMETHODIMP nsXFormsItemSetElement::Refresh() { // We need to create item elements for each element referenced by the // nodeset. Each of these items will create an anonymous HTML option element // which will return from GetAnonymousNodes. We then clone our template // content and insert the cloned content as children of the HTML option. if (!nsXFormsUtils::IsDocumentReadyForBind(mElement)) { // not ready to bind yet, defer nsXFormsModelElement::DeferElementBind(this); return NS_OK; } nsCOMPtr<nsIModelElementPrivate> model; nsCOMPtr<nsIDOMXPathResult> result; nsresult rv = ProcessNodeBinding(NS_LITERAL_STRING("nodeset"), nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, getter_AddRefs(result), getter_AddRefs(model)); if (NS_FAILED(rv) | !result | !model) return rv; nsCOMPtr<nsIDOMNode> node, templateNode, cloneNode, tmpNode; nsCOMPtr<nsIDOMElement> itemNode, itemWrapperNode, contextContainer; nsCOMPtr<nsIDOMNodeList> templateNodes; mElement->GetChildNodes(getter_AddRefs(templateNodes)); PRUint32 templateNodeCount = 0; if (templateNodes) templateNodes->GetLength(&templateNodeCount); nsCOMPtr<nsIContent> content(do_QueryInterface(mElement)); NS_ENSURE_STATE(content); nsCOMPtr<nsIDocument> doc = content->GetCurrentDoc(); nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc)); NS_ENSURE_STATE(domDoc); PRUint32 nodeCount; result->GetSnapshotLength(&nodeCount); nsCOMPtr<nsIDOMNode> parent, tmp; mElement->GetParentNode(getter_AddRefs(parent)); while (parent) { if (nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("select1")) || nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("select"))) { break; } tmp.swap(parent); tmp->GetParentNode(getter_AddRefs(parent)); } nsCOMPtr<nsIXFormsItemSetUIElement> uiItemSet(do_QueryInterface(mElement)); nsCOMPtr<nsIDOMElement> anonContent; if (uiItemSet) { uiItemSet->GetAnonymousItemSetContent(getter_AddRefs(anonContent)); } NS_ENSURE_STATE(anonContent); nsCOMPtr<nsIDOMNode> childNode, nodeReturn; while (NS_SUCCEEDED(anonContent->GetFirstChild(getter_AddRefs(childNode))) && childNode) { anonContent->RemoveChild(childNode, getter_AddRefs(nodeReturn)); } for (PRUint32 i = 0; i < nodeCount; ++i) { result->SnapshotItem(i, getter_AddRefs(node)); NS_ASSERTION(node, "incorrect snapshot length"); rv = domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS), NS_LITERAL_STRING("item"), getter_AddRefs(itemNode)); NS_ENSURE_SUCCESS(rv, rv); anonContent->AppendChild(itemNode, getter_AddRefs(tmpNode)); nsCOMPtr<nsIXFormsContextControl> ctx(do_QueryInterface(itemNode)); if (ctx) { ctx->SetContext(node, i + 1, nodeCount); } // Clone the template content under the item for (PRUint32 j = 0; j < templateNodeCount; ++j) { templateNodes->Item(j, getter_AddRefs(templateNode)); templateNode->CloneNode(PR_TRUE, getter_AddRefs(cloneNode)); itemNode->AppendChild(cloneNode, getter_AddRefs(templateNode)); } } // refresh parent so that it has a chance to reflect the changes we just made if (parent) { nsCOMPtr<nsIXFormsControlBase> control = do_QueryInterface(parent); if (control) { control->Refresh(); } } return NS_OK; }