/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

Large files are truncated click here to view the full 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…