PageRenderTime 60ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/hippo/src/main/webapp/yui/layout/layout-debug.js

http://hdbc.googlecode.com/
JavaScript | 1781 lines | 1103 code | 83 blank | 595 comment | 208 complexity | 3faf7abd41763cde29d7d15e80358885 MD5 | raw file
  1. /*
  2. Copyright (c) 2009, Yahoo! Inc. All rights reserved.
  3. Code licensed under the BSD License:
  4. http://developer.yahoo.net/yui/license.txt
  5. version: 2.7.0
  6. */
  7. /**
  8. * @description <p>Provides a fixed layout containing, top, bottom, left, right and center layout units. It can be applied to either the body or an element.</p>
  9. * @namespace YAHOO.widget
  10. * @requires yahoo, dom, element, event
  11. * @module layout
  12. */
  13. (function() {
  14. var Dom = YAHOO.util.Dom,
  15. Event = YAHOO.util.Event,
  16. Lang = YAHOO.lang;
  17. /**
  18. * @constructor
  19. * @class Layout
  20. * @extends YAHOO.util.Element
  21. * @description <p>Provides a fixed layout containing, top, bottom, left, right and center layout units. It can be applied to either the body or an element.</p>
  22. * @param {String/HTMLElement} el The element to make contain a layout.
  23. * @param {Object} attrs Object liternal containing configuration parameters.
  24. */
  25. var Layout = function(el, config) {
  26. YAHOO.log('Creating the Layout Object', 'info', 'Layout');
  27. if (Lang.isObject(el) && !el.tagName) {
  28. config = el;
  29. el = null;
  30. }
  31. if (Lang.isString(el)) {
  32. if (Dom.get(el)) {
  33. el = Dom.get(el);
  34. }
  35. }
  36. if (!el) {
  37. el = document.body;
  38. }
  39. var oConfig = {
  40. element: el,
  41. attributes: config || {}
  42. };
  43. Layout.superclass.constructor.call(this, oConfig.element, oConfig.attributes);
  44. };
  45. /**
  46. * @private
  47. * @static
  48. * @property _instances
  49. * @description Internal hash table for all layout instances
  50. * @type Object
  51. */
  52. Layout._instances = {};
  53. /**
  54. * @static
  55. * @method getLayoutById
  56. * @description Get's a layout object by the HTML id of the element associated with the Layout object.
  57. * @return {Object} The Layout Object
  58. */
  59. Layout.getLayoutById = function(id) {
  60. if (Layout._instances[id]) {
  61. return Layout._instances[id];
  62. }
  63. return false;
  64. };
  65. YAHOO.extend(Layout, YAHOO.util.Element, {
  66. /**
  67. * @property browser
  68. * @description A modified version of the YAHOO.env.ua object
  69. * @type Object
  70. */
  71. browser: function() {
  72. var b = YAHOO.env.ua;
  73. b.standardsMode = false;
  74. b.secure = false;
  75. return b;
  76. }(),
  77. /**
  78. * @private
  79. * @property _units
  80. * @description An object literal that contains a list of units in the layout
  81. * @type Object
  82. */
  83. _units: null,
  84. /**
  85. * @private
  86. * @property _rendered
  87. * @description Set to true when the layout is rendered
  88. * @type Boolean
  89. */
  90. _rendered: null,
  91. /**
  92. * @private
  93. * @property _zIndex
  94. * @description The zIndex to set all LayoutUnits to
  95. * @type Number
  96. */
  97. _zIndex: null,
  98. /**
  99. * @private
  100. * @property _sizes
  101. * @description A collection of the current sizes of all usable LayoutUnits to be used for calculations
  102. * @type Object
  103. */
  104. _sizes: null,
  105. /**
  106. * @private
  107. * @method _setBodySize
  108. * @param {Boolean} set If set to false, it will NOT set the size, just perform the calculations (used for collapsing units)
  109. * @description Used to set the body size of the layout, sets the height and width of the parent container
  110. */
  111. _setBodySize: function(set) {
  112. var h = 0, w = 0;
  113. set = ((set === false) ? false : true);
  114. if (this._isBody) {
  115. h = Dom.getClientHeight();
  116. w = Dom.getClientWidth();
  117. } else {
  118. h = parseInt(this.getStyle('height'), 10);
  119. w = parseInt(this.getStyle('width'), 10);
  120. if (isNaN(w)) {
  121. w = this.get('element').clientWidth;
  122. }
  123. if (isNaN(h)) {
  124. h = this.get('element').clientHeight;
  125. }
  126. }
  127. if (this.get('minWidth')) {
  128. if (w < this.get('minWidth')) {
  129. w = this.get('minWidth');
  130. }
  131. }
  132. if (this.get('minHeight')) {
  133. if (h < this.get('minHeight')) {
  134. h = this.get('minHeight');
  135. }
  136. }
  137. if (set) {
  138. Dom.setStyle(this._doc, 'height', h + 'px');
  139. Dom.setStyle(this._doc, 'width', w + 'px');
  140. }
  141. this._sizes.doc = { h: h, w: w };
  142. YAHOO.log('Setting Body height and width: (' + h + ',' + w + ')', 'info', 'Layout');
  143. this._setSides(set);
  144. },
  145. /**
  146. * @private
  147. * @method _setSides
  148. * @param {Boolean} set If set to false, it will NOT set the size, just perform the calculations (used for collapsing units)
  149. * @description Used to set the size and position of the left, right, top and bottom units
  150. */
  151. _setSides: function(set) {
  152. YAHOO.log('Setting side units', 'info', 'Layout');
  153. var h1 = ((this._units.top) ? this._units.top.get('height') : 0),
  154. h2 = ((this._units.bottom) ? this._units.bottom.get('height') : 0),
  155. h = this._sizes.doc.h,
  156. w = this._sizes.doc.w;
  157. set = ((set === false) ? false : true);
  158. this._sizes.top = {
  159. h: h1, w: ((this._units.top) ? w : 0),
  160. t: 0
  161. };
  162. this._sizes.bottom = {
  163. h: h2, w: ((this._units.bottom) ? w : 0)
  164. };
  165. var newH = (h - (h1 + h2));
  166. this._sizes.left = {
  167. h: newH, w: ((this._units.left) ? this._units.left.get('width') : 0)
  168. };
  169. this._sizes.right = {
  170. h: newH, w: ((this._units.right) ? this._units.right.get('width') : 0),
  171. l: ((this._units.right) ? (w - this._units.right.get('width')) : 0),
  172. t: ((this._units.top) ? this._sizes.top.h : 0)
  173. };
  174. if (this._units.right && set) {
  175. this._units.right.set('top', this._sizes.right.t);
  176. if (!this._units.right._collapsing) {
  177. this._units.right.set('left', this._sizes.right.l);
  178. }
  179. this._units.right.set('height', this._sizes.right.h, true);
  180. }
  181. if (this._units.left) {
  182. this._sizes.left.l = 0;
  183. if (this._units.top) {
  184. this._sizes.left.t = this._sizes.top.h;
  185. } else {
  186. this._sizes.left.t = 0;
  187. }
  188. if (set) {
  189. this._units.left.set('top', this._sizes.left.t);
  190. this._units.left.set('height', this._sizes.left.h, true);
  191. this._units.left.set('left', 0);
  192. }
  193. }
  194. if (this._units.bottom) {
  195. this._sizes.bottom.t = this._sizes.top.h + this._sizes.left.h;
  196. if (set) {
  197. this._units.bottom.set('top', this._sizes.bottom.t);
  198. this._units.bottom.set('width', this._sizes.bottom.w, true);
  199. }
  200. }
  201. if (this._units.top) {
  202. if (set) {
  203. this._units.top.set('width', this._sizes.top.w, true);
  204. }
  205. }
  206. YAHOO.log('Setting sizes: (' + Lang.dump(this._sizes) + ')', 'info', 'Layout');
  207. this._setCenter(set);
  208. },
  209. /**
  210. * @private
  211. * @method _setCenter
  212. * @param {Boolean} set If set to false, it will NOT set the size, just perform the calculations (used for collapsing units)
  213. * @description Used to set the size and position of the center unit
  214. */
  215. _setCenter: function(set) {
  216. set = ((set === false) ? false : true);
  217. var h = this._sizes.left.h;
  218. var w = (this._sizes.doc.w - (this._sizes.left.w + this._sizes.right.w));
  219. if (set) {
  220. this._units.center.set('height', h, true);
  221. this._units.center.set('width', w, true);
  222. this._units.center.set('top', this._sizes.top.h);
  223. this._units.center.set('left', this._sizes.left.w);
  224. }
  225. this._sizes.center = { h: h, w: w, t: this._sizes.top.h, l: this._sizes.left.w };
  226. YAHOO.log('Setting Center size to: (' + h + ', ' + w + ')', 'info', 'Layout');
  227. },
  228. /**
  229. * @method getSizes
  230. * @description Get a reference to the internal Layout Unit sizes object used to build the layout wireframe
  231. * @return {Object} An object of the layout unit sizes
  232. */
  233. getSizes: function() {
  234. return this._sizes;
  235. },
  236. /**
  237. * @method getUnitById
  238. * @param {String} id The HTML element id of the unit
  239. * @description Get the LayoutUnit by it's HTML id
  240. * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
  241. */
  242. getUnitById: function(id) {
  243. return YAHOO.widget.LayoutUnit.getLayoutUnitById(id);
  244. },
  245. /**
  246. * @method getUnitByPosition
  247. * @param {String} pos The position of the unit in this layout
  248. * @description Get the LayoutUnit by it's position in this layout
  249. * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
  250. */
  251. getUnitByPosition: function(pos) {
  252. if (pos) {
  253. pos = pos.toLowerCase();
  254. if (this._units[pos]) {
  255. return this._units[pos];
  256. }
  257. return false;
  258. }
  259. return false;
  260. },
  261. /**
  262. * @method removeUnit
  263. * @param {Object} unit The LayoutUnit that you want to remove
  264. * @description Remove the unit from this layout and resize the layout.
  265. */
  266. removeUnit: function(unit) {
  267. delete this._units[unit.get('position')];
  268. this.resize();
  269. },
  270. /**
  271. * @method addUnit
  272. * @param {Object} cfg The config for the LayoutUnit that you want to add
  273. * @description Add a unit to this layout and if the layout is rendered, resize the layout.
  274. * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
  275. */
  276. addUnit: function(cfg) {
  277. if (!cfg.position) {
  278. YAHOO.log('No position property passed', 'error', 'Layout');
  279. return false;
  280. }
  281. if (this._units[cfg.position]) {
  282. YAHOO.log('Position already exists', 'error', 'Layout');
  283. return false;
  284. }
  285. YAHOO.log('Adding Unit at position: ' + cfg.position, 'info', 'Layout');
  286. var element = null,
  287. el = null;
  288. if (cfg.id) {
  289. if (Dom.get(cfg.id)) {
  290. element = Dom.get(cfg.id);
  291. delete cfg.id;
  292. }
  293. }
  294. if (cfg.element) {
  295. element = cfg.element;
  296. }
  297. if (!el) {
  298. el = document.createElement('div');
  299. var id = Dom.generateId();
  300. el.id = id;
  301. }
  302. if (!element) {
  303. element = document.createElement('div');
  304. }
  305. Dom.addClass(element, 'yui-layout-wrap');
  306. if (this.browser.ie && !this.browser.standardsMode) {
  307. el.style.zoom = 1;
  308. element.style.zoom = 1;
  309. }
  310. if (el.firstChild) {
  311. el.insertBefore(element, el.firstChild);
  312. } else {
  313. el.appendChild(element);
  314. }
  315. this._doc.appendChild(el);
  316. var h = false, w = false;
  317. if (cfg.height) {
  318. h = parseInt(cfg.height, 10);
  319. }
  320. if (cfg.width) {
  321. w = parseInt(cfg.width, 10);
  322. }
  323. var unitConfig = {};
  324. YAHOO.lang.augmentObject(unitConfig, cfg); // break obj ref
  325. unitConfig.parent = this;
  326. unitConfig.wrap = element;
  327. unitConfig.height = h;
  328. unitConfig.width = w;
  329. var unit = new YAHOO.widget.LayoutUnit(el, unitConfig);
  330. unit.on('heightChange', this.resize, this, true);
  331. unit.on('widthChange', this.resize, this, true);
  332. unit.on('gutterChange', this.resize, this, true);
  333. this._units[cfg.position] = unit;
  334. if (this._rendered) {
  335. this.resize();
  336. }
  337. return unit;
  338. },
  339. /**
  340. * @private
  341. * @method _createUnits
  342. * @description Private method to create units from the config that was passed in.
  343. */
  344. _createUnits: function() {
  345. var units = this.get('units');
  346. for (var i in units) {
  347. if (Lang.hasOwnProperty(units, i)) {
  348. this.addUnit(units[i]);
  349. }
  350. }
  351. },
  352. /**
  353. * @method resize
  354. * @param {Boolean} set If set to false, it will NOT set the size, just perform the calculations (used for collapsing units)
  355. * @description Starts the chain of resize routines that will resize all the units.
  356. * @return {<a href="YAHOO.widget.Layout.html">YAHOO.widget.Layout</a>} The Layout instance
  357. */
  358. resize: function(set) {
  359. set = ((set === false) ? false : true);
  360. if (set) {
  361. var retVal = this.fireEvent('beforeResize');
  362. if (retVal === false) {
  363. set = false;
  364. }
  365. if (this.browser.ie) {
  366. if (this._isBody) {
  367. Dom.removeClass(document.documentElement, 'yui-layout');
  368. Dom.addClass(document.documentElement, 'yui-layout');
  369. } else {
  370. this.removeClass('yui-layout');
  371. this.addClass('yui-layout');
  372. }
  373. }
  374. }
  375. this._setBodySize(set);
  376. if (set) {
  377. this.fireEvent('resize', { target: this, sizes: this._sizes });
  378. }
  379. return this;
  380. },
  381. /**
  382. * @private
  383. * @method _setupBodyElements
  384. * @description Sets up the main doc element when using the body as the main element.
  385. */
  386. _setupBodyElements: function() {
  387. this._doc = Dom.get('layout-doc');
  388. if (!this._doc) {
  389. this._doc = document.createElement('div');
  390. this._doc.id = 'layout-doc';
  391. if (document.body.firstChild) {
  392. document.body.insertBefore(this._doc, document.body.firstChild);
  393. } else {
  394. document.body.appendChild(this._doc);
  395. }
  396. }
  397. this._createUnits();
  398. this._setBodySize();
  399. Event.on(window, 'resize', this.resize, this, true);
  400. Dom.addClass(this._doc, 'yui-layout-doc');
  401. },
  402. /**
  403. * @private
  404. * @method _setupElements
  405. * @description Sets up the main doc element when not using the body as the main element.
  406. */
  407. _setupElements: function() {
  408. this._doc = this.getElementsByClassName('yui-layout-doc')[0];
  409. if (!this._doc) {
  410. this._doc = document.createElement('div');
  411. this.get('element').appendChild(this._doc);
  412. }
  413. this._createUnits();
  414. this._setBodySize();
  415. Dom.addClass(this._doc, 'yui-layout-doc');
  416. },
  417. /**
  418. * @private
  419. * @property _isBody
  420. * @description Flag to determine if we are using the body as the root element.
  421. * @type Boolean
  422. */
  423. _isBody: null,
  424. /**
  425. * @private
  426. * @property _doc
  427. * @description Reference to the root element
  428. * @type HTMLElement
  429. */
  430. _doc: null,
  431. /**
  432. * @private
  433. * @method init
  434. * @description The Layout class' initialization method
  435. */
  436. init: function(p_oElement, p_oAttributes) {
  437. YAHOO.log('init', 'info', 'Layout');
  438. this._zIndex = 0;
  439. Layout.superclass.init.call(this, p_oElement, p_oAttributes);
  440. if (this.get('parent')) {
  441. this._zIndex = this.get('parent')._zIndex + 10;
  442. }
  443. this._sizes = {};
  444. this._units = {};
  445. var id = p_oElement;
  446. if (!Lang.isString(id)) {
  447. id = Dom.generateId(id);
  448. }
  449. Layout._instances[id] = this;
  450. },
  451. /**
  452. * @method render
  453. * @description This method starts the render process, applying classnames and creating elements
  454. * @return {<a href="YAHOO.widget.Layout.html">YAHOO.widget.Layout</a>} The Layout instance
  455. */
  456. render: function() {
  457. YAHOO.log('Render', 'info', 'Layout');
  458. this._stamp();
  459. var el = this.get('element');
  460. if (el && el.tagName && (el.tagName.toLowerCase() == 'body')) {
  461. this._isBody = true;
  462. Dom.addClass(document.body, 'yui-layout');
  463. if (Dom.hasClass(document.body, 'yui-skin-sam')) {
  464. //Move the class up so we can have a css chain
  465. Dom.addClass(document.documentElement, 'yui-skin-sam');
  466. Dom.removeClass(document.body, 'yui-skin-sam');
  467. }
  468. this._setupBodyElements();
  469. } else {
  470. this._isBody = false;
  471. this.addClass('yui-layout');
  472. this._setupElements();
  473. }
  474. this.resize();
  475. this._rendered = true;
  476. this.fireEvent('render');
  477. return this;
  478. },
  479. /**
  480. * @private
  481. * @method _stamp
  482. * @description Stamps the root node with a secure classname for ease of use. Also sets the this.browser.standardsMode variable.
  483. */
  484. _stamp: function() {
  485. if (document.compatMode == 'CSS1Compat') {
  486. this.browser.standardsMode = true;
  487. }
  488. if (window.location.href.toLowerCase().indexOf("https") === 0) {
  489. Dom.addClass(document.documentElement, 'secure');
  490. this.browser.secure = true;
  491. }
  492. },
  493. /**
  494. * @private
  495. * @method initAttributes
  496. * @description Processes the config
  497. */
  498. initAttributes: function(attr) {
  499. Layout.superclass.initAttributes.call(this, attr);
  500. /**
  501. * @attribute units
  502. * @description An array of config definitions for the LayoutUnits to add to this layout
  503. * @type Array
  504. */
  505. this.setAttributeConfig('units', {
  506. writeOnce: true,
  507. validator: YAHOO.lang.isArray,
  508. value: attr.units || []
  509. });
  510. /**
  511. * @attribute minHeight
  512. * @description The minimum height in pixels
  513. * @type Number
  514. */
  515. this.setAttributeConfig('minHeight', {
  516. value: attr.minHeight || false,
  517. validator: YAHOO.lang.isNumber
  518. });
  519. /**
  520. * @attribute minWidth
  521. * @description The minimum width in pixels
  522. * @type Number
  523. */
  524. this.setAttributeConfig('minWidth', {
  525. value: attr.minWidth || false,
  526. validator: YAHOO.lang.isNumber
  527. });
  528. /**
  529. * @attribute height
  530. * @description The height in pixels
  531. * @type Number
  532. */
  533. this.setAttributeConfig('height', {
  534. value: attr.height || false,
  535. validator: YAHOO.lang.isNumber,
  536. method: function(h) {
  537. this.setStyle('height', h + 'px');
  538. }
  539. });
  540. /**
  541. * @attribute width
  542. * @description The width in pixels
  543. * @type Number
  544. */
  545. this.setAttributeConfig('width', {
  546. value: attr.width || false,
  547. validator: YAHOO.lang.isNumber,
  548. method: function(w) {
  549. this.setStyle('width', w + 'px');
  550. }
  551. });
  552. /**
  553. * @attribute parent
  554. * @description If this layout is to be used as a child of another Layout instance, this config will bind the resize events together.
  555. * @type Object YAHOO.widget.Layout
  556. */
  557. this.setAttributeConfig('parent', {
  558. writeOnce: true,
  559. value: attr.parent || false,
  560. method: function(p) {
  561. if (p) {
  562. p.on('resize', this.resize, this, true);
  563. }
  564. }
  565. });
  566. },
  567. /**
  568. * @method destroy
  569. * @description Removes this layout from the page and destroys all units that it contains. This will destroy all data inside the layout and it's children.
  570. */
  571. destroy: function() {
  572. var par = this.get('parent');
  573. if (par) {
  574. par.removeListener('resize', this.resize, this, true);
  575. }
  576. Event.removeListener(window, 'resize', this.resize, this, true);
  577. this.unsubscribeAll();
  578. for (var u in this._units) {
  579. if (Lang.hasOwnProperty(this._units, u)) {
  580. if (this._units[u]) {
  581. this._units[u].destroy(true);
  582. }
  583. }
  584. }
  585. Event.purgeElement(this.get('element'));
  586. this.get('parentNode').removeChild(this.get('element'));
  587. delete YAHOO.widget.Layout._instances[this.get('id')];
  588. //Brutal Object Destroy
  589. for (var i in this) {
  590. if (Lang.hasOwnProperty(this, i)) {
  591. this[i] = null;
  592. delete this[i];
  593. }
  594. }
  595. if (par) {
  596. par.resize();
  597. }
  598. },
  599. /**
  600. * @method toString
  601. * @description Returns a string representing the Layout.
  602. * @return {String}
  603. */
  604. toString: function() {
  605. if (this.get) {
  606. return 'Layout #' + this.get('id');
  607. }
  608. return 'Layout';
  609. }
  610. });
  611. /**
  612. * @event resize
  613. * @description Fired when this.resize is called
  614. * @type YAHOO.util.CustomEvent
  615. */
  616. /**
  617. * @event startResize
  618. * @description Fired when the Resize Utility for a Unit fires it's startResize Event.
  619. * @type YAHOO.util.CustomEvent
  620. */
  621. /**
  622. * @event beforeResize
  623. * @description Fires at the beginning of the resize method. If you return false, the resize is cancelled.
  624. * @type YAHOO.util.CustomEvent
  625. */
  626. /**
  627. * @event render
  628. * @description Fired after the render method completes.
  629. * @type YAHOO.util.CustomEvent
  630. */
  631. YAHOO.widget.Layout = Layout;
  632. })();
  633. /**
  634. * @description <p>Provides a fixed position unit containing a header, body and footer for use with a YAHOO.widget.Layout instance.</p>
  635. * @namespace YAHOO.widget
  636. * @requires yahoo, dom, element, event, layout
  637. * @optional animation, dragdrop, selector
  638. */
  639. (function() {
  640. var Dom = YAHOO.util.Dom,
  641. Sel = YAHOO.util.Selector,
  642. Event = YAHOO.util.Event,
  643. Lang = YAHOO.lang;
  644. /**
  645. * @constructor
  646. * @class LayoutUnit
  647. * @extends YAHOO.util.Element
  648. * @description <p>Provides a fixed position unit containing a header, body and footer for use with a YAHOO.widget.Layout instance.</p>
  649. * @param {String/HTMLElement} el The element to make a unit.
  650. * @param {Object} attrs Object liternal containing configuration parameters.
  651. */
  652. var LayoutUnit = function(el, config) {
  653. var oConfig = {
  654. element: el,
  655. attributes: config || {}
  656. };
  657. LayoutUnit.superclass.constructor.call(this, oConfig.element, oConfig.attributes);
  658. };
  659. /**
  660. * @private
  661. * @static
  662. * @property _instances
  663. * @description Internal hash table for all layout unit instances
  664. * @type Object
  665. */
  666. LayoutUnit._instances = {};
  667. /**
  668. * @static
  669. * @method getLayoutUnitById
  670. * @description Get's a layout unit object by the HTML id of the element associated with the Layout Unit object.
  671. * @return {Object} The Layout Object
  672. */
  673. LayoutUnit.getLayoutUnitById = function(id) {
  674. if (LayoutUnit._instances[id]) {
  675. return LayoutUnit._instances[id];
  676. }
  677. return false;
  678. };
  679. YAHOO.extend(LayoutUnit, YAHOO.util.Element, {
  680. /**
  681. * @property STR_CLOSE
  682. * @description String used for close button title
  683. * @type {String}
  684. */
  685. STR_CLOSE: 'Click to close this pane.',
  686. /**
  687. * @property STR_COLLAPSE
  688. * @description String used for collapse button title
  689. * @type {String}
  690. */
  691. STR_COLLAPSE: 'Click to collapse this pane.',
  692. /**
  693. * @property STR_EXPAND
  694. * @description String used for expand button title
  695. * @type {String}
  696. */
  697. STR_EXPAND: 'Click to expand this pane.',
  698. /**
  699. * The class name applied to dynamic tabs while loading.
  700. * @property LOADING_CLASSNAME
  701. * @type String
  702. * @default "disabled"
  703. */
  704. LOADING_CLASSNAME: 'loading',
  705. /**
  706. * @property browser
  707. * @description A modified version of the YAHOO.env.ua object
  708. * @type Object
  709. */
  710. browser: null,
  711. /**
  712. * @private
  713. * @property _sizes
  714. * @description A collection of the current sizes of the contents of this Layout Unit
  715. * @type Object
  716. */
  717. _sizes: null,
  718. /**
  719. * @private
  720. * @property _anim
  721. * @description A reference to the Animation instance used by this LayouUnit
  722. * @type YAHOO.util.Anim
  723. */
  724. _anim: null,
  725. /**
  726. * @private
  727. * @property _resize
  728. * @description A reference to the Resize instance used by this LayoutUnit
  729. * @type YAHOO.util.Resize
  730. */
  731. _resize: null,
  732. /**
  733. * @private
  734. * @property _clip
  735. * @description A reference to the clip element used when collapsing the unit
  736. * @type HTMLElement
  737. */
  738. _clip: null,
  739. /**
  740. * @private
  741. * @property _gutter
  742. * @description A simple hash table used to store the gutter to apply to the Unit
  743. * @type Object
  744. */
  745. _gutter: null,
  746. /**
  747. * @property header
  748. * @description A reference to the HTML element used for the Header
  749. * @type HTMLELement
  750. */
  751. header: null,
  752. /**
  753. * @property body
  754. * @description A reference to the HTML element used for the body
  755. * @type HTMLElement
  756. */
  757. body: null,
  758. /**
  759. * @property footer
  760. * @description A reference to the HTML element used for the footer
  761. * @type HTMLElement
  762. */
  763. footer: null,
  764. /**
  765. * @private
  766. * @property _collapsed
  767. * @description Flag to determine if the unit is collapsed or not.
  768. * @type Boolean
  769. */
  770. _collapsed: null,
  771. /**
  772. * @private
  773. * @property _collapsing
  774. * @description A flag set while the unit is being collapsed, used so we don't fire events while animating the size
  775. * @type Boolean
  776. */
  777. _collapsing: null,
  778. /**
  779. * @private
  780. * @property _lastWidth
  781. * @description A holder for the last known width of the unit
  782. * @type Number
  783. */
  784. _lastWidth: null,
  785. /**
  786. * @private
  787. * @property _lastHeight
  788. * @description A holder for the last known height of the unit
  789. * @type Number
  790. */
  791. _lastHeight: null,
  792. /**
  793. * @private
  794. * @property _lastTop
  795. * @description A holder for the last known top of the unit
  796. * @type Number
  797. */
  798. _lastTop: null,
  799. /**
  800. * @private
  801. * @property _lastLeft
  802. * @description A holder for the last known left of the unit
  803. * @type Number
  804. */
  805. _lastLeft: null,
  806. /**
  807. * @private
  808. * @property _lastScroll
  809. * @description A holder for the last known scroll state of the unit
  810. * @type Boolean
  811. */
  812. _lastScroll: null,
  813. /**
  814. * @private
  815. * @property _lastCenetrScroll
  816. * @description A holder for the last known scroll state of the center unit
  817. * @type Boolean
  818. */
  819. _lastCenterScroll: null,
  820. /**
  821. * @private
  822. * @property _lastScrollTop
  823. * @description A holder for the last known scrollTop state of the unit
  824. * @type Number
  825. */
  826. _lastScrollTop: null,
  827. /**
  828. * @method resize
  829. * @description Resize either the unit or it's clipped state, also updating the box inside
  830. * @param {Boolean} force This will force full calculations even when the unit is collapsed
  831. * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
  832. */
  833. resize: function(force) {
  834. YAHOO.log('Resize', 'info', 'LayoutUnit');
  835. var retVal = this.fireEvent('beforeResize');
  836. if (retVal === false) {
  837. return this;
  838. }
  839. if (!this._collapsing || (force === true)) {
  840. var scroll = this.get('scroll');
  841. this.set('scroll', false);
  842. var hd = this._getBoxSize(this.header),
  843. ft = this._getBoxSize(this.footer),
  844. box = [this.get('height'), this.get('width')];
  845. var nh = (box[0] - hd[0] - ft[0]) - (this._gutter.top + this._gutter.bottom),
  846. nw = box[1] - (this._gutter.left + this._gutter.right);
  847. var wrapH = (nh + (hd[0] + ft[0])),
  848. wrapW = nw;
  849. if (this._collapsed && !this._collapsing) {
  850. this._setHeight(this._clip, wrapH);
  851. this._setWidth(this._clip, wrapW);
  852. Dom.setStyle(this._clip, 'top', this.get('top') + this._gutter.top + 'px');
  853. Dom.setStyle(this._clip, 'left', this.get('left') + this._gutter.left + 'px');
  854. } else if (!this._collapsed || (this._collapsed && this._collapsing)) {
  855. wrapH = this._setHeight(this.get('wrap'), wrapH);
  856. wrapW = this._setWidth(this.get('wrap'), wrapW);
  857. this._sizes.wrap.h = wrapH;
  858. this._sizes.wrap.w = wrapW;
  859. Dom.setStyle(this.get('wrap'), 'top', this._gutter.top + 'px');
  860. Dom.setStyle(this.get('wrap'), 'left', this._gutter.left + 'px');
  861. this._sizes.header.w = this._setWidth(this.header, wrapW);
  862. this._sizes.header.h = hd[0];
  863. this._sizes.footer.w = this._setWidth(this.footer, wrapW);
  864. this._sizes.footer.h = ft[0];
  865. Dom.setStyle(this.footer, 'bottom', '0px');
  866. this._sizes.body.h = this._setHeight(this.body, (wrapH - (hd[0] + ft[0])));
  867. this._sizes.body.w =this._setWidth(this.body, wrapW);
  868. Dom.setStyle(this.body, 'top', hd[0] + 'px');
  869. this.set('scroll', scroll);
  870. this.fireEvent('resize');
  871. }
  872. }
  873. return this;
  874. },
  875. /**
  876. * @private
  877. * @method _setWidth
  878. * @description Sets the width of the element based on the border size of the element.
  879. * @param {HTMLElement} el The HTMLElement to have it's width set
  880. * @param {Number} w The width that you want it the element set to
  881. * @return {Number} The new width, fixed for borders and IE QuirksMode
  882. */
  883. _setWidth: function(el, w) {
  884. if (el) {
  885. var b = this._getBorderSizes(el);
  886. w = (w - (b[1] + b[3]));
  887. w = this._fixQuirks(el, w, 'w');
  888. if (w < 0) {
  889. w = 0;
  890. }
  891. Dom.setStyle(el, 'width', w + 'px');
  892. }
  893. return w;
  894. },
  895. /**
  896. * @private
  897. * @method _setHeight
  898. * @description Sets the height of the element based on the border size of the element.
  899. * @param {HTMLElement} el The HTMLElement to have it's height set
  900. * @param {Number} h The height that you want it the element set to
  901. * @return {Number} The new height, fixed for borders and IE QuirksMode
  902. */
  903. _setHeight: function(el, h) {
  904. if (el) {
  905. var b = this._getBorderSizes(el);
  906. h = (h - (b[0] + b[2]));
  907. h = this._fixQuirks(el, h, 'h');
  908. if (h < 0) {
  909. h = 0;
  910. }
  911. Dom.setStyle(el, 'height', h + 'px');
  912. }
  913. return h;
  914. },
  915. /**
  916. * @private
  917. * @method _fixQuirks
  918. * @description Fixes the box calculations for IE in QuirksMode
  919. * @param {HTMLElement} el The HTMLElement to set the dimension on
  920. * @param {Number} dim The number of the dimension to fix
  921. * @param {String} side The dimension (h or w) to fix. Defaults to h
  922. * @return {Number} The fixed dimension
  923. */
  924. _fixQuirks: function(el, dim, side) {
  925. var i1 = 0, i2 = 2;
  926. if (side == 'w') {
  927. i1 = 1;
  928. i2 = 3;
  929. }
  930. if (this.browser.ie && !this.browser.standardsMode) {
  931. //Internet Explorer - Quirks Mode
  932. var b = this._getBorderSizes(el),
  933. bp = this._getBorderSizes(el.parentNode);
  934. if ((b[i1] === 0) && (b[i2] === 0)) { //No Borders, check parent
  935. if ((bp[i1] !== 0) && (bp[i2] !== 0)) { //Parent has Borders
  936. dim = (dim - (bp[i1] + bp[i2]));
  937. }
  938. } else {
  939. if ((bp[i1] === 0) && (bp[i2] === 0)) {
  940. dim = (dim + (b[i1] + b[i2]));
  941. }
  942. }
  943. }
  944. return dim;
  945. },
  946. /**
  947. * @private
  948. * @method _getBoxSize
  949. * @description Get's the elements clientHeight and clientWidth plus the size of the borders
  950. * @param {HTMLElement} el The HTMLElement to get the size of
  951. * @return {Array} An array of height and width
  952. */
  953. _getBoxSize: function(el) {
  954. var size = [0, 0];
  955. if (el) {
  956. if (this.browser.ie && !this.browser.standardsMode) {
  957. el.style.zoom = 1;
  958. }
  959. var b = this._getBorderSizes(el);
  960. size[0] = el.clientHeight + (b[0] + b[2]);
  961. size[1] = el.clientWidth + (b[1] + b[3]);
  962. }
  963. return size;
  964. },
  965. /**
  966. * @private
  967. * @method _getBorderSizes
  968. * @description Get the CSS border size of the element passed.
  969. * @param {HTMLElement} el The element to get the border size of
  970. * @return {Array} An array of the top, right, bottom, left borders.
  971. */
  972. _getBorderSizes: function(el) {
  973. var s = [];
  974. el = el || this.get('element');
  975. if (this.browser.ie && !this.browser.standardsMode) {
  976. el.style.zoom = 1;
  977. }
  978. s[0] = parseInt(Dom.getStyle(el, 'borderTopWidth'), 10);
  979. s[1] = parseInt(Dom.getStyle(el, 'borderRightWidth'), 10);
  980. s[2] = parseInt(Dom.getStyle(el, 'borderBottomWidth'), 10);
  981. s[3] = parseInt(Dom.getStyle(el, 'borderLeftWidth'), 10);
  982. //IE will return NaN on these if they are set to auto, we'll set them to 0
  983. for (var i = 0; i < s.length; i++) {
  984. if (isNaN(s[i])) {
  985. s[i] = 0;
  986. }
  987. }
  988. return s;
  989. },
  990. /**
  991. * @private
  992. * @method _createClip
  993. * @description Create the clip element used when the Unit is collapsed
  994. */
  995. _createClip: function() {
  996. if (!this._clip) {
  997. this._clip = document.createElement('div');
  998. this._clip.className = 'yui-layout-clip yui-layout-clip-' + this.get('position');
  999. this._clip.innerHTML = '<div class="collapse"></div>';
  1000. var c = this._clip.firstChild;
  1001. c.title = this.STR_EXPAND;
  1002. Event.on(c, 'click', this.expand, this, true);
  1003. this.get('element').parentNode.appendChild(this._clip);
  1004. }
  1005. },
  1006. /**
  1007. * @private
  1008. * @method _toggleClip
  1009. * @description Toggle th current state of the Clip element and set it's height, width and position
  1010. */
  1011. _toggleClip: function() {
  1012. if (!this._collapsed) {
  1013. //show
  1014. var hd = this._getBoxSize(this.header),
  1015. ft = this._getBoxSize(this.footer),
  1016. box = [this.get('height'), this.get('width')];
  1017. var nh = (box[0] - hd[0] - ft[0]) - (this._gutter.top + this._gutter.bottom),
  1018. nw = box[1] - (this._gutter.left + this._gutter.right),
  1019. wrapH = (nh + (hd[0] + ft[0]));
  1020. switch (this.get('position')) {
  1021. case 'top':
  1022. case 'bottom':
  1023. this._setWidth(this._clip, nw);
  1024. this._setHeight(this._clip, this.get('collapseSize'));
  1025. Dom.setStyle(this._clip, 'left', (this._lastLeft + this._gutter.left) + 'px');
  1026. if (this.get('position') == 'bottom') {
  1027. Dom.setStyle(this._clip, 'top', ((this._lastTop + this._lastHeight) - (this.get('collapseSize') - this._gutter.top)) + 'px');
  1028. } else {
  1029. Dom.setStyle(this._clip, 'top', this.get('top') + this._gutter.top + 'px');
  1030. }
  1031. break;
  1032. case 'left':
  1033. case 'right':
  1034. this._setWidth(this._clip, this.get('collapseSize'));
  1035. this._setHeight(this._clip, wrapH);
  1036. Dom.setStyle(this._clip, 'top', (this.get('top') + this._gutter.top) + 'px');
  1037. if (this.get('position') == 'right') {
  1038. Dom.setStyle(this._clip, 'left', (((this._lastLeft + this._lastWidth) - this.get('collapseSize')) - this._gutter.left) + 'px');
  1039. } else {
  1040. Dom.setStyle(this._clip, 'left', (this.get('left') + this._gutter.left) + 'px');
  1041. }
  1042. break;
  1043. }
  1044. Dom.setStyle(this._clip, 'display', 'block');
  1045. this.setStyle('display', 'none');
  1046. } else {
  1047. //Hide
  1048. Dom.setStyle(this._clip, 'display', 'none');
  1049. }
  1050. },
  1051. /**
  1052. * @method getSizes
  1053. * @description Get a reference to the internal sizes object for this unit
  1054. * @return {Object} An object of the sizes used for calculations
  1055. */
  1056. getSizes: function() {
  1057. return this._sizes;
  1058. },
  1059. /**
  1060. * @method toggle
  1061. * @description Toggles the Unit, replacing it with a clipped version.
  1062. * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
  1063. */
  1064. toggle: function() {
  1065. if (this._collapsed) {
  1066. this.expand();
  1067. } else {
  1068. this.collapse();
  1069. }
  1070. return this;
  1071. },
  1072. /**
  1073. * @method expand
  1074. * @description Expand the Unit if it is collapsed.
  1075. * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
  1076. */
  1077. expand: function() {
  1078. if (!this._collapsed) {
  1079. return this;
  1080. }
  1081. var retVal = this.fireEvent('beforeExpand');
  1082. if (retVal === false) {
  1083. return this;
  1084. }
  1085. this._collapsing = true;
  1086. this.setStyle('zIndex', this.get('parent')._zIndex + 1);
  1087. if (this._anim) {
  1088. this.setStyle('display', 'none');
  1089. var attr = {}, s;
  1090. switch (this.get('position')) {
  1091. case 'left':
  1092. case 'right':
  1093. this.set('width', this._lastWidth, true);
  1094. this.setStyle('width', this._lastWidth + 'px');
  1095. this.get('parent').resize(false);
  1096. s = this.get('parent').getSizes()[this.get('position')];
  1097. this.set('height', s.h, true);
  1098. var left = s.l;
  1099. attr = {
  1100. left: {
  1101. to: left
  1102. }
  1103. };
  1104. if (this.get('position') == 'left') {
  1105. attr.left.from = (left - s.w);
  1106. this.setStyle('left', (left - s.w) + 'px');
  1107. }
  1108. break;
  1109. case 'top':
  1110. case 'bottom':
  1111. this.set('height', this._lastHeight, true);
  1112. this.setStyle('height', this._lastHeight + 'px');
  1113. this.get('parent').resize(false);
  1114. s = this.get('parent').getSizes()[this.get('position')];
  1115. this.set('width', s.w, true);
  1116. var top = s.t;
  1117. attr = {
  1118. top: {
  1119. to: top
  1120. }
  1121. };
  1122. if (this.get('position') == 'top') {
  1123. this.setStyle('top', (top - s.h) + 'px');
  1124. attr.top.from = (top - s.h);
  1125. }
  1126. break;
  1127. }
  1128. this._anim.attributes = attr;
  1129. var exStart = function() {
  1130. this.setStyle('display', 'block');
  1131. this.resize(true);
  1132. this._anim.onStart.unsubscribe(exStart, this, true);
  1133. };
  1134. var expand = function() {
  1135. this._collapsing = false;
  1136. this.setStyle('zIndex', this.get('parent')._zIndex);
  1137. this.set('width', this._lastWidth);
  1138. this.set('height', this._lastHeight);
  1139. this._collapsed = false;
  1140. this.resize();
  1141. this.set('scroll', this._lastScroll);
  1142. if (this._lastScrollTop > 0) {
  1143. this.body.scrollTop = this._lastScrollTop;
  1144. }
  1145. this._anim.onComplete.unsubscribe(expand, this, true);
  1146. this.fireEvent('expand');
  1147. };
  1148. this._anim.onStart.subscribe(exStart, this, true);
  1149. this._anim.onComplete.subscribe(expand, this, true);
  1150. this._anim.animate();
  1151. this._toggleClip();
  1152. } else {
  1153. this._collapsing = false;
  1154. this._toggleClip();
  1155. this._collapsed = false;
  1156. this.setStyle('zIndex', this.get('parent')._zIndex);
  1157. this.setStyle('display', 'block');
  1158. this.set('width', this._lastWidth);
  1159. this.set('height', this._lastHeight);
  1160. this.resize();
  1161. this.set('scroll', this._lastScroll);
  1162. if (this._lastScrollTop > 0) {
  1163. this.body.scrollTop = this._lastScrollTop;
  1164. }
  1165. this.fireEvent('expand');
  1166. }
  1167. return this;
  1168. },
  1169. /**
  1170. * @method collapse
  1171. * @description Collapse the Unit if it is not collapsed.
  1172. * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
  1173. */
  1174. collapse: function() {
  1175. if (this._collapsed) {
  1176. return this;
  1177. }
  1178. var retValue = this.fireEvent('beforeCollapse');
  1179. if (retValue === false) {
  1180. return this;
  1181. }
  1182. if (!this._clip) {
  1183. this._createClip();
  1184. }
  1185. this._collapsing = true;
  1186. var w = this.get('width'),
  1187. h = this.get('height'),
  1188. attr = {};
  1189. this._lastWidth = w;
  1190. this._lastHeight = h;
  1191. this._lastScroll = this.get('scroll');
  1192. this._lastScrollTop = this.body.scrollTop;
  1193. this.set('scroll', false, true);
  1194. this._lastLeft = parseInt(this.get('element').style.left, 10);
  1195. this._lastTop = parseInt(this.get('element').style.top, 10);
  1196. if (isNaN(this._lastTop)) {
  1197. this._lastTop = 0;
  1198. this.set('top', 0);
  1199. }
  1200. if (isNaN(this._lastLeft)) {
  1201. this._lastLeft = 0;
  1202. this.set('left', 0);
  1203. }
  1204. this.setStyle('zIndex', this.get('parent')._zIndex + 1);
  1205. var pos = this.get('position');
  1206. switch (pos) {
  1207. case 'top':
  1208. case 'bottom':
  1209. this.set('height', (this.get('collapseSize') + (this._gutter.top + this._gutter.bottom)));
  1210. attr = {
  1211. top: {
  1212. to: (this.get('top') - h)
  1213. }
  1214. };
  1215. if (pos == 'bottom') {
  1216. attr.top.to = (this.get('top') + h);
  1217. }
  1218. break;
  1219. case 'left':
  1220. case 'right':
  1221. this.set('width', (this.get('collapseSize') + (this._gutter.left + this._gutter.right)));
  1222. attr = {
  1223. left: {
  1224. to: -(this._lastWidth)
  1225. }
  1226. };
  1227. if (pos == 'right') {
  1228. attr.left = {
  1229. to: (this.get('left') + w)
  1230. };
  1231. }
  1232. break;
  1233. }
  1234. if (this._anim) {
  1235. this._anim.attributes = attr;
  1236. var collapse = function() {
  1237. this._collapsing = false;
  1238. this._toggleClip();
  1239. this.setStyle('zIndex', this.get('parent')._zIndex);
  1240. this._collapsed = true;
  1241. this.get('parent').resize();
  1242. this._anim.onComplete.unsubscribe(collapse, this, true);
  1243. this.fireEvent('collapse');
  1244. };
  1245. this._anim.onComplete.subscribe(collapse, this, true);
  1246. this._anim.animate();
  1247. } else {
  1248. this._collapsing = false;
  1249. this.setStyle('display', 'none');
  1250. this._toggleClip();
  1251. this.setStyle('zIndex', this.get('parent')._zIndex);
  1252. this.get('parent').resize();
  1253. this._collapsed = true;
  1254. this.fireEvent('collapse');
  1255. }
  1256. return this;
  1257. },
  1258. /**
  1259. * @method close
  1260. * @description Close the unit, removing it from the parent Layout.
  1261. * @return {<a href="YAHOO.widget.Layout.html">YAHOO.widget.Layout</a>} The parent Layout instance
  1262. */
  1263. close: function() {
  1264. this.setStyle('display', 'none');
  1265. this.get('parent').removeUnit(this);
  1266. this.fireEvent('close');
  1267. if (this._clip) {
  1268. this._clip.parentNode.removeChild(this._clip);
  1269. this._clip = null;
  1270. }
  1271. return this.get('parent');
  1272. },
  1273. /**
  1274. * @property loadHandler
  1275. * @description Callback method for the YUI Connection Manager used for load the body using AJAX
  1276. * @type Object
  1277. */
  1278. loadHandler: {
  1279. success: function(o) {
  1280. this.body.innerHTML = o.responseText;
  1281. this.resize (true);
  1282. },
  1283. failure: function(o) {
  1284. }
  1285. },
  1286. /**
  1287. * @property dataConnection
  1288. * @description YUI Connection Manager handler
  1289. * @type Object
  1290. */
  1291. dataConnection: null,
  1292. /**
  1293. * @private
  1294. * @property _loading
  1295. * @description During the loading process this variable will be true
  1296. * @type Number
  1297. */
  1298. _loading: false,
  1299. /**
  1300. * @method loadContent
  1301. * @description Loading the content of the unit using the connection manager
  1302. * @return {object} YUI Connection Manager handler
  1303. */
  1304. loadContent: function() {
  1305. // load dynamic content unless already loading or loaded and caching
  1306. if (YAHOO.util.Connect && this.get('dataSrc') && !this._loading && !this.get('dataLoaded')) {
  1307. this._loading = true;
  1308. Dom.addClass(this.body, this.LOADING_CLASSNAME);
  1309. this.dataConnection = YAHOO.util.Connect.asyncRequest(
  1310. this.get('loadMethod'),
  1311. this.get('dataSrc'),
  1312. {
  1313. success: function(o) {
  1314. this.loadHandler.success.call(this, o);
  1315. this.set('dataLoaded', true);
  1316. this.dataConnection = null;
  1317. Dom.removeClass(this.body, this.LOADING_CLASSNAME);
  1318. this._loading = false;
  1319. this.fireEvent('load');
  1320. },
  1321. failure: function(o) {
  1322. this.loadHandler.failure.call(this, o);
  1323. this.dataConnection = null;
  1324. Dom.removeClass(this.body, this.LOADING_CLASSNAME);
  1325. this._loading = false;
  1326. this.fireEvent('loadError', { error: o });
  1327. },
  1328. scope: this,
  1329. timeout: this.get('dataTimeout')
  1330. }
  1331. );
  1332. return this.dataConnection;
  1333. }
  1334. return false;
  1335. },
  1336. /**
  1337. * @private
  1338. * @method init
  1339. * @description The initalization method inherited from Element.
  1340. */
  1341. init: function(p_oElement, p_oAttributes) {
  1342. YAHOO.log('init', 'info', 'LayoutUnit');
  1343. this._gutter = {
  1344. left: 0,
  1345. right: 0,
  1346. top: 0,
  1347. bottom: 0
  1348. };
  1349. this._sizes = {
  1350. wrap: {
  1351. h: 0,
  1352. w: 0
  1353. },
  1354. header: {
  1355. h: 0,
  1356. w: 0
  1357. },
  1358. body: {
  1359. h: 0,
  1360. w: 0
  1361. },
  1362. footer: {
  1363. h: 0,
  1364. w: 0
  1365. }
  1366. };
  1367. LayoutUnit.superclass.init.call(this, p_oElement, p_oAttributes);
  1368. this.browser = this.get('parent').browser;
  1369. var id = p_oElement;
  1370. if (!Lang.isString(id)) {
  1371. id = Dom.generateId(id);
  1372. }
  1373. LayoutUnit._instances[id] = this;
  1374. this.setStyle('position', 'absolute');
  1375. this.addClass('yui-layout-unit');
  1376. this.addClass('yui-layout-unit-' + this.get('position'));
  1377. var header = this.getElementsByClassName('yui-layout-hd', 'div')[0];
  1378. if (header) {
  1379. this.header = header;
  1380. }
  1381. var body = this.getElementsByClassName('yui-layout-bd', 'div')[0];
  1382. if (body) {
  1383. this.body = body;
  1384. }
  1385. var footer = this.getElementsByClassName('yui-layout-ft', 'div')[0];
  1386. if (footer) {
  1387. this.footer = footer;
  1388. }
  1389. this.on('contentChange', this.resize, this, true);
  1390. this._lastScrollTop = 0;
  1391. this.set('animate', this.get('animate'));
  1392. },
  1393. /**
  1394. * @private
  1395. * @method initAttributes
  1396. * @description Processes the config
  1397. */
  1398. initAttributes: function(attr) {
  1399. LayoutUnit.superclass.initAttributes.call(this, attr);
  1400. /**
  1401. * @private
  1402. * @attribute wrap
  1403. * @description A reference to the wrap element
  1404. * @type HTMLElement
  1405. */
  1406. this.setAttributeConfig('wrap', {
  1407. value: attr.wrap || null,
  1408. method: function(w) {
  1409. if (w) {
  1410. var id = Dom.generateId(w);
  1411. LayoutUnit._instances[id] = this;
  1412. }
  1413. }
  1414. });
  1415. /**
  1416. * @attribute grids
  1417. * @description Set this option to true if you want the LayoutUnit to fix the first layer of YUI CSS Grids (margins)
  1418. * @type Boolean
  1419. */
  1420. this.setAttributeConfig('grids', {
  1421. value: attr.grids || false
  1422. });
  1423. /**
  1424. * @private
  1425. * @attribute top
  1426. * @description The current top positioning of the Unit
  1427. * @type Number
  1428. */
  1429. this.setAttributeConfig('top', {
  1430. value: attr.top || 0,
  1431. validator: Lang.isNumber,
  1432. method: function(t) {
  1433. if (!this._collapsing) {
  1434. this.setStyle('top', t + 'px');
  1435. }
  1436. }
  1437. });
  1438. /**
  1439. * @private
  1440. * @attribute left
  1441. * @description The current left position of the Unit
  1442. * @type Number
  1443. */
  1444. this.setAttributeConfig('left', {
  1445. value: attr.left || 0,
  1446. validator: Lang.isNumber,
  1447. method: function(l) {
  1448. if (!this._collapsing) {
  1449. this.setStyle('left', l + 'px');
  1450. }
  1451. }
  1452. });
  1453. /**
  1454. * @attribute minWidth
  1455. * @description The minWidth parameter passed to the Resize Utility
  1456. * @type Number
  1457. */
  1458. this.setAttributeConfig('minWidth', {
  1459. value: attr.minWidth || false,
  1460. validator: YAHOO.lang.isNumber
  1461. });
  1462. /**
  1463. * @attribute maxWidth
  1464. * @description The maxWidth parameter passed to the Resize Utility
  1465. * @type Number
  1466. */
  1467. this.setAttributeConfig('maxWidth', {
  1468. value: attr.maxWidth || false,
  1469. validator: YAHOO.lang.isNumber
  1470. });
  1471. /**
  1472. * @attribute minHeight
  1473. * @description The minHeight parameter passed to the Resize Utility
  1474. * @type Number
  1475. */
  1476. this.setAttributeConfig('minHeight', {
  1477. value: attr.minHeight || false,
  1478. validator: YAHOO.lang.isNumber
  1479. });
  1480. /**
  1481. * @attribute maxHeight
  1482. * @description The maxHeight parameter passed to the Resize Utility
  1483. * @type Number
  1484. */
  1485. this.setAttributeConfig('maxHeight', {
  1486. value: attr.maxHeight || false,
  1487. validator: YAHOO.lang.isNumber
  1488. });
  1489. /**
  1490. * @attribute height
  1491. * @description The height of the Unit
  1492. * @type Number
  1493. */
  1494. this.setAttributeConfig('height', {
  1495. value: attr.height,
  1496. validator: Lang.isNumber,
  1497. method: function(h) {
  1498. if (!this._collapsing) {
  1499. if (h < 0) {
  1500. h = 0;
  1501. }
  1502. this.setStyle('height', h + 'px');
  1503. }
  1504. }
  1505. });
  1506. /**
  1507. * @attribute width
  1508. * @description The width of the Unit
  1509. * @type Number
  1510. */
  1511. this.setAttributeConfig('width', {
  1512. value: attr.width,
  1513. validator: Lang.isNumber,
  1514. method: function(w) {
  1515. if (!this._collapsing) {
  1516. if (w < 0) {
  1517. w = 0;
  1518. }
  1519. this.setStyle('width', w + 'px');
  1520. }
  1521. }
  1522. });
  1523. /**
  1524. * @attribute zIndex
  1525. * @description The CSS zIndex to give to the unit, so you can have overlapping elements such as menus in a unit.
  1526. * @type {Number}
  1527. */
  1528. this.setAttributeConfig('zIndex', {
  1529. value: attr.zIndex || false,
  1530. method: function(z) {
  1531. this.setStyle('zIndex', z);
  1532. }
  1533. });
  1534. /**
  1535. * @attribute position
  1536. * @description The position (top, right, bottom, left or center) of the Unit in the Layout
  1537. * @type {String}
  1538. */
  1539. this.setAttributeConfig('position', {
  1540. value: attr.position
  1541. });
  1542. /**
  1543. * @attribute gutter
  1544. * @description The gutter that we should apply to the parent Layout around this Unit. Supports standard CSS markup: (2 4 0 5) or (2) or (2 5)
  1545. * @type String
  1546. */
  1547. this.setAttributeConfig('gutter', {
  1548. value: attr.gutter || 0,
  1549. validator: YAHOO.lang.isString,
  1550. method: function(gutter) {
  1551. var p = gutter.split(' ');
  1552. if (p.length) {
  1553. this._gutter.top = parseInt(p[0], 10);
  1554. if (p[1]) {
  1555. this._gutter.right = parseInt(p[1], 10);
  1556. } else {
  1557. this._gutter.right = this._gutter.top;
  1558. }
  1559. if (p[2]) {
  1560. this._gutter.bottom = parseInt(p[2], 10);
  1561. } else {
  1562. this._gutter.bottom = this._gutter.top;
  1563. }
  1564. if (p[3]) {
  1565. this._gutter.left = parseInt(p[3], 10);
  1566. } else if (p[1]) {
  1567. this._gutter.left = this._gutter.right;
  1568. } else {
  1569. this._gutter.left = this._gutter.top;
  1570. }
  1571. }
  1572. }
  1573. });
  1574. /**
  1575. * @attribute parent
  1576. * @description The parent Layout that we are assigned to
  1577. * @type {Object} YAHOO.widget.Layout
  1578. */
  1579. this.setAttributeConfig('parent', {
  1580. writeOnce: true,
  1581. value: attr.parent || false,
  1582. method: function(p) {
  1583. if (p) {
  1584. p.on('resize', this.resize, this, true);
  1585. }
  1586. }
  1587. });
  1588. /**
  1589. * @attribute collapseSize
  1590. * @description The pixel size of the Clip that we will collapse to
  1591. * @type Number
  1592. */
  1593. this.setAttributeConfig('collapseSize', {
  1594. value: attr.collapseSize || 25,
  1595. validator: YAHOO.lang.isNumber
  1596. });
  1597. /**
  1598. * @attribute duration
  1599. * @description The duration to give the Animation Utility when animating the opening and closing of Units
  1600. */
  1601. this.setAttributeConfig('duration', {
  1602. value: attr.duration || 0.5
  1603. });
  1604. /**
  1605. * @attribute easing
  1606. * @description The Animation Easing to apply to the Animation instance for this unit.
  1607. */
  1608. this.setAttributeConfig('easing', {
  1609. value: attr.easing || ((YAHOO.util && YAHOO.util.Easing) ? YAHOO.util.Easing.BounceIn : 'false')
  1610. });
  1611. /**
  1612. * @attribute animate
  1613. * @description Use animation to collapse/expand the unit
  1614. * @type Boolean
  1615. */
  1616. this.setAttributeConfig('animate', {
  1617. value: ((attr.animate === false) ? false : true),
  1618. validator: function() {
  1619. var anim = false;
  1620. if (YAHOO.util.Anim) {
  1621. anim = true;
  1622. }
  1623. return anim;
  1624. },
  1625. method: function(anim) {
  1626. if (anim) {
  1627. this._anim = new YAHOO.util.Anim(this.get('element'), {}, this.get('duration'), this.get('easing'));
  1628. } else {
  1629. this._anim = false;
  1630. }
  1631. }
  1632. });
  1633. /**
  1634. * @attribute header
  1635. * @description The text to use as the Header of the Unit
  1636. */
  1637. this.setAttributeConfig('header', {
  1638. value: attr.header || false,
  1639. method: function(txt) {
  1640. if (txt === false) {
  1641. //Remove the footer
  1642. if (this.header) {
  1643. Dom.addClass(this.body, 'yui-layout-bd-nohd');
  1644. this.header.parentNode.removeChild(this.header);
  1645. this.header = null;
  1646. }
  1647. } else {
  1648. if (!this.header) {
  1649. var header = this.getElementsByClassName('yui-layout-hd', 'div')[0];
  1650. if (!header) {
  1651. header = this._createHeader();
  1652. }
  1653. this.header = header;
  1654. }
  1655. var h = this.header.getElementsByTagName('h2')[0];
  1656. if (!h) {
  1657. h = document.createElement('h2');
  1658. this.header.appendChild(h);
  1659. }
  1660. h.innerHTML = txt;
  1661. if (this.body) {
  1662. Dom.removeClass(this.body, 'yui-layout-bd-nohd');
  1663. }
  1664. }
  1665. this.fireEvent('contentChange', { target: 'header' });
  1666. }
  1667. });
  1668. /**
  1669. * @attribute proxy
  1670. * @description Use the proxy config setting for the Resize Utility
  1671. * @type Boolean
  1672. */
  1673. this.setAttributeConfig('proxy', {
  1674. writeOnce: true,
  1675. value: ((attr.proxy === false) ? false : true)
  1676. });
  1677. /**
  1678. * @attribute body
  1679. * @description The content for the body. If we find an element in the page with an id that matches the passed option we will move that element into the body of this unit.
  1680. */
  1681. this.setAttributeConfig('body', {
  1682. value: attr.body || false,
  1683. method: function(content) {
  1684. if (!this.body) {
  1685. var body = this.getElementsByClassName('yui-layout-bd', 'div')[0];
  1686. if (body) {
  1687. this.body = body;
  1688. } else {
  1689. body = document.createElement('div');
  1690. body.className = 'yui-layout-bd';
  1691. this.body = body;
  1692. this.get('wrap').appendChild(body);
  1693. }
  1694. }
  1695. if (!this.header) {
  1696. Dom.addClass(this.body, 'yui-layout-bd-nohd');
  1697. }
  1698. Dom.a