!import
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1 <?xml version="1.0"?>
2
3 <!-- ***** BEGIN LICENSE BLOCK *****
4 - Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 -
6 - The contents of this file are subject to the Mozilla Public License Version
7 - 1.1 (the "License"); you may not use this file except in compliance with
8 - the License. You may obtain a copy of the License at
9 - http://www.mozilla.org/MPL/
10 -
11 - Software distributed under the License is distributed on an "AS IS" basis,
12 - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 - for the specific language governing rights and limitations under the
14 - License.
15 -
16 - The Original Code is toolkit code.
17 -
18 - The Initial Developer of the Original Code is
19 - Netscape Communications Corporation.
20 - Portions created by the Initial Developer are Copyright (C) 2002
21 - the Initial Developer. All Rights Reserved.
22 -
23 - Contributor(s):
24 - Joe Hewitt <hewitt@netscape.com> (original author)
25 - Simon Bünzli <zeniko@gmail.com>
26 - Alexander Surkov <surkov.alexander@gmail.com>
27 -
28 - Alternatively, the contents of this file may be used under the terms of
29 - either the GNU General Public License Version 2 or later (the "GPL"), or
30 - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 - in which case the provisions of the GPL or the LGPL are applicable instead
32 - of those above. If you wish to allow use of your version of this file only
33 - under the terms of either the GPL or the LGPL, and not to allow others to
34 - use your version of this file under the terms of the MPL, indicate your
35 - decision by deleting the provisions above and replace them with the notice
36 - and other provisions required by the GPL or the LGPL. If you do not delete
37 - the provisions above, a recipient may use your version of this file under
38 - the terms of any one of the MPL, the GPL or the LGPL.
39 -
40 - ***** END LICENSE BLOCK ***** -->
41
42 <bindings id="listboxBindings"
43 xmlns="http://www.mozilla.org/xbl"
44 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
45 xmlns:xbl="http://www.mozilla.org/xbl">
46
47 <!--
48 Interface binding that is base for bindings of xul:listbox and
49 xul:richlistbox elements. This binding assumes that successors bindings
50 will implement the following properties and methods:
51
52 /** Return the number of items */
53 readonly itemCount
54
55 /** Return index of given item
56 * @param aItem - given item element */
57 getIndexOfItem(aItem)
58
59 /** Return item at given index
60 * @param aIndex - index of item element */
61 getItemAtIndex(aIndex)
62
63 /** Return count of item elements */
64 getRowCount()
65
66 /** Return count of visible item elements */
67 getNumberOfVisibleRows()
68
69 /** Return index of first visible item element */
70 getIndexOfFirstVisibleRow()
71
72 /** Return true if item of given index is visible
73 * @param aIndex - index of item element
74 *
75 * @note XXX: this method should be removed after bug 364612 is fixed
76 */
77 ensureIndexIsVisible(aIndex)
78
79 /** Return true if item element is visible
80 * @param aElement - given item element */
81 ensureElementIsVisible(aElement)
82
83 /** Scroll list control to make visible item of given index
84 * @param aIndex - index of item element
85 *
86 * @note XXX: this method should be removed after bug 364612 is fixed
87 */
88 scrollToIndex(aIndex)
89
90 /** Create item element and append it to the end of listbox
91 * @param aLabel - label of new item element
92 * @param aValue - value of new item element */
93 appendItem(aLabel, aValue)
94
95 /** Create item element and insert it to given position
96 * @param aIndex - insertion position
97 * @param aLabel - label of new item element
98 * @param aValue - value of new item element */
99 insertItemAt(aIndex, aLabel, aValue)
100
101 /** Scroll up/down one page
102 * @param aDirection - specifies scrolling direction, should be either -1 or 1
103 * @return the number of elements the selection scrolled
104 */
105 scrollOnePage(aDirection)
106
107 /** Fire "select" event */
108 _fireOnSelect()
109 -->
110 <binding id="listbox-base"
111 extends="chrome://global/content/bindings/general.xml#basecontrol">
112
113 <implementation implements="nsIDOMXULMultiSelectControlElement, nsIAccessibleProvider">
field__lastKeyTime
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
114 <field name="_lastKeyTime">0</field>
field__incrementalString
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
115 <field name="_incrementalString">""</field>
116
117 <!-- nsIAccessibleProvider -->
118 <property name="accessibleType" readonly="true">
get_accessibleType
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
119 <getter>
120 return Components.interfaces.nsIAccessibleProvider.XULListbox;
121 </getter>
122 </property>
123
124 <!-- nsIDOMXULSelectControlElement -->
set_selectedItem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
125 <property name="selectedItem"
126 onset="this.selectItem(val);">
get_selectedItem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
127 <getter>
128 <![CDATA[
129 return this.selectedItems.length > 0 ? this.selectedItems[0] : null;
130 ]]>
131 </getter>
132 </property>
133
134 <property name="selectedIndex">
get_selectedIndex
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
135 <getter>
136 <![CDATA[
137 if (this.selectedItems.length > 0)
138 return this.getIndexOfItem(this.selectedItems[0]);
139 return -1;
140 ]]>
141 </getter>
set_selectedIndex
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
142 <setter>
143 <![CDATA[
144 if (val >= 0)
145 this.selectItem(this.getItemAtIndex(val));
146 else
147 this.clearSelection();
148 ]]>
149 </setter>
150 </property>
151
152 <property name="value">
get_value
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
153 <getter>
154 <![CDATA[
155 if (this.selectedItems.length > 0)
156 return this.selectedItem.value;
157 return null;
158 ]]>
159 </getter>
set_value
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
160 <setter>
161 <![CDATA[
162 var kids = this.getElementsByAttribute("value", val);
163 if (kids && kids.item(0))
164 this.selectItem(kids[0]);
165 return val;
166 ]]>
167 </setter>
168 </property>
169
170 <method name="removeItemAt">
171 <parameter name="index"/>
removeItemAt
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
172 <body>
173 <![CDATA[
174 var remove = this.getItemAtIndex(index);
175 if (remove)
176 this.removeChild(remove);
177 return remove;
178 ]]>
179 </body>
180 </method>
181
182 <!-- nsIDOMXULMultiSelectControlElement -->
get_selType
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
set_selType
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
183 <property name="selType"
184 onget="return this.getAttribute('seltype');"
185 onset="this.setAttribute('seltype', val); return val;"/>
186
get_currentItem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
187 <property name="currentItem" onget="return this._currentItem;">
set_currentItem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
188 <setter>
189 if (this._currentItem == val)
190 return val;
191
192 if (this._currentItem)
193 this._currentItem.current = false;
194 this._currentItem = val;
195
196 if (val)
197 val.current = true;
198
199 return val;
200 </setter>
201 </property>
202
203 <property name="currentIndex">
get_currentIndex
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
204 <getter>
205 return this.currentItem ? this.getIndexOfItem(this.currentItem) : -1;
206 </getter>
set_currentIndex
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
207 <setter>
208 <![CDATA[
209 if (val >= 0)
210 this.currentItem = this.getItemAtIndex(val);
211 else
212 this.currentItem = null;
213 ]]>
214 </setter>
215 </property>
216
field_selectedItems
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
217 <field name="selectedItems">[]</field>
218
219 <method name="addItemToSelection">
220 <parameter name="aItem"/>
addItemToSelection
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
221 <body>
222 <![CDATA[
223 if (this.selType != "multiple" && this.selectedCount)
224 return;
225
226 if (aItem.selected)
227 return;
228
229 this.selectedItems.push(aItem);
230 aItem.selected = true;
231
232 this._fireOnSelect();
233 ]]>
234 </body>
235 </method>
236
237 <method name="removeItemFromSelection">
238 <parameter name="aItem"/>
removeItemFromSelection
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
239 <body>
240 <![CDATA[
241 if (!aItem.selected)
242 return;
243
244 for (var i = 0; i < this.selectedItems.length; ++i) {
245 if (this.selectedItems[i] == aItem) {
246 this.selectedItems.splice(i, 1);
247 aItem.selected = false;
248 break;
249 }
250 }
251
252 this._fireOnSelect();
253 ]]>
254 </body>
255 </method>
256
257 <method name="toggleItemSelection">
258 <parameter name="aItem"/>
toggleItemSelection
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
259 <body>
260 <![CDATA[
261 if (aItem.selected)
262 this.removeItemFromSelection(aItem);
263 else
264 this.addItemToSelection(aItem);
265 ]]>
266 </body>
267 </method>
268
269 <method name="selectItem">
270 <parameter name="aItem"/>
selectItem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
271 <body>
272 <![CDATA[
273 if (!aItem)
274 return;
275
276 if (this.selectedItems.length == 1 && this.selectedItems[0] == aItem)
277 return;
278
279 this._selectionStart = null;
280
281 var suppress = this._suppressOnSelect;
282 this._suppressOnSelect = true;
283
284 this.clearSelection();
285 this.addItemToSelection(aItem);
286 this.currentItem = aItem;
287
288 this._suppressOnSelect = suppress;
289 this._fireOnSelect();
290 ]]>
291 </body>
292 </method>
293
294 <method name="selectItemRange">
295 <parameter name="aStartItem"/>
296 <parameter name="aEndItem"/>
selectItemRange
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
297 <body>
298 <![CDATA[
299 if (this.selType != "multiple")
300 return;
301
302 if (!aStartItem)
303 aStartItem = this._selectionStart ?
304 this._selectionStart : this.currentItem;
305
306 if (!aStartItem)
307 aStartItem = aEndItem;
308
309 var suppressSelect = this._suppressOnSelect;
310 this._suppressOnSelect = true;
311
312 this._selectionStart = aStartItem;
313
314 var currentItem;
315 var startIndex = this.getIndexOfItem(aStartItem);
316 var endIndex = this.getIndexOfItem(aEndItem);
317 if (endIndex < startIndex) {
318 currentItem = aEndItem;
319 aEndItem = aStartItem;
320 aStartItem = currentItem;
321 } else {
322 currentItem = aStartItem;
323 }
324
325 while (currentItem) {
326 this.addItemToSelection(currentItem);
327 if (currentItem == aEndItem) {
328 currentItem = this.getNextItem(currentItem, 1);
329 break;
330 }
331 currentItem = this.getNextItem(currentItem, 1);
332 }
333
334 // Clear around new selection
335 // Don't use clearSelection() because it causes a lot of noise
336 // with respect to selection removed notifications used by the
337 // accessibility API support.
338 var userSelecting = this._userSelecting;
339 this._userSelecting = false; // that's US automatically unselecting
340 for (; currentItem; currentItem = this.getNextItem(currentItem, 1))
341 this.removeItemFromSelection(currentItem);
342
343 for (currentItem = this.getItemAtIndex(0); currentItem != aStartItem;
344 currentItem = this.getNextItem(currentItem, 1))
345 this.removeItemFromSelection(currentItem);
346 this._userSelecting = userSelecting;
347
348 this._suppressOnSelect = suppressSelect;
349
350 this._fireOnSelect();
351 ]]>
352 </body>
353 </method>
354
355 <method name="selectAll">
selectAll
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
356 <body>
357 this._selectionStart = null;
358
359 var suppress = this._suppressOnSelect;
360 this._suppressOnSelect = true;
361
362 var item = this.getItemAtIndex(0);
363 while (item) {
364 this.addItemToSelection(item);
365 item = this.getNextItem(item, 1);
366 }
367
368 this._suppressOnSelect = suppress;
369 this._fireOnSelect();
370 </body>
371 </method>
372
373 <method name="invertSelection">
invertSelection
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
374 <body>
375 this._selectionStart = null;
376
377 var suppress = this._suppressOnSelect;
378 this._suppressOnSelect = true;
379
380 var item = this.getItemAtIndex(0);
381 while (item) {
382 if (item.selected)
383 this.removeItemFromSelection(item);
384 else
385 this.addItemToSelection(item);
386 item = this.getNextItem(item, 1);
387 }
388
389 this._suppressOnSelect = suppress;
390 this._fireOnSelect();
391 </body>
392 </method>
393
394 <method name="clearSelection">
clearSelection
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
395 <body>
396 <![CDATA[
397 if (this.selectedItems) {
398 for (var i = this.selectedItems.length - 1; i >= 0; --i)
399 this.selectedItems[i].selected = false;
400
401 this.selectedItems.splice(0, this.selectedItems.length);
402 }
403
404 this._selectionStart = null;
405 this._fireOnSelect();
406 ]]>
407 </body>
408 </method>
409
get_selectedCount
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
410 <property name="selectedCount" readonly="true"
411 onget="return this.selectedItems.length;"/>
412
413 <method name="getSelectedItem">
414 <parameter name="aIndex"/>
getSelectedItem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
415 <body>
416 <![CDATA[
417 return aIndex < this.selectedItems.length ?
418 this.selectedItems[aIndex] : null;
419 ]]>
420 </body>
421 </method>
422
423 <!-- Other public members -->
get_disableKeyNavigation
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
424 <property name="disableKeyNavigation"
425 onget="return this.hasAttribute('disableKeyNavigation');">
set_disableKeyNavigation
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
426 <setter>
427 if (val)
428 this.setAttribute("disableKeyNavigation", "true");
429 else
430 this.removeAttribute("disableKeyNavigation");
431 return val;
432 </setter>
433 </property>
434
get_suppressOnSelect
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
set_suppressOnSelect
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
435 <property name="suppressOnSelect"
436 onget="return this.getAttribute('suppressonselect') == 'true';"
437 onset="this.setAttribute('suppressonselect', val);"/>
438
get__selectDelay
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
set__selectDelay
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
439 <property name="_selectDelay"
440 onset="this.setAttribute('_selectDelay', val);"
441 onget="return this.getAttribute('_selectDelay') || 50;"/>
442
443 <method name="timedSelect">
444 <parameter name="aItem"/>
445 <parameter name="aTimeout"/>
timedSelect
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
446 <body>
447 <![CDATA[
448 var suppress = this._suppressOnSelect;
449 if (aTimeout != -1)
450 this._suppressOnSelect = true;
451
452 this.selectItem(aItem);
453
454 this._suppressOnSelect = suppress;
455
456 if (aTimeout != -1) {
457 if (this._selectTimeout)
458 window.clearTimeout(this._selectTimeout);
459 this._selectTimeout =
460 window.setTimeout(this._selectTimeoutHandler, aTimeout, this);
461 }
462 ]]>
463 </body>
464 </method>
465
466 <method name="moveByOffset">
467 <parameter name="aOffset"/>
468 <parameter name="aIsSelecting"/>
469 <parameter name="aIsSelectingRange"/>
moveByOffset
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
470 <body>
471 <![CDATA[
472 if ((aIsSelectingRange || !aIsSelecting) &&
473 this.selType != "multiple")
474 return;
475
476 var newIndex = this.currentIndex + aOffset;
477 if (newIndex < 0)
478 newIndex = 0;
479
480 var numItems = this.getRowCount();
481 if (newIndex > numItems - 1)
482 newIndex = numItems - 1;
483
484 var newItem = this.getItemAtIndex(newIndex);
485 // make sure that the item is actually visible/selectable
486 if (this._userSelecting && newItem && !this._canUserSelect(newItem))
487 newItem =
488 aOffset > 0 ? this.getNextItem(newItem, 1) || this.getPreviousItem(newItem, 1) :
489 this.getPreviousItem(newItem, 1) || this.getNextItem(newItem, 1);
490 if (newItem) {
491 this.ensureIndexIsVisible(this.getIndexOfItem(newItem));
492 if (aIsSelectingRange)
493 this.selectItemRange(null, newItem);
494 else if (aIsSelecting)
495 this.selectItem(newItem);
496
497 this.currentItem = newItem;
498 }
499 ]]>
500 </body>
501 </method>
502
503 <!-- Private -->
504 <method name="getNextItem">
505 <parameter name="aStartItem"/>
506 <parameter name="aDelta"/>
getNextItem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
507 <body>
508 <![CDATA[
509 while (aStartItem) {
510 aStartItem = aStartItem.nextSibling;
511 if (aStartItem && aStartItem instanceof
512 Components.interfaces.nsIDOMXULSelectControlItemElement &&
513 (!this._userSelecting || this._canUserSelect(aStartItem))) {
514 --aDelta;
515 if (aDelta == 0)
516 return aStartItem;
517 }
518 }
519 return null;
520 ]]></body>
521 </method>
522
523 <method name="getPreviousItem">
524 <parameter name="aStartItem"/>
525 <parameter name="aDelta"/>
getPreviousItem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
526 <body>
527 <![CDATA[
528 while (aStartItem) {
529 aStartItem = aStartItem.previousSibling;
530 if (aStartItem && aStartItem instanceof
531 Components.interfaces.nsIDOMXULSelectControlItemElement &&
532 (!this._userSelecting || this._canUserSelect(aStartItem))) {
533 --aDelta;
534 if (aDelta == 0)
535 return aStartItem;
536 }
537 }
538 return null;
539 ]]>
540 </body>
541 </method>
542
543 <method name="_moveByOffsetFromUserEvent">
544 <parameter name="aOffset"/>
545 <parameter name="aEvent"/>
_moveByOffsetFromUserEvent
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
546 <body>
547 <![CDATA[
548 if (!aEvent.getPreventDefault()) {
549 this._userSelecting = true;
550 this.moveByOffset(aOffset, !aEvent.ctrlKey, aEvent.shiftKey);
551 this._userSelecting = false;
552 aEvent.preventDefault();
553 }
554 ]]>
555 </body>
556 </method>
557
558 <method name="_canUserSelect">
559 <parameter name="aItem"/>
_canUserSelect
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
560 <body>
561 <![CDATA[
562 var style = document.defaultView.getComputedStyle(aItem, "");
563 return style.display != "none" && style.visibility == "visible";
564 ]]>
565 </body>
566 </method>
567
568 <method name="_selectTimeoutHandler">
569 <parameter name="aMe"/>
_selectTimeoutHandler
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
570 <body>
571 aMe._fireOnSelect();
572 aMe._selectTimeout = null;
573 </body>
574 </method>
575
field__suppressOnSelect
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
576 <field name="_suppressOnSelect">false</field>
field__userSelecting
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
577 <field name="_userSelecting">false</field>
field__selectTimeout
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
578 <field name="_selectTimeout">null</field>
field__currentItem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
579 <field name="_currentItem">null</field>
field__selectionStart
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
580 <field name="_selectionStart">null</field>
581 </implementation>
582
583 <handlers>
onkeypress
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
584 <handler event="keypress" keycode="VK_UP" modifiers="control shift any"
585 action="this._moveByOffsetFromUserEvent(-1, event);"
586 group="system"/>
onkeypress
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
587 <handler event="keypress" keycode="VK_DOWN" modifiers="control shift any"
588 action="this._moveByOffsetFromUserEvent(1, event);"
589 group="system"/>
onkeypress
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
590 <handler event="keypress" keycode="VK_HOME" modifiers="control shift any"
591 action="this._moveByOffsetFromUserEvent(-this.currentIndex, event);"
592 group="system"/>
onkeypress
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
593 <handler event="keypress" keycode="VK_END" modifiers="control shift any"
594 action="this._moveByOffsetFromUserEvent(this.getRowCount() - this.currentIndex - 1, event);"
595 group="system"/>
onkeypress
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
596 <handler event="keypress" keycode="VK_PAGE_UP" modifiers="control shift any"
597 action="this._moveByOffsetFromUserEvent(this.scrollOnePage(-1), event);"
598 group="system"/>
onkeypress
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
599 <handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="control shift any"
600 action="this._moveByOffsetFromUserEvent(this.scrollOnePage(1), event);"
601 group="system"/>
onkeypress
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
602 <handler event="keypress" key=" " modifiers="control" phase="target">
603 <![CDATA[
604 if (this.currentItem && this.selType == "multiple")
605 this.toggleItemSelection(this.currentItem);
606 ]]>
607 </handler>
onfocus
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
608 <handler event="focus">
609 <![CDATA[
610 if (this.getRowCount() > 0) {
611 if (this.currentIndex == -1) {
612 this.currentIndex = this.getIndexOfFirstVisibleRow();
613 }
614 else {
615 this.currentItem._fireEvent("DOMMenuItemActive");
616 }
617 }
618 this._lastKeyTime = 0;
619 ]]>
620 </handler>
onkeypress
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
621 <handler event="keypress" phase="target">
622 <![CDATA[
623 if (this.disableKeyNavigation || !event.charCode ||
624 event.altKey || event.ctrlKey || event.metaKey)
625 return;
626
627 if (event.timeStamp - this._lastKeyTime > 1000)
628 this._incrementalString = "";
629
630 var key = String.fromCharCode(event.charCode).toLowerCase();
631 this._incrementalString += key;
632 this._lastKeyTime = event.timeStamp;
633
634 // If all letters in the incremental string are the same, just
635 // try to match the first one
636 var incrementalString = /^(.)\1+$/.test(this._incrementalString) ?
637 RegExp.$1 : this._incrementalString;
638 var length = incrementalString.length;
639
640 var rowCount = this.getRowCount();
641 var l = this.selectedItems.length;
642 var start = l > 0 ? this.getIndexOfItem(this.selectedItems[l - 1]) : -1;
643 // start from the first element if none was selected or from the one
644 // following the selected one if it's a new or a repeated-letter search
645 if (start == -1 || length == 1)
646 start++;
647
648 for (var i = 0; i < rowCount; i++) {
649 var k = (start + i) % rowCount;
650 var listitem = this.getItemAtIndex(k);
651 if (!this._canUserSelect(listitem))
652 continue;
653 // allow richlistitems to specify the string being searched for
654 var searchText = "searchLabel" in listitem ? listitem.searchLabel :
655 listitem.getAttribute("label"); // (see also bug 250123)
656 searchText = searchText.substring(0, length).toLowerCase();
657 if (searchText == incrementalString) {
658 this.ensureIndexIsVisible(k);
659 this.timedSelect(listitem, this._selectDelay);
660 break;
661 }
662 }
663 ]]>
664 </handler>
665 </handlers>
666 </binding>
667
668
669 <!-- Binding for xul:listbox element.
670 -->
671 <binding id="listbox"
672 extends="#listbox-base">
673
674 <resources>
675 <stylesheet src="chrome://global/skin/listbox.css"/>
676 </resources>
677
678 <content>
679 <children includes="listcols">
680 <xul:listcols>
681 <xul:listcol flex="1"/>
682 </xul:listcols>
683 </children>
684 <xul:listrows>
685 <children includes="listhead"/>
686 <xul:listboxbody xbl:inherits="rows,size,minheight">
687 <children includes="listitem"/>
688 </xul:listboxbody>
689 </xul:listrows>
690 </content>
691
692 <implementation>
693
694 <!-- ///////////////// public listbox members ///////////////// -->
695
get_listBoxObject
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
696 <property name="listBoxObject"
697 onget="return this.boxObject.QueryInterface(Components.interfaces.nsIListBoxObject);"
698 readonly="true"/>
699
700 <!-- ///////////////// private listbox members ///////////////// -->
701
702 <method name="_fireOnSelect">
_fireOnSelect
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
703 <body>
704 <![CDATA[
705 if (!this._suppressOnSelect && !this.suppressOnSelect) {
706 var event = document.createEvent("Events");
707 event.initEvent("select", true, true);
708 this.dispatchEvent(event);
709 }
710 ]]>
711 </body>
712 </method>
713
constructor
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
714 <constructor>
715 <![CDATA[
716 var count = this.itemCount;
717 for (var index = 0; index < count; index++) {
718 var item = this.getItemAtIndex(index);
719 if (item.getAttribute("selected") == "true")
720 this.selectedItems.push(item);
721 }
722 ]]>
723 </constructor>
724
725 <!-- ///////////////// nsIDOMXULSelectControlElement ///////////////// -->
726
727 <method name="appendItem">
728 <parameter name="aLabel"/>
729 <parameter name="aValue"/>
appendItem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
730 <body>
731 const XULNS =
732 "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
733
734 var item = this.ownerDocument.createElementNS(XULNS, "listitem");
735 item.setAttribute("label", aLabel);
736 item.setAttribute("value", aValue);
737 this.appendChild(item);
738 return item;
739 </body>
740 </method>
741
742 <method name="insertItemAt">
743 <parameter name="aIndex"/>
744 <parameter name="aLabel"/>
745 <parameter name="aValue"/>
insertItemAt
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
746 <body>
747 const XULNS =
748 "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
749
750 var item = this.ownerDocument.createElementNS(XULNS, "listitem");
751 item.setAttribute("label", aLabel);
752 item.setAttribute("value", aValue);
753 var before = this.getItemAtIndex(aIndex);
754 if (before)
755 this.insertBefore(item, before);
756 else
757 this.appendChild(item);
758 return item;
759 </body>
760 </method>
761
get_itemCount
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
762 <property name="itemCount" readonly="true"
763 onget="return this.listBoxObject.getRowCount()"/>
764
765 <!-- ///////////////// nsIListBoxObject ///////////////// -->
766 <method name="getIndexOfItem">
767 <parameter name="item"/>
getIndexOfItem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
768 <body>
769 return this.listBoxObject.getIndexOfItem(item);
770 </body>
771 </method>
772 <method name="getItemAtIndex">
773 <parameter name="index"/>
getItemAtIndex
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
774 <body>
775 return this.listBoxObject.getItemAtIndex(index);
776 </body>
777 </method>
778 <method name="ensureIndexIsVisible">
779 <parameter name="index"/>
ensureIndexIsVisible
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
780 <body>
781 return this.listBoxObject.ensureIndexIsVisible(index);
782 </body>
783 </method>
784 <method name="ensureElementIsVisible">
785 <parameter name="element"/>
ensureElementIsVisible
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
786 <body>
787 return this.ensureIndexIsVisible(this.listBoxObject.getIndexOfItem(element));
788 </body>
789 </method>
790 <method name="scrollToIndex">
791 <parameter name="index"/>
scrollToIndex
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
792 <body>
793 return this.listBoxObject.scrollToIndex(index);
794 </body>
795 </method>
796 <method name="getNumberOfVisibleRows">
getNumberOfVisibleRows
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
797 <body>
798 return this.listBoxObject.getNumberOfVisibleRows();
799 </body>
800 </method>
801 <method name="getIndexOfFirstVisibleRow">
getIndexOfFirstVisibleRow
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
802 <body>
803 return this.listBoxObject.getIndexOfFirstVisibleRow();
804 </body>
805 </method>
806 <method name="getRowCount">
getRowCount
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
807 <body>
808 return this.listBoxObject.getRowCount();
809 </body>
810 </method>
811
812 <method name="scrollOnePage">
813 <parameter name="direction"/> <!-- Must be -1 or 1 -->
scrollOnePage
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
814 <body>
815 <![CDATA[
816 var pageOffset = this.getNumberOfVisibleRows() * direction;
817 // skip over invisible elements - the user won't care about them
818 for (var i = 0; i != pageOffset; i += direction) {
819 var item = this.getItemAtIndex(this.currentIndex + i);
820 if (item && !this._canUserSelect(item))
821 pageOffset += direction;
822 }
823 var newTop = this.getIndexOfFirstVisibleRow() + pageOffset;
824 if (direction == 1) {
825 var maxTop = this.getRowCount() - this.getNumberOfVisibleRows();
826 for (i = this.getRowCount(); i >= 0 && i > maxTop; i--) {
827 item = this.getItemAtIndex(i);
828 if (item && !this._canUserSelect(item))
829 maxTop--;
830 }
831 if (newTop >= maxTop)
832 newTop = maxTop;
833 }
834 if (newTop < 0)
835 newTop = 0;
836 this.scrollToIndex(newTop);
837 return pageOffset;
838 ]]>
839 </body>
840 </method>
841 </implementation>
842
843 <handlers>
onkeypress
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
844 <handler event="keypress" key=" " phase="target">
845 <![CDATA[
846 if (this.currentItem) {
847 if (this.currentItem.getAttribute("type") != "checkbox")
848 this.addItemToSelection(this.currentItem);
849 else if (!this.currentItem.disabled) {
850 this.currentItem.checked = !this.currentItem.checked;
851 this.currentItem.doCommand();
852 }
853 }
854 ]]>
855 </handler>
856 </handlers>
857 </binding>
858
859 <binding id="listrows">
860
861 <resources>
862 <stylesheet src="chrome://global/skin/listbox.css"/>
863 </resources>
864
865 <handlers>
onDOMMouseScroll
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
866 <handler event="DOMMouseScroll" phase="capturing">
867 <![CDATA[
868 var listBox = this.parentNode.listBoxObject;
869 var rows = event.detail;
870 if (rows == NSUIEvent.SCROLL_PAGE_UP)
871 rows = -listBox.getNumberOfVisibleRows();
872 else if (rows == NSUIEvent.SCROLL_PAGE_DOWN)
873 rows = listBox.getNumberOfVisibleRows();
874
875 listBox.scrollByLines(rows);
876 event.preventDefault();
877 ]]>
878 </handler>
879 </handlers>
880 </binding>
881
882 <binding id="listitem"
883 extends="chrome://global/content/bindings/general.xml#basetext">
884 <resources>
885 <stylesheet src="chrome://global/skin/listbox.css"/>
886 </resources>
887
888 <content>
889 <children>
890 <xul:listcell xbl:inherits="label,crop,disabled,flexlabel"/>
891 </children>
892 </content>
893
894 <implementation implements="nsIDOMXULSelectControlItemElement, nsIAccessibleProvider">
get_current
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
895 <property name="current" onget="return this.getAttribute('current') == 'true';">
set_current
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
896 <setter><![CDATA[
897 if (val)
898 this.setAttribute("current", "true");
899 else
900 this.removeAttribute("current");
901
902 this._fireEvent(val ? "DOMMenuItemActive" : "DOMMenuItemInactive");
903
904 return val;
905 ]]></setter>
906 </property>
907
908 <!-- ///////////////// nsIAccessibleProvider ///////////////// -->
909
910 <property name="accessibleType" readonly="true">
get_accessibleType
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
911 <getter>
912 <![CDATA[
913 return Components.interfaces.nsIAccessibleProvider.XULListitem;
914 ]]>
915 </getter>
916 </property>
917
918 <!-- ///////////////// nsIDOMXULSelectControlItemElement ///////////////// -->
919
get_value
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
set_value
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
920 <property name="value" onget="return this.getAttribute('value');"
921 onset="this.setAttribute('value', val); return val;"/>
get_label
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
set_label
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
922 <property name="label" onget="return this.getAttribute('label');"
923 onset="this.setAttribute('label', val); return val;"/>
924
get_selected
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
925 <property name="selected" onget="return this.getAttribute('selected') == 'true';">
set_selected
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
926 <setter><![CDATA[
927 if (val)
928 this.setAttribute("selected", "true");
929 else
930 this.removeAttribute("selected");
931
932 return val;
933 ]]></setter>
934 </property>
935
936 <property name="control">
get_control
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
937 <getter><![CDATA[
938 var parent = this.parentNode;
939 while (parent) {
940 if (parent instanceof Components.interfaces.nsIDOMXULSelectControlElement)
941 return parent;
942 parent = parent.parentNode;
943 }
944 return null;
945 ]]></getter>
946 </property>
947
948 <method name="_fireEvent">
949 <parameter name="name"/>
_fireEvent
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
950 <body>
951 <![CDATA[
952 var event = document.createEvent("Events");
953 event.initEvent(name, true, true);
954 this.dispatchEvent(event);
955 ]]>
956 </body>
957 </method>
958 </implementation>
959 <handlers>
960 <!-- If there is no modifier key, we select on mousedown, not
961 click, so that drags work correctly. -->
onmousedown
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
962 <handler event="mousedown">
963 <![CDATA[
964 var control = this.control;
965 if (!control || control.disabled)
966 return;
967 if ((!event.ctrlKey
968 || event.button == 2
969 ) && !event.shiftKey && !event.metaKey) {
970 if (!this.selected) {
971 control.selectItem(this);
972 }
973 control.currentItem = this;
974 }
975 ]]>
976 </handler>
977
978 <!-- On a click (up+down on the same item), deselect everything
979 except this item. -->
onclick
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
980 <handler event="click" button="0">
981 <![CDATA[
982 var control = this.control;
983 if (!control || control.disabled)
984 return;
985 control._userSelecting = true;
986 if (control.selType != "multiple") {
987 control.selectItem(this);
988 }
989 else if (event.ctrlKey || event.metaKey) {
990 control.toggleItemSelection(this);
991 control.currentItem = this;
992 }
993 else if (event.shiftKey) {
994 control.selectItemRange(null, this);
995 control.currentItem = this;
996 }
997 else {
998 /* We want to deselect all the selected items except what was
999 clicked, UNLESS it was a right-click. We have to do this
1000 in click rather than mousedown so that you can drag a
1001 selected group of items */
1002
1003 // use selectItemRange instead of selectItem, because this
1004 // doesn't de- and reselect this item if it is selected
1005 control.selectItemRange(this, this);
1006 }
1007 control._userSelecting = false;
1008 ]]>
1009 </handler>
1010 </handlers>
1011 </binding>
1012
1013 <binding id="listitem-iconic"
1014 extends="chrome://global/content/bindings/listbox.xml#listitem">
1015 <content>
1016 <children>
1017 <xul:listcell class="listcell-iconic" xbl:inherits="label,image,crop,disabled,flexlabel"/>
1018 </children>
1019 </content>
1020 </binding>
1021
1022 <binding id="listitem-checkbox"
1023 extends="chrome://global/content/bindings/listbox.xml#listitem">
1024 <content>
1025 <children>
1026 <xul:listcell type="checkbox" xbl:inherits="label,crop,checked,disabled,flexlabel"/>
1027 </children>
1028 </content>
1029
1030 <implementation>
get_checked
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1031 <property name="checked"
1032 onget="return this.getAttribute('checked') == 'true';">
set_checked
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1033 <setter><![CDATA[
1034 if (val)
1035 this.setAttribute('checked', 'true');
1036 else
1037 this.removeAttribute('checked');
1038 var event = document.createEvent('Events');
1039 event.initEvent('CheckboxStateChange', true, true);
1040 this.dispatchEvent(event);
1041 return val;
1042 ]]></setter>
1043 </property>
1044 </implementation>
1045
1046 <handlers>
onmousedown
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1047 <handler event="mousedown" button="0">
1048 <![CDATA[
1049 if (!this.disabled && !this.control.disabled) {
1050 this.checked = !this.checked;
1051 this.doCommand();
1052 }
1053 ]]>
1054 </handler>
1055 </handlers>
1056 </binding>
1057
1058 <binding id="listitem-checkbox-iconic"
1059 extends="chrome://global/content/bindings/listbox.xml#listitem-checkbox">
1060 <content>
1061 <children>
1062 <xul:listcell type="checkbox" class="listcell-iconic" xbl:inherits="label,image,crop,checked,disabled,flexlabel"/>
1063 </children>
1064 </content>
1065 </binding>
1066
1067 <binding id="listcell"
1068 extends="chrome://global/content/bindings/general.xml#basecontrol">
1069
1070 <resources>
1071 <stylesheet src="chrome://global/skin/listbox.css"/>
1072 </resources>
1073
1074 <content>
1075 <children>
1076 <xul:label class="listcell-label" xbl:inherits="value=label,flex=flexlabel,crop,disabled" flex="1" crop="right"/>
1077 </children>
1078 </content>
1079
1080 <implementation implements="nsIAccessibleProvider">
1081 <property name="accessibleType" readonly="true">
get_accessibleType
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1082 <getter>
1083 <![CDATA[
1084 // Don't expose xul:listcell as cell accessible until listbox is
1085 // multicolumn.
1086 const Ci = Components.interfaces;
1087 const kNoAccessible = Ci.nsIAccessibleProvider.NoAccessible;
1088 const kListCellAccessible = Ci.nsIAccessibleProvider.XULListCell;
1089
1090 var listitem = this.parentNode;
1091 if (!(listitem instanceof Ci.nsIDOMXULSelectControlItemElement))
1092 return kNoAccessible;
1093
1094 var list = listitem.control;
1095 if (!list)
1096 return kNoAccessible;
1097
1098 var listhead = list.getElementsByTagName("listhead")[0];
1099 if (!listhead)
1100 return kNoAccessible;
1101
1102 var listheaders = listhead.getElementsByTagName("listheader");
1103 if (listheaders.length <= 1)
1104 return kNoAccessible;
1105
1106 return kListCellAccessible;
1107 ]]>
1108 </getter>
1109 </property>
1110 </implementation>
1111 </binding>
1112
1113 <binding id="listcell-iconic"
1114 extends="chrome://global/content/bindings/listbox.xml#listcell">
1115 <content>
1116 <children>
1117 <xul:image class="listcell-icon" xbl:inherits="src=image"/>
1118 <xul:label class="listcell-label" xbl:inherits="value=label,flex=flexlabel,crop,disabled" flex="1" crop="right"/>
1119 </children>
1120 </content>
1121 </binding>
1122
1123 <binding id="listcell-checkbox"
1124 extends="chrome://global/content/bindings/listbox.xml#listcell">
1125 <content>
1126 <children>
1127 <xul:image class="listcell-check" xbl:inherits="checked,disabled"/>
1128 <xul:label class="listcell-label" xbl:inherits="value=label,flex=flexlabel,crop,disabled" flex="1" crop="right"/>
1129 </children>
1130 </content>
1131 </binding>
1132
1133 <binding id="listcell-checkbox-iconic"
1134 extends="chrome://global/content/bindings/listbox.xml#listcell-checkbox">
1135 <content>
1136 <children>
1137 <xul:image class="listcell-check" xbl:inherits="checked,disabled"/>
1138 <xul:image class="listcell-icon" xbl:inherits="src=image"/>
1139 <xul:label class="listcell-label" xbl:inherits="value=label,flex=flexlabel,crop,disabled" flex="1" crop="right"/>
1140 </children>
1141 </content>
1142 </binding>
1143
1144 <binding id="listhead">
1145
1146 <resources>
1147 <stylesheet src="chrome://global/skin/listbox.css"/>
1148 </resources>
1149
1150 <content>
1151 <xul:listheaditem>
1152 <children includes="listheader"/>
1153 </xul:listheaditem>
1154 </content>
1155
1156 <implementation implements="nsIAccessibleProvider">
1157 <property name="accessibleType" readonly="true">
get_accessibleType
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1158 <getter>
1159 return Components.interfaces.nsIAccessibleProvider.XULListHead;
1160 </getter>
1161 </property>
1162 </implementation>
1163 </binding>
1164
1165 <binding id="listheader" display="xul:button">
1166
1167 <resources>
1168 <stylesheet src="chrome://global/skin/listbox.css"/>
1169 </resources>
1170
1171 <content>
1172 <xul:image class="listheader-icon"/>
1173 <xul:label class="listheader-label" xbl:inherits="value=label,crop" flex="1" crop="right"/>
1174 <xul:image class="listheader-sortdirection" xbl:inherits="sortDirection"/>
1175 </content>
1176
1177 <implementation implements="nsIAccessibleProvider">
1178 <property name="accessibleType" readonly="true">
get_accessibleType
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1179 <getter>
1180 return Components.interfaces.nsIAccessibleProvider.XULListHeader;
1181 </getter>
1182 </property>
1183 </implementation>
1184 </binding>
1185
1186 </bindings>