зеркало из https://github.com/mozilla/gecko-dev.git
Bug 339827, reorg of select that use native widgets, p=surkov, r=aaronr+me
This commit is contained in:
Родитель
fcdbf7f447
Коммит
291b3c50dc
|
@ -23,12 +23,12 @@ xforms.jar:
|
|||
content/xforms/select1.xml (resources/content/select1.xml)
|
||||
content/xforms/range.xml (resources/content/range.xml)
|
||||
content/xforms/range-xhtml.xml (resources/content/range-xhtml.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/selects.xml (resources/content/selects.xml)
|
||||
content/xforms/selects-xhtml.xml (resources/content/selects-xhtml.xml)
|
||||
content/xforms/selects-xul.xml (resources/content/selects-xul.xml)
|
||||
content/xforms/selectsnw.xml (resources/content/selectsnw.xml)
|
||||
content/xforms/selectsnw-xhtml.xml (resources/content/selectsnw-xhtml.xml)
|
||||
content/xforms/selectsnw-xul.xml (resources/content/selectsnw-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)
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
/**
|
||||
* Interface implemented by the item element.
|
||||
*/
|
||||
[scriptable, uuid(e7e65a10-bf37-488f-9c74-add34abdd309)]
|
||||
[scriptable, uuid(0acdfa92-0b0a-4c7a-bcd8-7256ec04673c)]
|
||||
interface nsIXFormsItemElement : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -63,13 +63,6 @@ interface nsIXFormsItemElement : nsISupports
|
|||
*/
|
||||
void setActive(in boolean aActive);
|
||||
|
||||
/**
|
||||
* This is called by the \<label\> child element whenever it is refreshed.
|
||||
* This information will be propagated by the \<item\> to the nearest
|
||||
* \<select1\> element, which can then refresh its UI.
|
||||
*/
|
||||
void labelRefreshed();
|
||||
|
||||
/**
|
||||
* Indicates whether the item element contains a value child or a copy
|
||||
* child. We'll assume that if the item is NOT a copy item, then it must
|
||||
|
|
|
@ -481,27 +481,6 @@ nsXFormsItemElement::GetLabelText(nsAString& aValue)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsItemElement::LabelRefreshed()
|
||||
{
|
||||
NS_ENSURE_STATE(mElement);
|
||||
nsCOMPtr<nsIDOMNode> parent, current;
|
||||
current = mElement;
|
||||
do {
|
||||
current->GetParentNode(getter_AddRefs(parent));
|
||||
if (nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("select1")) ||
|
||||
nsXFormsUtils::IsXFormsElement(parent, NS_LITERAL_STRING("select"))) {
|
||||
nsCOMPtr<nsIXFormsControl> select(do_QueryInterface(parent));
|
||||
if (select) {
|
||||
select->Refresh();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
current = parent;
|
||||
} while(current);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsItemElement::GetIsCopyItem(PRBool *aIsCopyItem)
|
||||
{
|
||||
|
|
|
@ -311,20 +311,6 @@ nsXFormsLabelElement::Refresh()
|
|||
nsCOMPtr<nsIDOMNode> parent;
|
||||
mElement->GetParentNode(getter_AddRefs(parent));
|
||||
|
||||
// If <label> is inside <select1> its parent is <item>
|
||||
// or <contextcontainer> (which parent is <item>).
|
||||
nsCOMPtr<nsIXFormsItemElement> item(do_QueryInterface(parent));
|
||||
if (item) {
|
||||
item->LabelRefreshed();
|
||||
} else if (parent) {
|
||||
nsCOMPtr<nsIDOMNode> grandparent;
|
||||
parent->GetParentNode(getter_AddRefs(grandparent));
|
||||
item = do_QueryInterface(grandparent);
|
||||
if (item) {
|
||||
item->LabelRefreshed();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,224 +0,0 @@
|
|||
<?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
|
||||
- IBM Corporation.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2005
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Doron Rosenberg <doronr@us.ibm.com>
|
||||
- Olli Pettay <Olli.Pettay@helsinki.fi>
|
||||
- Alexander Surkov <surkov@dc.baikal.ru>
|
||||
-
|
||||
- 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 ***** -->
|
||||
|
||||
<!-- SELECT CONTROLS FOR XHTML
|
||||
This file contains xforms select controls implementations for XHTML.
|
||||
-->
|
||||
|
||||
|
||||
<bindings id="xformsSelectBindingsForXHTML"
|
||||
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:mozType="http://www.mozilla.org/projects/xforms/2005/type">
|
||||
|
||||
|
||||
<!-- SELECT/SELECT1 CONTROLS
|
||||
The section contains xforms select/select1 controls implementations for XHTML.
|
||||
All controls are inherited from interface bindings realized in select.xml.
|
||||
|
||||
XXX: select of minimal appearance is not implemented (see bug 332928).
|
||||
|
||||
select1 of minimal appearance is implemented in select1.xml file.
|
||||
select/select1 of appearance="full" is implemented in selects-xhtml.xml file.
|
||||
-->
|
||||
|
||||
<!-- SELECT APPEARANCE='COMPACT' : <DEFAULT> -->
|
||||
<binding id="xformswidget-select-compact"
|
||||
extends="chrome://xforms/content/select.xml#xformswidget-select-base">
|
||||
<content>
|
||||
<html:span class="label-container">
|
||||
<children includes="label"/>
|
||||
</html:span>
|
||||
<html:span anonid="control"
|
||||
xbl:inherits="style, mozType:tabindex=tabindex"/>
|
||||
<children/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<!-- SELECT1 APPEARANCE='COMPACT' : <DEFAULT> -->
|
||||
<binding id="xformswidget-select1-compact"
|
||||
extends="chrome://xforms/content/select.xml#xformswidget-select1-base">
|
||||
<content>
|
||||
<html:label>
|
||||
<html:span class="label-container">
|
||||
<children includes="label"/>
|
||||
</html:span>
|
||||
<html:span anonid="control"
|
||||
xbl:inherits="style, mozType:tabindex=tabindex"/>
|
||||
<children/>
|
||||
</html:label>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- CONTROL WIDGETS FOR SELECT/SELECT1 CONTROLS
|
||||
All control widgets are underlying controls for select/select1 and serve to
|
||||
realize functionality needed for select/select1 work in XHTML context. Thease
|
||||
widgets are inherited from 'controlwidget-base' binding and implement the
|
||||
interface what base widget for xforms select/select1 controls ask for. You can
|
||||
find interface description in 'select.xml' file.
|
||||
-->
|
||||
|
||||
|
||||
<!-- CONTROL WIDGETS FOR SELECT CONTROLS
|
||||
The section contains underlying widgets implementations needed for select
|
||||
controls.
|
||||
-->
|
||||
|
||||
<!-- CONTROL WIDGET FOR SELECT APPEARANCE='COMPACT' -->
|
||||
<binding id="controlwidget-select-compact"
|
||||
extends="chrome://xforms/content/select.xml#controlwidget-base">
|
||||
|
||||
<content>
|
||||
<html:select xbl:inherits="style, disabled=readonly, tabindex=mozType:tabindex"
|
||||
class="xf-value" multiple="true" size="5" anonid="control"/>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<method name="removeAllItems">
|
||||
<body>
|
||||
for (var i = this.control.childNodes.length; i > 0; i--) {
|
||||
this.control.removeChild(this.control.childNodes[i-1]);
|
||||
}
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="appendItem">
|
||||
<parameter name="aLabel"/>
|
||||
<parameter name="aValue"/>
|
||||
<parameter name="aGroup"/>
|
||||
<body>
|
||||
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;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="appendGroup">
|
||||
<parameter name="aLabel"/>
|
||||
<parameter name="aGroup"/>
|
||||
<body>
|
||||
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;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="addItemToSelection">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
aItem.selected = true;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="removeItemFromSelection">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
aItem.selected = false;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemSelected">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return aItem.selected;
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="focus" phase="capturing">
|
||||
this.dispatchDOMUIEvent("DOMFocusIn");
|
||||
</handler>
|
||||
|
||||
<handler event="blur" phase="capturing">
|
||||
this.updateInstanceData(false);
|
||||
this.dispatchDOMUIEvent("DOMFocusOut");
|
||||
</handler>
|
||||
|
||||
<handler event="change">
|
||||
this.updateInstanceData(true);
|
||||
</handler>
|
||||
|
||||
<!--
|
||||
XXX: since xforms:label can include arbitrary elements then 'focus',
|
||||
'blur' and 'change' events should be listen from 'xhtml:select'
|
||||
element only.
|
||||
-->
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- CONTROL WIDGETS FOR SELECT1 CONTROLS
|
||||
The section contains underlying widgets implementations needed for select1
|
||||
controls.
|
||||
-->
|
||||
|
||||
<!-- CONTROL WIDGET FOR SELECT1 APPEARANCE='COMPACT' -->
|
||||
<binding id="controlwidget-select1-compact"
|
||||
extends="#controlwidget-select-compact">
|
||||
<content>
|
||||
<html:select xbl:inherits="style, disabled=readonly, tabindex=mozType:tabindex"
|
||||
class="xf-value" size="5" anonid="control"/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
|
|
@ -1,395 +0,0 @@
|
|||
<?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
|
||||
- Alexander Surkov.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2006
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Alexander Surkov <surkov@dc.baikal.ru>
|
||||
-
|
||||
- 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 ***** -->
|
||||
|
||||
<!-- SELECT CONTROLS FOR XUL
|
||||
This file contains xforms select and xforms select1 controls implementations
|
||||
for XUL.
|
||||
-->
|
||||
|
||||
<bindings id="xformsBindings"
|
||||
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:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:mozType="http://www.mozilla.org/projects/xforms/2005/type">
|
||||
|
||||
|
||||
<!-- SELECT, SELECT1 CONTROLS
|
||||
The section contains xforms select and select1 controls implementations for
|
||||
XUL. All controls are inherited from interface bindings realized in
|
||||
select.xml file.
|
||||
|
||||
XXX: Element select of minimal appearance is not implemented (see bug 332928).
|
||||
|
||||
select/select1 of full appearance are implemented in selects-xul.xml file.
|
||||
-->
|
||||
|
||||
<binding id="xformswidget-select"
|
||||
extends="chrome://xforms/content/select.xml#xformswidget-select-base">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<children includes="label"/>
|
||||
<xul:box anonid="control"
|
||||
xbl:inherits="style, mozType:tabindex=tabindex"
|
||||
class="xf-value" flex="1"/>
|
||||
</xul:hbox>
|
||||
<children/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="xformswidget-select1"
|
||||
extends="chrome://xforms/content/select.xml#xformswidget-select1-base">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<children includes="label"/>
|
||||
<xul:box anonid="control"
|
||||
xbl:inherits="style, mozType:tabindex=tabindex"
|
||||
class="xf-value" flex="1"/>
|
||||
</xul:hbox>
|
||||
<children/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- The following bindings do a trick. When appearance attribute is changed
|
||||
then we should call nsIXFormsDelegate.widgetAttached() method. If we'll have
|
||||
separate binding for each appearance attribute value then it will be happen
|
||||
automatically.
|
||||
-->
|
||||
|
||||
<binding id="xformswidget-select-compact"
|
||||
extends="#xformswidget-select"/>
|
||||
|
||||
<binding id="xformswidget-select1-minimal"
|
||||
extends="#xformswidget-select1"/>
|
||||
|
||||
<binding id="xformswidget-select1-compact"
|
||||
extends="#xformswidget-select1"/>
|
||||
|
||||
<!-- CONTROL WIDGETS FOR SELECT CONTROLS
|
||||
The section contains underlying widgets implementations needed for xforms
|
||||
select controls. All underlying widgets implement the interface what base
|
||||
widget for xforms select controls ask for. You can find interface description
|
||||
in 'select.xml' file.
|
||||
-->
|
||||
|
||||
<!-- CONTROL WIDGET FOR SELECT APPEARANCE='COMPACT' -->
|
||||
<binding id="controlwidget-select-compact"
|
||||
extends="chrome://xforms/content/select.xml#controlwidget-base">
|
||||
|
||||
<content>
|
||||
<xul:listbox xbl:inherits="style, disabled=readonly, tabindex=mozType:tabindex"
|
||||
rows="5" flex="1"
|
||||
seltype="multiple"
|
||||
anonid="control"/>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<method name="removeAllItems">
|
||||
<body>
|
||||
// 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;
|
||||
</body>
|
||||
</method>
|
||||
<field name="suppress">false</field>
|
||||
|
||||
<method name="appendItem">
|
||||
<parameter name="aLabel"/>
|
||||
<parameter name="aValue"/>
|
||||
<parameter name="aGroup"/>
|
||||
<body>
|
||||
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;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="appendGroup">
|
||||
<parameter name="aLabel"/>
|
||||
<parameter name="aGroup"/>
|
||||
<body>
|
||||
// XXX: Group supporting isn't implemented
|
||||
return null;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="addItemToSelection">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
// 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
|
||||
);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="removeItemFromSelection">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
this.control.setAttribute("suppressonselect", "true");
|
||||
this.control.removeItemFromSelection(aItem);
|
||||
this.control.removeAttribute("suppressonselect");
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemSelected">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return aItem.selected;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<constructor>
|
||||
// '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);
|
||||
</constructor>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="focus" phase="capturing">
|
||||
this.dispatchDOMUIEvent("DOMFocusIn");
|
||||
</handler>
|
||||
|
||||
<handler event="blur" phase="capturing">
|
||||
this.updateInstanceData(false);
|
||||
this.dispatchDOMUIEvent("DOMFocusOut");
|
||||
</handler>
|
||||
|
||||
<!--
|
||||
XXX: Since xforms:label can include arbitrary elements then 'focus',
|
||||
'blur' and 'command' events should be listen from 'xul:listbox'
|
||||
element only.
|
||||
-->
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- CONTROL WIDGETS FOR SELECT1 CONTROLS
|
||||
The section contains underlying widgets implementations needed for xforms
|
||||
select1 controls. All underlying widgets implement the interface what base
|
||||
widget for xforms select1 controls ask for. You can find interface description
|
||||
in 'select.xml' file.
|
||||
-->
|
||||
|
||||
<!-- CONTROL WIDGET FOR SELECT1 APPEARANCE='MINIMAL' -->
|
||||
<binding id="controlwidget-select1-minimal"
|
||||
extends="chrome://xforms/content/select.xml#controlwidget-base">
|
||||
|
||||
<content>
|
||||
<xul:menulist xbl:inherits="style, disabled=readonly, tabindex=mozType:tabindex"
|
||||
anonid="control" flex="1">
|
||||
<xul:menupopup/>
|
||||
</xul:menulist>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<property name="editor" readonly="true">
|
||||
<getter>
|
||||
if (!this.control.hasAttribute("editable"))
|
||||
return null;
|
||||
|
||||
return this.control.editor;
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<method name="removeAllItems">
|
||||
<body>
|
||||
var popup = this.control.menupopup;
|
||||
while (popup.hasChildNodes()) {
|
||||
popup.removeChild(popup.lastChild);
|
||||
}
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="appendItem">
|
||||
<parameter name="aLabel"/>
|
||||
<parameter name="aValue"/>
|
||||
<parameter name="aGroup"/>
|
||||
<body>
|
||||
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;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="appendGroup">
|
||||
<parameter name="aLabel"/>
|
||||
<parameter name="aGroup"/>
|
||||
<body>
|
||||
// XXX: Group supporting isn't implemented
|
||||
return null;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="addItemToSelection">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
this.control.selectedItem = aItem;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="removeItemFromSelection">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
if (this.control.selectedItem == aItem)
|
||||
this.control.selectedItem = null;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemSelected">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return aItem.getAttribute("selected") == "true";
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="getFreeEntryValues">
|
||||
<body>
|
||||
if (this.control.getAttribute("editable") == "true") {
|
||||
if (!this.control.selectedItem)
|
||||
return this.control.value;
|
||||
return "";
|
||||
}
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="allowFreeEntry">
|
||||
<parameter name="aAllowed"/>
|
||||
<body>
|
||||
if (aAllowed)
|
||||
this.control.setAttribute("editable", "true");
|
||||
else
|
||||
this.control.removeAttribute("editable");
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="appendFreeEntryItem">
|
||||
<parameter name="aValue"/>
|
||||
<body>
|
||||
if (this.control.getAttribute("editable") == "true") {
|
||||
this.control.value = aValue;
|
||||
}
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="input">
|
||||
this.updateInstanceData(true);
|
||||
</handler>
|
||||
|
||||
<handler event="focus" phase="capturing">
|
||||
this.dispatchDOMUIEvent("DOMFocusIn");
|
||||
</handler>
|
||||
|
||||
<handler event="blur" phase="capturing">
|
||||
this.updateInstanceData(false);
|
||||
this.dispatchDOMUIEvent("DOMFocusOut");
|
||||
</handler>
|
||||
|
||||
<handler event="command">
|
||||
this.updateInstanceData(true);
|
||||
</handler>
|
||||
|
||||
<!--
|
||||
XXX: Since xforms:label can include arbitrary elements then 'focus',
|
||||
'blur', 'command' and 'input' events should be listen from
|
||||
'xul:menulist' element only. The described problem is not actual now.
|
||||
Note we will get it when we will use node instead of text content for
|
||||
a label.
|
||||
-->
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- CONTROL WIDGET FOR SELECT1 APPEARANCE='COMPACT' -->
|
||||
<binding id="controlwidget-select1-compact"
|
||||
extends="#controlwidget-select-compact">
|
||||
<content>
|
||||
<xul:listbox xbl:inherits="style, disabled=readonly, tabindex=mozType:tabindex"
|
||||
rows="5" anonid="control"/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1220,6 +1220,53 @@
|
|||
}
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<property name="parentControl" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
if (!this._parentControl) {
|
||||
var parent = this.parentNode;
|
||||
for (; parent; parent = parent.parentNode) {
|
||||
if (parent.namespaceURI == this.XFORMS_NS &&
|
||||
(parent.localName == "select" ||
|
||||
parent.localName == "select1"))
|
||||
break;
|
||||
}
|
||||
this._parentControl = parent;
|
||||
}
|
||||
return this._parentControl;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<method name="refreshParentControl">
|
||||
<parameter name="aTarget"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!this.parentControl)
|
||||
return;
|
||||
|
||||
var parent = aTarget.parentNode;
|
||||
for (; parent; parent = parent.parentNode) {
|
||||
if (parent.namespaceURI == this.XFORMS_NS &&
|
||||
parent.localName == "label") {
|
||||
this.parentControl.refreshWidth();
|
||||
return;
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<property name="XFORMS_NS" readonly="true"
|
||||
onget="return 'http://www.w3.org/2002/xforms';"/>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="DOMNodeInserted"
|
||||
action="refreshParentControl(event.originalTarget);"/>
|
||||
<handler event="DOMNodeRemoved"
|
||||
action="refreshParentControl(event.originalTarget);"/>
|
||||
</handlers>
|
||||
</binding>
|
||||
</bindings>
|
||||
|
|
|
@ -51,6 +51,15 @@
|
|||
<children/>
|
||||
</html:div>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<!-- nsIAccessibleProvider -->
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
return Components.interfaces.nsIAccessibleProvider.XFormsSelectFull;
|
||||
</getter>
|
||||
</property>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<!-- SELECT1: APPEARANCE FULL -->
|
||||
|
@ -63,6 +72,15 @@
|
|||
</html:div>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<!-- nsIAccessibleProvider -->
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
return Components.interfaces.nsIAccessibleProvider.XFormsSelectFull;
|
||||
</getter>
|
||||
</property>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="keypress" keycode="VK_UP" preventdefault="true">
|
||||
var item = this.selectedItem;
|
||||
|
|
|
@ -51,6 +51,15 @@
|
|||
<children/>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<!-- nsIAccessibleProvider -->
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
return Components.interfaces.nsIAccessibleProvider.XFormsSelectFull;
|
||||
</getter>
|
||||
</property>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
|
||||
|
@ -94,6 +103,13 @@
|
|||
</content>
|
||||
|
||||
<implementation>
|
||||
<!-- nsIAccessibleProvider -->
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
return Components.interfaces.nsIAccessibleProvider.XFormsSelectFull;
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<method name="getControlElement">
|
||||
<body>
|
||||
return this.ownerDocument.
|
||||
|
|
|
@ -44,30 +44,20 @@
|
|||
|
||||
<!--
|
||||
This file implements the "abstract" UI classes for XForms select/select1
|
||||
controls. The approach used here is different from approach that is realized
|
||||
in select.xml file. Here we don't build programmaticaly native widget that
|
||||
will represent select/select1 control. Instead that every item or choices
|
||||
element is visible and represented. An example is the controls for XHTML in
|
||||
select-xhtml.xml.
|
||||
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.
|
||||
Right now this binding is used only by full appearance select/select1
|
||||
elements. Be care with this accessible type and implementation logic if you
|
||||
want to use this binding for other types of select/select1 elements.
|
||||
-->
|
||||
<!-- BASE for select/select1 elements. -->
|
||||
<binding id="selectcontrols-base"
|
||||
extends="chrome://xforms/content/xforms.xml#xformswidget-base">
|
||||
|
||||
<implementation implements="nsIAccessibleProvider">
|
||||
|
||||
<!-- nsIAccessibleProvider -->
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
return Components.interfaces.nsIAccessibleProvider.XFormsSelectFull;
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIXFormsUIWidget -->
|
||||
<method name="refresh">
|
||||
<body>
|
||||
|
@ -83,6 +73,8 @@
|
|||
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);
|
||||
|
@ -97,14 +89,16 @@
|
|||
<method name="focus">
|
||||
<body>
|
||||
function focusItem(aItem) {
|
||||
if (!aItem.disabled)
|
||||
aItem.focus();
|
||||
return aItem.disabled;
|
||||
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";
|
||||
|
@ -117,6 +111,16 @@
|
|||
</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
|
||||
|
@ -131,36 +135,38 @@
|
|||
<parameter name="aItem"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
aItem.disabled = this.accessors.isReadonly();
|
||||
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.
|
||||
aItem.disabled = true;
|
||||
this.markItemDisabled(aItem, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.nodes.length; i++) {
|
||||
var length = this.nodes.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (aItem.copyNodeEquals(this.nodes[i].node)) {
|
||||
aItem.selected = true;
|
||||
this.markItemSelected(aItem, true);
|
||||
this.nodes[i].isUsed = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < this.values.length; i++) {
|
||||
var length = this.values.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (this.values[i].value == aItem.value) {
|
||||
aItem.selected = true;
|
||||
this.markItemSelected(aItem, true);
|
||||
this.values[i].isUsed = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aItem.selected)
|
||||
aItem.selected = false;
|
||||
if (this.isItemMarkedSelected(aItem))
|
||||
this.markItemSelected(aItem, false);
|
||||
|
||||
return true;
|
||||
]]>
|
||||
|
@ -274,6 +280,8 @@
|
|||
|
||||
var forceRebuild = {value: false};
|
||||
this.traverseItems(this, this.buildInstanceData, node, forceRebuild);
|
||||
if (this.freeEntryAllowed)
|
||||
this.appendValueForInstanceNode(node, this.getFreeEntryValues());
|
||||
|
||||
var nsIDOMNode = Components.interfaces.nsIDOMNode;
|
||||
|
||||
|
@ -306,24 +314,38 @@
|
|||
<parameter name="aForceRebuild"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
const nsIDOMNode = Components.interfaces.nsIDOMNode;
|
||||
|
||||
if (aItem.isCopyItem) {
|
||||
// Per specs we should fire 'xforms-binding-exception' event if
|
||||
// bound node is not element and copy item is selected. We don't do
|
||||
// it because in this case copy items are disabled and can't be
|
||||
// selected.
|
||||
var wasSelected = false;
|
||||
if (this.nodes) {
|
||||
for (var i = 0; i < this.nodes.length; i++) {
|
||||
var length = this.nodes.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (aItem.copyNodeEquals(this.nodes[i].node)) {
|
||||
wasSelected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wasSelected != aItem.selected)
|
||||
if (wasSelected != this.isItemMarkedSelected(aItem))
|
||||
aForceRebuild.value = true;
|
||||
|
||||
if (aItem.selected) {
|
||||
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);
|
||||
|
@ -331,11 +353,9 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!aItem.selected)
|
||||
if (!this.isItemMarkedSelected(aItem))
|
||||
return true;
|
||||
|
||||
var nsIDOMNode = Components.interfaces.nsIDOMNode;
|
||||
|
||||
if (aInstanceNode.nodeType != nsIDOMNode.ELEMENT_NODE) {
|
||||
if (aInstanceNode.textContent)
|
||||
aInstanceNode.textContent += " ";
|
||||
|
@ -343,22 +363,37 @@
|
|||
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 += aItem.value;
|
||||
fchild.nodeValue += aValue;
|
||||
} else {
|
||||
var textnode =
|
||||
aInstanceNode.ownerDocument.createTextNode(aItem.value);
|
||||
aInstanceNode.ownerDocument.createTextNode(aValue);
|
||||
if (fchild)
|
||||
aInstanceNode.insertBefore(textnode, fchild);
|
||||
else
|
||||
aInstanceNode.appendChild(textnode);
|
||||
}
|
||||
|
||||
return true;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
@ -481,9 +516,125 @@
|
|||
</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>
|
||||
|
@ -492,7 +643,9 @@
|
|||
</binding>
|
||||
|
||||
|
||||
<!-- SELECT: BASE -->
|
||||
<!-- SELECT: BASE
|
||||
Note, keep synchronized with 'selectsnw.xml#select-base' binding
|
||||
-->
|
||||
<binding id="select-base"
|
||||
extends="#selectcontrols-base">
|
||||
|
||||
|
@ -502,7 +655,7 @@
|
|||
<property name="selectedItems" readonly="true">
|
||||
<getter>
|
||||
function _isSelected(aItem, aItemList) {
|
||||
if (aItem.selected)
|
||||
if (this.isItemMarkedSelected(aItem))
|
||||
aItemList.push(aItem);
|
||||
return true;
|
||||
}
|
||||
|
@ -515,23 +668,21 @@
|
|||
<method name="addItemToSelection">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
if (aItem)
|
||||
aItem.selected = true;
|
||||
this.markItemSelected(aItem, true);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="removeItemFromSelection">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
if (aItem)
|
||||
aItem.selected = false;
|
||||
this.markItemSelected(aItem, false);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="clearSelection">
|
||||
<body>
|
||||
function _clearSelection(aItem) {
|
||||
aItem.selected = false;
|
||||
this.markItemSelected(aItem, false);
|
||||
return true;
|
||||
}
|
||||
this.traverseItems(this, _clearSelection);
|
||||
|
@ -541,7 +692,7 @@
|
|||
<method name="selectAll">
|
||||
<body>
|
||||
function _selectAll(aItem) {
|
||||
aItem.selected = true;
|
||||
this.markItemSelected(aItem, true);
|
||||
return true;
|
||||
}
|
||||
this.traverseItems(this, _selectAll);
|
||||
|
@ -551,7 +702,7 @@
|
|||
<method name="isItemSelected">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return aItem ? aItem.selected : false;
|
||||
return this.isItemMarkedSelected(aItem);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
|
@ -586,7 +737,8 @@
|
|||
var parent = this.ownerDocument.getBindingParent(aItem);
|
||||
var target = parent && parent.localName == "itemset" ? parent : aItem;
|
||||
|
||||
var eventName = aItem.selected ? "xforms-select" : "xforms-deselect";
|
||||
var eventName = this.isItemMarkedSelected(aItem) ?
|
||||
"xforms-select" : "xforms-deselect";
|
||||
this.dispatchXFormsNotificationEvent(eventName, target);
|
||||
}
|
||||
|
||||
|
@ -595,6 +747,20 @@
|
|||
</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>
|
||||
|
@ -612,7 +778,9 @@
|
|||
</binding>
|
||||
|
||||
|
||||
<!-- SELECT1: BASE -->
|
||||
<!-- SELECT1: BASE
|
||||
Note, keep synchronized with 'selects.xml#select1-base' binding.
|
||||
-->
|
||||
<binding id="select1-base"
|
||||
extends="#selectcontrols-base">
|
||||
|
||||
|
@ -621,9 +789,9 @@
|
|||
<property name="selectedItem">
|
||||
<getter>
|
||||
function getSelectedItem(aItem, aSelectedItem) {
|
||||
if (aItem.selected)
|
||||
if (this.isItemMarkedSelected(aItem))
|
||||
aSelectedItem.value = aItem;
|
||||
return !aItem.selected;
|
||||
return !this.isItemMarkedSelected(aItem);
|
||||
}
|
||||
var selectedItem = {value: null};
|
||||
this.traverseItems(this, getSelectedItem, selectedItem);
|
||||
|
@ -631,7 +799,7 @@
|
|||
</getter>
|
||||
<setter>
|
||||
function setSelectedItem(aItem, aSelectedItem) {
|
||||
aItem.selected = aItem == aSelectedItem;
|
||||
this.markItemSelected(aItem, aItem == aSelectedItem);
|
||||
return true;
|
||||
}
|
||||
this.traverseItems(this, setSelectedItem, val);
|
||||
|
@ -662,8 +830,8 @@
|
|||
|
||||
function _unselectItems(aItem, aNewSelectedItem, aTarget) {
|
||||
if (aItem != aNewSelectedItem) {
|
||||
if (aItem.selected) {
|
||||
aItem.selected = false;
|
||||
if (this.isItemMarkedSelected(aItem)) {
|
||||
this.markItemSelected(aItem, false);
|
||||
this.dispatchXFormsNotificationEvent("xforms-deselect",
|
||||
aTarget);
|
||||
return false;
|
||||
|
@ -673,7 +841,8 @@
|
|||
}
|
||||
this.traverseItems(this, _unselectItems, aItem, target);
|
||||
|
||||
var eventName = aItem.selected ? "xforms-select" : "xforms-deselect";
|
||||
var eventName = this.isItemMarkedSelected(aItem) ?
|
||||
"xforms-select" : "xforms-deselect";
|
||||
this.dispatchXFormsNotificationEvent(eventName, target);
|
||||
}
|
||||
|
||||
|
@ -682,6 +851,18 @@
|
|||
</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>
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
<?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) 2007
|
||||
- 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="xformsSelectsNativeWidgetBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<!-- SELECT, SELECT1 CONTROLS
|
||||
The section contains xforms select and select1 controls implementations for
|
||||
XHTML. All controls are inherited from interface bindings realized in
|
||||
'selectsnw.xml' file.
|
||||
|
||||
XXX: Element select of minimal appearance is not implemented (see bug 332928).
|
||||
|
||||
select/select1 of full appearance implementation uses a different approach
|
||||
taken in 'selects.xml' file, their implementation is hosted in
|
||||
'selects-xhtml.xml' file.
|
||||
-->
|
||||
|
||||
<binding id="select"
|
||||
extends="chrome://xforms/content/selectsnw.xml#select-base">
|
||||
|
||||
<content>
|
||||
<children includes="label"/>
|
||||
<html:span anonid="nativewidget" xbl:inherits="style, accesskey"/>
|
||||
<children/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
|
||||
<binding id="select1"
|
||||
extends="chrome://xforms/content/selectsnw.xml#select1-base">
|
||||
|
||||
<content>
|
||||
<children includes="label"/>
|
||||
<html:span anonid="nativewidget" xbl:inherits="style, accesskey"/>
|
||||
<children/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- CONTROL WIDGETS FOR SELECT/SELECT1 CONTROLS
|
||||
The section contains underlying widgets implementations needed for xforms
|
||||
select controls. All underlying widgets implement the interface what base
|
||||
widget for xforms select controls ask for. You can find interface description
|
||||
in 'selectsnw.xml' file.
|
||||
-->
|
||||
|
||||
<binding id="nativewidget-select-compact"
|
||||
extends="chrome://xforms/content/selectsnw.xml#nativewidget-select">
|
||||
<content>
|
||||
<html:select xbl:inherits="style, accesskey, disabled=readonly"
|
||||
class="xf-value" multiple="true" size="5" anonid="control"/>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<method name="createGroupElm">
|
||||
<parameter name="aParentElm"/>
|
||||
<parameter name="aNextElm"/>
|
||||
<parameter name="aXFLabel"/>
|
||||
<body>
|
||||
var elm = this.ownerDocument.createElementNS(this.XHTML_NS,
|
||||
"optgroup");
|
||||
if (aXFLabel)
|
||||
elm.textContent = aXFLabel.textValue;
|
||||
|
||||
return aParentElm.insertBefore(elm, aNextElm);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="createItemElm">
|
||||
<parameter name="aParentElm"/>
|
||||
<parameter name="aNextElm"/>
|
||||
<parameter name="aXFLabel"/>
|
||||
<body>
|
||||
var elm = this.ownerDocument.createElementNS(this.XHTML_NS, "option");
|
||||
if (aXFLabel)
|
||||
elm.textContent = aXFLabel.textValue;
|
||||
|
||||
return aParentElm.insertBefore(elm, aNextElm);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="setLabelForNative">
|
||||
<parameter name="aElm"/>
|
||||
<parameter name="aXFLabel"/>
|
||||
<body>
|
||||
aElm.textContent = aXFLabel ? aXFLabel.textValue : "";
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemSelectedNative">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return aItem.selected;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="selectItemNative">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aDoSelect"/>
|
||||
<body>
|
||||
aItem.selected = aDoSelect;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemDisabledNative">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return aItem.disabled;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="disableItemNative">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aDoDisable"/>
|
||||
<body>
|
||||
aItem.disabled = aDoDisable;
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="change">
|
||||
this.updateInstanceData(true);
|
||||
</handler>
|
||||
|
||||
<handler event="blur" phase="capturing">
|
||||
this.updateInstanceData(false);
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
|
||||
<binding id="nativewidget-select1-compact"
|
||||
extends="#nativewidget-select-compact">
|
||||
<content>
|
||||
<html:select xbl:inherits="style, accesskey, disabled=readonly"
|
||||
class="xf-value" anonid="control"/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
|
@ -0,0 +1,286 @@
|
|||
<?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) 2007
|
||||
- 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="xformsSelectsNativeWidgetBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<!-- SELECT, SELECT1 CONTROLS
|
||||
The section contains xforms select and select1 controls implementations for
|
||||
XUL. All controls are inherited from interface bindings realized in
|
||||
'selectsnw.xml' file.
|
||||
|
||||
XXX: Element select of minimal appearance is not implemented (see bug 332928).
|
||||
|
||||
select/select1 of full appearance implementation uses a different approach
|
||||
taken in 'selects.xml' file, their implementation is hosted in
|
||||
'selects-xul.xml' file.
|
||||
-->
|
||||
|
||||
<binding id="select"
|
||||
extends="chrome://xforms/content/selectsnw.xml#select-base">
|
||||
|
||||
<content>
|
||||
<children includes="label"/>
|
||||
<xul:box anonid="nativewidget" xbl:inherits="style, accesskey"/>
|
||||
<children/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
|
||||
<binding id="select1"
|
||||
extends="chrome://xforms/content/selectsnw.xml#select1-base">
|
||||
|
||||
<content>
|
||||
<children includes="label"/>
|
||||
<xul:box anonid="nativewidget" xbl:inherits="style, accesskey"/>
|
||||
<children/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="select1-minimal"
|
||||
extends="#select1">
|
||||
<implementation implements="nsIXFormsNSEditableElement">
|
||||
|
||||
<!-- nsIXFormsNSEditableElement -->
|
||||
<property name="editor" readonly="true"
|
||||
onget="return this.nativeWidget.editor;"/>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- CONTROL WIDGETS FOR SELECT CONTROLS
|
||||
The section contains underlying widgets implementations needed for xforms
|
||||
select controls. All underlying widgets implement the interface what base
|
||||
widget for xforms select controls ask for. You can find interface description
|
||||
in 'selectsnw.xml' file.
|
||||
-->
|
||||
|
||||
<binding id="nativewidget-select1-minimal"
|
||||
extends="chrome://xforms/content/selectsnw.xml#nativewidget-select">
|
||||
<content>
|
||||
<xul:menulist xbl:inherits="style, accesskey, disabled=readonly"
|
||||
class="xf-value" anonid="control"/>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<method name="createGroupElm">
|
||||
<parameter name="aXFLabel"/>
|
||||
<body>
|
||||
return null;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="createItemElm">
|
||||
<parameter name="aParentElm"/>
|
||||
<parameter name="aNextElm"/>
|
||||
<parameter name="aXFLabel"/>
|
||||
<body>
|
||||
return this.control.appendItem(aXFLabel ? aXFLabel.textValue : "");
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="setLabelForNative">
|
||||
<parameter name="aElm"/>
|
||||
<parameter name="aXFLabel"/>
|
||||
<body>
|
||||
aElm.setAttribute("label", aXFLabel ? aXFLabel.textValue : "");
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemSelectedNative">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return aItem.selected;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="selectItemNative">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aDoSelect"/>
|
||||
<body>
|
||||
this.control.selectedItem = aDoSelect ? aItem : null;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="getFreeEntryValues">
|
||||
<body>
|
||||
if (this.control.getAttribute("editable") == "true") {
|
||||
if (!this.control.selectedItem)
|
||||
return this.control.value;
|
||||
return "";
|
||||
}
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="allowFreeEntry">
|
||||
<parameter name="aAllowed"/>
|
||||
<body>
|
||||
if (aAllowed)
|
||||
this.control.setAttribute("editable", "true");
|
||||
else
|
||||
this.control.removeAttribute("editable");
|
||||
|
||||
return aAllowed;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="appendFreeEntryItem">
|
||||
<parameter name="aValue"/>
|
||||
<body>
|
||||
if (this.control.getAttribute("editable") == "true")
|
||||
this.control.value = aValue;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<property name="editor" readonly="true">
|
||||
<getter>
|
||||
if (!this.control.hasAttribute("editable"))
|
||||
return null;
|
||||
|
||||
return this.control.editor;
|
||||
</getter>
|
||||
</property>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="input">
|
||||
this.updateInstanceData(true);
|
||||
</handler>
|
||||
|
||||
<handler event="command">
|
||||
this.updateInstanceData(true);
|
||||
</handler>
|
||||
|
||||
<handler event="blur" phase="capturing">
|
||||
this.updateInstanceData(false);
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
|
||||
<binding id="nativewidget-select-compact"
|
||||
extends="chrome://xforms/content/selectsnw.xml#nativewidget-select">
|
||||
<content>
|
||||
<xul:listbox xbl:inherits="style, accesskey, disabled=readonly"
|
||||
class="xf-value" seltype="multiple" rows="5"
|
||||
anonid="control"/>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<method name="createGroupElm">
|
||||
<parameter name="aXFLabel"/>
|
||||
<body>
|
||||
return null;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="createItemElm">
|
||||
<parameter name="aParentElm"/>
|
||||
<parameter name="aNextElm"/>
|
||||
<parameter name="aXFLabel"/>
|
||||
<body>
|
||||
var elm = this.ownerDocument.createElementNS(this.XUL_NS, "listitem");
|
||||
if (aXFLabel)
|
||||
elm.setAttribute("label", aXFLabel.textValue);
|
||||
|
||||
return aParentElm.insertBefore(elm, aNextElm);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="setLabelForNative">
|
||||
<parameter name="aElm"/>
|
||||
<parameter name="aXFLabel"/>
|
||||
<body>
|
||||
aElm.setAttribute("label", aXFLabel.textValue);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemSelectedNative">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return aItem.selected;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="selectItemNative">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aDoSelect"/>
|
||||
<body>
|
||||
this.control.setAttribute("suppressonselect", "true");
|
||||
if (aDoSelect)
|
||||
this.control.addItemToSelection(aItem);
|
||||
else
|
||||
this.control.removeItemFromSelection(aItem);
|
||||
this.control.removeAttribute("suppressonselect");
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<constructor>
|
||||
// 'select' event is fired by 'listbox' binding and therefore it is
|
||||
// not handled in 'handler' element until bug 350334 is fixed.
|
||||
var selectHandler = {
|
||||
control: this,
|
||||
handleEvent: function() {
|
||||
this.control.updateInstanceData(true);
|
||||
}
|
||||
};
|
||||
this.addEventListener("select", selectHandler, false);
|
||||
</constructor>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="blur" phase="capturing">
|
||||
this.updateInstanceData(false);
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
|
||||
<binding id="nativewidget-select1-compact"
|
||||
extends="#nativewidget-select-compact">
|
||||
<content>
|
||||
<xul:listbox xbl:inherits="style, accesskey, disabled=readonly"
|
||||
class="xf-value" seltype="single" rows="5"
|
||||
anonid="control"/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
|
@ -0,0 +1,991 @@
|
|||
<?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) 2007
|
||||
- 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="xformsSelectsNativeWidgetBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<!--
|
||||
This file implements the "abstract" UI classes for XForms select/select1
|
||||
controls that are used native widgets for their representation.
|
||||
-->
|
||||
|
||||
<!-- BASE binding for select/select1 elements that are used native widgets -->
|
||||
<binding id="selectcontrols-base"
|
||||
extends="chrome://xforms/content/selects.xml#selectcontrols-base">
|
||||
|
||||
<implementation>
|
||||
<!-- nsIAccessibleProvider -->
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
return Components.interfaces.nsIAccessibleProvider.XFormsSelect;
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<!-- overriding the methods from the 'selectcontrols-base' binding -->
|
||||
<method name="getFreeEntryValues">
|
||||
<body>
|
||||
return this.nativeWidget.getFreeEntryValues();
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="allowFreeEntry">
|
||||
<parameter name="aAllowed"/>
|
||||
<body>
|
||||
return this.nativeWidget.allowFreeEntry(aAllowed);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="appendFreeEntryItem">
|
||||
<parameter name="aValue"/>
|
||||
<body>
|
||||
this.nativeWidget.appendFreeEntryItem(aValue);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="markItemSelected">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aIsSelected"/>
|
||||
<body>
|
||||
this.nativeWidget.selectItem(aItem, aIsSelected);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemMarkedSelected">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return this.nativeWidget.isItemSelected(aItem);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="markItemDisabled">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aIsDisabled"/>
|
||||
<body>
|
||||
this.nativeWidget.disableItem(aItem, aIsDisabled);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemMarkedDisabled">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return this.nativeWidget.isItemDisabled(aItem);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="focusItem">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
this.nativeWidget.focus();
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- private -->
|
||||
<constructor>
|
||||
this.handleInsertion(this, null);
|
||||
</constructor>
|
||||
|
||||
<!-- Return native widget control -->
|
||||
<property name="nativeWidget">
|
||||
<getter>
|
||||
if (!this._nativeWidget)
|
||||
this._nativeWidget = this.ownerDocument.
|
||||
getAnonymousElementByAttribute(this, "anonid", "nativewidget");
|
||||
return this._nativeWidget;
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<!-- Try to update label element when DOM tree has been changed.
|
||||
|
||||
@param aNode - the node that was inserted or will be removed
|
||||
@param aIsInsertion - if true then node was inserted
|
||||
-->
|
||||
<method name="handleLabel">
|
||||
<parameter name="aNode"/>
|
||||
<parameter name="aIsInsertion"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var node = aNode;
|
||||
while (node && node != this && (node.namespaceURI != this.XFORMS_NS ||
|
||||
node.localName != "label")) {
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
if (!node || node == this)
|
||||
return;
|
||||
|
||||
var label = node;
|
||||
|
||||
var parent = label.parentNode;
|
||||
var labels = parent.getElementsByTagNameNS(this.XFORMS_NS, "label");
|
||||
if (labels[0] != label)
|
||||
return;
|
||||
|
||||
label = ((aNode == label) && !aIsInsertion) ? null : label;
|
||||
if (parent.namespaceURI == this.XFORMS_NS) {
|
||||
// Set label only for xf:item or xf:choices elements.
|
||||
switch (parent.localName) {
|
||||
case "choices":
|
||||
case "item":
|
||||
this.nativeWidget.setLabelFor(parent, label);
|
||||
break;
|
||||
case "contextcontainer":
|
||||
// Parent of xf:contextcontainer element is xf:item element in
|
||||
// the case of auto-generated content of xf:itemset.
|
||||
this.nativeWidget.setLabelFor(parent.parentNode, label);
|
||||
break;
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Updates native widget when DOM tree has been changed i.e. "item"/
|
||||
"itemset"/"choices" elements have been inserted or removed.
|
||||
|
||||
@param aNode - the given node, is is either "select"/"select1" elements
|
||||
to initialize native widget or "choices"/"item"/"itemset"
|
||||
if it was inserted
|
||||
@param aParentNode - either parent node of the given node or null if
|
||||
native widget is initialized
|
||||
@param aParentIndex - index of parent node (for recursive calls)
|
||||
@param aPrevSiblingIndex - index of previous sibling node (for recursive
|
||||
calls)
|
||||
-->
|
||||
<method name="handleInsertion">
|
||||
<parameter name="aNode"/>
|
||||
<parameter name="aParentNode"/>
|
||||
<parameter name="aParentIndex"/>
|
||||
<parameter name="aPrevSiblingIndex"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
const nsIXFormsItemSetUIElement =
|
||||
Components.interfaces.nsIXFormsItemSetUIElement;
|
||||
if (aNode.namespaceURI != this.XFORMS_NS)
|
||||
return -1;
|
||||
|
||||
var container = null;
|
||||
var index = -1;
|
||||
var prevIndex = -1;
|
||||
|
||||
switch (aNode.localName) {
|
||||
case "select1":
|
||||
case "select":
|
||||
case "choices":
|
||||
container = aNode;
|
||||
break;
|
||||
case "item":
|
||||
break;
|
||||
case "itemset":
|
||||
var itemset = aNode.QueryInterface(nsIXFormsItemSetUIElement);
|
||||
container = itemset.anonymousItemSetContent;
|
||||
index = aParentIndex;
|
||||
prevIndex = aPrevSiblingIndex;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create native item/choices and insert it into native widget
|
||||
// hierarchy if inserted elements are xf:item or xf:choices only.
|
||||
if (index == -1) {
|
||||
this.isInsertionHandlingPrevented = true;
|
||||
if (aParentIndex != null && aParentIndex != -1) {
|
||||
index = this.nativeWidget.appendElm(aNode, aParentIndex,
|
||||
aPrevSiblingIndex);
|
||||
} else {
|
||||
index = this.nativeWidget.insertElm(aNode, aParentNode);
|
||||
}
|
||||
this.isInsertionHandlingPrevented = false;
|
||||
}
|
||||
|
||||
// We return whether inserted element is not container of
|
||||
// select/select1 child elements or native element wasn't inserted
|
||||
// successfully.
|
||||
if (index == -1 || !container)
|
||||
return index;
|
||||
|
||||
// Create/insert native elements for choices/item/itemset child
|
||||
// elements of inserted element if any.
|
||||
var hasChildNodes = false;
|
||||
for (var child = container.firstChild; child; child = child.nextSibling) {
|
||||
if (child.namespaceURI != this.XFORMS_NS)
|
||||
continue;
|
||||
|
||||
switch (child.localName) {
|
||||
case "choices":
|
||||
case "itemset":
|
||||
case "item":
|
||||
hasChildNodes = true;
|
||||
prevIndex = this.handleInsertion(child, null, index, prevIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hasChildNodes ? prevIndex : index;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Flag prevents to handle DOM mutation events if mutation events are
|
||||
cause of native widget is updated. -->
|
||||
<field name="isInsertionHandlingPrevented">false</field>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="DOMNodeInserted">
|
||||
<![CDATA[
|
||||
if (this.isInsertionHandlingPrevented)
|
||||
return;
|
||||
|
||||
var target = event.originalTarget;
|
||||
var parent = event.relatedNode;
|
||||
|
||||
// If inserted element is item/itemset/choides element then we should
|
||||
// update native widget
|
||||
if (target.namespaceURI == this.XFORMS_NS &&
|
||||
(target.localName == "choices" || target.localName == "itemset" ||
|
||||
target.localName == "item")) {
|
||||
|
||||
// Search for parent element that is reflected by native widget.
|
||||
// The parent element can be select/select1, itemset or choices
|
||||
// element so we skip itemset element because it isn't presented
|
||||
// in native widget.
|
||||
while (parent != this && (parent.namespaceURI != this.XFORMS_NS ||
|
||||
parent.localName != "choices"))
|
||||
parent = parent.parentNode;
|
||||
|
||||
this.handleInsertion(target, parent);
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise we try to update label for item/choices element.
|
||||
this.handleLabel(target, true);
|
||||
]]>
|
||||
</handler>
|
||||
|
||||
<handler event="DOMNodeRemoved">
|
||||
if (this.isInsertionHandlingPrevented)
|
||||
return;
|
||||
|
||||
var target = event.originalTarget;
|
||||
|
||||
if (target.namespaceURI == this.XFORMS_NS) {
|
||||
switch (target.localName) {
|
||||
case "choices":
|
||||
case "item":
|
||||
this.nativeWidget.removeNativeElm(target);
|
||||
return;
|
||||
|
||||
case "itemset":
|
||||
var itemset = target.QueryInterface(Components.interfaces.nsIXFormsItemSetUIElement);
|
||||
var container = itemset.anonymousItemSetContent;
|
||||
for (var child = container.firstChild; child; child = child.nextSibling)
|
||||
this.nativeWidget.removeNativeElm(child);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.handleLabel(target, false);
|
||||
</handler>
|
||||
|
||||
<handler event="DOMCharacterDataModified">
|
||||
if (this.isInsertionHandlingPrevented)
|
||||
return;
|
||||
|
||||
this.handleLabel(event.originalTarget, true);
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
|
||||
<!-- SELECT: BASE
|
||||
Note, keep synchronized with 'selects.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="selectFreeEntryItemElements">
|
||||
<body>
|
||||
for (var i = 0; this.values.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) {
|
||||
var selected = this.isItemMarkedSelected(aItem);
|
||||
if (selected)
|
||||
aSelectedItem.value = aItem;
|
||||
return !selected;
|
||||
}
|
||||
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="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>
|
||||
|
||||
|
||||
<!-- BASE binding for NATIVE WIDGET CONTROL -->
|
||||
<binding id="nativewidget-select">
|
||||
|
||||
<implementation>
|
||||
<!-- public -->
|
||||
<method name="selectItem">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aDoSelect"/>
|
||||
<body>
|
||||
var index = this.getIndexByElm(aItem);
|
||||
if (index != -1) {
|
||||
var listElm = this.nodeList[index];
|
||||
this.selectItemNative(listElm.nativeElm, aDoSelect);
|
||||
listElm.wasSelected = aDoSelect;
|
||||
}
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemSelected">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
var index = this.getIndexByElm(aItem);
|
||||
if (index != -1)
|
||||
return this.isItemSelectedNative(this.nodeList[index].nativeElm);
|
||||
return false;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="disableItem">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aDoDisable"/>
|
||||
<body>
|
||||
var index = this.getIndexByElm(aItem);
|
||||
if (index != -1)
|
||||
this.disableItemNative(this.nodeList[index].nativeElm, aDoDisable);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemDisabled">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
var index = this.getIndexByElm(aItem);
|
||||
if (index != -1)
|
||||
return this.isItemDisabledNative(this.nodeList[index].nativeElm);
|
||||
return false;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="focus">
|
||||
<body>
|
||||
this.control.focus();
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="getFreeEntryValues">
|
||||
<body>
|
||||
return "";
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="allowFreeEntry">
|
||||
<parameter name="aAllowed"/>
|
||||
<body>
|
||||
return false;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="appendFreeEntryItem">
|
||||
<parameter name="aValue"/>
|
||||
<body>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="setLabelFor">
|
||||
<parameter name="aNode"/>
|
||||
<parameter name="aLabelNode"/>
|
||||
<body>
|
||||
var index = this.getIndexByElm(aNode);
|
||||
if (index != -1)
|
||||
this.setLabelForNative(this.nodeList[index].nativeElm, aLabelNode);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Create and appends native element.
|
||||
|
||||
@param aElm - the given element
|
||||
@param aParentIndex - the index of parent element
|
||||
@param aPrevSiblingIndex - the index of previous sibling element
|
||||
|
||||
@note - previous sibling elements must be in native widget already
|
||||
-->
|
||||
<method name="appendElm">
|
||||
<parameter name="aElm"/>
|
||||
<parameter name="aParentIndex"/>
|
||||
<parameter name="aPrevSiblingIndex"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var parentListElm = this.nodeList[aParentIndex];
|
||||
var nativeParentElm = parentListElm.nativeElm;
|
||||
|
||||
var isItemElm = {value: false};
|
||||
var nativeElm = this.createNativeElm(aElm, nativeParentElm, null,
|
||||
isItemElm);
|
||||
if (!nativeElm)
|
||||
return -1;
|
||||
|
||||
var parentElm = parentListElm.elm;
|
||||
var parentLevel = parentListElm.level;
|
||||
|
||||
var listElm = {
|
||||
elm: aElm,
|
||||
nativeElm: nativeElm,
|
||||
level: parentLevel + 1,
|
||||
};
|
||||
|
||||
if (isItemElm.value)
|
||||
listElm.wasSelected = false;
|
||||
|
||||
var index = -1;
|
||||
if (aPrevSiblingIndex == null || aPrevSiblingIndex == -1)
|
||||
index = aParentIndex + 1;
|
||||
else
|
||||
index = aPrevSiblingIndex + 1;
|
||||
|
||||
this.nodeList.splice(index, 0, listElm);
|
||||
|
||||
return index;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Create and insert native element.
|
||||
|
||||
@param aElm - the given element
|
||||
@param aParent - parent of the given element
|
||||
-->
|
||||
<method name="insertElm">
|
||||
<parameter name="aElm"/>
|
||||
<parameter name="aParent"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!aParent)
|
||||
return this.appendTopElm(aElm);
|
||||
|
||||
var parentIndex = this.getIndexByElm(aParent);
|
||||
if (parentIndex == -1)
|
||||
return -1;
|
||||
|
||||
var nativeParent = this.nodeList[parentIndex].nativeElm;
|
||||
|
||||
var index = this.getInsertionIndexForElm(aElm, parentIndex);
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
var isItemElm = {value: false};
|
||||
var nextElm = aElm.nextSibling ? this.nodeList[index].nativeElm : null;
|
||||
|
||||
var nativeElm = this.createNativeElm(aElm, nativeParent, nextElm,
|
||||
isItemElm);
|
||||
if (!nativeElm)
|
||||
return -1;
|
||||
|
||||
var parentLevel = this.nodeList[parentIndex].level;
|
||||
var listElm = {
|
||||
elm: aElm,
|
||||
nativeElm: nativeElm,
|
||||
level: parentLevel + 1,
|
||||
};
|
||||
|
||||
if (isItemElm.value)
|
||||
listElm.wasSelected = false;
|
||||
|
||||
this.nodeList.splice(index, 0, listElm);
|
||||
|
||||
return index;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Remove native node and its children. -->
|
||||
<method name="removeNativeElm">
|
||||
<parameter name="aElm"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var index = this.getIndexByElm(aElm);
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
var nativeElm = this.nodeList[index];
|
||||
nativeElm.parentNode.removeChild(nativeElm);
|
||||
|
||||
var childCount = 1;
|
||||
var level = this.nodeList[index];
|
||||
for (var i = index + 1; i < this.nodeList.length; ++i) {
|
||||
var childLevel = this.nodeList[i].level;
|
||||
if (childLevel <= level)
|
||||
break;
|
||||
|
||||
childCount++;
|
||||
}
|
||||
|
||||
this.nodeList.splice(index - 1, childCount);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- overrideable -->
|
||||
<method name="disableItemNative">
|
||||
<parameter name="aItem"/>
|
||||
<parameter name="aDoDisable"/>
|
||||
<body>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="isItemDisabledNative">
|
||||
<parameter name="aItem"/>
|
||||
<body>
|
||||
return false;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- private -->
|
||||
<method name="appendTopElm">
|
||||
<parameter name="aSelect"/>
|
||||
<body>
|
||||
var listElm = {
|
||||
elm: aSelect,
|
||||
nativeElm: this.control,
|
||||
level: 0,
|
||||
wasSelected: false
|
||||
};
|
||||
|
||||
this.nodeList = [listElm];
|
||||
this.selectControl = aSelect;
|
||||
return 0;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Create and append native element.
|
||||
|
||||
@param aElm - the given element, this is either item or choices element
|
||||
@param aParentElm - parent element of the given element
|
||||
@param aNextElm - next sibling of the given element if any
|
||||
@param aIsItemElm - [out] returns true if the given element is item
|
||||
-->
|
||||
<method name="createNativeElm">
|
||||
<parameter name="aElm"/>
|
||||
<parameter name="aParentElm"/>
|
||||
<parameter name="aNextElm"/>
|
||||
<parameter name="aIsItemElm"/>
|
||||
<body>
|
||||
switch (aElm.localName) {
|
||||
case "choices":
|
||||
aIsItemElm.value = false;
|
||||
var group = this.createGroupElm(aParentElm, aNextElm,
|
||||
this.getLabelFor(aElm));
|
||||
return group ? group : this.control;
|
||||
case "item":
|
||||
aIsItemElm.value = true;
|
||||
return this.createItemElm(aParentElm, aNextElm,
|
||||
this.getLabelFor(aElm));
|
||||
}
|
||||
return null;
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Return label element for the given element -->
|
||||
<method name="getLabelFor">
|
||||
<parameter name="aNode"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!aNode)
|
||||
return null;
|
||||
|
||||
for (var child = aNode.firstChild; child; child = child.nextSibling) {
|
||||
if (child.namespaceURI == this.XFORMS_NS) {
|
||||
if (child.localName == "label")
|
||||
return child;
|
||||
|
||||
if (child.localName == "contextcontainer")
|
||||
return this.getLabelFor(child);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Returns index for the given element.
|
||||
@param aElm - the given element
|
||||
@return - index of the given element
|
||||
-->
|
||||
<method name="getIndexByElm">
|
||||
<parameter name="aElm"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
for (var i = 0; i < this.nodeList.length; ++i) {
|
||||
if (this.nodeList[i].elm == aElm)
|
||||
return i;
|
||||
}
|
||||
|
||||
dump("ERROR: selectsnw binding, can't locate the given element in the node list\n");
|
||||
return -1;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Return index that the given element will be inserted at
|
||||
@param aElm - the inserted element
|
||||
@param aParentIndex - index of parent element
|
||||
@return - index for inserted element
|
||||
-->
|
||||
<method name="getInsertionIndexForElm">
|
||||
<parameter name="aElm"/>
|
||||
<parameter name="aParentIndex"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var delta = 0;
|
||||
var elm = aElm;
|
||||
while (elm = elm.previousSibling)
|
||||
delta++;
|
||||
|
||||
var parentLevel = this.nodeList[aParentIndex].level;
|
||||
var index = aParentIndex + 1;
|
||||
var length = this.nodeList.length;
|
||||
for (; index < length && delta; ++index) {
|
||||
if (this.nodeList[index].level == parentLevel + 1)
|
||||
delta--;
|
||||
}
|
||||
|
||||
if (!delta)
|
||||
return index;
|
||||
|
||||
dump("ERROR: selectsnw binding, can't find insertion point in the node list for the given element\n");
|
||||
return -1;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Fires 'xforms-select'/'xforms-deselect' events and updates instance
|
||||
data. The method is used by bindings of native widget implementation.
|
||||
|
||||
@param aIncremental - specifies if update is incremental
|
||||
-->
|
||||
<method name="updateInstanceData">
|
||||
<parameter name="aIncremental"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!this.selectControl)
|
||||
return;
|
||||
|
||||
if (aIncremental) {
|
||||
var deferredEventTargets = [];
|
||||
for (var index = 0; index < this.nodeList.length; ++index) {
|
||||
var listElm = this.nodeList[index];
|
||||
if (!("wasSelected" in listElm))
|
||||
continue;
|
||||
|
||||
// event state can be either:
|
||||
// 0 - the state of element wasn't changed
|
||||
// 1 - the element was selected
|
||||
// 2 - the element was unselected
|
||||
var eventState = 0;
|
||||
|
||||
var selected = this.isItemSelectedNative(listElm.nativeElm);
|
||||
if (listElm.wasSelected && !selected)
|
||||
eventState = 1;
|
||||
else if (!listElm.wasSelected && selected)
|
||||
eventState = 2;
|
||||
|
||||
if (!eventState)
|
||||
continue;
|
||||
|
||||
var target = listElm.elm;
|
||||
var parent = target.parentNode;
|
||||
while (parent && parent != this.selectControl) {
|
||||
if (parent.namespaceURI == this.XFORMS_NS &&
|
||||
parent.localName == "itemset") {
|
||||
target = parent;
|
||||
break;
|
||||
}
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
|
||||
// First we should send 'xforms-unselect' events for all
|
||||
// unselected item elements and then 'xforms-select' events.
|
||||
if (eventState == 1) {
|
||||
listElm.wasSelected = false;
|
||||
this.selectControl.
|
||||
dispatchXFormsNotificationEvent("xforms-deselect", target);
|
||||
} else {
|
||||
listElm.wasSelected = true;
|
||||
deferredEventTargets.push(target);
|
||||
}
|
||||
}
|
||||
|
||||
for (var index = 0; index < deferredEventTargets.length; ++index) {
|
||||
this.selectControl.dispatchXFormsNotificationEvent("xforms-select",
|
||||
target);
|
||||
}
|
||||
}
|
||||
|
||||
this.selectControl.updateInstanceData(aIncremental);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- Returns the underlying control (native widget) -->
|
||||
<property name="control" readonly="true">
|
||||
<getter>
|
||||
if (!this._control)
|
||||
this._control = this.ownerDocument.
|
||||
getAnonymousElementByAttribute(this, "anonid", "control");
|
||||
return this._control;
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<!-- Reference on xforms 'select'/'select1' element -->
|
||||
<field name="selectControl">null</field>
|
||||
|
||||
<!-- Contains a list of objects each of them has the following properties:
|
||||
elm - xforms element (may be select/select1, item or choices)
|
||||
nativeElm - native element that represents related xforms element
|
||||
level - level of elements hierarchy (level of select/select1 is 0)
|
||||
wasSelected - if 'elm' property contains item element then this property
|
||||
is presented and takes boolean value
|
||||
|
||||
First object in the list is for 'select'/'select1' element.
|
||||
-->
|
||||
<field name="nodeList">new Array()</field>
|
||||
|
||||
<!-- Debug method. Dumps current state of node list into console. -->
|
||||
<method name="dumpNodeList">
|
||||
<body>
|
||||
<![CDATA[
|
||||
dump("\n\n");
|
||||
for (var i = 0; i < this.nodeList.length; ++i) {
|
||||
var obj = this.nodeList[i];
|
||||
for (var j = 0; j < obj.level; j++)
|
||||
dump(" ");
|
||||
dump("elm: " + obj.elm.localName + "\n");
|
||||
|
||||
for (var j = 0; j < obj.level; j++)
|
||||
dump(" ");
|
||||
dump("native elm: " + obj.nativeElm.localName);
|
||||
var label = this.getLabelFor(obj.elm);
|
||||
if (label)
|
||||
dump(", label: " + label.textContent);
|
||||
dump("\n");
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<property name="XFORMS_NS" readonly="true"
|
||||
onget="return 'http://www.w3.org/2002/xforms';"/>
|
||||
|
||||
<property name="XHTML_NS" readonly="true"
|
||||
onget="return 'http://www.w3.org/1999/xhtml';"/>
|
||||
|
||||
<property name="XUL_NS" readonly="true"
|
||||
onget="return 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';"/>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="focus" phase="capturing">
|
||||
if (this.selectControl)
|
||||
this.selectControl.dispatchDOMUIEvent("DOMFocusIn");
|
||||
</handler>
|
||||
|
||||
<handler event="blur" phase="capturing">
|
||||
if (this.selectControl)
|
||||
this.selectControl.dispatchDOMUIEvent("DOMFocusOut");
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
|
|
@ -110,18 +110,15 @@ contextcontainer-inline {
|
|||
xul|*:root select1:not([appearance]) item,
|
||||
xul|*:root select1[appearance='minimal'] item,
|
||||
select1[appearance='compact'] item,
|
||||
select:not([appearance]) item,
|
||||
select[appearance='compact'] item,
|
||||
select:not([appearance="full"]) item,
|
||||
xul|*:root select1:not([appearance]) itemset,
|
||||
xul|*:root select1[appearance='minimal'] itemset,
|
||||
select1[appearance='compact'] itemset,
|
||||
select:not([appearance]) itemset,
|
||||
select[appearance='compact'] itemset,
|
||||
select:not([appearance="full"]) itemset,
|
||||
xul|*:root select1:not([appearance]) choices,
|
||||
xul|*:root select1[appearance='minimal'] choices,
|
||||
select1[appearance='compact'] choices,
|
||||
select:not([appearance]) choices,
|
||||
select[appearance='compact'] choices {
|
||||
select:not([appearance="full"]) choices {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -531,25 +528,25 @@ html|*:root select1[appearance='minimal'] item {
|
|||
}
|
||||
|
||||
xul|*:root select1 {
|
||||
-moz-binding: url('chrome://xforms/content/select-xul.xml#xformswidget-select1-minimal');
|
||||
-moz-binding: url('chrome://xforms/content/selectsnw-xul.xml#select1-minimal');
|
||||
}
|
||||
xul|*:root select1 xul|box[anonid="control"] {
|
||||
-moz-binding: url('chrome://xforms/content/select-xul.xml#controlwidget-select1-minimal');
|
||||
xul|*:root select1 xul|box[anonid="nativewidget"] {
|
||||
-moz-binding: url('chrome://xforms/content/selectsnw-xul.xml#nativewidget-select1-minimal');
|
||||
}
|
||||
|
||||
/* select1 appearance='compact' */
|
||||
html|*:root select1[appearance="compact"] {
|
||||
-moz-binding: url('chrome://xforms/content/select-xhtml.xml#xformswidget-select1-compact');
|
||||
-moz-binding: url('chrome://xforms/content/selectsnw-xhtml.xml#select1');
|
||||
}
|
||||
html|*:root select1[appearance="compact"] html|span[anonid="control"] {
|
||||
-moz-binding: url('chrome://xforms/content/select-xhtml.xml#controlwidget-select1-compact');
|
||||
html|*:root select1[appearance="compact"] html|span[anonid="nativewidget"] {
|
||||
-moz-binding: url('chrome://xforms/content/selectsnw-xhtml.xml#nativewidget-select1-compact');
|
||||
}
|
||||
|
||||
xul|*:root select1[appearance="compact"] {
|
||||
-moz-binding: url('chrome://xforms/content/select-xul.xml#xformswidget-select1-compact');
|
||||
-moz-binding: url('chrome://xforms/content/selectsnw-xul.xml#select1');
|
||||
}
|
||||
xul|*:root select1[appearance="compact"] xul|box[anonid="control"] {
|
||||
-moz-binding: url('chrome://xforms/content/select-xul.xml#controlwidget-select1-compact');
|
||||
xul|*:root select1[appearance="compact"] xul|box[anonid="nativewidget"] {
|
||||
-moz-binding: url('chrome://xforms/content/selectsnw-xul.xml#nativewidget-select1-compact');
|
||||
}
|
||||
|
||||
/* select1 appearance='full' */
|
||||
|
@ -669,17 +666,17 @@ select1[appearance="full"] choices > choices {
|
|||
|
||||
/* select appearance="compact" (default) */
|
||||
html|*:root select {
|
||||
-moz-binding: url('chrome://xforms/content/select-xhtml.xml#xformswidget-select-compact');
|
||||
-moz-binding: url('chrome://xforms/content/selectsnw-xhtml.xml#select');
|
||||
}
|
||||
html|*:root select html|span[anonid="control"] {
|
||||
-moz-binding: url('chrome://xforms/content/select-xhtml.xml#controlwidget-select-compact');
|
||||
html|*:root select html|span[anonid="nativewidget"] {
|
||||
-moz-binding: url('chrome://xforms/content/selectsnw-xhtml.xml#nativewidget-select-compact');
|
||||
}
|
||||
|
||||
xul|*:root select {
|
||||
-moz-binding: url('chrome://xforms/content/select-xul.xml#xformswidget-select-compact');
|
||||
-moz-binding: url('chrome://xforms/content/selectsnw-xul.xml#select');
|
||||
}
|
||||
xul|*:root select xul|box[anonid="control"] {
|
||||
-moz-binding: url('chrome://xforms/content/select-xul.xml#controlwidget-select-compact');
|
||||
xul|*:root select xul|box[anonid="nativewidget"] {
|
||||
-moz-binding: url('chrome://xforms/content/selectsnw-xul.xml#nativewidget-select-compact');
|
||||
}
|
||||
|
||||
/* select appearance="full" */
|
||||
|
|
Загрузка…
Ссылка в новой задаче