~vono22/cookiekeeper/1.9.0

« back to all changes in this revision

Viewing changes to cookiekeeper/chrome/content/iradio.xml

  • Committer: Yvon TANGUY
  • Date: 2014-01-23 12:08:35 UTC
  • Revision ID: vono@vono.zsh.jp-20140123120835-btzrqyhypbvf3nll
initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?xml version="1.0"?>
2
 
<!--
3
 
   - CookieKeeper - a Mozilla add-on
4
 
   - (c) 2013-2016 Yvon TANGUY
5
 
   -
6
 
   - ==================================================================
7
 
   - This Source Code Form is subject to the terms of the Mozilla Public
8
 
   - License, v. 2.0. If a copy of the MPL was not distributed with this
9
 
   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
10
 
 
11
 
<!--
12
 
  This code is based on mozilla radio.xml code.
13
 
  radio image button:
14
 
    - Always have a image (icon)
15
 
    - Like some Blender radio buttons (icon for each choice), packed.
16
 
    - Can be focus, menu can be triggered with the keyboard
17
 
-->
18
 
 
19
 
 
20
 
<bindings id="iradioBindings"
21
 
   xmlns="http://www.mozilla.org/xbl"
22
 
   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
23
 
   xmlns:xbl="http://www.mozilla.org/xbl">
24
 
 
25
 
  <binding id="iradiogroup" role="xul:radiogroup"
26
 
           extends="chrome://global/content/bindings/general.xml#basecontrol">
27
 
    <resources>
28
 
      <stylesheet src="chrome://cookiekeeper/skin/iradio.css"/>
29
 
    </resources>
30
 
 
31
 
    <implementation implements="nsIDOMXULSelectControlElement">
32
 
      <constructor>
33
 
        <![CDATA[
34
 
          if (this.getAttribute("disabled") == "true")
35
 
            this.disabled = true;
36
 
 
37
 
          var children = this._getRadioChildren();
38
 
          var length = children.length;
39
 
          for (var i = 0; i < length; i++) {
40
 
            if (children[i].getAttribute("selected") == "true") {
41
 
              this.selectedIndex = i;
42
 
              return;
43
 
            }
44
 
          }
45
 
 
46
 
          var value = this.value;
47
 
          if (value)
48
 
            this.value = value;
49
 
          else
50
 
            this.selectedIndex = 0;
51
 
        ]]>
52
 
      </constructor>
53
 
 
54
 
      <property name="value" onget="return this.getAttribute('value');">
55
 
        <setter>
56
 
          <![CDATA[
57
 
            this.setAttribute("value", val);
58
 
            var children = this._getRadioChildren();
59
 
            for (var i = 0; i < children.length; i++) {
60
 
              if (String(children[i].value) == String(val)) {
61
 
                this.selectedItem = children[i];
62
 
                break;
63
 
              }
64
 
            }
65
 
            return val;
66
 
          ]]>
67
 
        </setter>
68
 
      </property>
69
 
      <property name="disabled">
70
 
        <getter>
71
 
        <![CDATA[
72
 
          if (this.getAttribute('disabled') == 'true')
73
 
            return true;
74
 
          var children = this._getRadioChildren();
75
 
          for (var i = 0; i < children.length; ++i) {
76
 
            if (!children[i].hidden && !children[i].collapsed && !children[i].disabled)
77
 
              return false;
78
 
          }
79
 
          return true;
80
 
        ]]>
81
 
        </getter>
82
 
        <setter>
83
 
        <![CDATA[
84
 
          if (val)
85
 
            this.setAttribute('disabled', 'true');
86
 
          else
87
 
            this.removeAttribute('disabled');
88
 
          var children = this._getRadioChildren();
89
 
          for (var i = 0; i < children.length; ++i) {
90
 
            children[i].disabled = val;
91
 
          }
92
 
          return val;
93
 
        ]]>
94
 
        </setter>
95
 
      </property>
96
 
 
97
 
      <property name="itemCount" readonly="true"
98
 
                onget="return this._getRadioChildren().length"/>
99
 
 
100
 
      <property name="selectedIndex">
101
 
        <getter>
102
 
        <![CDATA[
103
 
          var children = this._getRadioChildren();
104
 
          for (var i = 0; i < children.length; ++i) {
105
 
            if (children[i].selected)
106
 
              return i;
107
 
          }
108
 
          return -1;
109
 
        ]]>
110
 
        </getter>
111
 
        <setter>
112
 
        <![CDATA[
113
 
          this.selectedItem = this._getRadioChildren()[val];
114
 
          return val;
115
 
        ]]>
116
 
        </setter>
117
 
      </property>
118
 
 
119
 
      <property name="selectedItem">
120
 
        <getter>
121
 
        <![CDATA[
122
 
          var children = this._getRadioChildren();
123
 
          for (var i = 0; i < children.length; ++i) {
124
 
            if (children[i].selected)
125
 
              return children[i];
126
 
          }
127
 
          return null;
128
 
        ]]>
129
 
        </getter>
130
 
        <setter>
131
 
        <![CDATA[
132
 
          var focused = this.getAttribute("focused") == "true";
133
 
          var alreadySelected = false;
134
 
 
135
 
          if (val) {
136
 
            alreadySelected = val.getAttribute("selected") == "true";
137
 
            val.setAttribute("focused", focused);
138
 
            val.setAttribute("selected", "true");
139
 
            this.setAttribute("value", val.value);
140
 
          }
141
 
          else {
142
 
            this.removeAttribute("value");
143
 
          }
144
 
 
145
 
          // uncheck all other group nodes
146
 
          var children = this._getRadioChildren();
147
 
          var previousItem = null;
148
 
          for (var i = 0; i < children.length; ++i) {
149
 
            if (children[i] != val) {
150
 
              if (children[i].getAttribute("selected") == "true")
151
 
                previousItem = children[i];
152
 
 
153
 
              children[i].removeAttribute("selected");
154
 
              children[i].removeAttribute("focused");
155
 
            }
156
 
          }
157
 
 
158
 
          var event = document.createEvent("Events");
159
 
          event.initEvent("select", false, true);
160
 
          this.dispatchEvent(event);
161
 
 
162
 
          if (!alreadySelected && focused) {
163
 
            // Only report if actual change
164
 
            var myEvent;
165
 
            if (val) {
166
 
              myEvent = document.createEvent("Events");
167
 
              myEvent.initEvent("RadioStateChange", true, true);
168
 
              val.dispatchEvent(myEvent);
169
 
            }
170
 
 
171
 
            if (previousItem) {
172
 
              myEvent = document.createEvent("Events");
173
 
              myEvent.initEvent("RadioStateChange", true, true);
174
 
              previousItem.dispatchEvent(myEvent);
175
 
            }
176
 
          }
177
 
 
178
 
          return val;
179
 
        ]]>
180
 
        </setter>
181
 
      </property>
182
 
 
183
 
      <property name="focusedItem">
184
 
        <getter>
185
 
        <![CDATA[
186
 
          var children = this._getRadioChildren();
187
 
          for (var i = 0; i < children.length; ++i) {
188
 
            if (children[i].getAttribute("focused") == "true")
189
 
              return children[i];
190
 
          }
191
 
          return null;
192
 
        ]]>
193
 
        </getter>
194
 
        <setter>
195
 
        <![CDATA[
196
 
          if (val) val.setAttribute("focused", "true");
197
 
 
198
 
          // unfocus all other group nodes
199
 
          var children = this._getRadioChildren();
200
 
          for (var i = 0; i < children.length; ++i) {
201
 
            if (children[i] != val)
202
 
              children[i].removeAttribute("focused");
203
 
          }
204
 
          return val;
205
 
        ]]>
206
 
        </setter>
207
 
      </property>
208
 
 
209
 
      <method name="checkAdjacentElement">
210
 
        <parameter name="aNextFlag"/>
211
 
        <body>
212
 
        <![CDATA[
213
 
          var currentElement = this.focusedItem || this.selectedItem;
214
 
          var i;
215
 
          var children = this._getRadioChildren();
216
 
          for (i = 0; i < children.length; ++i ) {
217
 
            if (children[i] == currentElement)
218
 
              break;
219
 
          }
220
 
          var index = i;
221
 
 
222
 
          if (aNextFlag) {
223
 
            do {
224
 
              if (++i == children.length)
225
 
                i = 0;
226
 
              if (i == index)
227
 
                break;
228
 
            }
229
 
            while (children[i].hidden || children[i].collapsed || children[i].disabled);
230
 
            // XXX check for display/visibility props too
231
 
 
232
 
            this.selectedItem = children[i];
233
 
            children[i].doCommand();
234
 
          }
235
 
          else {
236
 
            do {
237
 
              if (i == 0)
238
 
                i = children.length;
239
 
              if (--i == index)
240
 
                break;
241
 
            }
242
 
            while (children[i].hidden || children[i].collapsed || children[i].disabled);
243
 
            // XXX check for display/visibility props too
244
 
 
245
 
            this.selectedItem = children[i];
246
 
            children[i].doCommand();
247
 
          }
248
 
        ]]>
249
 
        </body>
250
 
      </method>
251
 
      <field name="_radioChildren">null</field>
252
 
      <method name="_getRadioChildren">
253
 
        <body>
254
 
        <![CDATA[
255
 
          if (this._radioChildren)
256
 
            return this._radioChildren;
257
 
 
258
 
          var radioChildren = [];
259
 
          var doc = this.ownerDocument;
260
 
 
261
 
          if (this.hasChildNodes()) {
262
 
            // Don't store the collected child nodes immediately,
263
 
            // collecting the child nodes could trigger constructors
264
 
            // which would blow away our list.
265
 
 
266
 
            const nsIDOMNodeFilter = Components.interfaces.nsIDOMNodeFilter;
267
 
            var iterator = doc.createTreeWalker(this,
268
 
                                                nsIDOMNodeFilter.SHOW_ELEMENT,
269
 
                                                this._filterRadioGroup);
270
 
            while (iterator.nextNode())
271
 
              radioChildren.push(iterator.currentNode);
272
 
            return this._radioChildren = radioChildren;
273
 
          }
274
 
 
275
 
          // We don't have child nodes.
276
 
          const XUL_NS = "http://www.mozilla.org/keymaster/"
277
 
                       + "gatekeeper/there.is.only.xul";
278
 
          var elems = doc.getElementsByAttribute("group", this.id);
279
 
          for (var i = 0; i < elems.length; i++) {
280
 
            if ((elems[i].namespaceURI == XUL_NS) &&
281
 
                (elems[i].localName == "radio")) {
282
 
              radioChildren.push(elems[i]);
283
 
            }
284
 
          }
285
 
          return this._radioChildren = radioChildren;
286
 
        ]]>
287
 
        </body>
288
 
      </method>
289
 
      <method name="_filterRadioGroup">
290
 
        <parameter name="node"/>
291
 
        <body>
292
 
        <![CDATA[
293
 
          switch (node.localName) {
294
 
            case "iradio": return NodeFilter.FILTER_ACCEPT;
295
 
            default: return NodeFilter.FILTER_SKIP;
296
 
          }
297
 
        ]]>
298
 
        </body>
299
 
      </method>
300
 
 
301
 
      <method name="getIndexOfItem">
302
 
        <parameter name="item"/>
303
 
        <body>
304
 
          return this._getRadioChildren().indexOf(item);
305
 
        </body>
306
 
      </method>
307
 
 
308
 
      <method name="getItemAtIndex">
309
 
        <parameter name="index"/>
310
 
        <body>
311
 
        <![CDATA[
312
 
          var children = this._getRadioChildren();
313
 
          return (index >= 0 && index < children.length) ? children[index] : null;
314
 
        ]]>
315
 
        </body>
316
 
      </method>
317
 
 
318
 
    </implementation>
319
 
 
320
 
    <handlers>
321
 
      <handler event="mousedown">
322
 
        if (this.disabled)
323
 
          event.preventDefault();
324
 
       </handler>
325
 
 
326
 
      <!-- keyboard navigation -->
327
 
      <!-- Here's how keyboard navigation works in radio groups on Windows:
328
 
           The group takes 'focus'
329
 
           The user is then free to navigate around inside the group
330
 
           using the arrow keys. Accessing previous or following radio buttons
331
 
           is done solely through the arrow keys and not the tab button. Tab
332
 
           takes you to the next widget in the tab order -->
333
 
      <handler event="keypress" key=" " phase="target">
334
 
         this.selectedItem = this.focusedItem;
335
 
         this.selectedItem.doCommand();
336
 
      </handler>
337
 
      <handler event="keypress" keycode="VK_UP" phase="target">
338
 
        this.checkAdjacentElement(false);
339
 
        event.stopPropagation();
340
 
      </handler>
341
 
      <handler event="keypress" keycode="VK_LEFT" phase="target">
342
 
        // left arrow goes back when we are ltr, forward when we are rtl
343
 
        this.checkAdjacentElement(document.defaultView.getComputedStyle(
344
 
                                    this, "").direction == "rtl");
345
 
        event.stopPropagation();
346
 
      </handler>
347
 
      <handler event="keypress" keycode="VK_DOWN" phase="target">
348
 
        this.checkAdjacentElement(true);
349
 
        event.stopPropagation();
350
 
      </handler>
351
 
      <handler event="keypress" keycode="VK_RIGHT" phase="target">
352
 
        // right arrow goes forward when we are ltr, back when we are rtl
353
 
        this.checkAdjacentElement(document.defaultView.getComputedStyle(
354
 
                                    this, "").direction == "ltr");
355
 
        event.stopPropagation();
356
 
      </handler>
357
 
 
358
 
      <!-- set a focused attribute on the selected item when the group
359
 
           receives focus so that we can style it as if it were focused even though
360
 
           it is not (Windows platform behaviour is for the group to receive focus,
361
 
           not the item -->
362
 
      <handler event="focus" phase="target">
363
 
        <![CDATA[
364
 
          this.setAttribute("focused", "true");
365
 
          if (this.focusedItem)
366
 
            return;
367
 
 
368
 
          var val = this.selectedItem;
369
 
          if (!val || val.disabled || val.hidden || val.collapsed) {
370
 
            var children = this._getRadioChildren();
371
 
            for (var i = 0; i < children.length; ++i) {
372
 
              if (!children[i].hidden && !children[i].collapsed && !children[i].disabled) {
373
 
                val = children[i];
374
 
                break;
375
 
              }
376
 
            }
377
 
          }
378
 
          this.focusedItem = val;
379
 
        ]]>
380
 
      </handler>
381
 
      <handler event="blur" phase="target">
382
 
        this.removeAttribute("focused");
383
 
        this.focusedItem = null;
384
 
      </handler>
385
 
    </handlers>
386
 
  </binding>
387
 
 
388
 
  <binding id="iradio" role="xul:radiobutton"
389
 
    extends="chrome://global/content/bindings/general.xml#control-item">
390
 
    <resources>
391
 
      <stylesheet src="chrome://cookiekeeper/skin/iradio.css"/>
392
 
    </resources>
393
 
 
394
 
    <content>
395
 
      <xul:box class="iradio-box" orient="vectical" align="center">
396
 
        <xul:image class="iradio-icon" xbl:inherits="disabled,selected,src"/>
397
 
      </xul:box>
398
 
    </content>
399
 
 
400
 
    <implementation implements="nsIDOMXULSelectControlItemElement">
401
 
      <constructor>
402
 
        <![CDATA[
403
 
          // Just clear out the parent's cached list of radio children
404
 
          var control = this.control;
405
 
          if (control)
406
 
            control._radioChildren = null;
407
 
        ]]>
408
 
      </constructor>
409
 
      <destructor>
410
 
        <![CDATA[
411
 
          if (!this.radioGroup)
412
 
            return;
413
 
 
414
 
          var radioList = this.radioGroup.mRadioChildren;
415
 
          if (!radioList)
416
 
            return;
417
 
          for (var i = 0; i < radioList.length; ++i) {
418
 
            if (radioList[i] == this) {
419
 
              radioList.splice(i, 1);
420
 
              return;
421
 
            }
422
 
          }
423
 
        ]]>
424
 
      </destructor>
425
 
      <property name="selected" readonly="true">
426
 
        <getter>
427
 
          <![CDATA[
428
 
            return this.hasAttribute('selected');
429
 
          ]]>
430
 
        </getter>
431
 
      </property>
432
 
      <property name="radioGroup" readonly="true" onget="return this.control"/>
433
 
      <property name="control" readonly="true">
434
 
        <getter>
435
 
        <![CDATA[
436
 
          const XUL_NS = "http://www.mozilla.org/keymaster/"
437
 
                       + "gatekeeper/there.is.only.xul";
438
 
          var parent = this.parentNode;
439
 
          while (parent) {
440
 
            if ((parent.namespaceURI == XUL_NS) &&
441
 
                (parent.localName == "iradiogroup")) {
442
 
              return parent;
443
 
            }
444
 
            parent = parent.parentNode;
445
 
          }
446
 
 
447
 
          var group = this.getAttribute("group");
448
 
          if (!group) {
449
 
            return null;
450
 
          }
451
 
 
452
 
          parent = this.ownerDocument.getElementById(group);
453
 
          if (!parent ||
454
 
              (parent.namespaceURI != XUL_NS) ||
455
 
              (parent.localName != "iradiogroup")) {
456
 
            parent = null;
457
 
          }
458
 
          return parent;
459
 
        ]]>
460
 
        </getter>
461
 
      </property>
462
 
    </implementation>
463
 
    <handlers>
464
 
      <handler event="click" button="0">
465
 
        <![CDATA[
466
 
          if (!this.disabled) {
467
 
            this.control.selectedItem = this;
468
 
            this.setAttribute("focused", true);
469
 
            this.doCommand();
470
 
          }
471
 
         ]]>
472
 
      </handler>
473
 
 
474
 
      <handler event="mousedown" button="0">
475
 
        <![CDATA[
476
 
          if (!this.disabled) {
477
 
            this.control.focusedItem = this;
478
 
          }
479
 
         ]]>
480
 
      </handler>
481
 
 
482
 
      <handler event="keypress" key=" " phase="target">
483
 
        <![CDATA[
484
 
          this.control.selectedItem = this;
485
 
          this.doCommand();
486
 
        ]]>
487
 
      </handler>
488
 
      <handler event="blur" phase="target">
489
 
        <![CDATA[
490
 
          this.removeAttribute("focused");
491
 
        ]]>
492
 
      </handler>
493
 
 
494
 
      <handler event="focus" phase="target">
495
 
        <![CDATA[
496
 
          this.setAttribute("focused", true);
497
 
        ]]>
498
 
      </handler>
499
 
      <handler event="keypress" keycode="VK_UP" phase="target">
500
 
        <![CDATA[
501
 
        this.control.checkAdjacentElement(false);
502
 
        event.stopPropagation();
503
 
        ]]>
504
 
      </handler>
505
 
      <handler event="keypress" keycode="VK_LEFT" phase="target">
506
 
        <![CDATA[
507
 
        // left arrow goes back when we are ltr, forward when we are rtl
508
 
        this.control.checkAdjacentElement(document.defaultView.getComputedStyle(
509
 
                                    this.control, "").direction == "rtl");
510
 
        event.stopPropagation();
511
 
        ]]>
512
 
      </handler>
513
 
      <handler event="keypress" keycode="VK_DOWN" phase="target">
514
 
        <![CDATA[
515
 
        this.control.checkAdjacentElement(true);
516
 
        event.stopPropagation();
517
 
        ]]>
518
 
      </handler>
519
 
      <handler event="keypress" keycode="VK_RIGHT" phase="target">
520
 
        <![CDATA[
521
 
        // right arrow goes forward when we are ltr, back when we are rtl
522
 
        this.control.checkAdjacentElement(document.defaultView.getComputedStyle(
523
 
                                    this.control, "").direction == "ltr");
524
 
        event.stopPropagation();
525
 
        ]]>
526
 
      </handler>
527
 
    </handlers>
528
 
  </binding>
529
 
</bindings>