toolkit/content/widgets/richlistbox.xml

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

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="richlistboxBindings"
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 <binding id="richlistbox"
michael@0 13 extends="chrome://global/content/bindings/listbox.xml#listbox-base">
michael@0 14 <resources>
michael@0 15 <stylesheet src="chrome://global/skin/richlistbox.css"/>
michael@0 16 </resources>
michael@0 17
michael@0 18 <content>
michael@0 19 <children includes="listheader"/>
michael@0 20 <xul:scrollbox allowevents="true" orient="vertical" anonid="main-box"
michael@0 21 flex="1" style="overflow: auto;" xbl:inherits="dir,pack">
michael@0 22 <children/>
michael@0 23 </xul:scrollbox>
michael@0 24 </content>
michael@0 25
michael@0 26 <implementation>
michael@0 27 <field name="_scrollbox">
michael@0 28 document.getAnonymousElementByAttribute(this, "anonid", "main-box");
michael@0 29 </field>
michael@0 30 <field name="scrollBoxObject">
michael@0 31 this._scrollbox.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
michael@0 32 </field>
michael@0 33 <constructor>
michael@0 34 <![CDATA[
michael@0 35 // add a template build listener
michael@0 36 if (this.builder)
michael@0 37 this.builder.addListener(this._builderListener);
michael@0 38 else
michael@0 39 this._refreshSelection();
michael@0 40 ]]>
michael@0 41 </constructor>
michael@0 42
michael@0 43 <destructor>
michael@0 44 <![CDATA[
michael@0 45 // remove the template build listener
michael@0 46 if (this.builder)
michael@0 47 this.builder.removeListener(this._builderListener);
michael@0 48 ]]>
michael@0 49 </destructor>
michael@0 50
michael@0 51 <!-- Overriding baselistbox -->
michael@0 52 <method name="_fireOnSelect">
michael@0 53 <body>
michael@0 54 <![CDATA[
michael@0 55 // make sure not to modify last-selected when suppressing select events
michael@0 56 // (otherwise we'll lose the selection when a template gets rebuilt)
michael@0 57 if (this._suppressOnSelect || this.suppressOnSelect)
michael@0 58 return;
michael@0 59
michael@0 60 // remember the current item and all selected items with IDs
michael@0 61 var state = this.currentItem ? this.currentItem.id : "";
michael@0 62 if (this.selType == "multiple" && this.selectedCount) {
michael@0 63 let getId = function getId(aItem) { return aItem.id; }
michael@0 64 state += " " + this.selectedItems.filter(getId).map(getId).join(" ");
michael@0 65 }
michael@0 66 if (state)
michael@0 67 this.setAttribute("last-selected", state);
michael@0 68 else
michael@0 69 this.removeAttribute("last-selected");
michael@0 70
michael@0 71 // preserve the index just in case no IDs are available
michael@0 72 if (this.currentIndex > -1)
michael@0 73 this._currentIndex = this.currentIndex + 1;
michael@0 74
michael@0 75 var event = document.createEvent("Events");
michael@0 76 event.initEvent("select", true, true);
michael@0 77 this.dispatchEvent(event);
michael@0 78
michael@0 79 // always call this (allows a commandupdater without controller)
michael@0 80 document.commandDispatcher.updateCommands("richlistbox-select");
michael@0 81 ]]>
michael@0 82 </body>
michael@0 83 </method>
michael@0 84
michael@0 85 <!-- We override base-listbox here because those methods don't take dir
michael@0 86 into account on listbox (which doesn't support dir yet) -->
michael@0 87 <method name="getNextItem">
michael@0 88 <parameter name="aStartItem"/>
michael@0 89 <parameter name="aDelta"/>
michael@0 90 <body>
michael@0 91 <![CDATA[
michael@0 92 var prop = this.dir == "reverse" && this._mayReverse ?
michael@0 93 "previousSibling" :
michael@0 94 "nextSibling";
michael@0 95 while (aStartItem) {
michael@0 96 aStartItem = aStartItem[prop];
michael@0 97 if (aStartItem && aStartItem instanceof
michael@0 98 Components.interfaces.nsIDOMXULSelectControlItemElement &&
michael@0 99 (!this._userSelecting || this._canUserSelect(aStartItem))) {
michael@0 100 --aDelta;
michael@0 101 if (aDelta == 0)
michael@0 102 return aStartItem;
michael@0 103 }
michael@0 104 }
michael@0 105 return null;
michael@0 106 ]]></body>
michael@0 107 </method>
michael@0 108
michael@0 109 <method name="getPreviousItem">
michael@0 110 <parameter name="aStartItem"/>
michael@0 111 <parameter name="aDelta"/>
michael@0 112 <body>
michael@0 113 <![CDATA[
michael@0 114 var prop = this.dir == "reverse" && this._mayReverse ?
michael@0 115 "nextSibling" :
michael@0 116 "previousSibling";
michael@0 117 while (aStartItem) {
michael@0 118 aStartItem = aStartItem[prop];
michael@0 119 if (aStartItem && aStartItem instanceof
michael@0 120 Components.interfaces.nsIDOMXULSelectControlItemElement &&
michael@0 121 (!this._userSelecting || this._canUserSelect(aStartItem))) {
michael@0 122 --aDelta;
michael@0 123 if (aDelta == 0)
michael@0 124 return aStartItem;
michael@0 125 }
michael@0 126 }
michael@0 127 return null;
michael@0 128 ]]>
michael@0 129 </body>
michael@0 130 </method>
michael@0 131
michael@0 132 <method name="appendItem">
michael@0 133 <parameter name="aLabel"/>
michael@0 134 <parameter name="aValue"/>
michael@0 135 <body>
michael@0 136 return this.insertItemAt(-1, aLabel, aValue);
michael@0 137 </body>
michael@0 138 </method>
michael@0 139
michael@0 140 <method name="insertItemAt">
michael@0 141 <parameter name="aIndex"/>
michael@0 142 <parameter name="aLabel"/>
michael@0 143 <parameter name="aValue"/>
michael@0 144 <body>
michael@0 145 const XULNS =
michael@0 146 "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
michael@0 147
michael@0 148 var item =
michael@0 149 this.ownerDocument.createElementNS(XULNS, "richlistitem");
michael@0 150 item.setAttribute("value", aValue);
michael@0 151
michael@0 152 var label = this.ownerDocument.createElementNS(XULNS, "label");
michael@0 153 label.setAttribute("value", aLabel);
michael@0 154 label.setAttribute("flex", "1");
michael@0 155 label.setAttribute("crop", "end");
michael@0 156 item.appendChild(label);
michael@0 157
michael@0 158 var before = this.getItemAtIndex(aIndex);
michael@0 159 if (!before)
michael@0 160 this.appendChild(item);
michael@0 161 else
michael@0 162 this.insertBefore(item, before);
michael@0 163
michael@0 164 return item;
michael@0 165 </body>
michael@0 166 </method>
michael@0 167
michael@0 168 <property name="itemCount" readonly="true"
michael@0 169 onget="return this.children.length"/>
michael@0 170
michael@0 171 <method name="getIndexOfItem">
michael@0 172 <parameter name="aItem"/>
michael@0 173 <body>
michael@0 174 <![CDATA[
michael@0 175 // don't search the children, if we're looking for none of them
michael@0 176 if (aItem == null)
michael@0 177 return -1;
michael@0 178
michael@0 179 return this.children.indexOf(aItem);
michael@0 180 ]]>
michael@0 181 </body>
michael@0 182 </method>
michael@0 183
michael@0 184 <method name="getItemAtIndex">
michael@0 185 <parameter name="aIndex"/>
michael@0 186 <body>
michael@0 187 return this.children[aIndex] || null;
michael@0 188 </body>
michael@0 189 </method>
michael@0 190
michael@0 191 <method name="ensureIndexIsVisible">
michael@0 192 <parameter name="aIndex"/>
michael@0 193 <body>
michael@0 194 <![CDATA[
michael@0 195 // work around missing implementation in scrollBoxObject
michael@0 196 return this.ensureElementIsVisible(this.getItemAtIndex(aIndex));
michael@0 197 ]]>
michael@0 198 </body>
michael@0 199 </method>
michael@0 200
michael@0 201 <method name="ensureElementIsVisible">
michael@0 202 <parameter name="aElement"/>
michael@0 203 <body>
michael@0 204 <![CDATA[
michael@0 205 if (!aElement)
michael@0 206 return;
michael@0 207 var targetRect = aElement.getBoundingClientRect();
michael@0 208 var scrollRect = this._scrollbox.getBoundingClientRect();
michael@0 209 var offset = targetRect.top - scrollRect.top;
michael@0 210 if (offset >= 0) {
michael@0 211 // scrollRect.bottom wouldn't take a horizontal scroll bar into account
michael@0 212 let scrollRectBottom = scrollRect.top + this._scrollbox.clientHeight;
michael@0 213 offset = targetRect.bottom - scrollRectBottom;
michael@0 214 if (offset <= 0)
michael@0 215 return;
michael@0 216 }
michael@0 217 this._scrollbox.scrollTop += offset;
michael@0 218 ]]>
michael@0 219 </body>
michael@0 220 </method>
michael@0 221
michael@0 222 <method name="scrollToIndex">
michael@0 223 <parameter name="aIndex"/>
michael@0 224 <body>
michael@0 225 <![CDATA[
michael@0 226 var item = this.getItemAtIndex(aIndex);
michael@0 227 if (item)
michael@0 228 this.scrollBoxObject.scrollToElement(item);
michael@0 229 ]]>
michael@0 230 </body>
michael@0 231 </method>
michael@0 232
michael@0 233 <method name="getNumberOfVisibleRows">
michael@0 234 <!-- returns the number of currently visible rows -->
michael@0 235 <!-- don't rely on this function, if the items' height can vary! -->
michael@0 236 <body>
michael@0 237 <![CDATA[
michael@0 238 var children = this.children;
michael@0 239
michael@0 240 for (var top = 0; top < children.length && !this._isItemVisible(children[top]); top++);
michael@0 241 for (var ix = top; ix < children.length && this._isItemVisible(children[ix]); ix++);
michael@0 242
michael@0 243 return ix - top;
michael@0 244 ]]>
michael@0 245 </body>
michael@0 246 </method>
michael@0 247
michael@0 248 <method name="getIndexOfFirstVisibleRow">
michael@0 249 <body>
michael@0 250 <![CDATA[
michael@0 251 var children = this.children;
michael@0 252
michael@0 253 for (var ix = 0; ix < children.length; ix++)
michael@0 254 if (this._isItemVisible(children[ix]))
michael@0 255 return ix;
michael@0 256
michael@0 257 return -1;
michael@0 258 ]]>
michael@0 259 </body>
michael@0 260 </method>
michael@0 261
michael@0 262 <method name="getRowCount">
michael@0 263 <body>
michael@0 264 <![CDATA[
michael@0 265 return this.children.length;
michael@0 266 ]]>
michael@0 267 </body>
michael@0 268 </method>
michael@0 269
michael@0 270 <method name="scrollOnePage">
michael@0 271 <parameter name="aDirection"/> <!-- Must be -1 or 1 -->
michael@0 272 <body>
michael@0 273 <![CDATA[
michael@0 274 var children = this.children;
michael@0 275
michael@0 276 if (children.length == 0)
michael@0 277 return 0;
michael@0 278
michael@0 279 // If nothing is selected, we just select the first element
michael@0 280 // at the extreme we're moving away from
michael@0 281 if (!this.currentItem)
michael@0 282 return aDirection == -1 ? children.length : 0;
michael@0 283
michael@0 284 // If the current item is visible, scroll by one page so that
michael@0 285 // the new current item is at approximately the same position as
michael@0 286 // the existing current item.
michael@0 287 if (this._isItemVisible(this.currentItem))
michael@0 288 this.scrollBoxObject.scrollBy(0, this.scrollBoxObject.height * aDirection);
michael@0 289
michael@0 290 // Figure out, how many items fully fit into the view port
michael@0 291 // (including the currently selected one), and determine
michael@0 292 // the index of the first one lying (partially) outside
michael@0 293 var height = this.scrollBoxObject.height;
michael@0 294 var startBorder = this.currentItem.boxObject.y;
michael@0 295 if (aDirection == -1)
michael@0 296 startBorder += this.currentItem.boxObject.height;
michael@0 297
michael@0 298 var index = this.currentIndex;
michael@0 299 for (var ix = index; 0 <= ix && ix < children.length; ix += aDirection) {
michael@0 300 var boxObject = children[ix].boxObject;
michael@0 301 if (boxObject.height == 0)
michael@0 302 continue; // hidden children have a y of 0
michael@0 303 var endBorder = boxObject.y + (aDirection == -1 ? boxObject.height : 0);
michael@0 304 if ((endBorder - startBorder) * aDirection > height)
michael@0 305 break; // we've reached the desired distance
michael@0 306 index = ix;
michael@0 307 }
michael@0 308
michael@0 309 return index != this.currentIndex ? index - this.currentIndex : aDirection;
michael@0 310 ]]>
michael@0 311 </body>
michael@0 312 </method>
michael@0 313
michael@0 314 <!-- richlistbox specific -->
michael@0 315 <property name="children" readonly="true">
michael@0 316 <getter>
michael@0 317 <![CDATA[
michael@0 318 var childNodes = [];
michael@0 319 var isReverse = this.dir == "reverse" && this._mayReverse;
michael@0 320 var child = isReverse ? this.lastChild : this.firstChild;
michael@0 321 var prop = isReverse ? "previousSibling" : "nextSibling";
michael@0 322 while (child) {
michael@0 323 if (child instanceof Components.interfaces.nsIDOMXULSelectControlItemElement)
michael@0 324 childNodes.push(child);
michael@0 325 child = child[prop];
michael@0 326 }
michael@0 327 return childNodes;
michael@0 328 ]]>
michael@0 329 </getter>
michael@0 330 </property>
michael@0 331
michael@0 332 <field name="_builderListener" readonly="true">
michael@0 333 <![CDATA[
michael@0 334 ({
michael@0 335 mOuter: this,
michael@0 336 item: null,
michael@0 337 willRebuild: function(builder) { },
michael@0 338 didRebuild: function(builder) {
michael@0 339 this.mOuter._refreshSelection();
michael@0 340 }
michael@0 341 });
michael@0 342 ]]>
michael@0 343 </field>
michael@0 344
michael@0 345 <method name="_refreshSelection">
michael@0 346 <body>
michael@0 347 <![CDATA[
michael@0 348 // when this method is called, we know that either the currentItem
michael@0 349 // and selectedItems we have are null (ctor) or a reference to an
michael@0 350 // element no longer in the DOM (template).
michael@0 351
michael@0 352 // first look for the last-selected attribute
michael@0 353 var state = this.getAttribute("last-selected");
michael@0 354 if (state) {
michael@0 355 var ids = state.split(" ");
michael@0 356
michael@0 357 var suppressSelect = this._suppressOnSelect;
michael@0 358 this._suppressOnSelect = true;
michael@0 359 this.clearSelection();
michael@0 360 for (var i = 1; i < ids.length; i++) {
michael@0 361 var selectedItem = document.getElementById(ids[i]);
michael@0 362 if (selectedItem)
michael@0 363 this.addItemToSelection(selectedItem);
michael@0 364 }
michael@0 365
michael@0 366 var currentItem = document.getElementById(ids[0]);
michael@0 367 if (!currentItem && this._currentIndex)
michael@0 368 currentItem = this.getItemAtIndex(Math.min(
michael@0 369 this._currentIndex - 1, this.getRowCount()));
michael@0 370 if (currentItem) {
michael@0 371 this.currentItem = currentItem;
michael@0 372 if (this.selType != "multiple" && this.selectedCount == 0)
michael@0 373 this.selectedItem = currentItem;
michael@0 374
michael@0 375 if (this.scrollBoxObject.height) {
michael@0 376 this.ensureElementIsVisible(currentItem);
michael@0 377 }
michael@0 378 else {
michael@0 379 // XXX hack around a bug in ensureElementIsVisible as it will
michael@0 380 // scroll beyond the last element, bug 493645.
michael@0 381 var previousElement = this.dir == "reverse" ? currentItem.nextSibling :
michael@0 382 currentItem.previousSibling;
michael@0 383 this.ensureElementIsVisible(previousElement);
michael@0 384 }
michael@0 385 }
michael@0 386 this._suppressOnSelect = suppressSelect;
michael@0 387 // XXX actually it's just a refresh, but at least
michael@0 388 // the Extensions manager expects this:
michael@0 389 this._fireOnSelect();
michael@0 390 return;
michael@0 391 }
michael@0 392
michael@0 393 // try to restore the selected items according to their IDs
michael@0 394 // (applies after a template rebuild, if last-selected was not set)
michael@0 395 if (this.selectedItems) {
michael@0 396 for (i = this.selectedCount - 1; i >= 0; i--) {
michael@0 397 if (this.selectedItems[i] && this.selectedItems[i].id)
michael@0 398 this.selectedItems[i] = document.getElementById(this.selectedItems[i].id);
michael@0 399 else
michael@0 400 this.selectedItems[i] = null;
michael@0 401 if (!this.selectedItems[i])
michael@0 402 this.selectedItems.splice(i, 1);
michael@0 403 }
michael@0 404 }
michael@0 405 if (this.currentItem && this.currentItem.id)
michael@0 406 this.currentItem = document.getElementById(this.currentItem.id);
michael@0 407 else
michael@0 408 this.currentItem = null;
michael@0 409
michael@0 410 // if we have no previously current item or if the above check fails to
michael@0 411 // find the previous nodes (which causes it to clear selection)
michael@0 412 if (!this.currentItem && this.selectedCount == 0) {
michael@0 413 this.currentIndex = this._currentIndex ? this._currentIndex - 1 : 0;
michael@0 414
michael@0 415 // cf. listbox constructor:
michael@0 416 // select items according to their attributes
michael@0 417 var children = this.children;
michael@0 418 for (var i = 0; i < children.length; ++i) {
michael@0 419 if (children[i].getAttribute("selected") == "true")
michael@0 420 this.selectedItems.push(children[i]);
michael@0 421 }
michael@0 422 }
michael@0 423
michael@0 424 if (this.selType != "multiple" && this.selectedCount == 0)
michael@0 425 this.selectedItem = this.currentItem;
michael@0 426 ]]>
michael@0 427 </body>
michael@0 428 </method>
michael@0 429
michael@0 430 <method name="_isItemVisible">
michael@0 431 <parameter name="aItem"/>
michael@0 432 <body>
michael@0 433 <![CDATA[
michael@0 434 if (!aItem)
michael@0 435 return false;
michael@0 436
michael@0 437 var y = {};
michael@0 438 this.scrollBoxObject.getPosition({}, y);
michael@0 439 y.value += this.scrollBoxObject.y;
michael@0 440
michael@0 441 // Partially visible items are also considered visible
michael@0 442 return (aItem.boxObject.y + aItem.boxObject.height > y.value) &&
michael@0 443 (aItem.boxObject.y < y.value + this.scrollBoxObject.height);
michael@0 444 ]]>
michael@0 445 </body>
michael@0 446 </method>
michael@0 447
michael@0 448 <field name="_currentIndex">null</field>
michael@0 449
michael@0 450 <!-- For backwards-compatibility and for convenience.
michael@0 451 Use getIndexOfItem instead. -->
michael@0 452 <method name="getIndexOf">
michael@0 453 <parameter name="aElement"/>
michael@0 454 <body>
michael@0 455 <![CDATA[
michael@0 456 return this.getIndexOfItem(aElement);
michael@0 457 ]]>
michael@0 458 </body>
michael@0 459 </method>
michael@0 460
michael@0 461 <!-- For backwards-compatibility and for convenience.
michael@0 462 Use ensureElementIsVisible instead -->
michael@0 463 <method name="ensureSelectedElementIsVisible">
michael@0 464 <body>
michael@0 465 <![CDATA[
michael@0 466 return this.ensureElementIsVisible(this.selectedItem);
michael@0 467 ]]>
michael@0 468 </body>
michael@0 469 </method>
michael@0 470
michael@0 471 <!-- For backwards-compatibility and for convenience.
michael@0 472 Use moveByOffset instead. -->
michael@0 473 <method name="goUp">
michael@0 474 <body>
michael@0 475 <![CDATA[
michael@0 476 var index = this.currentIndex;
michael@0 477 this.moveByOffset(-1, true, false);
michael@0 478 return index != this.currentIndex;
michael@0 479 ]]>
michael@0 480 </body>
michael@0 481 </method>
michael@0 482 <method name="goDown">
michael@0 483 <body>
michael@0 484 <![CDATA[
michael@0 485 var index = this.currentIndex;
michael@0 486 this.moveByOffset(1, true, false);
michael@0 487 return index != this.currentIndex;
michael@0 488 ]]>
michael@0 489 </body>
michael@0 490 </method>
michael@0 491
michael@0 492 <!-- deprecated (is implied by currentItem and selectItem) -->
michael@0 493 <method name="fireActiveItemEvent"><body/></method>
michael@0 494 </implementation>
michael@0 495
michael@0 496 <handlers>
michael@0 497 <handler event="click">
michael@0 498 <![CDATA[
michael@0 499 // clicking into nothing should unselect
michael@0 500 if (event.originalTarget == this._scrollbox) {
michael@0 501 this.clearSelection();
michael@0 502 this.currentItem = null;
michael@0 503 }
michael@0 504 ]]>
michael@0 505 </handler>
michael@0 506
michael@0 507 <handler event="MozSwipeGesture">
michael@0 508 <![CDATA[
michael@0 509 // Only handle swipe gestures up and down
michael@0 510 switch (event.direction) {
michael@0 511 case event.DIRECTION_DOWN:
michael@0 512 this._scrollbox.scrollTop = this._scrollbox.scrollHeight;
michael@0 513 break;
michael@0 514 case event.DIRECTION_UP:
michael@0 515 this._scrollbox.scrollTop = 0;
michael@0 516 break;
michael@0 517 }
michael@0 518 ]]>
michael@0 519 </handler>
michael@0 520 </handlers>
michael@0 521 </binding>
michael@0 522
michael@0 523 <binding id="richlistitem"
michael@0 524 extends="chrome://global/content/bindings/listbox.xml#listitem">
michael@0 525 <content>
michael@0 526 <children/>
michael@0 527 </content>
michael@0 528
michael@0 529 <resources>
michael@0 530 <stylesheet src="chrome://global/skin/richlistbox.css"/>
michael@0 531 </resources>
michael@0 532
michael@0 533 <implementation>
michael@0 534 <destructor>
michael@0 535 <![CDATA[
michael@0 536 var control = this.control;
michael@0 537 if (!control)
michael@0 538 return;
michael@0 539 // When we are destructed and we are current or selected, unselect ourselves
michael@0 540 // so that richlistbox's selection doesn't point to something not in the DOM.
michael@0 541 // We don't want to reset last-selected, so we set _suppressOnSelect.
michael@0 542 if (this.selected) {
michael@0 543 var suppressSelect = control._suppressOnSelect;
michael@0 544 control._suppressOnSelect = true;
michael@0 545 control.removeItemFromSelection(this);
michael@0 546 control._suppressOnSelect = suppressSelect;
michael@0 547 }
michael@0 548 if (this.current)
michael@0 549 control.currentItem = null;
michael@0 550 ]]>
michael@0 551 </destructor>
michael@0 552
michael@0 553 <property name="label" readonly="true">
michael@0 554 <!-- Setter purposely not implemented; the getter returns a
michael@0 555 concatentation of label text to expose via accessibility APIs -->
michael@0 556 <getter>
michael@0 557 <![CDATA[
michael@0 558 const XULNS =
michael@0 559 "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
michael@0 560 return Array.map(this.getElementsByTagNameNS(XULNS, "label"),
michael@0 561 function (label) label.value)
michael@0 562 .join(" ");
michael@0 563 ]]>
michael@0 564 </getter>
michael@0 565 </property>
michael@0 566
michael@0 567 <property name="searchLabel">
michael@0 568 <getter>
michael@0 569 <![CDATA[
michael@0 570 return this.hasAttribute("searchlabel") ?
michael@0 571 this.getAttribute("searchlabel") : this.label;
michael@0 572 ]]>
michael@0 573 </getter>
michael@0 574 <setter>
michael@0 575 <![CDATA[
michael@0 576 if (val !== null)
michael@0 577 this.setAttribute("searchlabel", val);
michael@0 578 else
michael@0 579 // fall back to the label property (default value)
michael@0 580 this.removeAttribute("searchlabel");
michael@0 581 return val;
michael@0 582 ]]>
michael@0 583 </setter>
michael@0 584 </property>
michael@0 585 </implementation>
michael@0 586 </binding>
michael@0 587 </bindings>
michael@0 588

mercurial