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
                returnVal = Y.Attribute.INVALID_VALUE;
200
            }
201
 
202
            return returnVal;
203
        }
204
    }
205
 
206
};
207
 
208
Parent.prototype = {
209
 
210
    /**
211
     * The destructor implementation for Parent widgets. Destroys all children.
212
     * @method destructor
213
     */
214
    destructor: function() {
215
        this._destroyChildren();
216
    },
217
 
218
    /**
219
     * Destroy event listener for each child Widget, responsible for removing
220
     * the destroyed child Widget from the parent's internal array of children
221
     * (_items property).
222
     *
223
     * @method _afterDestroyChild
224
     * @protected
225
     * @param {EventFacade} event The event facade for the attribute change.
226
     */
227
    _afterDestroyChild: function (event) {
228
        var child = event.target;
229
 
230
        if (child.get("parent") == this) {
231
            child.remove();
232
        }
233
    },
234
 
235
    /**
236
     * Attribute change listener for the <code>selection</code>
237
     * attribute, responsible for setting the value of the
238
     * parent's <code>selected</code> attribute.
239
     *
240
     * @method _afterSelectionChange
241
     * @protected
242
     * @param {EventFacade} event The event facade for the attribute change.
243
     */
244
    _afterSelectionChange: function (event) {
245
 
246
        if (event.target == this && event.src != this) {
247
 
248
            var selection = event.newVal,
249
                selectedVal = 0;    //  Not selected
250
 
251
 
252
            if (selection) {
253
 
254
                selectedVal = 2;    //  Assume partially selected, confirm otherwise
255
 
256
 
257
                if (Y.instanceOf(selection, Y.ArrayList) &&
258
                    (selection.size() === this.size())) {
259
 
260
                    selectedVal = 1;    //  Fully selected
261
 
262
                }
263
 
264
            }
265
 
266
            this.set("selected", selectedVal, { src: this });
267
 
268
        }
269
    },
270
 
271
 
272
    /**
273
     * Attribute change listener for the <code>activeDescendant</code>
274
     * attribute, responsible for setting the value of the
275
     * parent's <code>activeDescendant</code> attribute.
276
     *
277
     * @method _afterActiveDescendantChange
278
     * @protected
279
     * @param {EventFacade} event The event facade for the attribute change.
280
     */
281
    _afterActiveDescendantChange: function (event) {
282
        var parent = this.get("parent");
283
 
284
        if (parent) {
285
            parent._set("activeDescendant", event.newVal);
286
        }
287
    },
288
 
289
    /**
290
     * Attribute change listener for the <code>selected</code>
291
     * attribute, responsible for syncing the selected state of all children to
292
     * match that of their parent Widget.
293
     *
294
     *
295
     * @method _afterParentSelectedChange
296
     * @protected
297
     * @param {EventFacade} event The event facade for the attribute change.
298
     */
299
    _afterParentSelectedChange: function (event) {
300
 
301
        var value = event.newVal;
302
 
303
        if (this == event.target && event.src != this &&
304
            (value === 0 || value === 1)) {
305
 
306
            this.each(function (child) {
307
 
308
                //  Specify the source of this change as the parent so that
309
                //  value of the parent's "selection" attribute isn't
310
                //  recalculated
311
 
312
                child.set("selected", value, { src: this });
313
 
314
            }, this);
315
 
316
        }
317
 
318
    },
319
 
320
 
321
    /**
322
     * Default setter for <code>selection</code> attribute changes.
323
     *
324
     * @method _setSelection
325
     * @protected
326
     * @param child {Widget|Array} Widget or Array of Widget instances.
327
     * @return {Widget|Array} Widget or Array of Widget instances.
328
     */
329
    _setSelection: function (child) {
330
 
331
        var selection = null,
332
            selected;
333
 
334
        if (this.get("multiple") && !this.isEmpty()) {
335
 
336
            selected = [];
337
 
338
            this.each(function (v) {
339
 
340
               if (v.get("selected") > 0) {
341
                   selected.push(v);
342
               }
343
 
344
            });
345
 
346
            if (selected.length > 0) {
347
                selection = selected;
348
            }
349
 
350
        }
351
        else {
352
 
353
            if (child.get("selected") > 0) {
354
                selection = child;
355
            }
356
 
357
        }
358
 
359
        return selection;
360
 
361
    },
362
 
363
 
364
    /**
365
     * Attribute change listener for the <code>selected</code>
366
     * attribute of child Widgets, responsible for setting the value of the
367
     * parent's <code>selection</code> attribute.
368
     *
369
     * @method _updateSelection
370
     * @protected
371
     * @param {EventFacade} event The event facade for the attribute change.
372
     */
373
    _updateSelection: function (event) {
374
 
375
        var child = event.target,
376
            selection;
377
 
378
        if (child.get("parent") == this) {
379
 
380
            if (event.src != "_updateSelection") {
381
 
382
                selection = this.get("selection");
383
 
384
                if (!this.get("multiple") && selection && event.newVal > 0) {
385
 
386
                    //  Deselect the previously selected child.
387
                    //  Set src equal to the current context to prevent
388
                    //  unnecessary re-calculation of the selection.
389
 
390
                    selection.set("selected", 0, { src: "_updateSelection" });
391
 
392
                }
393
 
394
                this._set("selection", child);
395
 
396
            }
397
 
398
            if (event.src == this) {
399
                this._set("selection", child, { src: this });
400
            }
401
 
402
        }
403
 
404
    },
405
 
406
    /**
407
     * Attribute change listener for the <code>focused</code>
408
     * attribute of child Widgets, responsible for setting the value of the
409
     * parent's <code>activeDescendant</code> attribute.
410
     *
411
     * @method _updateActiveDescendant
412
     * @protected
413
     * @param {EventFacade} event The event facade for the attribute change.
414
     */
415
    _updateActiveDescendant: function (event) {
416
        var activeDescendant = (event.newVal === true) ? event.target : null;
417
        this._set("activeDescendant", activeDescendant);
418
    },
419
 
420
    /**
421
     * Creates an instance of a child Widget using the specified configuration.
422
     * By default Widget instances will be created of the type specified
423
     * by the <code>defaultChildType</code> attribute.  Types can be explicitly
424
     * defined via the <code>childType</code> property of the configuration object
425
     * literal. The use of the <code>type</code> property has been deprecated, but
426
     * will still be used as a fallback, if <code>childType</code> is not defined,
427
     * for backwards compatibility.
428
     *
429
     * @method _createChild
430
     * @protected
431
     * @param config {Object} Object literal representing the configuration
432
     * used to create an instance of a Widget.
433
     */
434
    _createChild: function (config) {
435
 
436
        var defaultType = this.get("defaultChildType"),
437
            altType = config.childType || config.type,
438
            child,
439
            Fn,
440
            FnConstructor;
441
 
442
        if (altType) {
443
            Fn = Lang.isString(altType) ? Y[altType] : altType;
444
        }
445
 
446
        if (Lang.isFunction(Fn)) {
447
            FnConstructor = Fn;
448
        } else if (defaultType) {
449
            // defaultType is normalized to a function in it's setter
450
            FnConstructor = defaultType;
451
        }
452
 
453
        if (FnConstructor) {
454
            child = new FnConstructor(config);
455
        } else {
456
            Y.error("Could not create a child instance because its constructor is either undefined or invalid.");
457
        }
458
 
459
        return child;
460
 
461
    },
462
 
463
    /**
464
     * Default addChild handler
465
     *
466
     * @method _defAddChildFn
467
     * @protected
468
     * @param event {EventFacade} The Event object
469
     * @param child {Widget} The Widget instance, or configuration
470
     * object for the Widget to be added as a child.
471
     * @param index {Number} Number representing the position at
472
     * which the child will be inserted.
473
     */
474
    _defAddChildFn: function (event) {
475
 
476
        var child = event.child,
477
            index = event.index,
478
            children = this._items;
479
 
480
        if (child.get("parent")) {
481
            child.remove();
482
        }
483
 
484
        if (Lang.isNumber(index)) {
485
            children.splice(index, 0, child);
486
        }
487
        else {
488
            children.push(child);
489
        }
490
 
491
        child._set("parent", this);
492
        child.addTarget(this);
493
 
494
        // Update index in case it got normalized after addition
495
        // (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).
496
        event.index = child.get("index");
497
 
498
        //  TO DO: Remove in favor of using event bubbling
499
        child.after("selectedChange", Y.bind(this._updateSelection, this));
500
    },
501
 
502
 
503
    /**
504
     * Default removeChild handler
505
     *
506
     * @method _defRemoveChildFn
507
     * @protected
508
     * @param event {EventFacade} The Event object
509
     * @param child {Widget} The Widget instance to be removed.
510
     * @param index {Number} Number representing the index of the Widget to
511
     * be removed.
512
     */
513
    _defRemoveChildFn: function (event) {
514
 
515
        var child = event.child,
516
            index = event.index,
517
            children = this._items;
518
 
519
        if (child.get("focused")) {
520
            child.blur(); // focused is readOnly, so use the public i/f to unset it
521
        }
522
 
523
        if (child.get("selected")) {
524
            child.set("selected", 0);
525
        }
526
 
527
        children.splice(index, 1);
528
 
529
        child.removeTarget(this);
530
        child._oldParent = child.get("parent");
531
        child._set("parent", null);
532
    },
533
 
534
    /**
535
    * @method _add
536
    * @protected
537
    * @param child {Widget|Object|Array} The Widget instance, or configuration
538
    * object for the Widget, or Array of Widget instances to be added as a child.
539
    * @param index {Number} Number representing the position at which the child
540
    * should be inserted.
541
    * @description Adds a Widget as a child.  If the specified Widget already
542
    * has a parent it will be removed from its current parent before
543
    * being added as a child.
544
    * @return {Widget|Array} Successfully added Widget or Array containing the
545
    * successfully added Widget instance(s). If no children where added, will
546
    * will return undefined.
547
    */
548
    _add: function (child, index) {
549
 
550
        var children,
551
            oChild,
552
            returnVal;
553
 
554
 
555
        if (Lang.isArray(child)) {
556
 
557
            children = [];
558
 
559
            Y.each(child, function (v, k) {
560
 
561
                oChild = this._add(v, (index + k));
562
 
563
                if (oChild) {
564
                    children.push(oChild);
565
                }
566
 
567
            }, this);
568
 
569
 
570
            if (children.length > 0) {
571
                returnVal = children;
572
            }
573
 
574
        }
575
        else {
576
 
577
            if (Y.instanceOf(child, Y.Widget)) {
578
                oChild = child;
579
            }
580
            else {
581
                oChild = this._createChild(child);
582
            }
583
 
584
            if (oChild && this.fire("addChild", { child: oChild, index: index })) {
585
                returnVal = oChild;
586
            }
587
 
588
        }
589
 
590
        return returnVal;
591
 
592
    },
593
 
594
 
595
    /**
596
    * @method add
597
    * @param child {Widget|Object|Array} The Widget instance, or configuration
598
    * object for the Widget, or Array of Widget instances to be added as a child.
599
    * The configuration object for the child can include a <code>childType</code>
600
    * property, which is either a constructor function or a string which names
601
    * a constructor function on the Y instance (e.g. "Tab" would refer to Y.Tab).
602
    * <code>childType</code> used to be named <code>type</code>, support for
603
    * which has been deprecated, but is still maintained for backward compatibility.
604
    * <code>childType</code> takes precedence over <code>type</code> if both are defined.
605
    * @param index {Number} Number representing the position at which the child
606
    * should be inserted.
607
    * @description Adds a Widget as a child.  If the specified Widget already
608
    * has a parent it will be removed from its current parent before
609
    * being added as a child.
610
    * @return {ArrayList} Y.ArrayList containing the successfully added
611
    * Widget instance(s).  If no children where added, will return an empty
612
    * Y.ArrayList instance.
613
    */
614
    add: function () {
615
 
616
        var added = this._add.apply(this, arguments),
617
            children = added ? (Lang.isArray(added) ? added : [added]) : [];
618
 
619
        return (new Y.ArrayList(children));
620
 
621
    },
622
 
623
 
624
    /**
625
    * @method remove
626
    * @param index {Number} (Optional.)  Number representing the index of the
627
    * child to be removed.
628
    * @description Removes the Widget from its parent.  Optionally, can remove
629
    * a child by specifying its index.
630
    * @return {Widget} Widget instance that was successfully removed, otherwise
631
    * undefined.
632
    */
633
    remove: function (index) {
634
 
635
        var child = this._items[index],
636
            returnVal;
637
 
638
        if (child && this.fire("removeChild", { child: child, index: index })) {
639
            returnVal = child;
640
        }
641
 
642
        return returnVal;
643
 
644
    },
645
 
646
 
647
    /**
648
    * @method removeAll
649
    * @description Removes all of the children from the Widget.
650
    * @return {ArrayList} Y.ArrayList instance containing Widgets that were
651
    * successfully removed.  If no children where removed, will return an empty
652
    * Y.ArrayList instance.
653
    */
654
    removeAll: function () {
655
 
656
        var removed = [],
657
            child;
658
 
659
        Y.each(this._items.concat(), function () {
660
 
661
            child = this.remove(0);
662
 
663
            if (child) {
664
                removed.push(child);
665
            }
666
 
667
        }, this);
668
 
669
        return (new Y.ArrayList(removed));
670
 
671
    },
672
 
673
    /**
674
     * Selects the child at the given index (zero-based).
675
     *
676
     * @method selectChild
677
     * @param {Number} i the index of the child to be selected
678
     */
679
    selectChild: function(i) {
680
        this.item(i).set('selected', 1);
681
    },
682
 
683
    /**
684
     * Selects all children.
685
     *
686
     * @method selectAll
687
     */
688
    selectAll: function () {
689
        this.set("selected", 1);
690
    },
691
 
692
    /**
693
     * Deselects all children.
694
     *
695
     * @method deselectAll
696
     */
697
    deselectAll: function () {
698
        this.set("selected", 0);
699
    },
700
 
701
    /**
702
     * Updates the UI in response to a child being added.
703
     *
704
     * @method _uiAddChild
705
     * @protected
706
     * @param child {Widget} The child Widget instance to render.
707
     * @param parentNode {Object} The Node under which the
708
     * child Widget is to be rendered.
709
     */
710
    _uiAddChild: function (child, parentNode) {
711
 
712
        child.render(parentNode);
713
 
714
        // TODO: Ideally this should be in Child's render UI.
715
 
716
        var childBB = child.get("boundingBox"),
717
            siblingBB,
718
            nextSibling = child.next(false),
719
            prevSibling;
720
 
721
        // Insert or Append to last child.
722
 
723
        // Avoiding index, and using the current sibling
724
        // state (which should be accurate), means we don't have
725
        // to worry about decorator elements which may be added
726
        // to the _childContainer node.
727
 
728
        if (nextSibling && nextSibling.get(RENDERED)) {
729
 
730
            siblingBB = nextSibling.get(BOUNDING_BOX);
731
            siblingBB.insert(childBB, "before");
732
 
733
        } else {
734
 
735
            prevSibling = child.previous(false);
736
 
737
            if (prevSibling && prevSibling.get(RENDERED)) {
738
 
739
                siblingBB = prevSibling.get(BOUNDING_BOX);
740
                siblingBB.insert(childBB, "after");
741
 
742
            } else if (!parentNode.contains(childBB)) {
743
 
744
                // Based on pull request from andreas-karlsson
745
                // https://github.com/yui/yui3/pull/25#issuecomment-2103536
746
 
747
                // Account for case where a child was rendered independently of the
748
                // parent-child framework, to a node outside of the parentNode,
749
                // and there are no siblings.
750
 
751
                parentNode.appendChild(childBB);
752
            }
753
        }
754
 
755
    },
756
 
757
    /**
758
     * Updates the UI in response to a child being removed.
759
     *
760
     * @method _uiRemoveChild
761
     * @protected
762
     * @param child {Widget} The child Widget instance to render.
763
     */
764
    _uiRemoveChild: function (child) {
765
        child.get("boundingBox").remove();
766
    },
767
 
768
    _afterAddChild: function (event) {
769
        var child = event.child;
770
 
771
        if (child.get("parent") == this) {
772
            this._uiAddChild(child, this._childrenContainer);
773
        }
774
    },
775
 
776
    _afterRemoveChild: function (event) {
777
        var child = event.child;
778
 
779
        if (child._oldParent == this) {
780
            this._uiRemoveChild(child);
781
        }
782
    },
783
 
784
    /**
785
     * Sets up DOM and CustomEvent listeners for the parent widget.
786
     * <p>
787
     * This method in invoked after bindUI is invoked for the Widget class
788
     * using YUI's aop infrastructure.
789
     * </p>
790
     *
791
     * @method _bindUIParent
792
     * @protected
793
     */
794
    _bindUIParent: function () {
795
        this.after("addChild", this._afterAddChild);
796
        this.after("removeChild", this._afterRemoveChild);
797
    },
798
 
799
    /**
800
     * Renders all child Widgets for the parent.
801
     * <p>
802
     * This method in invoked after renderUI is invoked for the Widget class
803
     * using YUI's aop infrastructure.
804
     * </p>
805
     * @method _renderChildren
806
     * @protected
807
     */
808
    _renderChildren: function () {
809
 
810
        /**
811
         * <p>By default WidgetParent will render it's children to the parent's content box.</p>
812
         *
813
         * <p>If the children need to be rendered somewhere else, the _childrenContainer property
814
         * can be set to the Node which the children should be rendered to. This property should be
815
         * set before the _renderChildren method is invoked, ideally in your renderUI method,
816
         * as soon as you create the element to be rendered to.</p>
817
         *
818
         * @protected
819
         * @property _childrenContainer
820
         * @value The content box
821
         * @type Node
822
         */
823
        var renderTo = this._childrenContainer || this.get("contentBox");
824
 
825
        this._childrenContainer = renderTo;
826
 
827
        this.each(function (child) {
828
            child.render(renderTo);
829
        });
830
    },
831
 
832
    /**
833
     * Destroys all child Widgets for the parent.
834
     * <p>
835
     * This method is invoked before the destructor is invoked for the Widget
836
     * class using YUI's aop infrastructure.
837
     * </p>
838
     * @method _destroyChildren
839
     * @protected
840
     */
841
    _destroyChildren: function () {
842
 
843
        //  Detach the handler responsible for removing children in
844
        //  response to destroying them since:
845
        //  1)  It is unnecessary/inefficient at this point since we are doing
846
        //      a batch destroy of all children.
847
        //  2)  Removing each child will affect our ability to iterate the
848
        //      children since the size of _items will be changing as we
849
        //      iterate.
850
        this._hDestroyChild.detach();
851
 
852
        //  Need to clone the _items array since
853
        this.each(function (child) {
854
            child.destroy();
855
        });
856
    }
857
 
858
};
859
 
860
Y.augment(Parent, Y.ArrayList);
861
 
862
Y.WidgetParent = Parent;
863
 
864
 
865
}, '3.18.1', {"requires": ["arraylist", "base-build", "widget"]});