PageRenderTime 280ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

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

http://hdbc.googlecode.com/
JavaScript | 2037 lines | 887 code | 216 blank | 934 comment | 195 complexity | 9d7b699ff8ed1b88a66ad4840e2ef2c3 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. * Mechanism to execute a series of callbacks in a non-blocking queue. Each callback is executed via setTimout unless configured with a negative timeout, in which case it is run in blocking mode in the same execution thread as the previous callback. Callbacks can be function references or object literals with the following keys:
  9. * <ul>
  10. * <li><code>method</code> - {Function} REQUIRED the callback function.</li>
  11. * <li><code>scope</code> - {Object} the scope from which to execute the callback. Default is the global window scope.</li>
  12. * <li><code>argument</code> - {Array} parameters to be passed to method as individual arguments.</li>
  13. * <li><code>timeout</code> - {number} millisecond delay to wait after previous callback completion before executing this callback. Negative values cause immediate blocking execution. Default 0.</li>
  14. * <li><code>until</code> - {Function} boolean function executed before each iteration. Return true to indicate completion and proceed to the next callback.</li>
  15. * <li><code>iterations</code> - {Number} number of times to execute the callback before proceeding to the next callback in the chain. Incompatible with <code>until</code>.</li>
  16. * </ul>
  17. *
  18. * @namespace YAHOO.util
  19. * @class Chain
  20. * @constructor
  21. * @param callback* {Function|Object} Any number of callbacks to initialize the queue
  22. */
  23. YAHOO.util.Chain = function () {
  24. /**
  25. * The callback queue
  26. * @property q
  27. * @type {Array}
  28. * @private
  29. */
  30. this.q = [].slice.call(arguments);
  31. /**
  32. * Event fired when the callback queue is emptied via execution (not via
  33. * a call to chain.stop().
  34. * @event end
  35. */
  36. this.createEvent('end');
  37. };
  38. YAHOO.util.Chain.prototype = {
  39. /**
  40. * Timeout id used to pause or stop execution and indicate the execution state of the Chain. 0 indicates paused or stopped, -1 indicates blocking execution, and any positive number indicates non-blocking execution.
  41. * @property id
  42. * @type {number}
  43. * @private
  44. */
  45. id : 0,
  46. /**
  47. * Begin executing the chain, or resume execution from the last paused position.
  48. * @method run
  49. * @return {Chain} the Chain instance
  50. */
  51. run : function () {
  52. // Grab the first callback in the queue
  53. var c = this.q[0],
  54. fn;
  55. // If there is no callback in the queue or the Chain is currently
  56. // in an execution mode, return
  57. if (!c) {
  58. this.fireEvent('end');
  59. return this;
  60. } else if (this.id) {
  61. return this;
  62. }
  63. fn = c.method || c;
  64. if (typeof fn === 'function') {
  65. var o = c.scope || {},
  66. args = c.argument || [],
  67. ms = c.timeout || 0,
  68. me = this;
  69. if (!(args instanceof Array)) {
  70. args = [args];
  71. }
  72. // Execute immediately if the callback timeout is negative.
  73. if (ms < 0) {
  74. this.id = ms;
  75. if (c.until) {
  76. for (;!c.until();) {
  77. // Execute the callback from scope, with argument
  78. fn.apply(o,args);
  79. }
  80. } else if (c.iterations) {
  81. for (;c.iterations-- > 0;) {
  82. fn.apply(o,args);
  83. }
  84. } else {
  85. fn.apply(o,args);
  86. }
  87. this.q.shift();
  88. this.id = 0;
  89. return this.run();
  90. } else {
  91. // If the until condition is set, check if we're done
  92. if (c.until) {
  93. if (c.until()) {
  94. // Shift this callback from the queue and execute the next
  95. // callback
  96. this.q.shift();
  97. return this.run();
  98. }
  99. // Otherwise if either iterations is not set or we're
  100. // executing the last iteration, shift callback from the queue
  101. } else if (!c.iterations || !--c.iterations) {
  102. this.q.shift();
  103. }
  104. // Otherwise set to execute after the configured timeout
  105. this.id = setTimeout(function () {
  106. // Execute the callback from scope, with argument
  107. fn.apply(o,args);
  108. // Check if the Chain was not paused from inside the callback
  109. if (me.id) {
  110. // Indicate ready to run state
  111. me.id = 0;
  112. // Start the fun all over again
  113. me.run();
  114. }
  115. },ms);
  116. }
  117. }
  118. return this;
  119. },
  120. /**
  121. * Add a callback to the end of the queue
  122. * @method add
  123. * @param c {Function|Object} the callback function ref or object literal
  124. * @return {Chain} the Chain instance
  125. */
  126. add : function (c) {
  127. this.q.push(c);
  128. return this;
  129. },
  130. /**
  131. * Pause the execution of the Chain after the current execution of the
  132. * current callback completes. If called interstitially, clears the
  133. * timeout for the pending callback. Paused Chains can be restarted with
  134. * chain.run()
  135. * @method pause
  136. * @return {Chain} the Chain instance
  137. */
  138. pause: function () {
  139. clearTimeout(this.id);
  140. this.id = 0;
  141. return this;
  142. },
  143. /**
  144. * Stop and clear the Chain's queue after the current execution of the
  145. * current callback completes.
  146. * @method stop
  147. * @return {Chain} the Chain instance
  148. */
  149. stop : function () {
  150. this.pause();
  151. this.q = [];
  152. return this;
  153. }
  154. };
  155. YAHOO.lang.augmentProto(YAHOO.util.Chain,YAHOO.util.EventProvider);
  156. /****************************************************************************/
  157. /****************************************************************************/
  158. /****************************************************************************/
  159. /**
  160. * The ColumnSet class defines and manages a DataTable's Columns,
  161. * including nested hierarchies and access to individual Column instances.
  162. *
  163. * @namespace YAHOO.widget
  164. * @class ColumnSet
  165. * @uses YAHOO.util.EventProvider
  166. * @constructor
  167. * @param aDefinitions {Object[]} Array of object literals that define cells in
  168. * the THEAD.
  169. */
  170. YAHOO.widget.ColumnSet = function(aDefinitions) {
  171. this._sId = "yui-cs" + YAHOO.widget.ColumnSet._nCount;
  172. // First clone the defs
  173. aDefinitions = YAHOO.widget.DataTable._cloneObject(aDefinitions);
  174. this._init(aDefinitions);
  175. YAHOO.widget.ColumnSet._nCount++;
  176. YAHOO.log("ColumnSet initialized", "info", this.toString());
  177. };
  178. /////////////////////////////////////////////////////////////////////////////
  179. //
  180. // Private member variables
  181. //
  182. /////////////////////////////////////////////////////////////////////////////
  183. /**
  184. * Internal class variable to index multiple ColumnSet instances.
  185. *
  186. * @property ColumnSet._nCount
  187. * @type Number
  188. * @private
  189. * @static
  190. */
  191. YAHOO.widget.ColumnSet._nCount = 0;
  192. YAHOO.widget.ColumnSet.prototype = {
  193. /**
  194. * Unique instance name.
  195. *
  196. * @property _sId
  197. * @type String
  198. * @private
  199. */
  200. _sId : null,
  201. /**
  202. * Array of object literal Column definitions passed to the constructor.
  203. *
  204. * @property _aDefinitions
  205. * @type Object[]
  206. * @private
  207. */
  208. _aDefinitions : null,
  209. /////////////////////////////////////////////////////////////////////////////
  210. //
  211. // Public member variables
  212. //
  213. /////////////////////////////////////////////////////////////////////////////
  214. /**
  215. * Top-down tree representation of Column hierarchy.
  216. *
  217. * @property tree
  218. * @type YAHOO.widget.Column[]
  219. */
  220. tree : null,
  221. /**
  222. * Flattened representation of all Columns.
  223. *
  224. * @property flat
  225. * @type YAHOO.widget.Column[]
  226. * @default []
  227. */
  228. flat : null,
  229. /**
  230. * Array of Columns that map one-to-one to a table column.
  231. *
  232. * @property keys
  233. * @type YAHOO.widget.Column[]
  234. * @default []
  235. */
  236. keys : null,
  237. /**
  238. * ID index of nested parent hierarchies for HEADERS accessibility attribute.
  239. *
  240. * @property headers
  241. * @type String[]
  242. * @default []
  243. */
  244. headers : null,
  245. /////////////////////////////////////////////////////////////////////////////
  246. //
  247. // Private methods
  248. //
  249. /////////////////////////////////////////////////////////////////////////////
  250. /**
  251. * Initializes ColumnSet instance with data from Column definitions.
  252. *
  253. * @method _init
  254. * @param aDefinitions {Object[]} Array of object literals that define cells in
  255. * the THEAD .
  256. * @private
  257. */
  258. _init : function(aDefinitions) {
  259. // DOM tree representation of all Columns
  260. var tree = [];
  261. // Flat representation of all Columns
  262. var flat = [];
  263. // Flat representation of only Columns that are meant to display data
  264. var keys = [];
  265. // Array of HEADERS attribute values for all keys in the "keys" array
  266. var headers = [];
  267. // Tracks current node list depth being tracked
  268. var nodeDepth = -1;
  269. // Internal recursive function to define Column instances
  270. var parseColumns = function(nodeList, parent) {
  271. // One level down
  272. nodeDepth++;
  273. // Create corresponding tree node if not already there for this depth
  274. if(!tree[nodeDepth]) {
  275. tree[nodeDepth] = [];
  276. }
  277. // Parse each node at this depth for attributes and any children
  278. for(var j=0; j<nodeList.length; j++) {
  279. var currentNode = nodeList[j];
  280. // Instantiate a new Column for each node
  281. var oColumn = new YAHOO.widget.Column(currentNode);
  282. // Cross-reference Column ID back to the original object literal definition
  283. currentNode.yuiColumnId = oColumn._sId;
  284. // Add the new Column to the flat list
  285. flat.push(oColumn);
  286. // Assign its parent as an attribute, if applicable
  287. if(parent) {
  288. oColumn._oParent = parent;
  289. }
  290. // The Column has descendants
  291. if(YAHOO.lang.isArray(currentNode.children)) {
  292. oColumn.children = currentNode.children;
  293. // Determine COLSPAN value for this Column
  294. var terminalChildNodes = 0;
  295. var countTerminalChildNodes = function(ancestor) {
  296. var descendants = ancestor.children;
  297. // Drill down each branch and count terminal nodes
  298. for(var k=0; k<descendants.length; k++) {
  299. // Keep drilling down
  300. if(YAHOO.lang.isArray(descendants[k].children)) {
  301. countTerminalChildNodes(descendants[k]);
  302. }
  303. // Reached branch terminus
  304. else {
  305. terminalChildNodes++;
  306. }
  307. }
  308. };
  309. countTerminalChildNodes(currentNode);
  310. oColumn._nColspan = terminalChildNodes;
  311. // Cascade certain properties to children if not defined on their own
  312. var currentChildren = currentNode.children;
  313. for(var k=0; k<currentChildren.length; k++) {
  314. var child = currentChildren[k];
  315. if(oColumn.className && (child.className === undefined)) {
  316. child.className = oColumn.className;
  317. }
  318. if(oColumn.editor && (child.editor === undefined)) {
  319. child.editor = oColumn.editor;
  320. }
  321. //TODO: Deprecated
  322. if(oColumn.editorOptions && (child.editorOptions === undefined)) {
  323. child.editorOptions = oColumn.editorOptions;
  324. }
  325. if(oColumn.formatter && (child.formatter === undefined)) {
  326. child.formatter = oColumn.formatter;
  327. }
  328. if(oColumn.resizeable && (child.resizeable === undefined)) {
  329. child.resizeable = oColumn.resizeable;
  330. }
  331. if(oColumn.sortable && (child.sortable === undefined)) {
  332. child.sortable = oColumn.sortable;
  333. }
  334. if(oColumn.hidden) {
  335. child.hidden = true;
  336. }
  337. if(oColumn.width && (child.width === undefined)) {
  338. child.width = oColumn.width;
  339. }
  340. if(oColumn.minWidth && (child.minWidth === undefined)) {
  341. child.minWidth = oColumn.minWidth;
  342. }
  343. if(oColumn.maxAutoWidth && (child.maxAutoWidth === undefined)) {
  344. child.maxAutoWidth = oColumn.maxAutoWidth;
  345. }
  346. // Backward compatibility
  347. if(oColumn.type && (child.type === undefined)) {
  348. child.type = oColumn.type;
  349. }
  350. if(oColumn.type && !oColumn.formatter) {
  351. YAHOO.log("The property type has been" +
  352. " deprecated in favor of formatter", "warn", oColumn.toString());
  353. oColumn.formatter = oColumn.type;
  354. }
  355. if(oColumn.text && !YAHOO.lang.isValue(oColumn.label)) {
  356. YAHOO.log("The property text has been" +
  357. " deprecated in favor of label", "warn", oColumn.toString());
  358. oColumn.label = oColumn.text;
  359. }
  360. if(oColumn.parser) {
  361. YAHOO.log("The property parser is no longer supported",
  362. "warn", this.toString());
  363. }
  364. if(oColumn.sortOptions && ((oColumn.sortOptions.ascFunction) ||
  365. (oColumn.sortOptions.descFunction))) {
  366. YAHOO.log("The properties sortOptions.ascFunction and " +
  367. " sortOptions.descFunction have been deprecated in favor " +
  368. " of sortOptions.sortFunction", "warn", oColumn.toString());
  369. }
  370. }
  371. // The children themselves must also be parsed for Column instances
  372. if(!tree[nodeDepth+1]) {
  373. tree[nodeDepth+1] = [];
  374. }
  375. parseColumns(currentChildren, oColumn);
  376. }
  377. // This Column does not have any children
  378. else {
  379. oColumn._nKeyIndex = keys.length;
  380. oColumn._nColspan = 1;
  381. keys.push(oColumn);
  382. }
  383. // Add the Column to the top-down tree
  384. tree[nodeDepth].push(oColumn);
  385. }
  386. nodeDepth--;
  387. };
  388. // Parse out Column instances from the array of object literals
  389. if(YAHOO.lang.isArray(aDefinitions)) {
  390. parseColumns(aDefinitions);
  391. // Store the array
  392. this._aDefinitions = aDefinitions;
  393. }
  394. else {
  395. YAHOO.log("Could not initialize ColumnSet due to invalid definitions","error");
  396. return null;
  397. }
  398. var i;
  399. // Determine ROWSPAN value for each Column in the tree
  400. var parseTreeForRowspan = function(tree) {
  401. var maxRowDepth = 1;
  402. var currentRow;
  403. var currentColumn;
  404. // Calculate the max depth of descendants for this row
  405. var countMaxRowDepth = function(row, tmpRowDepth) {
  406. tmpRowDepth = tmpRowDepth || 1;
  407. for(var n=0; n<row.length; n++) {
  408. var col = row[n];
  409. // Column has children, so keep counting
  410. if(YAHOO.lang.isArray(col.children)) {
  411. tmpRowDepth++;
  412. countMaxRowDepth(col.children, tmpRowDepth);
  413. tmpRowDepth--;
  414. }
  415. // No children, is it the max depth?
  416. else {
  417. if(tmpRowDepth > maxRowDepth) {
  418. maxRowDepth = tmpRowDepth;
  419. }
  420. }
  421. }
  422. };
  423. // Count max row depth for each row
  424. for(var m=0; m<tree.length; m++) {
  425. currentRow = tree[m];
  426. countMaxRowDepth(currentRow);
  427. // Assign the right ROWSPAN values to each Column in the row
  428. for(var p=0; p<currentRow.length; p++) {
  429. currentColumn = currentRow[p];
  430. if(!YAHOO.lang.isArray(currentColumn.children)) {
  431. currentColumn._nRowspan = maxRowDepth;
  432. }
  433. else {
  434. currentColumn._nRowspan = 1;
  435. }
  436. }
  437. // Reset counter for next row
  438. maxRowDepth = 1;
  439. }
  440. };
  441. parseTreeForRowspan(tree);
  442. // Store tree index values
  443. for(i=0; i<tree[0].length; i++) {
  444. tree[0][i]._nTreeIndex = i;
  445. }
  446. // Store header relationships in an array for HEADERS attribute
  447. var recurseAncestorsForHeaders = function(i, oColumn) {
  448. headers[i].push(oColumn.getSanitizedKey());
  449. if(oColumn._oParent) {
  450. recurseAncestorsForHeaders(i, oColumn._oParent);
  451. }
  452. };
  453. for(i=0; i<keys.length; i++) {
  454. headers[i] = [];
  455. recurseAncestorsForHeaders(i, keys[i]);
  456. headers[i] = headers[i].reverse();
  457. }
  458. // Save to the ColumnSet instance
  459. this.tree = tree;
  460. this.flat = flat;
  461. this.keys = keys;
  462. this.headers = headers;
  463. },
  464. /////////////////////////////////////////////////////////////////////////////
  465. //
  466. // Public methods
  467. //
  468. /////////////////////////////////////////////////////////////////////////////
  469. /**
  470. * Returns unique name of the ColumnSet instance.
  471. *
  472. * @method getId
  473. * @return {String} Unique name of the ColumnSet instance.
  474. */
  475. getId : function() {
  476. return this._sId;
  477. },
  478. /**
  479. * ColumnSet instance name, for logging.
  480. *
  481. * @method toString
  482. * @return {String} Unique name of the ColumnSet instance.
  483. */
  484. toString : function() {
  485. return "ColumnSet instance " + this._sId;
  486. },
  487. /**
  488. * Public accessor to the definitions array.
  489. *
  490. * @method getDefinitions
  491. * @return {Object[]} Array of object literal Column definitions.
  492. */
  493. getDefinitions : function() {
  494. var aDefinitions = this._aDefinitions;
  495. // Internal recursive function to define Column instances
  496. var parseColumns = function(nodeList, oSelf) {
  497. // Parse each node at this depth for attributes and any children
  498. for(var j=0; j<nodeList.length; j++) {
  499. var currentNode = nodeList[j];
  500. // Get the Column for each node
  501. var oColumn = oSelf.getColumnById(currentNode.yuiColumnId);
  502. if(oColumn) {
  503. // Update the current values
  504. var oDefinition = oColumn.getDefinition();
  505. for(var name in oDefinition) {
  506. if(YAHOO.lang.hasOwnProperty(oDefinition, name)) {
  507. currentNode[name] = oDefinition[name];
  508. }
  509. }
  510. }
  511. // The Column has descendants
  512. if(YAHOO.lang.isArray(currentNode.children)) {
  513. // The children themselves must also be parsed for Column instances
  514. parseColumns(currentNode.children, oSelf);
  515. }
  516. }
  517. };
  518. parseColumns(aDefinitions, this);
  519. this._aDefinitions = aDefinitions;
  520. return aDefinitions;
  521. },
  522. /**
  523. * Returns Column instance with given ID.
  524. *
  525. * @method getColumnById
  526. * @param column {String} Column ID.
  527. * @return {YAHOO.widget.Column} Column instance.
  528. */
  529. getColumnById : function(column) {
  530. if(YAHOO.lang.isString(column)) {
  531. var allColumns = this.flat;
  532. for(var i=allColumns.length-1; i>-1; i--) {
  533. if(allColumns[i]._sId === column) {
  534. return allColumns[i];
  535. }
  536. }
  537. }
  538. return null;
  539. },
  540. /**
  541. * Returns Column instance with given key or ColumnSet key index.
  542. *
  543. * @method getColumn
  544. * @param column {String | Number} Column key or ColumnSet key index.
  545. * @return {YAHOO.widget.Column} Column instance.
  546. */
  547. getColumn : function(column) {
  548. if(YAHOO.lang.isNumber(column) && this.keys[column]) {
  549. return this.keys[column];
  550. }
  551. else if(YAHOO.lang.isString(column)) {
  552. var allColumns = this.flat;
  553. var aColumns = [];
  554. for(var i=0; i<allColumns.length; i++) {
  555. if(allColumns[i].key === column) {
  556. aColumns.push(allColumns[i]);
  557. }
  558. }
  559. if(aColumns.length === 1) {
  560. return aColumns[0];
  561. }
  562. else if(aColumns.length > 1) {
  563. return aColumns;
  564. }
  565. }
  566. return null;
  567. },
  568. /**
  569. * Public accessor returns array of given Column's desendants (if any), including itself.
  570. *
  571. * @method getDescendants
  572. * @parem {YAHOO.widget.Column} Column instance.
  573. * @return {Array} Array including the Column itself and all descendants (if any).
  574. */
  575. getDescendants : function(oColumn) {
  576. var oSelf = this;
  577. var allDescendants = [];
  578. var i;
  579. // Recursive function to loop thru all children
  580. var parse = function(oParent) {
  581. allDescendants.push(oParent);
  582. // This Column has children
  583. if(oParent.children) {
  584. for(i=0; i<oParent.children.length; i++) {
  585. parse(oSelf.getColumn(oParent.children[i].key));
  586. }
  587. }
  588. };
  589. parse(oColumn);
  590. return allDescendants;
  591. }
  592. };
  593. /****************************************************************************/
  594. /****************************************************************************/
  595. /****************************************************************************/
  596. /**
  597. * The Column class defines and manages attributes of DataTable Columns
  598. *
  599. * @namespace YAHOO.widget
  600. * @class Column
  601. * @constructor
  602. * @param oConfigs {Object} Object literal of definitions.
  603. */
  604. YAHOO.widget.Column = function(oConfigs) {
  605. this._sId = "yui-col" + YAHOO.widget.Column._nCount;
  606. // Object literal defines Column attributes
  607. if(oConfigs && YAHOO.lang.isObject(oConfigs)) {
  608. for(var sConfig in oConfigs) {
  609. if(sConfig) {
  610. this[sConfig] = oConfigs[sConfig];
  611. }
  612. }
  613. }
  614. // Assign a key if not found
  615. if(!YAHOO.lang.isValue(this.key)) {
  616. this.key = "yui-dt-col" + YAHOO.widget.Column._nCount;
  617. }
  618. // Assign a field if not found, defaults to key
  619. if(!YAHOO.lang.isValue(this.field)) {
  620. this.field = this.key;
  621. }
  622. // Increment counter
  623. YAHOO.widget.Column._nCount++;
  624. // Backward compatibility
  625. if(this.width && !YAHOO.lang.isNumber(this.width)) {
  626. this.width = null;
  627. YAHOO.log("The Column property width must be a number", "warn", this.toString());
  628. }
  629. if(this.editor && YAHOO.lang.isString(this.editor)) {
  630. this.editor = new YAHOO.widget.CellEditor(this.editor, this.editorOptions);
  631. YAHOO.log("The Column property editor must be an instance of YAHOO.widget.CellEditor", "warn", this.toString());
  632. }
  633. };
  634. /////////////////////////////////////////////////////////////////////////////
  635. //
  636. // Private member variables
  637. //
  638. /////////////////////////////////////////////////////////////////////////////
  639. YAHOO.lang.augmentObject(YAHOO.widget.Column, {
  640. /**
  641. * Internal class variable to index multiple Column instances.
  642. *
  643. * @property Column._nCount
  644. * @type Number
  645. * @private
  646. * @static
  647. */
  648. _nCount : 0,
  649. formatCheckbox : function(elCell, oRecord, oColumn, oData) {
  650. YAHOO.log("The method YAHOO.widget.Column.formatCheckbox() has been" +
  651. " deprecated in favor of YAHOO.widget.DataTable.formatCheckbox()", "warn",
  652. "YAHOO.widget.Column.formatCheckbox");
  653. YAHOO.widget.DataTable.formatCheckbox(elCell, oRecord, oColumn, oData);
  654. },
  655. formatCurrency : function(elCell, oRecord, oColumn, oData) {
  656. YAHOO.log("The method YAHOO.widget.Column.formatCurrency() has been" +
  657. " deprecated in favor of YAHOO.widget.DataTable.formatCurrency()", "warn",
  658. "YAHOO.widget.Column.formatCurrency");
  659. YAHOO.widget.DataTable.formatCurrency(elCell, oRecord, oColumn, oData);
  660. },
  661. formatDate : function(elCell, oRecord, oColumn, oData) {
  662. YAHOO.log("The method YAHOO.widget.Column.formatDate() has been" +
  663. " deprecated in favor of YAHOO.widget.DataTable.formatDate()", "warn",
  664. "YAHOO.widget.Column.formatDate");
  665. YAHOO.widget.DataTable.formatDate(elCell, oRecord, oColumn, oData);
  666. },
  667. formatEmail : function(elCell, oRecord, oColumn, oData) {
  668. YAHOO.log("The method YAHOO.widget.Column.formatEmail() has been" +
  669. " deprecated in favor of YAHOO.widget.DataTable.formatEmail()", "warn",
  670. "YAHOO.widget.Column.formatEmail");
  671. YAHOO.widget.DataTable.formatEmail(elCell, oRecord, oColumn, oData);
  672. },
  673. formatLink : function(elCell, oRecord, oColumn, oData) {
  674. YAHOO.log("The method YAHOO.widget.Column.formatLink() has been" +
  675. " deprecated in favor of YAHOO.widget.DataTable.formatLink()", "warn",
  676. "YAHOO.widget.Column.formatLink");
  677. YAHOO.widget.DataTable.formatLink(elCell, oRecord, oColumn, oData);
  678. },
  679. formatNumber : function(elCell, oRecord, oColumn, oData) {
  680. YAHOO.log("The method YAHOO.widget.Column.formatNumber() has been" +
  681. " deprecated in favor of YAHOO.widget.DataTable.formatNumber()", "warn",
  682. "YAHOO.widget.Column.formatNumber");
  683. YAHOO.widget.DataTable.formatNumber(elCell, oRecord, oColumn, oData);
  684. },
  685. formatSelect : function(elCell, oRecord, oColumn, oData) {
  686. YAHOO.log("The method YAHOO.widget.Column.formatSelect() has been" +
  687. " deprecated in favor of YAHOO.widget.DataTable.formatDropdown()", "warn",
  688. "YAHOO.widget.Column.formatSelect");
  689. YAHOO.widget.DataTable.formatDropdown(elCell, oRecord, oColumn, oData);
  690. }
  691. });
  692. YAHOO.widget.Column.prototype = {
  693. /**
  694. * Unique String identifier assigned at instantiation.
  695. *
  696. * @property _sId
  697. * @type String
  698. * @private
  699. */
  700. _sId : null,
  701. /**
  702. * Reference to Column's current position index within its ColumnSet's keys
  703. * array, if applicable. This property only applies to non-nested and bottom-
  704. * level child Columns.
  705. *
  706. * @property _nKeyIndex
  707. * @type Number
  708. * @private
  709. */
  710. _nKeyIndex : null,
  711. /**
  712. * Reference to Column's current position index within its ColumnSet's tree
  713. * array, if applicable. This property only applies to non-nested and top-
  714. * level parent Columns.
  715. *
  716. * @property _nTreeIndex
  717. * @type Number
  718. * @private
  719. */
  720. _nTreeIndex : null,
  721. /**
  722. * Number of table cells the Column spans.
  723. *
  724. * @property _nColspan
  725. * @type Number
  726. * @private
  727. */
  728. _nColspan : 1,
  729. /**
  730. * Number of table rows the Column spans.
  731. *
  732. * @property _nRowspan
  733. * @type Number
  734. * @private
  735. */
  736. _nRowspan : 1,
  737. /**
  738. * Column's parent Column instance, or null.
  739. *
  740. * @property _oParent
  741. * @type YAHOO.widget.Column
  742. * @private
  743. */
  744. _oParent : null,
  745. /**
  746. * The DOM reference to the associated TH element.
  747. *
  748. * @property _elTh
  749. * @type HTMLElement
  750. * @private
  751. */
  752. _elTh : null,
  753. /**
  754. * The DOM reference to the associated TH element's liner DIV element.
  755. *
  756. * @property _elThLiner
  757. * @type HTMLElement
  758. * @private
  759. */
  760. _elThLiner : null,
  761. /**
  762. * The DOM reference to the associated TH element's label SPAN element.
  763. *
  764. * @property _elThLabel
  765. * @type HTMLElement
  766. * @private
  767. */
  768. _elThLabel : null,
  769. /**
  770. * The DOM reference to the associated resizerelement (if any).
  771. *
  772. * @property _elResizer
  773. * @type HTMLElement
  774. * @private
  775. */
  776. _elResizer : null,
  777. /**
  778. * Internal width tracker.
  779. *
  780. * @property _nWidth
  781. * @type Number
  782. * @private
  783. */
  784. _nWidth : null,
  785. /**
  786. * For unreg() purposes, a reference to the Column's DragDrop instance.
  787. *
  788. * @property _dd
  789. * @type YAHOO.util.DragDrop
  790. * @private
  791. */
  792. _dd : null,
  793. /**
  794. * For unreg() purposes, a reference to the Column resizer's DragDrop instance.
  795. *
  796. * @property _ddResizer
  797. * @type YAHOO.util.DragDrop
  798. * @private
  799. */
  800. _ddResizer : null,
  801. /////////////////////////////////////////////////////////////////////////////
  802. //
  803. // Public member variables
  804. //
  805. /////////////////////////////////////////////////////////////////////////////
  806. /**
  807. * Unique name, required.
  808. *
  809. * @property key
  810. * @type String
  811. */
  812. key : null,
  813. /**
  814. * Associated database field, or null.
  815. *
  816. * @property field
  817. * @type String
  818. */
  819. field : null,
  820. /**
  821. * Text or HTML for display as Column's label in the TH element.
  822. *
  823. * @property label
  824. * @type String
  825. */
  826. label : null,
  827. /**
  828. * Column head cell ABBR for accessibility.
  829. *
  830. * @property abbr
  831. * @type String
  832. */
  833. abbr : null,
  834. /**
  835. * Array of object literals that define children (nested headers) of a Column.
  836. *
  837. * @property children
  838. * @type Object[]
  839. */
  840. children : null,
  841. /**
  842. * Column width (in pixels).
  843. *
  844. * @property width
  845. * @type Number
  846. */
  847. width : null,
  848. /**
  849. * Minimum Column width (in pixels).
  850. *
  851. * @property minWidth
  852. * @type Number
  853. * @default null
  854. */
  855. minWidth : null,
  856. /**
  857. * When a width is not defined for a Column, maxAutoWidth defines an upper
  858. * limit that the Column should be auto-sized to. If resizeable is enabled,
  859. * users may still resize to a greater width. Most useful for Columns intended
  860. * to hold long unbroken, unwrapped Strings, such as URLs, to prevent very
  861. * wide Columns from disrupting visual readability by inducing truncation.
  862. *
  863. * @property maxAutoWidth
  864. * @type Number
  865. * @default null
  866. */
  867. maxAutoWidth : null,
  868. /**
  869. * True if Column is in hidden state.
  870. *
  871. * @property hidden
  872. * @type Boolean
  873. * @default false
  874. */
  875. hidden : false,
  876. /**
  877. * True if Column is in selected state.
  878. *
  879. * @property selected
  880. * @type Boolean
  881. * @default false
  882. */
  883. selected : false,
  884. /**
  885. * Custom CSS class or array of classes to be applied to every cell in the Column.
  886. *
  887. * @property className
  888. * @type String || String[]
  889. */
  890. className : null,
  891. /**
  892. * Defines a format function.
  893. *
  894. * @property formatter
  895. * @type String || HTMLFunction
  896. */
  897. formatter : null,
  898. /**
  899. * Config passed to YAHOO.util.Number.format() by the 'currency' Column formatter.
  900. *
  901. * @property currencyOptions
  902. * @type Object
  903. * @default null
  904. */
  905. currencyOptions : null,
  906. /**
  907. * Config passed to YAHOO.util.Date.format() by the 'date' Column formatter.
  908. *
  909. * @property dateOptions
  910. * @type Object
  911. * @default null
  912. */
  913. dateOptions : null,
  914. /**
  915. * A CellEditor instance, otherwise Column is not editable.
  916. *
  917. * @property editor
  918. * @type YAHOO.widget.CellEditor
  919. */
  920. editor : null,
  921. /**
  922. * True if Column is resizeable, false otherwise. The Drag & Drop Utility is
  923. * required to enable this feature. Only bottom-level and non-nested Columns are
  924. * resizeble.
  925. *
  926. * @property resizeable
  927. * @type Boolean
  928. * @default false
  929. */
  930. resizeable : false,
  931. /**
  932. * True if Column is sortable, false otherwise.
  933. *
  934. * @property sortable
  935. * @type Boolean
  936. * @default false
  937. */
  938. sortable : false,
  939. /**
  940. * @property sortOptions.defaultOrder
  941. * @deprecated Use sortOptions.defaultDir.
  942. */
  943. /**
  944. * Default sort direction for Column: YAHOO.widget.DataTable.CLASS_ASC or YAHOO.widget.DataTable.CLASS_DESC.
  945. *
  946. * @property sortOptions.defaultDir
  947. * @type String
  948. * @default null
  949. */
  950. /**
  951. * Custom field to sort on.
  952. *
  953. * @property sortOptions.field
  954. * @type String
  955. * @default null
  956. */
  957. /**
  958. * Custom sort handler.
  959. *
  960. * @property sortOptions.sortFunction
  961. * @type Function
  962. * @default null
  963. */
  964. sortOptions : null,
  965. /////////////////////////////////////////////////////////////////////////////
  966. //
  967. // Public methods
  968. //
  969. /////////////////////////////////////////////////////////////////////////////
  970. /**
  971. * Returns unique ID string.
  972. *
  973. * @method getId
  974. * @return {String} Unique ID string.
  975. */
  976. getId : function() {
  977. return this._sId;
  978. },
  979. /**
  980. * Column instance name, for logging.
  981. *
  982. * @method toString
  983. * @return {String} Column's unique name.
  984. */
  985. toString : function() {
  986. return "Column instance " + this._sId;
  987. },
  988. /**
  989. * Returns object literal definition.
  990. *
  991. * @method getDefinition
  992. * @return {Object} Object literal definition.
  993. */
  994. getDefinition : function() {
  995. var oDefinition = {};
  996. // Update the definition
  997. oDefinition.abbr = this.abbr;
  998. oDefinition.className = this.className;
  999. oDefinition.editor = this.editor;
  1000. oDefinition.editorOptions = this.editorOptions; //TODO: deprecated
  1001. oDefinition.field = this.field;
  1002. oDefinition.formatter = this.formatter;
  1003. oDefinition.hidden = this.hidden;
  1004. oDefinition.key = this.key;
  1005. oDefinition.label = this.label;
  1006. oDefinition.minWidth = this.minWidth;
  1007. oDefinition.maxAutoWidth = this.maxAutoWidth;
  1008. oDefinition.resizeable = this.resizeable;
  1009. oDefinition.selected = this.selected;
  1010. oDefinition.sortable = this.sortable;
  1011. oDefinition.sortOptions = this.sortOptions;
  1012. oDefinition.width = this.width;
  1013. return oDefinition;
  1014. },
  1015. /**
  1016. * Returns unique Column key.
  1017. *
  1018. * @method getKey
  1019. * @return {String} Column key.
  1020. */
  1021. getKey : function() {
  1022. return this.key;
  1023. },
  1024. /**
  1025. * Returns field.
  1026. *
  1027. * @method getField
  1028. * @return {String} Column field.
  1029. */
  1030. getField : function() {
  1031. return this.field;
  1032. },
  1033. /**
  1034. * Returns Column key which has been sanitized for DOM (class and ID) usage
  1035. * starts with letter, contains only letters, numbers, hyphen, or period.
  1036. *
  1037. * @method getSanitizedKey
  1038. * @return {String} Sanitized Column key.
  1039. */
  1040. getSanitizedKey : function() {
  1041. return this.getKey().replace(/[^\w\-]/g,"");
  1042. },
  1043. /**
  1044. * Public accessor returns Column's current position index within its
  1045. * ColumnSet's keys array, if applicable. Only non-nested and bottom-level
  1046. * child Columns will return a value.
  1047. *
  1048. * @method getKeyIndex
  1049. * @return {Number} Position index, or null.
  1050. */
  1051. getKeyIndex : function() {
  1052. return this._nKeyIndex;
  1053. },
  1054. /**
  1055. * Public accessor returns Column's current position index within its
  1056. * ColumnSet's tree array, if applicable. Only non-nested and top-level parent
  1057. * Columns will return a value;
  1058. *
  1059. * @method getTreeIndex
  1060. * @return {Number} Position index, or null.
  1061. */
  1062. getTreeIndex : function() {
  1063. return this._nTreeIndex;
  1064. },
  1065. /**
  1066. * Public accessor returns Column's parent instance if any, or null otherwise.
  1067. *
  1068. * @method getParent
  1069. * @return {YAHOO.widget.Column} Column's parent instance.
  1070. */
  1071. getParent : function() {
  1072. return this._oParent;
  1073. },
  1074. /**
  1075. * Public accessor returns Column's calculated COLSPAN value.
  1076. *
  1077. * @method getColspan
  1078. * @return {Number} Column's COLSPAN value.
  1079. */
  1080. getColspan : function() {
  1081. return this._nColspan;
  1082. },
  1083. // Backward compatibility
  1084. getColSpan : function() {
  1085. YAHOO.log("The method getColSpan() has been" +
  1086. " deprecated in favor of getColspan()", "warn", this.toString());
  1087. return this.getColspan();
  1088. },
  1089. /**
  1090. * Public accessor returns Column's calculated ROWSPAN value.
  1091. *
  1092. * @method getRowspan
  1093. * @return {Number} Column's ROWSPAN value.
  1094. */
  1095. getRowspan : function() {
  1096. return this._nRowspan;
  1097. },
  1098. /**
  1099. * Returns DOM reference to the key TH element.
  1100. *
  1101. * @method getThEl
  1102. * @return {HTMLElement} TH element.
  1103. */
  1104. getThEl : function() {
  1105. return this._elTh;
  1106. },
  1107. /**
  1108. * Returns DOM reference to the TH's liner DIV element. Introduced since
  1109. * resizeable Columns may have an extra resizer liner, making the DIV liner
  1110. * not reliably the TH element's first child.
  1111. *
  1112. * @method getThLInerEl
  1113. * @return {HTMLElement} TH element.
  1114. */
  1115. getThLinerEl : function() {
  1116. return this._elThLiner;
  1117. },
  1118. /**
  1119. * Returns DOM reference to the resizer element, or null.
  1120. *
  1121. * @method getResizerEl
  1122. * @return {HTMLElement} DIV element.
  1123. */
  1124. getResizerEl : function() {
  1125. return this._elResizer;
  1126. },
  1127. // Backward compatibility
  1128. /**
  1129. * @method getColEl
  1130. * @deprecated Use getThEl
  1131. */
  1132. getColEl : function() {
  1133. YAHOO.log("The method getColEl() has been" +
  1134. " deprecated in favor of getThEl()", "warn",
  1135. this.toString());
  1136. return this.getThEl();
  1137. },
  1138. getIndex : function() {
  1139. YAHOO.log("The method getIndex() has been" +
  1140. " deprecated in favor of getKeyIndex()", "warn",
  1141. this.toString());
  1142. return this.getKeyIndex();
  1143. },
  1144. format : function() {
  1145. YAHOO.log("The method format() has been deprecated in favor of the " +
  1146. "DataTable method formatCell()", "error", this.toString());
  1147. }
  1148. };
  1149. /****************************************************************************/
  1150. /****************************************************************************/
  1151. /****************************************************************************/
  1152. /**
  1153. * Sort static utility to support Column sorting.
  1154. *
  1155. * @namespace YAHOO.util
  1156. * @class Sort
  1157. * @static
  1158. */
  1159. YAHOO.util.Sort = {
  1160. /////////////////////////////////////////////////////////////////////////////
  1161. //
  1162. // Public methods
  1163. //
  1164. /////////////////////////////////////////////////////////////////////////////
  1165. /**
  1166. * Comparator function for simple case-insensitive string sorting.
  1167. *
  1168. * @method compare
  1169. * @param a {Object} First sort argument.
  1170. * @param b {Object} Second sort argument.
  1171. * @param desc {Boolean} True if sort direction is descending, false if
  1172. * sort direction is ascending.
  1173. */
  1174. compare: function(a, b, desc) {
  1175. if((a === null) || (typeof a == "undefined")) {
  1176. if((b === null) || (typeof b == "undefined")) {
  1177. return 0;
  1178. }
  1179. else {
  1180. return 1;
  1181. }
  1182. }
  1183. else if((b === null) || (typeof b == "undefined")) {
  1184. return -1;
  1185. }
  1186. if(a.constructor == String) {
  1187. a = a.toLowerCase();
  1188. }
  1189. if(b.constructor == String) {
  1190. b = b.toLowerCase();
  1191. }
  1192. if(a < b) {
  1193. return (desc) ? 1 : -1;
  1194. }
  1195. else if (a > b) {
  1196. return (desc) ? -1 : 1;
  1197. }
  1198. else {
  1199. return 0;
  1200. }
  1201. }
  1202. };
  1203. /****************************************************************************/
  1204. /****************************************************************************/
  1205. /****************************************************************************/
  1206. /**
  1207. * ColumnDD subclasses DragDrop to support rearrangeable Columns.
  1208. *
  1209. * @namespace YAHOO.util
  1210. * @class ColumnDD
  1211. * @extends YAHOO.util.DDProxy
  1212. * @constructor
  1213. * @param oDataTable {YAHOO.widget.DataTable} DataTable instance.
  1214. * @param oColumn {YAHOO.widget.Column} Column instance.
  1215. * @param elTh {HTMLElement} TH element reference.
  1216. * @param elTarget {HTMLElement} Drag target element.
  1217. */
  1218. YAHOO.widget.ColumnDD = function(oDataTable, oColumn, elTh, elTarget) {
  1219. if(oDataTable && oColumn && elTh && elTarget) {
  1220. this.datatable = oDataTable;
  1221. this.table = oDataTable.getTableEl();
  1222. this.column = oColumn;
  1223. this.headCell = elTh;
  1224. this.pointer = elTarget;
  1225. this.newIndex = null;
  1226. this.init(elTh);
  1227. this.initFrame(); // Needed for DDProxy
  1228. this.invalidHandleTypes = {};
  1229. // Set top/bottom padding to account for children of nested columns
  1230. this.setPadding(10, 0, (this.datatable.getTheadEl().offsetHeight + 10) , 0);
  1231. YAHOO.util.Event.on(window, 'resize', function() {
  1232. this.initConstraints();
  1233. }, this, true);
  1234. }
  1235. else {
  1236. YAHOO.log("Column dragdrop could not be created","warn",oDataTable.toString());
  1237. }
  1238. };
  1239. if(YAHOO.util.DDProxy) {
  1240. YAHOO.extend(YAHOO.widget.ColumnDD, YAHOO.util.DDProxy, {
  1241. initConstraints: function() {
  1242. //Get the top, right, bottom and left positions
  1243. var region = YAHOO.util.Dom.getRegion(this.table),
  1244. //Get the element we are working on
  1245. el = this.getEl(),
  1246. //Get the xy position of it
  1247. xy = YAHOO.util.Dom.getXY(el),
  1248. //Get the width and height
  1249. width = parseInt(YAHOO.util.Dom.getStyle(el, 'width'), 10),
  1250. height = parseInt(YAHOO.util.Dom.getStyle(el, 'height'), 10),
  1251. //Set left to x minus left
  1252. left = ((xy[0] - region.left) + 15), //Buffer of 15px
  1253. //Set right to right minus x minus width
  1254. right = ((region.right - xy[0] - width) + 15);
  1255. //Set the constraints based on the above calculations
  1256. this.setXConstraint(left, right);
  1257. this.setYConstraint(10, 10);
  1258. },
  1259. _resizeProxy: function() {
  1260. this.constructor.superclass._resizeProxy.apply(this, arguments);
  1261. var dragEl = this.getDragEl(),
  1262. el = this.getEl();
  1263. YAHOO.util.Dom.setStyle(this.pointer, 'height', (this.table.parentNode.offsetHeight + 10) + 'px');
  1264. YAHOO.util.Dom.setStyle(this.pointer, 'display', 'block');
  1265. var xy = YAHOO.util.Dom.getXY(el);
  1266. YAHOO.util.Dom.setXY(this.pointer, [xy[0], (xy[1] - 5)]);
  1267. YAHOO.util.Dom.setStyle(dragEl, 'height', this.datatable.getContainerEl().offsetHeight + "px");
  1268. YAHOO.util.Dom.setStyle(dragEl, 'width', (parseInt(YAHOO.util.Dom.getStyle(dragEl, 'width'),10) + 4) + 'px');
  1269. YAHOO.util.Dom.setXY(this.dragEl, xy);
  1270. },
  1271. onMouseDown: function() {
  1272. this.initConstraints();
  1273. this.resetConstraints();
  1274. },
  1275. clickValidator: function(e) {
  1276. if(!this.column.hidden) {
  1277. var target = YAHOO.util.Event.getTarget(e);
  1278. return ( this.isValidHandleChild(target) &&
  1279. (this.id == this.handleElId ||
  1280. this.DDM.handleWasClicked(target, this.id)) );
  1281. }
  1282. },
  1283. onDragOver: function(ev, id) {
  1284. // Validate target as a Column
  1285. var target = this.datatable.getColumn(id);
  1286. if(target) {
  1287. // Validate target as a top-level parent
  1288. var targetIndex = target.getTreeIndex();
  1289. while((targetIndex === null) && target.getParent()) {
  1290. target = target.getParent();
  1291. targetIndex = target.getTreeIndex();
  1292. }
  1293. if(targetIndex !== null) {
  1294. // Are we placing to left or right of target?
  1295. var elTarget = target.getThEl();
  1296. var newIndex = targetIndex;
  1297. var mouseX = YAHOO.util.Event.getPageX(ev),
  1298. targetX = YAHOO.util.Dom.getX(elTarget),
  1299. midX = targetX + ((YAHOO.util.Dom.get(elTarget).offsetWidth)/2),
  1300. currentIndex = this.column.getTreeIndex();
  1301. if (mouseX < midX) {
  1302. YAHOO.util.Dom.setX(this.pointer, targetX);
  1303. } else {
  1304. var targetWidth = parseInt(elTarget.offsetWidth, 10);
  1305. YAHOO.util.Dom.setX(this.pointer, (targetX + targetWidth));
  1306. newIndex++;
  1307. }
  1308. if (targetIndex > currentIndex) {
  1309. newIndex--;
  1310. }
  1311. if(newIndex < 0) {
  1312. newIndex = 0;
  1313. }
  1314. else if(newIndex > this.datatable.getColumnSet().tree[0].length) {
  1315. newIndex = this.datatable.getColumnSet().tree[0].length;
  1316. }
  1317. this.newIndex = newIndex;
  1318. }
  1319. }
  1320. },
  1321. onDragDrop: function() {
  1322. this.datatable.reorderColumn(this.column, this.newIndex);
  1323. },
  1324. endDrag: function() {
  1325. this.newIndex = null;
  1326. YAHOO.util.Dom.setStyle(this.pointer, 'display', 'none');
  1327. }
  1328. });
  1329. }
  1330. /****************************************************************************/
  1331. /****************************************************************************/
  1332. /****************************************************************************/
  1333. /**
  1334. * ColumnResizer subclasses DragDrop to support resizeable Columns.
  1335. *
  1336. * @namespace YAHOO.util
  1337. * @class ColumnResizer
  1338. * @extends YAHOO.util.DDProxy
  1339. * @constructor
  1340. * @param oDataTable {YAHOO.widget.DataTable} DataTable instance.
  1341. * @param oColumn {YAHOO.widget.Column} Column instance.
  1342. * @param elTh {HTMLElement} TH element reference.
  1343. * @param sHandleElId {String} DOM ID of the handle element that causes the resize.
  1344. * @param elProxy {HTMLElement} Resizer proxy element.
  1345. */
  1346. YAHOO.util.ColumnResizer = function(oDataTable, oColumn, elTh, sHandleId, elProxy) {
  1347. if(oDataTable && oColumn && elTh && sHandleId) {
  1348. this.datatable = oDataTable;
  1349. this.column = oColumn;
  1350. this.headCell = elTh;
  1351. this.headCellLiner = oColumn.getThLinerEl();
  1352. this.resizerLiner = elTh.firstChild;
  1353. this.init(sHandleId, sHandleId, {dragOnly:true, dragElId: elProxy.id});
  1354. this.initFrame(); // Needed for proxy
  1355. this.resetResizerEl(); // Needed when rowspan > 0
  1356. // Set right padding for bug 1858462
  1357. this.setPadding(0, 1, 0, 0);
  1358. }
  1359. else {
  1360. YAHOO.log("Column resizer could not be created","warn",oDataTable.toString());
  1361. }
  1362. };
  1363. if(YAHOO.util.DD) {
  1364. YAHOO.extend(YAHOO.util.ColumnResizer, YAHOO.util.DDProxy, {
  1365. /////////////////////////////////////////////////////////////////////////////
  1366. //
  1367. // Public methods
  1368. //
  1369. /////////////////////////////////////////////////////////////////////////////
  1370. /**
  1371. * Resets resizer element.
  1372. *
  1373. * @method resetResizerEl
  1374. */
  1375. resetResizerEl : function() {
  1376. var resizerStyle = YAHOO.util.Dom.get(this.handleElId).style;
  1377. resizerStyle.left = "auto";
  1378. resizerStyle.right = 0;
  1379. resizerStyle.top = "auto";
  1380. resizerStyle.bottom = 0;
  1381. resizerStyle.height = this.headCell.offsetHeight+"px";
  1382. },
  1383. /////////////////////////////////////////////////////////////////////////////
  1384. //
  1385. // Public DOM event handlers
  1386. //
  1387. /////////////////////////////////////////////////////////////////////////////
  1388. /**
  1389. * Handles mouseup events on the Column resizer.
  1390. *
  1391. * @method onMouseUp
  1392. * @param e {string} The mouseup event
  1393. */
  1394. onMouseUp : function(e) {
  1395. // Reset height of all resizer els in case TH's have changed height
  1396. var allKeys = this.datatable.getColumnSet().keys,
  1397. col;
  1398. for(var i=0, len=allKeys.length; i<len; i++) {
  1399. col = allKeys[i];
  1400. if(col._ddResizer) {
  1401. col._ddResizer.resetResizerEl();
  1402. }
  1403. }
  1404. this.resetResizerEl();
  1405. var el = this.headCellLiner;
  1406. var newWidth = el.offsetWidth -
  1407. (parseInt(YAHOO.util.Dom.getStyle(el,"paddingLeft"),10)|0) -
  1408. (parseInt(YAHOO.util.Dom.getStyle(el,"paddingRight"),10)|0);
  1409. this.datatable.fireEvent("columnResizeEvent", {column:this.column,target:this.headCell,width:newWidth});
  1410. },
  1411. /**
  1412. * Handles mousedown events on the Column resizer.
  1413. *
  1414. * @method onMouseDown
  1415. * @param e {string} The mousedown event
  1416. */
  1417. onMouseDown : function(e) {
  1418. this.startWidth = this.headCellLiner.offsetWidth;
  1419. this.startX = YAHOO.util.Event.getXY(e)[0];
  1420. this.nLinerPadding = (parseInt(YAHOO.util.Dom.getStyle(this.headCellLiner,"paddingLeft"),10)|0) +
  1421. (parseInt(YAHOO.util.Dom.getStyle(this.headCellLiner,"paddingRight"),10)|0);
  1422. },
  1423. /**
  1424. * Custom clickValidator to ensure Column is not in hidden state.
  1425. *
  1426. * @method clickValidator
  1427. * @param {Event} e
  1428. * @private
  1429. */
  1430. clickValidator : function(e) {
  1431. if(!this.column.hidden) {
  1432. var target = YAHOO.util.Event.getTarget(e);
  1433. return ( this.isValidHandleChild(target) &&
  1434. (this.id == this.handleElId ||
  1435. this.DDM.handleWasClicked(target, this.id)) );
  1436. }
  1437. },
  1438. /**
  1439. * Handles start drag on the Column resizer.
  1440. *
  1441. * @method startDrag
  1442. * @param e {string} The drag event
  1443. */
  1444. startDrag : function() {
  1445. // Shrinks height of all resizer els to not hold open TH els
  1446. var allKeys = this.datatable.getColumnSet().keys,
  1447. thisKey = this.column.getKeyIndex(),
  1448. col;
  1449. for(var i=0, len=allKeys.length; i<len; i++) {
  1450. col = allKeys[i];
  1451. if(col._ddResizer) {
  1452. YAHOO.util.Dom.get(col._ddResizer.handleElId).style.height = "1em";
  1453. }
  1454. }
  1455. },
  1456. /**
  1457. * Handles drag events on the Column resizer.
  1458. *
  1459. * @method onDrag
  1460. * @param e {string} The drag event
  1461. */
  1462. onDrag : function(e) {
  1463. var newX = YAHOO.util.Event.getXY(e)[0];
  1464. if(newX > YAHOO.util.Dom.getX(this.headCellLiner)) {
  1465. var offsetX = newX - this.startX;
  1466. var newWidth = this.startWidth + offsetX - this.nLinerPadding;
  1467. if(newWidth > 0) {
  1468. this.datatable.setColumnWidth(this.column, newWidth);
  1469. }
  1470. }
  1471. }
  1472. });
  1473. }
  1474. /////////////////////////////////////////////////////////////////////////////
  1475. //
  1476. // Deprecated
  1477. //
  1478. /////////////////////////////////////////////////////////////////////////////
  1479. /**
  1480. * @property editorOptions
  1481. * @deprecated Pass configs directly to CellEditor constructor.
  1482. */
  1483. (function () {
  1484. var lang = YAHOO.lang,
  1485. util = YAHOO.util,
  1486. widget = YAHOO.widget,
  1487. Dom = util.Dom,
  1488. Ev = util.Event,
  1489. DT = widget.DataTable;
  1490. /****************************************************************************/
  1491. /****************************************************************************/
  1492. /****************************************************************************/
  1493. /**
  1494. * A RecordSet defines and manages a set of Records.
  1495. *
  1496. * @namespace YAHOO.widget
  1497. * @class RecordSet
  1498. * @param data {Object || Object[]} An object literal or an array of data.
  1499. * @constructor
  1500. */
  1501. YAHOO.widget.RecordSet = function(data) {
  1502. // Internal variables
  1503. this._sId = "yui-rs" + widget.RecordSet._nCount;
  1504. widget.RecordSet._nCount++;
  1505. this._records = [];
  1506. //this._length = 0;
  1507. if(data) {
  1508. if(lang.isArray(data)) {
  1509. this.addRecords(data);
  1510. }
  1511. else if(lang.isObject(data)) {
  1512. this.addRecord(data);
  1513. }
  1514. }
  1515. YAHOO.log("RecordSet initialized", "info", this.toString());
  1516. };
  1517. var RS = widget.RecordSet;
  1518. /**
  1519. * Internal class variable to name multiple Recordset instances.
  1520. *
  1521. * @property RecordSet._nCount
  1522. * @type Number
  1523. * @private
  1524. * @static
  1525. */
  1526. RS._nCount = 0;
  1527. RS.prototype = {
  1528. /////////////////////////////////////////////////////////////////////////////
  1529. //
  1530. // Private member variables
  1531. //
  1532. /////////////////////////////////////////////////////////////////////////////
  1533. /**
  1534. * Unique String identifier assigned at instantiation.
  1535. *
  1536. * @property _sId
  1537. * @type String
  1538. * @private
  1539. */
  1540. _sId : null,
  1541. /**
  1542. * Internal counter of how many Records are in the RecordSet.
  1543. *
  1544. * @property _length
  1545. * @type Number
  1546. * @private
  1547. * @deprecated No longer used
  1548. */
  1549. //_length : null,
  1550. /////////////////////////////////////////////////////////////////////////////
  1551. //
  1552. // Private methods
  1553. //
  1554. /////////////////////////////////////////////////////////////////////////////
  1555. /**
  1556. * Adds one Record to the RecordSet at the given index. If index is null,
  1557. * then adds the Record to the end of the RecordSet.
  1558. *
  1559. * @method _addRecord
  1560. * @param oData {Object} An object literal of data.
  1561. * @param index {Number} (optional) Position index.
  1562. * @return {YAHOO.widget.Record} A Record instance.
  1563. * @private
  1564. */
  1565. _addRecord : function(oData, index) {
  1566. var oRecord = new YAHOO.widget.Record(oData);
  1567. if(YAHOO.lang.isNumber(index) && (index > -1)) {
  1568. this._records.splice(index,0,oRecord);
  1569. }
  1570. else {
  1571. //index = this.getLength();
  1572. //this._records[index] = oRecord;
  1573. this._records[this._records.length] = oRecord;
  1574. }
  1575. //this._length++;
  1576. return oRecord;
  1577. },
  1578. /**
  1579. * Sets/replaces one Record to the RecordSet at the given index. Existing
  1580. * Records with higher indexes are not shifted. If no index specified, the
  1581. * Record is added to the end of the RecordSet.
  1582. *
  1583. * @method _setRecord
  1584. * @param oData {Object} An object literal of data.
  1585. * @param index {Number} (optional) Position index.
  1586. * @return {YAHOO.widget.Record} A Record instance.
  1587. * @private
  1588. */
  1589. _setRecord : function(oData, index) {
  1590. if (!lang.isNumber(index) || index < 0) {
  1591. index = this._records.length;
  1592. }
  1593. return (this._records[index] = new widget.Record(oData));
  1594. /*
  1595. if(lang.isNumber(index) && (index > -1)) {
  1596. this._records[index] = oRecord;
  1597. if((index+1) > this.getLength()) {
  1598. this._length = index+1;
  1599. }
  1600. }
  1601. else {
  1602. this._records[this.getLength()] = oRecord;
  1603. this._length++;
  1604. }
  1605. return oRecord;
  1606. */
  1607. },
  1608. /**
  1609. * Deletes Records from the RecordSet at the given index. If range is null,
  1610. * then only one Record is deleted.
  1611. *
  1612. * @method _deleteRecord
  1613. * @param index {Number} Position index.
  1614. * @param range {Number} (optional) How many Records to delete
  1615. * @private
  1616. */
  1617. _deleteRecord : function(index, range) {
  1618. if(!lang.isNumber(range) || (range < 0)) {
  1619. range = 1;
  1620. }
  1621. this._records.splice(index, range);
  1622. //this._length = this._length - range;
  1623. },
  1624. /////////////////////////////////////////////////////////////////////////////
  1625. //
  1626. // Public methods
  1627. //
  1628. /////////////////////////////////////////////////////////////////////////////
  1629. /**
  1630. * Returns unique name of the RecordSet instance.
  1631. *
  1632. * @method getId
  1633. * @return {String} Unique name of the RecordSet instance.
  1634. */
  1635. getId : function() {
  1636. return this._sId;
  1637. },
  1638. /**
  1639. * Public accessor to the unique name of the RecordSet instance.
  1640. *
  1641. * @method toString
  1642. * @return {String} Unique name of the RecordSet instance.
  1643. */
  1644. toString : function() {
  1645. return "RecordSet instance " + this._sId;
  1646. },
  1647. /**
  1648. * Returns the number of Records held in the RecordSet.
  1649. *
  1650. * @method getLength
  1651. * @return {Number} Number of records in the RecordSet.
  1652. */
  1653. getLength : function() {
  1654. //return this._length;
  1655. return this._records.length;
  1656. },
  1657. /**
  1658. * Returns Record by ID or RecordSet position index.
  1659. *
  1660. * @method getRecord
  1661. * @param record {YAHOO.widget.Record | Number | String} Record instance,
  1662. * RecordSet position index, or Record ID.
  1663. * @return {YAHOO.widget.Record} Record object.
  1664. */
  1665. getRecord : function(record) {
  1666. var i;
  1667. if(record instanceof widget.Record) {
  1668. for(i=0; i<this._records.length; i++) {
  1669. if(this._records[i] && (this._records[i]._sId === record._sId)) {
  1670. return record;
  1671. }
  1672. }
  1673. }
  1674. else if(lang.isNumber(record)) {
  1675. if((record > -1) && (record < this.getLength())) {
  1676. return this._records[record];
  1677. }
  1678. }
  1679. else if(lang.isString(record)) {
  1680. for(i=0; i<this._records.length; i++) {
  1681. if(this._records[i] && (this._records[i]._sId === record)) {
  1682. return this._records[i];
  1683. }
  1684. }
  1685. }
  1686. // Not a valid Record for this RecordSet
  1687. return null;
  1688. },
  1689. /**
  1690. * Returns an array of Records from the RecordSet.
  1691. *
  1692. * @method getRecords
  1693. * @param index {Number} (optional) Recordset position index of which Record to
  1694. * start at.
  1695. * @param range {Number} (optional) Number of Records to get.
  1696. * @return {YAHOO.widget.Record[]} Array of Records starting at given index and
  1697. * length equal to given range. If index is not given, all Records are returned.
  1698. */
  1699. getRecords : function(index, range) {
  1700. if(!lang.isNumber(index)) {
  1701. return this._records;
  1702. }
  1703. if(!lang.isNumber(range)) {
  1704. return this._records.slice(index);
  1705. }
  1706. return this._records.slice(index, index+range);
  1707. },
  1708. /**
  1709. * Returns a boolean indicating whether Records exist in the RecordSet at the
  1710. * specified index range. Returns true if and only if a Record exists at each
  1711. * index in the range.
  1712. * @method hasRecords
  1713. * @param index
  1714. * @param range
  1715. * @return {Boolean} true if all indices are populated in the RecordSet
  1716. */
  1717. hasRecords : function (index, range) {
  1718. var recs = this.getRecords(index,range);
  1719. for (var i = 0; i < range; ++i) {
  1720. if (typeof recs[i] === 'undefined') {
  1721. return false;
  1722. }
  1723. }
  1724. return true;
  1725. },
  1726. /**
  1727. * Returns current position index for the given Record.
  1728. *
  1729. * @method getRecordIndex
  1730. * @param oRecord {YAHOO.widget.Record} Record instance.
  1731. * @return {Number} Record's RecordSet position index.
  1732. */
  1733. getRecordIndex : function(oRecord) {
  1734. if(oRecord) {
  1735. for(var i=this._records.length-1; i>-1; i--) {
  1736. if(this._records[i] && oRecord.getId() === this._records[i].getId()) {
  1737. return i;
  1738. }
  1739. }
  1740. }
  1741. return null;
  1742. },
  1743. /**
  1744. * Adds one Record to the RecordSet at the given index. If index is null,
  1745. * then adds the Record to the end of the RecordSet.
  1746. *
  1747. * @method addRecord
  1748. * @param oData {Object} An object literal of data.
  1749. * @param index {Number} (optional) Position index.
  1750. * @return {YAHOO.widget.Record} A Record instance.
  1751. */
  1752. addRecord : function(oData, index) {
  1753. if(lang.isObject(oData)) {
  1754. var oRecord = this._addRecord(oData, index);
  1755. this.fireEvent("recordAddEvent",{record:oRecord,data:oData});
  1756. YAHOO.log("Added Record at index " + index +
  1757. " with data " + lang.dump(oData), "info", this.toString());
  1758. return oRecord;
  1759. }
  1760. else {
  1761. YAHOO.log("Could not add Record with data" +
  1762. lang.dump(oData), "info", this.toString());
  1763. return null;
  1764. }
  1765. },
  1766. /**
  1767. * Adds multiple Records at once to the RecordSet at the given index with the
  1768. * given object literal data. If index is null, then the new Records are
  1769. * added to the end of the RecordSet.
  1770. *
  1771. * @method addRecords
  1772. * @param aData {Object[]} An object literal data or an array of data object literals.
  1773. * @param index {Number} (optional) Position index.
  1774. * @return {YAHOO.widget.Record[]} An array of Record instances.
  1775. */
  1776. addRecords : function(aData, index) {
  1777. if(lang.isArray(aData)) {
  1778. var newRecords = [],
  1779. idx,i,len;
  1780. index = lang.isNumber(index) ? index : this._records.length;
  1781. idx = index;
  1782. // Can't go backwards bc we need to preserve order
  1783. for(i=0,len=aData.length; i<len; ++i) {
  1784. if(lang.isObject(aData[i])) {
  1785. var record = this._addRecord(aData[i], idx++);
  1786. newRecords.push(record);
  1787. }
  1788. }
  1789. this.fireEvent("recordsAddEvent",{records:newRecords,data:aData});
  1790. YAHOO.log("Added " + newRecords.length + " Record(s) at index " + index +
  1791. " with data " + lang.dump(aData), "info", this.toString());
  1792. return newRecords;
  1793. }
  1794. else if(lang.isObject(aData)) {
  1795. var oRecord = this._addRecord(aData);
  1796. this.fireEvent("recordsAddEvent",{records:[oRecord],data:aData});
  1797. YAHOO.log("Added 1 Record at index " + index +
  1798. " with data " + lang.dump(aData), "info", this.toString());
  1799. return oRecord;
  1800. }
  1801. else {
  1802. YAHOO.log("Could not add Records with data " +
  1803. lang.dump(aData), "info", this.toString());
  1804. return null;
  1805. }
  1806. },
  1807. /**
  1808. * Sets or replaces one Record to the RecordSet at the given index. Unlike
  1809. * addRecord, an existing Record at that index is not shifted to preserve it.
  1810. * If no index is specified, it adds the Record to the end of the RecordSet.
  1811. *
  1812. * @method setRecord
  1813. * @param oData {Object} An object literal of data.
  1814. * @param index {Number} (optional) Position index.
  1815. * @return {YAHOO.widget.Record} A Record instance.
  1816. */
  1817. setRecord : function(oData, index) {
  1818. if(lang.isObject(oData)) {
  1819. var oRecord = this._setRecord(oData, index);
  1820. this.fireEvent("recordSetEvent",{record:oRecord,data:oData});
  1821. YAHOO.lo