Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('widget-parent', function (Y, NAME) {
2
 
3
/**
4
 * Extension enabling a Widget to be a parent of another Widget.
5
 *
6
 * @module widget-parent
7
 */
8
 
9
var Lang = Y.Lang,
10
    RENDERED = "rendered",
11
    BOUNDING_BOX = "boundingBox";
12
 
13
/**
14
 * Widget extension providing functionality enabling a Widget to be a
15
 * parent of another Widget.
16
 *
17
 * <p>In addition to the set of attributes supported by WidgetParent, the constructor
18
 * configuration object can also contain a <code>children</code> which can be used
19
 * to add child widgets to the parent during construction. The <code>children</code>
20
 * property is an array of either child widget instances or child widget configuration
21
 * objects, and is sugar for the <a href="#method_add">add</a> method. See the
22
 * <a href="#method_add">add</a> for details on the structure of the child widget
23
 * configuration object.
24
 * @class WidgetParent
25
 * @constructor
26
 * @uses ArrayList
27
 * @param {Object} config User configuration object.
28
 */
29
function Parent(config) {
30
 
31
    /**
32
    * Fires when a Widget is add as a child.  The event object will have a
33
    * 'child' property that returns a reference to the child Widget, as well
34
    * as an 'index' property that returns a reference to the index specified
35
    * when the add() method was called.
36
    * <p>
37
    * Subscribers to the "on" moment of this event, will be notified
38
    * before a child is added.
39
    * </p>
40
    * <p>
41
    * Subscribers to the "after" moment of this event, will be notified
42
    * after a child is added.
43
    * </p>
44
    *
45
    * @event addChild
46
    * @preventable _defAddChildFn
47
    * @param {EventFacade} e The Event Facade
48
    */
49
    this.publish("addChild", {
50
        defaultTargetOnly: true,
51
        defaultFn: this._defAddChildFn
52
    });
53
 
54
 
55
    /**
56
    * Fires when a child Widget is removed.  The event object will have a
57
    * 'child' property that returns a reference to the child Widget, as well
58
    * as an 'index' property that returns a reference child's ordinal position.
59
    * <p>
60
    * Subscribers to the "on" moment of this event, will be notified
61
    * before a child is removed.
62
    * </p>
63
    * <p>
64
    * Subscribers to the "after" moment of this event, will be notified
65
    * after a child is removed.
66
    * </p>
67
    *
68
    * @event removeChild
69
    * @preventable _defRemoveChildFn
70
    * @param {EventFacade} e The Event Facade
71
    */
72
    this.publish("removeChild", {
73
        defaultTargetOnly: true,
74
        defaultFn: this._defRemoveChildFn
75
    });
76
 
77
    this._items = [];
78
 
79
    var children,
80
        handle;
81
 
82
    if (config && config.children) {
83
 
84
        children = config.children;
85
 
86
        handle = this.after("initializedChange", function (e) {
87
            this._add(children);
88
            handle.detach();
89
        });
90
 
91
    }
92
 
93
    //  Widget method overlap
94
    Y.after(this._renderChildren, this, "renderUI");
95
    Y.after(this._bindUIParent, this, "bindUI");
96
 
97
    this.after("selectionChange", this._afterSelectionChange);
98
    this.after("selectedChange", this._afterParentSelectedChange);
99
    this.after("activeDescendantChange", this._afterActiveDescendantChange);
100
 
101
    this._hDestroyChild = this.after("*:destroy", this._afterDestroyChild);
102
    this.after("*:focusedChange", this._updateActiveDescendant);
103
 
104
}
105
 
106
Parent.ATTRS = {
107
 
108
    /**
109
     * @attribute defaultChildType
110
     * @type {String|Object}
111
     *
112
     * @description String representing the default type of the children
113
     * managed by this Widget.  Can also supply default type as a constructor
114
     * reference.
115
     */
116
    defaultChildType: {
117
        setter: function (val) {
118
 
119
            var returnVal = Y.Attribute.INVALID_VALUE,
120
                FnConstructor = Lang.isString(val) ? Y[val] : val;
121
 
122
            if (Lang.isFunction(FnConstructor)) {
123
                returnVal = FnConstructor;
124
            }
125
 
126
            return returnVal;
127
        }
128
    },
129
 
130
    /**
131
     * @attribute activeDescendant
132
     * @type Widget
133
     * @readOnly
134
     *
135
     * @description Returns the Widget's currently focused descendant Widget.
136
     */
137
    activeDescendant: {
138
        readOnly: true
139
    },
140
 
141
    /**
142
     * @attribute multiple
143
     * @type Boolean
144
     * @default false
145
     * @writeOnce
146
     *
147
     * @description Boolean indicating if multiple children can be selected at
148
     * once.  Whether or not multiple selection is enabled is always delegated
149
     * to the value of the <code>multiple</code> attribute of the root widget
150
     * in the object hierarchy.
151
     */
152
    multiple: {
153
        value: false,
154
        validator: Lang.isBoolean,
155
        writeOnce: true,
156
        getter: function (value) {
157
            var root = this.get("root");
158
            return (root && root != this) ? root.get("multiple") : value;
159
        }
160
    },
161
 
162
 
163
    /**
164
     * @attribute selection
165
     * @type {ArrayList|Widget}
166
     * @readOnly
167
     *
168
     * @description Returns the currently selected child Widget.  If the
169
     * <code>mulitple</code> attribte is set to <code>true</code> will
170
     * return an Y.ArrayList instance containing the currently selected
171
     * children.  If no children are selected, will return null.
172
     */
173
    selection: {
174
        readOnly: true,
175
        setter: "_setSelection",
176
        getter: function (value) {
177
            var selection = Lang.isArray(value) ?
178
                    (new Y.ArrayList(value)) : value;
179
            return selection;
180
        }
181
    },
182
 
183
    selected: {
184
        setter: function (value) {
185
 
186
            //  Enforces selection behavior on for parent Widgets.  Parent's
187
            //  selected attribute can be set to the following:
188
            //  0 - Not selected
189
            //  1 - Fully selected (all children are selected).  In order for
190
            //  all children to be selected, multiple selection must be
191
            //  enabled.  Therefore, you cannot set the "selected" attribute
192
            //  on a parent Widget to 1 unless multiple selection is enabled.
193
            //  2 - Partially selected, meaning one ore more (but not all)
194
            //  children are selected.
195
 
196
            var returnVal = value;
197
 
198
            if (value === 1 && !this.get("multiple")) {
199
                Y.log('The selected attribute can only be set to 1 if the "multiple" attribute is set to true.', "error", "widget");
200
                returnVal = Y.Attribute.INVALID_VALUE;
201
            }
202
 
203
            return returnVal;
204
        }
205
    }
206
 
207
};
208
 
209
Parent.prototype = {
210
 
211
    /**
212
     * The destructor implementation for Parent widgets. Destroys all children.
213
     * @method destructor
214
     */
215
    destructor: function() {
216
        this._destroyChildren();
217
    },
218
 
219
    /**
220
     * Destroy event listener for each child Widget, responsible for removing
221
     * the destroyed child Widget from the parent's internal array of children
222
     * (_items property).
223
     *
224
     * @method _afterDestroyChild
225
     * @protected
226
     * @param {EventFacade} event The event facade for the attribute change.
227
     */
228
    _afterDestroyChild: function (event) {
229
        var child = event.target;
230
 
231
        if (child.get("parent") == this) {
232
            child.remove();
233
        }
234
    },
235
 
236
    /**
237
     * Attribute change listener for the <code>selection</code>
238
     * attribute, responsible for setting the value of the
239
     * parent's <code>selected</code> attribute.
240
     *
241
     * @method _afterSelectionChange
242
     * @protected
243
     * @param {EventFacade} event The event facade for the attribute change.
244
     */
245
    _afterSelectionChange: function (event) {
246
 
247
        if (event.target == this && event.src != this) {
248
 
249
            var selection = event.newVal,
250
                selectedVal = 0;    //  Not selected
251
 
252
 
253
            if (selection) {
254
 
255
                selectedVal = 2;    //  Assume partially selected, confirm otherwise
256
 
257
 
258
                if (Y.instanceOf(selection, Y.ArrayList) &&
259
                    (selection.size() === this.size())) {
260
 
261
                    selectedVal = 1;    //  Fully selected
262
 
263
                }
264
 
265
            }
266
 
267
            this.set("selected", selectedVal, { src: this });
268
 
269
        }
270
    },
271
 
272
 
273
    /**
274
     * Attribute change listener for the <code>activeDescendant</code>
275
     * attribute, responsible for setting the value of the
276
     * parent's <code>activeDescendant</code> attribute.
277
     *
278
     * @method _afterActiveDescendantChange
279
     * @protected
280
     * @param {EventFacade} event The event facade for the attribute change.
281
     */
282
    _afterActiveDescendantChange: function (event) {
283
        var parent = this.get("parent");
284
 
285
        if (parent) {
286
            parent._set("activeDescendant", event.newVal);
287
        }
288
    },
289
 
290
    /**
291
     * Attribute change listener for the <code>selected</code>
292
     * attribute, responsible for syncing the selected state of all children to
293
     * match that of their parent Widget.
294
     *
295
     *
296
     * @method _afterParentSelectedChange
297
     * @protected
298
     * @param {EventFacade} event The event facade for the attribute change.
299
     */
300
    _afterParentSelectedChange: function (event) {
301
 
302
        var value = event.newVal;
303
 
304
        if (this == event.target && event.src != this &&
305
            (value === 0 || value === 1)) {
306
 
307
            this.each(function (child) {
308
 
309
                //  Specify the source of this change as the parent so that
310
                //  value of the parent's "selection" attribute isn't
311
                //  recalculated
312
 
313
                child.set("selected", value, { src: this });
314
 
315
            }, this);
316
 
317
        }
318
 
319
    },
320
 
321
 
322
    /**
323
     * Default setter for <code>selection</code> attribute changes.
324
     *
325
     * @method _setSelection
326
     * @protected
327
     * @param child {Widget|Array} Widget or Array of Widget instances.
328
     * @return {Widget|Array} Widget or Array of Widget instances.
329
     */
330
    _setSelection: function (child) {
331
 
332
        var selection = null,
333
            selected;
334
 
335
        if (this.get("multiple") && !this.isEmpty()) {
336
 
337
            selected = [];
338
 
339
            this.each(function (v) {
340
 
341
               if (v.get("selected") > 0) {
342
                   selected.push(v);
343
               }
344
 
345
            });
346
 
347
            if (selected.length > 0) {
348
                selection = selected;
349
            }
350
 
351
        }
352
        else {
353
 
354
            if (child.get("selected") > 0) {
355
                selection = child;
356
            }
357
 
358
        }
359
 
360
        return selection;
361
 
362
    },
363
 
364
 
365
    /**
366
     * Attribute change listener for the <code>selected</code>
367
     * attribute of child Widgets, responsible for setting the value of the
368
     * parent's <code>selection</code> attribute.
369
     *
370
     * @method _updateSelection
371
     * @protected
372
     * @param {EventFacade} event The event facade for the attribute change.
373
     */
374
    _updateSelection: function (event) {
375
 
376
        var child = event.target,
377
            selection;
378
 
379
        if (child.get("parent") == this) {
380
 
381
            if (event.src != "_updateSelection") {
382
 
383
                selection = this.get("selection");
384
 
385
                if (!this.get("multiple") && selection && event.newVal > 0) {
386
 
387
                    //  Deselect the previously selected child.
388
                    //  Set src equal to the current context to prevent
389
                    //  unnecessary re-calculation of the selection.
390
 
391
                    selection.set("selected", 0, { src: "_updateSelection" });
392
 
393
                }
394
 
395
                this._set("selection", child);
396
 
397
            }
398
 
399
            if (event.src == this) {
400
                this._set("selection", child, { src: this });
401
            }
402
 
403
        }
404
 
405
    },
406
 
407
    /**
408
     * Attribute change listener for the <code>focused</code>
409
     * attribute of child Widgets, responsible for setting the value of the
410
     * parent's <code>activeDescendant</code> attribute.
411
     *
412
     * @method _updateActiveDescendant
413
     * @protected
414
     * @param {EventFacade} event The event facade for the attribute change.
415
     */
416
    _updateActiveDescendant: function (event) {
417
        var activeDescendant = (event.newVal === true) ? event.target : null;
418
        this._set("activeDescendant", activeDescendant);
419
    },
420
 
421
    /**
422
     * Creates an instance of a child Widget using the specified configuration.
423
     * By default Widget instances will be created of the type specified
424
     * by the <code>defaultChildType</code> attribute.  Types can be explicitly
425
     * defined via the <code>childType</code> property of the configuration object
426
     * literal. The use of the <code>type</code> property has been deprecated, but
427
     * will still be used as a fallback, if <code>childType</code> is not defined,
428
     * for backwards compatibility.
429
     *
430
     * @method _createChild
431
     * @protected
432
     * @param config {Object} Object literal representing the configuration
433
     * used to create an instance of a Widget.
434
     */
435
    _createChild: function (config) {
436
 
437
        var defaultType = this.get("defaultChildType"),
438
            altType = config.childType || config.type,
439
            child,
440
            Fn,
441
            FnConstructor;
442
 
443
        if (altType) {
444
            Fn = Lang.isString(altType) ? Y[altType] : altType;
445
        }
446
 
447
        if (Lang.isFunction(Fn)) {
448
            FnConstructor = Fn;
449
        } else if (defaultType) {
450
            // defaultType is normalized to a function in it's setter
451
            FnConstructor = defaultType;
452
        }
453
 
454
        if (FnConstructor) {
455
            child = new FnConstructor(config);
456
        } else {
457
            Y.error("Could not create a child instance because its constructor is either undefined or invalid.");
458
        }
459
 
460
        return child;
461
 
462
    },
463
 
464
    /**
465
     * Default addChild handler
466
     *
467
     * @method _defAddChildFn
468
     * @protected
469
     * @param event {EventFacade} The Event object
470
     * @param child {Widget} The Widget instance, or configuration
471
     * object for the Widget to be added as a child.
472
     * @param index {Number} Number representing the position at
473
     * which the child will be inserted.
474
     */
475
    _defAddChildFn: function (event) {
476
 
477
        var child = event.child,
478
            index = event.index,
479
            children = this._items;
480
 
481
        if (child.get("parent")) {
482
            child.remove();
483
        }
484
 
485
        if (Lang.isNumber(index)) {
486
            children.splice(index, 0, child);
487
        }
488
        else {
489
            children.push(child);
490
        }
491
 
492
        child._set("parent", this);
493
        child.addTarget(this);
494
 
495
        // Update index in case it got normalized after addition
496
        // (e.g. user passed in 10, and there are only 3 items, the actual index would be 3. We don't want to pass 10 around in the event facade).
497
        event.index = child.get("index");
498
 
499
        //  TO DO: Remove in favor of using event bubbling
500
        child.after("selectedChange", Y.bind(this._updateSelection, this));
501
    },
502
 
503
 
504
    /**
505
     * Default removeChild handler
506
     *
507
     * @method _defRemoveChildFn
508
     * @protected
509
     * @param event {EventFacade} The Event object
510
     * @param child {Widget} The Widget instance to be removed.
511
     * @param index {Number} Number representing the index of the Widget to
512
     * be removed.
513
     */
514
    _defRemoveChildFn: function (event) {
515
 
516
        var child = event.child,
517
            index = event.index,
518
            children = this._items;
519
 
520
        if (child.get("focused")) {
521
            child.blur(); // focused is readOnly, so use the public i/f to unset it
522
        }
523
 
524
        if (child.get("selected")) {
525
            child.set("selected", 0);
526
        }
527
 
528
        children.splice(index, 1);
529
 
530
        child.removeTarget(this);
531
        child._oldParent = child.get("parent");
532
        child._set("parent", null);
533
    },
534
 
535
    /**
536
    * @method _add
537
    * @protected
538
    * @param child {Widget|Object|Array} The Widget instance, or configuration
539
    * object for the Widget, or Array of Widget instances to be added as a child.
540
    * @param index {Number} Number representing the position at which the child
541
    * should be inserted.
542
    * @description Adds a Widget as a child.  If the specified Widget already
543
    * has a parent it will be removed from its current parent before
544
    * being added as a child.
545
    * @return {Widget|Array} Successfully added Widget or Array containing the
546
    * successfully added Widget instance(s). If no children where added, will
547
    * will return undefined.
548
    */
549
    _add: function (child, index) {
550
 
551
        var children,
552
            oChild,
553
            returnVal;
554
 
555
 
556
        if (Lang.isArray(child)) {
557
 
558
            children = [];
559
 
560
            Y.each(child, function (v, k) {
561
 
562
                oChild = this._add(v, (index + k));
563
 
564
                if (oChild) {
565
                    children.push(oChild);
566
                }
567
 
568
            }, this);
569
 
570
 
571
            if (children.length > 0) {
572
                returnVal = children;
573
            }
574
 
575
        }
576
        else {
577
 
578
            if (Y.instanceOf(child, Y.Widget)) {
579
                oChild = child;
580
            }
581
            else {
582
                oChild = this._createChild(child);
583
            }
584
 
585
            if (oChild && this.fire("addChild", { child: oChild, index: index })) {
586
                returnVal = oChild;
587
            }
588
 
589
        }
590
 
591
        return returnVal;
592
 
593
    },
594
 
595
 
596
    /**
597
    * @method add
598
    * @param child {Widget|Object|Array} The Widget instance, or configuration
599
    * object for the Widget, or Array of Widget instances to be added as a child.
600
    * The configuration object for the child can include a <code>childType</code>
601
    * property, which is either a constructor function or a string which names
602
    * a constructor function on the Y instance (e.g. "Tab" would refer to Y.Tab).
603
    * <code>childType</code> used to be named <code>type</code>, support for
604
    * which has been deprecated, but is still maintained for backward compatibility.
605
    * <code>childType</code> takes precedence over <code>type</code> if both are defined.
606
    * @param index {Number} Number representing the position at which the child
607
    * should be inserted.
608
    * @description Adds a Widget as a child.  If the specified Widget already
609
    * has a parent it will be removed from its current parent before
610
    * being added as a child.
611
    * @return {ArrayList} Y.ArrayList containing the successfully added
612
    * Widget instance(s).  If no children where added, will return an empty
613
    * Y.ArrayList instance.
614
    */
615
    add: function () {
616
 
617
        var added = this._add.apply(this, arguments),
618
            children = added ? (Lang.isArray(added) ? added : [added]) : [];
619
 
620
        return (new Y.ArrayList(children));
621
 
622
    },
623
 
624
 
625
    /**
626
    * @method remove
627
    * @param index {Number} (Optional.)  Number representing the index of the
628
    * child to be removed.
629
    * @description Removes the Widget from its parent.  Optionally, can remove
630
    * a child by specifying its index.
631
    * @return {Widget} Widget instance that was successfully removed, otherwise
632
    * undefined.
633
    */
634
    remove: function (index) {
635
 
636
        var child = this._items[index],
637
            returnVal;
638
 
639
        if (child && this.fire("removeChild", { child: child, index: index })) {
640
            returnVal = child;
641
        }
642
 
643
        return returnVal;
644
 
645
    },
646
 
647
 
648
    /**
649
    * @method removeAll
650
    * @description Removes all of the children from the Widget.
651
    * @return {ArrayList} Y.ArrayList instance containing Widgets that were
652
    * successfully removed.  If no children where removed, will return an empty
653
    * Y.ArrayList instance.
654
    */
655
    removeAll: function () {
656
 
657
        var removed = [],
658
            child;
659
 
660
        Y.each(this._items.concat(), function () {
661
 
662
            child = this.remove(0);
663
 
664
            if (child) {
665
                removed.push(child);
666
            }
667
 
668
        }, this);
669
 
670
        return (new Y.ArrayList(removed));
671
 
672
    },
673
 
674
    /**
675
     * Selects the child at the given index (zero-based).
676
     *
677
     * @method selectChild
678
     * @param {Number} i the index of the child to be selected
679
     */
680
    selectChild: function(i) {
681
        this.item(i).set('selected', 1);
682
    },
683
 
684
    /**
685
     * Selects all children.
686
     *
687
     * @method selectAll
688
     */
689
    selectAll: function () {
690
        this.set("selected", 1);
691
    },
692
 
693
    /**
694
     * Deselects all children.
695
     *
696
     * @method deselectAll
697
     */
698
    deselectAll: function () {
699
        this.set("selected", 0);
700
    },
701
 
702
    /**
703
     * Updates the UI in response to a child being added.
704
     *
705
     * @method _uiAddChild
706
     * @protected
707
     * @param child {Widget} The child Widget instance to render.
708
     * @param parentNode {Object} The Node under which the
709
     * child Widget is to be rendered.
710
     */
711
    _uiAddChild: function (child, parentNode) {
712
 
713
        child.render(parentNode);
714
 
715
        // TODO: Ideally this should be in Child's render UI.
716
 
717
        var childBB = child.get("boundingBox"),
718
            siblingBB,
719
            nextSibling = child.next(false),
720
            prevSibling;
721
 
722
        // Insert or Append to last child.
723
 
724
        // Avoiding index, and using the current sibling
725
        // state (which should be accurate), means we don't have
726
        // to worry about decorator elements which may be added
727
        // to the _childContainer node.
728
 
729
        if (nextSibling && nextSibling.get(RENDERED)) {
730
 
731
            siblingBB = nextSibling.get(BOUNDING_BOX);
732
            siblingBB.insert(childBB, "before");
733
 
734
        } else {
735
 
736
            prevSibling = child.previous(false);
737
 
738
            if (prevSibling && prevSibling.get(RENDERED)) {
739
 
740
                siblingBB = prevSibling.get(BOUNDING_BOX);
741
                siblingBB.insert(childBB, "after");
742
 
743
            } else if (!parentNode.contains(childBB)) {
744
 
745
                // Based on pull request from andreas-karlsson
746
                // https://github.com/yui/yui3/pull/25#issuecomment-2103536
747
 
748
                // Account for case where a child was rendered independently of the
749
                // parent-child framework, to a node outside of the parentNode,
750
                // and there are no siblings.
751
 
752
                parentNode.appendChild(childBB);
753
            }
754
        }
755
 
756
    },
757
 
758
    /**
759
     * Updates the UI in response to a child being removed.
760
     *
761
     * @method _uiRemoveChild
762
     * @protected
763
     * @param child {Widget} The child Widget instance to render.
764
     */
765
    _uiRemoveChild: function (child) {
766
        child.get("boundingBox").remove();
767
    },
768
 
769
    _afterAddChild: function (event) {
770
        var child = event.child;
771
 
772
        if (child.get("parent") == this) {
773
            this._uiAddChild(child, this._childrenContainer);
774
        }
775
    },
776
 
777
    _afterRemoveChild: function (event) {
778
        var child = event.child;
779
 
780
        if (child._oldParent == this) {
781
            this._uiRemoveChild(child);
782
        }
783
    },
784
 
785
    /**
786
     * Sets up DOM and CustomEvent listeners for the parent widget.
787
     * <p>
788
     * This method in invoked after bindUI is invoked for the Widget class
789
     * using YUI's aop infrastructure.
790
     * </p>
791
     *
792
     * @method _bindUIParent
793
     * @protected
794
     */
795
    _bindUIParent: function () {
796
        this.after("addChild", this._afterAddChild);
797
        this.after("removeChild", this._afterRemoveChild);
798
    },
799
 
800
    /**
801
     * Renders all child Widgets for the parent.
802
     * <p>
803
     * This method in invoked after renderUI is invoked for the Widget class
804
     * using YUI's aop infrastructure.
805
     * </p>
806
     * @method _renderChildren
807
     * @protected
808
     */
809
    _renderChildren: function () {
810
 
811
        /**
812
         * <p>By default WidgetParent will render it's children to the parent's content box.</p>
813
         *
814
         * <p>If the children need to be rendered somewhere else, the _childrenContainer property
815
         * can be set to the Node which the children should be rendered to. This property should be
816
         * set before the _renderChildren method is invoked, ideally in your renderUI method,
817
         * as soon as you create the element to be rendered to.</p>
818
         *
819
         * @protected
820
         * @property _childrenContainer
821
         * @value The content box
822
         * @type Node
823
         */
824
        var renderTo = this._childrenContainer || this.get("contentBox");
825
 
826
        this._childrenContainer = renderTo;
827
 
828
        this.each(function (child) {
829
            child.render(renderTo);
830
        });
831
    },
832
 
833
    /**
834
     * Destroys all child Widgets for the parent.
835
     * <p>
836
     * This method is invoked before the destructor is invoked for the Widget
837
     * class using YUI's aop infrastructure.
838
     * </p>
839
     * @method _destroyChildren
840
     * @protected
841
     */
842
    _destroyChildren: function () {
843
 
844
        //  Detach the handler responsible for removing children in
845
        //  response to destroying them since:
846
        //  1)  It is unnecessary/inefficient at this point since we are doing
847
        //      a batch destroy of all children.
848
        //  2)  Removing each child will affect our ability to iterate the
849
        //      children since the size of _items will be changing as we
850
        //      iterate.
851
        this._hDestroyChild.detach();
852
 
853
        //  Need to clone the _items array since
854
        this.each(function (child) {
855
            child.destroy();
856
        });
857
    }
858
 
859
};
860
 
861
Y.augment(Parent, Y.ArrayList);
862
 
863
Y.WidgetParent = Parent;
864
 
865
 
866
}, '3.18.1', {"requires": ["arraylist", "base-build", "widget"]});