Dashboard sipadu mbip
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

widget-parent-debug.js 25KB

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