This commit was manufactured by cvs2svn to create branch
'MOZILLA_1_8_0_BRANCH'. git-svn-id: svn://10.0.0.236/branches/MOZILLA_1_8_0_BRANCH@224162 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
142
mozilla/extensions/xforms/nsXFormsContextContainer.h
Normal file
142
mozilla/extensions/xforms/nsXFormsContextContainer.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Aaron Reed (aaronr@us.ibm.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsXFormsContextControl_h_
|
||||
#define nsXFormsContextControl_h_
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
#include "nsIXTFElementWrapper.h"
|
||||
#include "nsIXFormsRepeatItemElement.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOM3Node.h"
|
||||
#include "nsXFormsControlStub.h"
|
||||
|
||||
class nsXFormsContextContainer;
|
||||
|
||||
class nsXFormsFocusListener : public nsIDOMEventListener {
|
||||
public:
|
||||
nsXFormsFocusListener(nsXFormsContextContainer* aContainer)
|
||||
: mContainer(aContainer) {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
void Detach()
|
||||
{
|
||||
mContainer = nsnull;
|
||||
}
|
||||
protected:
|
||||
nsXFormsContextContainer* mContainer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of \<contextcontainer\>.
|
||||
*
|
||||
* \<contextcontainer\> is a pseudo-element that is wrapped around each row in
|
||||
* an "unrolled" \<repeat\>. @see nsXFormsRepeatElement
|
||||
*
|
||||
* @todo Support ::repeat-item and ::repeat-index pseudo-elements. (XXX)
|
||||
* @see http://www.w3.org/TR/xforms/sliceF.html#id2645142
|
||||
* @see http://bugzilla.mozilla.org/show_bug.cgi?id=271724
|
||||
*/
|
||||
class nsXFormsContextContainer : public nsXFormsControlStub,
|
||||
public nsIXFormsRepeatItemElement
|
||||
{
|
||||
protected:
|
||||
/** The handler for the focus event */
|
||||
nsRefPtr<nsXFormsFocusListener> mFocusListener;
|
||||
|
||||
/** The context position for the element */
|
||||
PRInt32 mContextPosition;
|
||||
|
||||
/** The context size for the element */
|
||||
PRInt32 mContextSize;
|
||||
|
||||
/** Does this element have the repeat-index? */
|
||||
PRPackedBool mHasIndex;
|
||||
|
||||
/** Has context changed since last bind? */
|
||||
PRPackedBool mContextIsDirty;
|
||||
|
||||
public:
|
||||
nsXFormsContextContainer()
|
||||
: mContextPosition(1), mContextSize(1), mHasIndex(PR_FALSE),
|
||||
mContextIsDirty(PR_FALSE) {}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIXTFElement overrides
|
||||
NS_IMETHOD CloneState(nsIDOMElement *aElement);
|
||||
NS_IMETHOD DocumentChanged(nsIDOMDocument *aNewDocument);
|
||||
|
||||
// nsIXFormsControl
|
||||
NS_IMETHOD Bind(PRBool *aContextChanged);
|
||||
NS_IMETHOD SetContext(nsIDOMNode *aContextNode,
|
||||
PRInt32 aContextPosition,
|
||||
PRInt32 aContextSize);
|
||||
NS_IMETHOD GetContext(nsAString &aModelID,
|
||||
nsIDOMNode **aContextNode,
|
||||
PRInt32 *aContextPosition,
|
||||
PRInt32 *aContextSize);
|
||||
NS_IMETHOD IsEventTarget(PRBool *aOK);
|
||||
|
||||
// nsIXFormsRepeatItemElement
|
||||
NS_DECL_NSIXFORMSREPEATITEMELEMENT
|
||||
|
||||
nsresult HandleFocus(nsIDOMEvent *aEvent);
|
||||
|
||||
// Overriding to make sure only appropriate values can be set.
|
||||
void SetRepeatState(nsRepeatState aState);
|
||||
|
||||
#ifdef DEBUG_smaug
|
||||
virtual const char* Name() {
|
||||
if (mElement) {
|
||||
nsAutoString localName;
|
||||
mElement->GetLocalName(localName);
|
||||
return NS_ConvertUTF16toUTF8(localName).get();
|
||||
}
|
||||
return "contextcontainer(inline?)";
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Factory methods */
|
||||
NS_HIDDEN_(nsresult)
|
||||
NS_NewXFormsContextContainer(nsIXTFElement **aResult);
|
||||
#endif
|
||||
966
mozilla/extensions/xforms/resources/content/selects.xml
Normal file
966
mozilla/extensions/xforms/resources/content/selects.xml
Normal file
@@ -0,0 +1,966 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- ***** 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
|
||||
- Mozilla Foundation.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2006
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
||||
-
|
||||
- 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 ***** -->
|
||||
|
||||
<bindings id="xformsSelectsBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<!--
|
||||
This file implements the "abstract" UI classes for XForms select/select1
|
||||
controls. Bindings defined here are base bindings that are used for two
|
||||
approaches of select/select1 elements implementations:
|
||||
1. Every item or choices element is visible and represented. An example is
|
||||
the controls for XHTML in "selects-xhtml.xml" file
|
||||
2. Using of native widget that represents select/select1 elements. An example
|
||||
is the controls for XHTML in "selectsnw-xhtml.xml" file.
|
||||
-->
|
||||
|
||||
<!-- BASE for select/select1 elements. -->
|
||||
<binding id="selectcontrols-base"
|
||||
extends="chrome://xforms/content/xforms.xml#xformswidget-base">
|
||||
|
||||
<implementation implements="nsIAccessibleProvider">
|
||||
|
||||
<!-- nsIXFormsUIWidget -->
|
||||
<method name="refresh">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var boundNode = this.accessors.getBoundNode();
|
||||
if (!boundNode)
|
||||
return null;
|
||||
|
||||
// Make sure that 'getNodesArray' method is called before
|
||||
// 'getValuesArray' method because nodes array returned by
|
||||
// 'getNodesArray' is used by 'getValuesArray' method.
|
||||
this.nodes = this.getNodesArray(boundNode);
|
||||
this.values = this.getValuesArray(boundNode);
|
||||
|
||||
this.traverseItems(this, this.selectItemElements);
|
||||
if (this.freeEntryAllowed)
|
||||
this.selectFreeEntryItemElements();
|
||||
|
||||
var outOfRange = this.isOutOfRange(this.values) ||
|
||||
this.isOutOfRange(this.nodes);
|
||||
if (this.outOfRange == null || this.outOfRange != outOfRange) {
|
||||
this.accessors.setInRange(!outOfRange);
|
||||
this.outOfRange = outOfRange;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="focus">
|
||||
<body>
|
||||
function focusItem(aItem) {
|
||||
var disabled = this.isItemMarkedDisabled(aItem);
|
||||
if (!disabled)
|
||||
this.focusItem(aItem);
|
||||
return disabled;
|
||||
}
|
||||
this.traverseItems(this, focusItem);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- public -->
|
||||
<property name="incremental">
|
||||
<getter>
|
||||
return this.getAttribute("incremental") != "false";
|
||||
</getter>
|
||||
<setter>
|
||||
if (!val)
|
||||
this.setAttribute("incremental", "false");
|
||||
else
|
||||
this.removeAttribute("incremental");
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<property name="selection">
|
||||
<getter>
|
||||
return this.getAttribute("selection");
|
||||
</getter>
|
||||
<setter>
|
||||
this.setAttribute("selection", val);
|
||||
this.freeEntryAllowed = this.allowFreeEntry(val == "open");
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<!-- private -->
|
||||
<!-- Run through xforms:item elements and select them if needed. If
|
||||
xforms:item element contains xforms:value element value of which is
|
||||
matched with item of given values array or if it contains xforms:copy
|
||||
element value of which is matched with item of given nodes array then
|
||||
that xforms:item element will be selected.
|
||||
The method is used in conjunction with traverseItems method.
|
||||
|
||||
@param aItem - current traversed item element
|
||||
-->
|
||||
<method name="selectItemElements">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this.markItemDisabled(aItem, this.accessors.isReadonly());
|
||||
|
||||
if (aItem.isCopyItem) {
|
||||
if (!this.nodes || !aItem.copyNode) {
|
||||
// aNodes is empty only if select controls is bound to non element
|
||||
// node. We just disable item element since it's value can't be
|
||||
// saved in bound node.
|
||||
this.markItemDisabled(aItem, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
var length = this.nodes.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (aItem.copyNodeEquals(this.nodes[i].node)) {
|
||||
this.markItemSelected(aItem, true);
|
||||
this.nodes[i].isUsed = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var length = this.values.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (this.values[i].value == aItem.value) {
|
||||
this.markItemSelected(aItem, true);
|
||||
this.values[i].isUsed = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isItemMarkedSelected(aItem))
|
||||
this.markItemSelected(aItem, false);
|
||||
|
||||
return true;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Return array of values each of them item elemnent should be selected
|
||||
for. -->
|
||||
<method name="getValuesArray">
|
||||
<parameter name="aNode"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var nsIDOMNode = Components.interfaces.nsIDOMNode;
|
||||
var whiteSpaceExpr = /\n|\t|\r/g;
|
||||
|
||||
var array = [];
|
||||
if (aNode.nodeType != nsIDOMNode.ELEMENT_NODE) {
|
||||
if (/\S/.test(aNode.nodeValue)) {
|
||||
var values = this.getValuesArrayFor(aNode.nodeValue,
|
||||
whiteSpaceExpr);
|
||||
|
||||
for (var i = 0; i < values.length; i++)
|
||||
array.push({value: values[i], isUsed: false});
|
||||
} else {
|
||||
array.push({value: "", isUsed: false});
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
if (!aNode.hasChildNodes()) {
|
||||
array.push({value: "", isUsed: false});
|
||||
return array;
|
||||
}
|
||||
|
||||
for (var child = aNode.firstChild; child; child = child.nextSibling) {
|
||||
if ((child.nodeType == nsIDOMNode.TEXT_NODE ||
|
||||
child.nodeType == nsIDOMNode.CDATA_SECTION_NODE) &&
|
||||
child.nodeValue) {
|
||||
if (/\S/.test(child.nodeValue)) {
|
||||
var values = this.getValuesArrayFor(child.nodeValue,
|
||||
whiteSpaceExpr)
|
||||
|
||||
for (var i = 0; i < values.length; i++)
|
||||
array.push({value: values[i], isUsed: false});
|
||||
} else if (!array.length && !this.nodes) {
|
||||
array.push({value: "", isUsed: false});
|
||||
}
|
||||
}
|
||||
}
|
||||
return array;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Exctact values from given string and return array of values. Should
|
||||
be implemented by successor bindings. -->
|
||||
<method name="getValuesArrayFor">
|
||||
<parameter name="aString"/>
|
||||
<parameter name="aWhiteSpaceExpr"/>
|
||||
<body>
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Return array of copy nodes each of them item element should be
|
||||
selected for. If bound node is not element node then return null. -->
|
||||
<method name="getNodesArray">
|
||||
<parameter name="aNode"/>
|
||||
<body>
|
||||
var nsIDOMNode = Components.interfaces.nsIDOMNode;
|
||||
if (aNode.nodeType != nsIDOMNode.ELEMENT_NODE)
|
||||
return;
|
||||
|
||||
var array = [];
|
||||
for (var child = aNode.firstChild; child; child = child.nextSibling) {
|
||||
if (child.nodeType == nsIDOMNode.ELEMENT_NODE)
|
||||
array.push({node: child, isUsed: false});
|
||||
}
|
||||
|
||||
return array;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Return true if instance data can't be presented by select element.
|
||||
Should be implemented by successors bindings. -->
|
||||
<method name="isOutOfRange">
|
||||
<body>
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Update instance node. This method is called when selection of select
|
||||
element is changed.
|
||||
|
||||
@param aIncremental - specifies if instance node should be updated
|
||||
incrementally.
|
||||
-->
|
||||
<method name="updateInstanceData">
|
||||
<parameter name="aIncremental"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (aIncremental != this.incremental)
|
||||
return;
|
||||
|
||||
var node = this.accessors.getBoundNode();
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
node = node.cloneNode(false);
|
||||
node.textContent = "";
|
||||
|
||||
var forceRebuild = {value: false};
|
||||
this.traverseItems(this, this.buildInstanceData, node, forceRebuild);
|
||||
if (this.freeEntryAllowed)
|
||||
this.appendValueForInstanceNode(node, this.getFreeEntryValues());
|
||||
|
||||
var nsIDOMNode = Components.interfaces.nsIDOMNode;
|
||||
|
||||
if (node.nodeType != nsIDOMNode.ELEMENT_NODE || !forceRebuild.value) {
|
||||
if (node.firstChild &&
|
||||
(node.firstChild.nodeType == nsIDOMNode.TEXT_NODE ||
|
||||
node.firstChild.nodeType == nsIDOMNode.CDATA_SECTION_NODE))
|
||||
this.accessors.setValue(node.firstChild.nodeValue);
|
||||
else
|
||||
this.accessors.setValue("");
|
||||
} else {
|
||||
this.accessors.setContent(node, true);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Run through item elements and build content of instance node for
|
||||
selected item elements.
|
||||
|
||||
@param aItem - currently traversed item element
|
||||
@param aInstanceNode - new generated instance node
|
||||
@param aForceRebuild - object, its 'value' property should have value
|
||||
'true' if copy item element was been selected or
|
||||
deselected.
|
||||
-->
|
||||
<method name="buildInstanceData">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aInstanceNode"/>
|
||||
<parameter name="aForceRebuild"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
const nsIDOMNode = Components.interfaces.nsIDOMNode;
|
||||
|
||||
if (aItem.isCopyItem) {
|
||||
var wasSelected = false;
|
||||
if (this.nodes) {
|
||||
var length = this.nodes.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (aItem.copyNodeEquals(this.nodes[i].node)) {
|
||||
wasSelected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wasSelected != this.isItemMarkedSelected(aItem))
|
||||
aForceRebuild.value = true;
|
||||
|
||||
if (this.isItemMarkedSelected(aItem)) {
|
||||
if (aInstanceNode.nodeType != nsIDOMNode.ELEMENT_NODE) {
|
||||
// Per specs we should fire 'xforms-binding-exception' event if
|
||||
// bound node is not element and copy item is selected.
|
||||
this.dispatchXFormsNotificationEvent("xforms-binding-exception",
|
||||
this);
|
||||
|
||||
// We should probably un-select the item so that the list
|
||||
// of selected data is accurate. This WON'T cause a
|
||||
// xforms-select/deselect to fire. Since the user just selected
|
||||
// this item and we are automatically deselecting it from
|
||||
// underneath the user, we'll treat it like nothing happened.
|
||||
this.markItemSelected(aItem, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
var importedNode =
|
||||
aInstanceNode.ownerDocument.importNode(aItem.copyNode, true);
|
||||
aInstanceNode.appendChild(importedNode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.isItemMarkedSelected(aItem))
|
||||
return true;
|
||||
|
||||
if (aInstanceNode.nodeType != nsIDOMNode.ELEMENT_NODE) {
|
||||
if (aInstanceNode.textContent)
|
||||
aInstanceNode.textContent += " ";
|
||||
aInstanceNode.textContent += aItem.value;
|
||||
return true;
|
||||
}
|
||||
|
||||
this.appendValueForInstanceNode(aInstanceNode, aItem.value);
|
||||
return true;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Append the given value for the instance node
|
||||
@param aInstanceNode - the given instance node
|
||||
@param aValue - appended value.
|
||||
-->
|
||||
<method name="appendValueForInstanceNode">
|
||||
<parameter name="aInstanceNode"/>
|
||||
<parameter name="aValue"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
const nsIDOMNode = Components.interfaces.nsIDOMNode;
|
||||
|
||||
var fchild = aInstanceNode.firstChild;
|
||||
if (fchild && (fchild.nodeType == nsIDOMNode.TEXT_NODE ||
|
||||
fchild.nodeType == nsIDOMNode.CDATA_SECTION_NODE)) {
|
||||
if (fchild.nodeValue)
|
||||
fchild.nodeValue += " ";
|
||||
fchild.nodeValue += aValue;
|
||||
} else {
|
||||
var textnode =
|
||||
aInstanceNode.ownerDocument.createTextNode(aValue);
|
||||
if (fchild)
|
||||
aInstanceNode.insertBefore(textnode, fchild);
|
||||
else
|
||||
aInstanceNode.appendChild(textnode);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Run through select child elements and invokes given function for
|
||||
every item element until given function retunrs false.
|
||||
|
||||
@param aContextNode - current select child node
|
||||
@param aFunc - the function that is invoked if current node is item
|
||||
element, if function returns true then traversing is
|
||||
stopped
|
||||
@param aFuncArg1 - 1st argument that is passed to function
|
||||
@param aFuncArg2 - 2nd argument that is passed to function
|
||||
@param aUpDirection - specifies direction of items navigation
|
||||
-->
|
||||
<method name="traverseItems">
|
||||
<parameter name="aContextNode"/>
|
||||
<parameter name="aFunc"/>
|
||||
<parameter name="aFuncArg1"/>
|
||||
<parameter name="aFuncArg2"/>
|
||||
<parameter name="aUpDirection"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (aContextNode.namespaceURI != this.XFORMS_NS)
|
||||
return true;
|
||||
|
||||
var container;
|
||||
switch (aContextNode.localName) {
|
||||
case "select":
|
||||
case "select1":
|
||||
case "choices":
|
||||
container = aContextNode;
|
||||
break;
|
||||
case "itemset":
|
||||
container = aContextNode.anonymousItemSetContent;
|
||||
break;
|
||||
case "item":
|
||||
var item = aContextNode.
|
||||
QueryInterface(Components.interfaces.nsIXFormsItemElement);
|
||||
if (!aFunc.call(this, item, aFuncArg1, aFuncArg2))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (container) {
|
||||
var child =
|
||||
aUpDirection ? container.lastChild : container.firstChild;
|
||||
while (child) {
|
||||
var res = this.traverseItems(child, aFunc, aFuncArg1, aFuncArg2,
|
||||
aUpDirection);
|
||||
if (!res)
|
||||
return false;
|
||||
child = aUpDirection ? child.previousSibling : child.nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Cycally traverse item elements for specified direction and invokes
|
||||
given function for every item element.
|
||||
|
||||
@param aItemNode - start item element
|
||||
@param aUpDirection - if true then then item elements are traversed in
|
||||
up direction
|
||||
@param aFunc, aFuncArg1, aFuncArg2 - invoked function and its arguments
|
||||
@param aCurrNode - current traversed node, used internally
|
||||
-->
|
||||
<method name="cycleTraverseItems">
|
||||
<parameter name="aItemNode"/>
|
||||
<parameter name="aUpDirection"/>
|
||||
<parameter name="aFunc"/>
|
||||
<parameter name="aFuncArg1"/>
|
||||
<parameter name="aFuncArg2"/>
|
||||
<parameter name="aCurrNode"/>
|
||||
<body>
|
||||
if (aCurrNode == aItemNode)
|
||||
return false;
|
||||
|
||||
if (!aCurrNode) {
|
||||
if (aItemNode.namespaceURI != this.XFORMS_NS ||
|
||||
aItemNode.localName != "item")
|
||||
return false;
|
||||
aCurrNode = aItemNode;
|
||||
}
|
||||
|
||||
var next = aUpDirection ? aCurrNode.previousSibling :
|
||||
aCurrNode.nextSibling;
|
||||
if (next) {
|
||||
var res = this.traverseItems(next, aFunc, aFuncArg1, aFuncArg2,
|
||||
aUpDirection);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
return this.cycleTraverseItems(aItemNode, aUpDirection, aFunc,
|
||||
aFuncArg1, aFuncArg2, next);
|
||||
}
|
||||
|
||||
var parent = aCurrNode;
|
||||
while (parent = parent.parentNode) {
|
||||
if (parent.namespaceURI == this.XFORMS_NS) {
|
||||
switch (parent.localName) {
|
||||
case "choices":
|
||||
case "itemset":
|
||||
next = parent;
|
||||
break;
|
||||
case "select":
|
||||
case "select1":
|
||||
next = aUpDirection ? parent.lastChild : parent.firstChild;
|
||||
break;
|
||||
}
|
||||
if (next)
|
||||
return this.cycleTraverseItems(aItemNode, aUpDirection, aFunc,
|
||||
aFuncArg1, aFuncArg2, next);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Return values of free entry. The method implementation is a stub and
|
||||
it should be removed when all native controls will support
|
||||
@selection="open".
|
||||
|
||||
@note - should be overriden by implementation binding
|
||||
-->
|
||||
<method name="getFreeEntryValues">
|
||||
<body>
|
||||
return "";
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Allow free entry. The method implementation is a stub and it should
|
||||
be removed when all native controls will support @selection="open".
|
||||
|
||||
@return - true if free entries has been allowed
|
||||
@note - should be overriden by implementation binding
|
||||
-->
|
||||
<method name="allowFreeEntry">
|
||||
<parameter name="aAllowed"/>
|
||||
<body>
|
||||
return false;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Append and select free entry item. The implementations of this method
|
||||
for xf:select should consider the scenario where several items may have
|
||||
been selected by the user in addition to the user typing several values
|
||||
directly into the editable field. In that case, these additional values
|
||||
should be appended to the control's value and the items that represent
|
||||
these additional values should be selected. In the case of
|
||||
implementations for xf:select1, we'll assume that the widget that
|
||||
represents the select1 will deselect the currently selected item if a
|
||||
user types in the editable field. So the free entry value, if present,
|
||||
is the only value that the control can have.
|
||||
|
||||
The method implementation is a stub and it should be removed when all
|
||||
native controls will support @selection="open".
|
||||
|
||||
@param aValue - the value of free entry item
|
||||
@note - should be overriden by implementation binding
|
||||
-->
|
||||
<method name="appendFreeEntryItem">
|
||||
<parameter name="aValue"/>
|
||||
<body>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Select/Unselect item element.
|
||||
|
||||
@param aItem - the given item element
|
||||
@param aIsSelected - if true then item should be selected, otherwise
|
||||
unselected
|
||||
-->
|
||||
<method name="markItemSelected">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aIsSelected"/>
|
||||
<body>
|
||||
if (aItem)
|
||||
aItem.selected = aIsSelected;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Return true if item is selected
|
||||
|
||||
@param aItem - the given item.
|
||||
-->
|
||||
<method name="isItemMarkedSelected">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return aItem ? aItem.selected : false;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Disable/enable the given item element
|
||||
|
||||
@param aItem - the given item
|
||||
@param aIsDisabled - if true then item should be disabled, otherwise
|
||||
enabled
|
||||
-->
|
||||
<method name="markItemDisabled">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aIsDisabled"/>
|
||||
<body>
|
||||
if (aItem)
|
||||
aItem.disabled = aIsDisabled;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Return true if the given item element disabled
|
||||
|
||||
@param aItem - the given item
|
||||
-->
|
||||
<method name="isItemMarkedDisabled">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return aItem ? aItem.disabled : false;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="focusItem">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
if (aItem)
|
||||
aItem.focus();
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<constructor>
|
||||
this.freeEntryAllowed = this.allowFreeEntry(this.selection == "open");
|
||||
</constructor>
|
||||
|
||||
<!-- Storage for previous value of 'in-range' state of select element -->
|
||||
<field name="outOfRange">null</field>
|
||||
|
||||
<!-- Specifies whether free entry is allowed by certain implementation of
|
||||
select/select1 element. -->
|
||||
<field name="freeEntryAllowed">false</field>
|
||||
|
||||
<!-- Arrays of selected values and nodes that combine to build the content
|
||||
of the bound instance node. -->
|
||||
<field name="values">null</field>
|
||||
<field name="nodes">null</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- SELECT: BASE
|
||||
Note, keep synchronized with 'selectsnw.xml#select-base' binding
|
||||
-->
|
||||
<binding id="select-base"
|
||||
extends="#selectcontrols-base">
|
||||
|
||||
<implementation implements="nsIXFormsNSSelectElement">
|
||||
|
||||
<!-- nsIXFormsNSSelectElement -->
|
||||
<property name="selectedItems" readonly="true">
|
||||
<getter>
|
||||
function _isSelected(aItem, aItemList) {
|
||||
if (this.isItemMarkedSelected(aItem))
|
||||
aItemList.push(aItem);
|
||||
return true;
|
||||
}
|
||||
var list = [];
|
||||
this.traverseItems(this, _isSelected, list);
|
||||
return list;
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<method name="addItemToSelection">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
this.markItemSelected(aItem, true);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="removeItemFromSelection">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
this.markItemSelected(aItem, false);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="clearSelection">
|
||||
<body>
|
||||
function _clearSelection(aItem) {
|
||||
this.markItemSelected(aItem, false);
|
||||
return true;
|
||||
}
|
||||
this.traverseItems(this, _clearSelection);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="selectAll">
|
||||
<body>
|
||||
function _selectAll(aItem) {
|
||||
this.markItemSelected(aItem, true);
|
||||
return true;
|
||||
}
|
||||
this.traverseItems(this, _selectAll);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemSelected">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return this.isItemMarkedSelected(aItem);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Private implementation -->
|
||||
<method name="getValuesArrayFor">
|
||||
<parameter name="aString"/>
|
||||
<parameter name="aWhiteSpaceExpr"/>
|
||||
<body>
|
||||
// A limitation of the XML Schema list datatypes is that white space
|
||||
// characters in the storage values (the value element) are always
|
||||
// interpreted as separators between individual data values.
|
||||
// Therefore, authors should avoid using white space characters within
|
||||
// storage values with list simpleContent.
|
||||
|
||||
// Replace new line (\n), tabs (\t) and carriage returns (\r) with
|
||||
// space (" ").
|
||||
var value = aString.replace(aWhiteSpaceExpr, " ");
|
||||
return value.split(/\s/);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="updateInstanceNodeByItem">
|
||||
<parameter name="aIncremental"/>
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (aIncremental) {
|
||||
// Fire 'select'/'deselect' only if user changed the select value.
|
||||
|
||||
// per errata for XForms 1.0 second edition, we send the event to
|
||||
// the item even if it is contained inside an itemset
|
||||
|
||||
var eventName = this.isItemMarkedSelected(aItem) ?
|
||||
"xforms-select" : "xforms-deselect";
|
||||
this.dispatchXFormsNotificationEvent(eventName, aItem);
|
||||
}
|
||||
|
||||
this.updateInstanceData(aIncremental);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="selectFreeEntryItemElements">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var length = this.values.length;
|
||||
for (var i = 0; i < length; ++i) {
|
||||
if (!this.values[i].isUsed) {
|
||||
this.appendFreeEntryItem(this.values[i].value);
|
||||
this.values[i].isUsed = true;
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isOutOfRange">
|
||||
<parameter name="aHitArray"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!aHitArray)
|
||||
return false;
|
||||
|
||||
var i = 0;
|
||||
for (; i < aHitArray.length && aHitArray[i].isUsed; ++i);
|
||||
return i != aHitArray.length;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- SELECT1: BASE
|
||||
Note, keep synchronized with 'selects.xml#select1-base' binding.
|
||||
-->
|
||||
<binding id="select1-base"
|
||||
extends="#selectcontrols-base">
|
||||
|
||||
<implementation implements="nsIXFormsNSSelect1Element">
|
||||
<!-- nsIXFormsNSSelect1Element -->
|
||||
<property name="selectedItem">
|
||||
<getter>
|
||||
function getSelectedItem(aItem, aSelectedItem) {
|
||||
if (this.isItemMarkedSelected(aItem))
|
||||
aSelectedItem.value = aItem;
|
||||
return !this.isItemMarkedSelected(aItem);
|
||||
}
|
||||
var selectedItem = {value: null};
|
||||
this.traverseItems(this, getSelectedItem, selectedItem);
|
||||
return selectedItem.value;
|
||||
</getter>
|
||||
<setter>
|
||||
function setSelectedItem(aItem, aSelectedItem) {
|
||||
this.markItemSelected(aItem, aItem == aSelectedItem);
|
||||
return true;
|
||||
}
|
||||
this.traverseItems(this, setSelectedItem, val);
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<!-- Private implementation -->
|
||||
<method name="getValuesArrayFor">
|
||||
<parameter name="aString"/>
|
||||
<parameter name="aWhiteSpaceExpr"/>
|
||||
<body>
|
||||
return [aString];
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="updateInstanceNodeByItem">
|
||||
<parameter name="aIncremental"/>
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (aIncremental) {
|
||||
// Fire 'select'/'deselect' only if user changed the select1 value.
|
||||
|
||||
// per errata for XForms 1.0 second edition, we send the event
|
||||
// to the item even if it is contained by an itemset
|
||||
|
||||
function _unselectItems(aItem, aNewSelectedItem, aTarget) {
|
||||
if (aItem != aNewSelectedItem) {
|
||||
if (this.isItemMarkedSelected(aItem)) {
|
||||
this.markItemSelected(aItem, false);
|
||||
this.dispatchXFormsNotificationEvent("xforms-deselect",
|
||||
aTarget);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
this.traverseItems(this, _unselectItems, aItem, aItem);
|
||||
|
||||
var eventName = this.isItemMarkedSelected(aItem) ?
|
||||
"xforms-select" : "xforms-deselect";
|
||||
this.dispatchXFormsNotificationEvent(eventName, aItem);
|
||||
}
|
||||
|
||||
this.updateInstanceData(aIncremental);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="selectFreeEntryItemElements">
|
||||
<body>
|
||||
if (this.values.length != 1)
|
||||
return;
|
||||
|
||||
if (!this.values[0].isUsed) {
|
||||
this.appendFreeEntryItem(this.values[0].value);
|
||||
this.values[0].isUsed = true;
|
||||
}
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isOutOfRange">
|
||||
<parameter name="aHitArray"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return aHitArray && (aHitArray.length > 1 || aHitArray.length == 1 &&
|
||||
!aHitArray[0].isUsed);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- ITEMSET -->
|
||||
<binding id="itemset"
|
||||
extends="chrome://xforms/content/xforms.xml#xformswidget-base">
|
||||
<content>
|
||||
<html:div style="display:none;">
|
||||
<children/>
|
||||
</html:div>
|
||||
<html:div anonid="insertion"/>
|
||||
</content>
|
||||
|
||||
<implementation implements="nsIXFormsItemSetUIElement">
|
||||
<field name="_anonymousItemSetContent">null</field>
|
||||
|
||||
<property name="anonymousItemSetContent" readonly="true">
|
||||
<getter>
|
||||
if (!this._anonymousItemSetContent) {
|
||||
this._anonymousItemSetContent =
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "insertion");
|
||||
}
|
||||
return this._anonymousItemSetContent;
|
||||
</getter>
|
||||
</property>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- ITEM -->
|
||||
<binding id="select-item-base"
|
||||
extends="chrome://xforms/content/xforms.xml#xformswidget-general">
|
||||
|
||||
<implementation>
|
||||
<!-- interface -->
|
||||
<property name="selected"
|
||||
onget="throw Error(Components.results.NS_ERROR_NOT_IMPLEMENTED);"
|
||||
onset="throw Error(Components.results.NS_ERROR_NOT_IMPLEMENTED);"/>
|
||||
|
||||
<property name="disabled"
|
||||
onget="throw Error(Components.results.NS_ERROR_NOT_IMPLEMENTED);"
|
||||
onset="throw Error(Components.results.NS_ERROR_NOT_IMPLEMENTED);"/>
|
||||
|
||||
<method name="focus">
|
||||
<body>
|
||||
this.control.focus();
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- successor's interface -->
|
||||
<method name="updateInstanceData">
|
||||
<parameter name="aIncremental"/>
|
||||
<body>
|
||||
if (this.selectControl)
|
||||
this.selectControl.updateInstanceNodeByItem(aIncremental, this);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- private -->
|
||||
<property name="selectControl" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
if (!this._selectControl) {
|
||||
var node = this;
|
||||
|
||||
while (node = node.parentNode) {
|
||||
if (node.namespaceURI == this.XFORMS_NS &&
|
||||
(node.localName == "select" || node.localName == "select1")) {
|
||||
this._selectControl = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this._selectControl;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
<field name="_selectControl">null</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- CHOICES element of FULL APPEARANCE SELECT/SELECT1 -->
|
||||
<binding id="choices">
|
||||
<implementation implements="nsIAccessibleProvider">
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
return Components.interfaces.nsIAccessibleProvider.XFormsChoices;
|
||||
</getter>
|
||||
</property>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
|
||||
Reference in New Issue
Block a user