API Docs for: 3.18.1
Show:

File: widget-child/js/Widget-Child.js

  1. /**
  2. * Extension enabling a Widget to be a child of another Widget.
  3. *
  4. * @module widget-child
  5. */
  6.  
  7. var Lang = Y.Lang;
  8.  
  9. /**
  10. * Widget extension providing functionality enabling a Widget to be a
  11. * child of another Widget.
  12. *
  13. * @class WidgetChild
  14. * @param {Object} config User configuration object.
  15. */
  16. function Child() {
  17.  
  18. // Widget method overlap
  19. Y.after(this._syncUIChild, this, "syncUI");
  20. Y.after(this._bindUIChild, this, "bindUI");
  21.  
  22. }
  23.  
  24. Child.ATTRS = {
  25.  
  26. /**
  27. * @attribute selected
  28. * @type Number
  29. * @default 0
  30. *
  31. * @description Number indicating if the Widget is selected. Possible
  32. * values are:
  33. * <dl>
  34. * <dt>0</dt> <dd>(Default) Not selected</dd>
  35. * <dt>1</dt> <dd>Fully selected</dd>
  36. * <dt>2</dt> <dd>Partially selected</dd>
  37. * </dl>
  38. */
  39. selected: {
  40. value: 0,
  41. validator: Lang.isNumber
  42. },
  43.  
  44.  
  45. /**
  46. * @attribute index
  47. * @type Number
  48. * @readOnly
  49. *
  50. * @description Number representing the Widget's ordinal position in its
  51. * parent Widget.
  52. */
  53. index: {
  54. readOnly: true,
  55. getter: function () {
  56.  
  57. var parent = this.get("parent"),
  58. index = -1;
  59.  
  60. if (parent) {
  61. index = parent.indexOf(this);
  62. }
  63.  
  64. return index;
  65.  
  66. }
  67. },
  68.  
  69.  
  70. /**
  71. * @attribute parent
  72. * @type Widget
  73. * @readOnly
  74. *
  75. * @description Retrieves the parent of the Widget in the object hierarchy.
  76. */
  77. parent: {
  78. readOnly: true
  79. },
  80.  
  81.  
  82. /**
  83. * @attribute depth
  84. * @type Number
  85. * @default -1
  86. * @readOnly
  87. *
  88. * @description Number representing the depth of this Widget relative to
  89. * the root Widget in the object heirarchy.
  90. */
  91. depth: {
  92. readOnly: true,
  93. getter: function () {
  94.  
  95. var parent = this.get("parent"),
  96. root = this.get("root"),
  97. depth = -1;
  98.  
  99. while (parent) {
  100.  
  101. depth = (depth + 1);
  102.  
  103. if (parent == root) {
  104. break;
  105. }
  106.  
  107. parent = parent.get("parent");
  108.  
  109. }
  110.  
  111. return depth;
  112.  
  113. }
  114. },
  115.  
  116. /**
  117. * @attribute root
  118. * @type Widget
  119. * @readOnly
  120. *
  121. * @description Returns the root Widget in the object hierarchy. If the
  122. * ROOT_TYPE property is set, the search for the root Widget will be
  123. * constrained to parent Widgets of the specified type.
  124. */
  125. root: {
  126. readOnly: true,
  127. getter: function () {
  128.  
  129. var getParent = function (child) {
  130.  
  131. var parent = child.get("parent"),
  132. FnRootType = child.ROOT_TYPE,
  133. criteria = parent;
  134.  
  135. if (FnRootType) {
  136. criteria = (parent && Y.instanceOf(parent, FnRootType));
  137. }
  138.  
  139. return (criteria ? getParent(parent) : child);
  140.  
  141. };
  142.  
  143. return getParent(this);
  144.  
  145. }
  146. }
  147.  
  148. };
  149.  
  150. Child.prototype = {
  151.  
  152. /**
  153. * Constructor reference used to determine the root of a Widget-based
  154. * object tree.
  155. * <p>
  156. * Currently used to control the behavior of the <code>root</code>
  157. * attribute so that recursing up the object heirarchy can be constrained
  158. * to a specific type of Widget. Widget authors should set this property
  159. * to the constructor function for a given Widget implementation.
  160. * </p>
  161. *
  162. * @property ROOT_TYPE
  163. * @type Object
  164. */
  165. ROOT_TYPE: null,
  166.  
  167. /**
  168. * Returns the node on which to bind delegate listeners.
  169. *
  170. * Override of Widget's implementation of _getUIEventNode() to ensure that
  171. * all event listeners are bound to the Widget's topmost DOM element.
  172. * This ensures that the firing of each type of Widget UI event (click,
  173. * mousedown, etc.) is facilitated by a single, top-level, delegated DOM
  174. * event listener.
  175. *
  176. * @method _getUIEventNode
  177. * @for Widget
  178. * @protected
  179. */
  180. _getUIEventNode: function () {
  181. var root = this.get("root"),
  182. returnVal;
  183.  
  184. if (root) {
  185. returnVal = root.get("boundingBox");
  186. }
  187.  
  188. return returnVal;
  189. },
  190.  
  191. /**
  192. * @method next
  193. * @description Returns the Widget's next sibling.
  194. * @param {Boolean} circular Boolean indicating if the parent's first child
  195. * should be returned if the child has no next sibling.
  196. * @return {Widget} Widget instance.
  197. */
  198. next: function (circular) {
  199.  
  200. var parent = this.get("parent"),
  201. sibling;
  202.  
  203. if (parent) {
  204. sibling = parent.item((this.get("index")+1));
  205. }
  206.  
  207. if (!sibling && circular) {
  208. sibling = parent.item(0);
  209. }
  210.  
  211. return sibling;
  212.  
  213. },
  214.  
  215.  
  216. /**
  217. * @method previous
  218. * @description Returns the Widget's previous sibling.
  219. * @param {Boolean} circular Boolean indicating if the parent's last child
  220. * should be returned if the child has no previous sibling.
  221. * @return {Widget} Widget instance.
  222. */
  223. previous: function (circular) {
  224.  
  225. var parent = this.get("parent"),
  226. index = this.get("index"),
  227. sibling;
  228.  
  229. if (parent && index > 0) {
  230. sibling = parent.item([(index-1)]);
  231. }
  232.  
  233. if (!sibling && circular) {
  234. sibling = parent.item((parent.size() - 1));
  235. }
  236.  
  237. return sibling;
  238.  
  239. },
  240.  
  241.  
  242. // Override of Y.WidgetParent.remove()
  243. // Sugar implementation allowing a child to remove itself from its parent.
  244. remove: function (index) {
  245.  
  246. var parent,
  247. removed;
  248.  
  249. if (Lang.isNumber(index)) {
  250. removed = Y.WidgetParent.prototype.remove.apply(this, arguments);
  251. }
  252. else {
  253.  
  254. parent = this.get("parent");
  255.  
  256. if (parent) {
  257. removed = parent.remove(this.get("index"));
  258. }
  259.  
  260. }
  261.  
  262. return removed;
  263.  
  264. },
  265.  
  266.  
  267. /**
  268. * @method isRoot
  269. * @description Determines if the Widget is the root Widget in the
  270. * object hierarchy.
  271. * @return {Boolean} Boolean indicating if Widget is the root Widget in the
  272. * object hierarchy.
  273. */
  274. isRoot: function () {
  275. return (this == this.get("root"));
  276. },
  277.  
  278.  
  279. /**
  280. * @method ancestor
  281. * @description Returns the Widget instance at the specified depth.
  282. * @param {number} depth Number representing the depth of the ancestor.
  283. * @return {Widget} Widget instance.
  284. */
  285. ancestor: function (depth) {
  286.  
  287. var root = this.get("root"),
  288. parent;
  289.  
  290. if (this.get("depth") > depth) {
  291.  
  292. parent = this.get("parent");
  293.  
  294. while (parent != root && parent.get("depth") > depth) {
  295. parent = parent.get("parent");
  296. }
  297.  
  298. }
  299.  
  300. return parent;
  301.  
  302. },
  303.  
  304.  
  305. /**
  306. * Updates the UI to reflect the <code>selected</code> attribute value.
  307. *
  308. * @method _uiSetChildSelected
  309. * @protected
  310. * @param {number} selected The selected value to be reflected in the UI.
  311. */
  312. _uiSetChildSelected: function (selected) {
  313.  
  314. var box = this.get("boundingBox"),
  315. sClassName = this.getClassName("selected");
  316.  
  317. if (selected === 0) {
  318. box.removeClass(sClassName);
  319. }
  320. else {
  321. box.addClass(sClassName);
  322. }
  323.  
  324. },
  325.  
  326.  
  327. /**
  328. * Default attribute change listener for the <code>selected</code>
  329. * attribute, responsible for updating the UI, in response to
  330. * attribute changes.
  331. *
  332. * @method _afterChildSelectedChange
  333. * @protected
  334. * @param {EventFacade} event The event facade for the attribute change.
  335. */
  336. _afterChildSelectedChange: function (event) {
  337. this._uiSetChildSelected(event.newVal);
  338. },
  339.  
  340.  
  341. /**
  342. * Synchronizes the UI to match the WidgetChild state.
  343. * <p>
  344. * This method is invoked after bindUI is invoked for the Widget class
  345. * using YUI's aop infrastructure.
  346. * </p>
  347. *
  348. * @method _syncUIChild
  349. * @protected
  350. */
  351. _syncUIChild: function () {
  352. this._uiSetChildSelected(this.get("selected"));
  353. },
  354.  
  355.  
  356. /**
  357. * Binds event listeners responsible for updating the UI state in response
  358. * to WidgetChild related state changes.
  359. * <p>
  360. * This method is invoked after bindUI is invoked for the Widget class
  361. * using YUI's aop infrastructure.
  362. * </p>
  363. * @method _bindUIChild
  364. * @protected
  365. */
  366. _bindUIChild: function () {
  367. this.after("selectedChange", this._afterChildSelectedChange);
  368. }
  369.  
  370. };
  371.  
  372. Y.WidgetChild = Child;
  373.