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