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

/hudson-war/src/main/webapp/scripts/yui/logger/logger-debug.js

http://github.com/hudson/hudson
JavaScript | 2030 lines | 778 code | 212 blank | 1040 comment | 138 complexity | 99ff4fd16c1ebf5bc7f0e463f3fcaf53 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause
  1. /*
  2. Copyright (c) 2008, Yahoo! Inc. All rights reserved.
  3. Code licensed under the BSD License:
  4. http://developer.yahoo.net/yui/license.txt
  5. version: 2.5.1
  6. */
  7. /****************************************************************************/
  8. /****************************************************************************/
  9. /****************************************************************************/
  10. /**
  11. * The LogMsg class defines a single log message.
  12. *
  13. * @class LogMsg
  14. * @constructor
  15. * @param oConfigs {Object} Object literal of configuration params.
  16. */
  17. YAHOO.widget.LogMsg = function(oConfigs) {
  18. // Parse configs
  19. /**
  20. * Log message.
  21. *
  22. * @property msg
  23. * @type String
  24. */
  25. this.msg =
  26. /**
  27. * Log timestamp.
  28. *
  29. * @property time
  30. * @type Date
  31. */
  32. this.time =
  33. /**
  34. * Log category.
  35. *
  36. * @property category
  37. * @type String
  38. */
  39. this.category =
  40. /**
  41. * Log source. The first word passed in as the source argument.
  42. *
  43. * @property source
  44. * @type String
  45. */
  46. this.source =
  47. /**
  48. * Log source detail. The remainder of the string passed in as the source argument, not
  49. * including the first word (if any).
  50. *
  51. * @property sourceDetail
  52. * @type String
  53. */
  54. this.sourceDetail = null;
  55. if (oConfigs && (oConfigs.constructor == Object)) {
  56. for(var param in oConfigs) {
  57. this[param] = oConfigs[param];
  58. }
  59. }
  60. };
  61. /****************************************************************************/
  62. /****************************************************************************/
  63. /****************************************************************************/
  64. /**
  65. * The LogWriter class provides a mechanism to log messages through
  66. * YAHOO.widget.Logger from a named source.
  67. *
  68. * @class LogWriter
  69. * @constructor
  70. * @param sSource {String} Source of LogWriter instance.
  71. */
  72. YAHOO.widget.LogWriter = function(sSource) {
  73. if(!sSource) {
  74. YAHOO.log("Could not instantiate LogWriter due to invalid source.",
  75. "error", "LogWriter");
  76. return;
  77. }
  78. this._source = sSource;
  79. };
  80. /////////////////////////////////////////////////////////////////////////////
  81. //
  82. // Public methods
  83. //
  84. /////////////////////////////////////////////////////////////////////////////
  85. /**
  86. * Public accessor to the unique name of the LogWriter instance.
  87. *
  88. * @method toString
  89. * @return {String} Unique name of the LogWriter instance.
  90. */
  91. YAHOO.widget.LogWriter.prototype.toString = function() {
  92. return "LogWriter " + this._sSource;
  93. };
  94. /**
  95. * Logs a message attached to the source of the LogWriter.
  96. *
  97. * @method log
  98. * @param sMsg {String} The log message.
  99. * @param sCategory {String} Category name.
  100. */
  101. YAHOO.widget.LogWriter.prototype.log = function(sMsg, sCategory) {
  102. YAHOO.widget.Logger.log(sMsg, sCategory, this._source);
  103. };
  104. /**
  105. * Public accessor to get the source name.
  106. *
  107. * @method getSource
  108. * @return {String} The LogWriter source.
  109. */
  110. YAHOO.widget.LogWriter.prototype.getSource = function() {
  111. return this._sSource;
  112. };
  113. /**
  114. * Public accessor to set the source name.
  115. *
  116. * @method setSource
  117. * @param sSource {String} Source of LogWriter instance.
  118. */
  119. YAHOO.widget.LogWriter.prototype.setSource = function(sSource) {
  120. if(!sSource) {
  121. YAHOO.log("Could not set source due to invalid source.", "error", this.toString());
  122. return;
  123. }
  124. else {
  125. this._sSource = sSource;
  126. }
  127. };
  128. /////////////////////////////////////////////////////////////////////////////
  129. //
  130. // Private member variables
  131. //
  132. /////////////////////////////////////////////////////////////////////////////
  133. /**
  134. * Source of the LogWriter instance.
  135. *
  136. * @property _source
  137. * @type String
  138. * @private
  139. */
  140. YAHOO.widget.LogWriter.prototype._source = null;
  141. /****************************************************************************/
  142. /****************************************************************************/
  143. /****************************************************************************/
  144. /**
  145. * The LogReader class provides UI to read messages logged to YAHOO.widget.Logger.
  146. *
  147. * @class LogReader
  148. * @constructor
  149. * @param elContainer {HTMLElement} (optional) DOM element reference of an existing DIV.
  150. * @param elContainer {String} (optional) String ID of an existing DIV.
  151. * @param oConfigs {Object} (optional) Object literal of configuration params.
  152. */
  153. YAHOO.widget.LogReader = function(elContainer, oConfigs) {
  154. this._sName = YAHOO.widget.LogReader._index;
  155. YAHOO.widget.LogReader._index++;
  156. // Internal vars
  157. this._buffer = []; // output buffer
  158. this._filterCheckboxes = {}; // pointers to checkboxes
  159. this._lastTime = YAHOO.widget.Logger.getStartTime(); // timestamp of last log message to console
  160. // Parse config vars here
  161. if (oConfigs && (oConfigs.constructor == Object)) {
  162. for(var param in oConfigs) {
  163. this[param] = oConfigs[param];
  164. }
  165. }
  166. this._initContainerEl(elContainer);
  167. if(!this._elContainer) {
  168. YAHOO.log("Could not instantiate LogReader due to an invalid container element " +
  169. elContainer, "error", this.toString());
  170. return;
  171. }
  172. this._initHeaderEl();
  173. this._initConsoleEl();
  174. this._initFooterEl();
  175. this._initDragDrop();
  176. this._initCategories();
  177. this._initSources();
  178. // Subscribe to Logger custom events
  179. YAHOO.widget.Logger.newLogEvent.subscribe(this._onNewLog, this);
  180. YAHOO.widget.Logger.logResetEvent.subscribe(this._onReset, this);
  181. YAHOO.widget.Logger.categoryCreateEvent.subscribe(this._onCategoryCreate, this);
  182. YAHOO.widget.Logger.sourceCreateEvent.subscribe(this._onSourceCreate, this);
  183. this._filterLogs();
  184. YAHOO.log("LogReader initialized", null, this.toString());
  185. };
  186. /////////////////////////////////////////////////////////////////////////////
  187. //
  188. // Static member variables
  189. //
  190. /////////////////////////////////////////////////////////////////////////////
  191. YAHOO.lang.augmentObject(YAHOO.widget.LogReader, {
  192. /**
  193. * Internal class member to index multiple LogReader instances.
  194. *
  195. * @property _memberName
  196. * @static
  197. * @type Number
  198. * @default 0
  199. * @private
  200. */
  201. _index : 0,
  202. /**
  203. * Node template for the log entries
  204. * @property ENTRY_TEMPLATE
  205. * @static
  206. * @type {HTMLElement}
  207. * @default PRE.yui-log-entry element
  208. */
  209. ENTRY_TEMPLATE : (function () {
  210. var t = document.createElement('pre');
  211. YAHOO.util.Dom.addClass(t,'yui-log-entry');
  212. return t;
  213. })(),
  214. /**
  215. * Template used for innerHTML of verbose entry output.
  216. * @property VERBOSE_TEMPLATE
  217. * @static
  218. * @default "<span class='{category}'>{label}</span>{totalTime}ms (+{elapsedTime}) {localTime}:</p><p>{sourceAndDetail}</p><p>{message}</p>"
  219. */
  220. VERBOSE_TEMPLATE : "<span class='{category}'>{label}</span>{totalTime}ms (+{elapsedTime}) {localTime}:</p><p>{sourceAndDetail}</p><p>{message}</p>",
  221. /**
  222. * Template used for innerHTML of compact entry output.
  223. * @property BASIC_TEMPLATE
  224. * @static
  225. * @default "<p><span class='{category}'>{label}</span>{totalTime}ms (+{elapsedTime}) {localTime}: {sourceAndDetail}: {message}</p>"
  226. */
  227. BASIC_TEMPLATE : "<p><span class='{category}'>{label}</span>{totalTime}ms (+{elapsedTime}) {localTime}: {sourceAndDetail}: {message}</p>"
  228. });
  229. /////////////////////////////////////////////////////////////////////////////
  230. //
  231. // Public member variables
  232. //
  233. /////////////////////////////////////////////////////////////////////////////
  234. YAHOO.widget.LogReader.prototype = {
  235. /**
  236. * Whether or not LogReader is enabled to output log messages.
  237. *
  238. * @property logReaderEnabled
  239. * @type Boolean
  240. * @default true
  241. */
  242. logReaderEnabled : true,
  243. /**
  244. * Public member to access CSS width of the LogReader container.
  245. *
  246. * @property width
  247. * @type String
  248. */
  249. width : null,
  250. /**
  251. * Public member to access CSS height of the LogReader container.
  252. *
  253. * @property height
  254. * @type String
  255. */
  256. height : null,
  257. /**
  258. * Public member to access CSS top position of the LogReader container.
  259. *
  260. * @property top
  261. * @type String
  262. */
  263. top : null,
  264. /**
  265. * Public member to access CSS left position of the LogReader container.
  266. *
  267. * @property left
  268. * @type String
  269. */
  270. left : null,
  271. /**
  272. * Public member to access CSS right position of the LogReader container.
  273. *
  274. * @property right
  275. * @type String
  276. */
  277. right : null,
  278. /**
  279. * Public member to access CSS bottom position of the LogReader container.
  280. *
  281. * @property bottom
  282. * @type String
  283. */
  284. bottom : null,
  285. /**
  286. * Public member to access CSS font size of the LogReader container.
  287. *
  288. * @property fontSize
  289. * @type String
  290. */
  291. fontSize : null,
  292. /**
  293. * Whether or not the footer UI is enabled for the LogReader.
  294. *
  295. * @property footerEnabled
  296. * @type Boolean
  297. * @default true
  298. */
  299. footerEnabled : true,
  300. /**
  301. * Whether or not output is verbose (more readable). Setting to true will make
  302. * output more compact (less readable).
  303. *
  304. * @property verboseOutput
  305. * @type Boolean
  306. * @default true
  307. */
  308. verboseOutput : true,
  309. /**
  310. * Custom output format for log messages. Defaults to null, which falls
  311. * back to verboseOutput param deciding between LogReader.VERBOSE_TEMPLATE
  312. * and LogReader.BASIC_TEMPLATE. Use bracketed place holders to mark where
  313. * message info should go. Available place holder names include:
  314. * <ul>
  315. * <li>category</li>
  316. * <li>label</li>
  317. * <li>sourceAndDetail</li>
  318. * <li>message</li>
  319. * <li>localTime</li>
  320. * <li>elapsedTime</li>
  321. * <li>totalTime</li>
  322. * </ul>
  323. *
  324. * @property entryFormat
  325. * @type String
  326. * @default null
  327. */
  328. entryFormat : null,
  329. /**
  330. * Whether or not newest message is printed on top.
  331. *
  332. * @property newestOnTop
  333. * @type Boolean
  334. */
  335. newestOnTop : true,
  336. /**
  337. * Output timeout buffer in milliseconds.
  338. *
  339. * @property outputBuffer
  340. * @type Number
  341. * @default 100
  342. */
  343. outputBuffer : 100,
  344. /**
  345. * Maximum number of messages a LogReader console will display.
  346. *
  347. * @property thresholdMax
  348. * @type Number
  349. * @default 500
  350. */
  351. thresholdMax : 500,
  352. /**
  353. * When a LogReader console reaches its thresholdMax, it will clear out messages
  354. * and print out the latest thresholdMin number of messages.
  355. *
  356. * @property thresholdMin
  357. * @type Number
  358. * @default 100
  359. */
  360. thresholdMin : 100,
  361. /**
  362. * True when LogReader is in a collapsed state, false otherwise.
  363. *
  364. * @property isCollapsed
  365. * @type Boolean
  366. * @default false
  367. */
  368. isCollapsed : false,
  369. /**
  370. * True when LogReader is in a paused state, false otherwise.
  371. *
  372. * @property isPaused
  373. * @type Boolean
  374. * @default false
  375. */
  376. isPaused : false,
  377. /**
  378. * Enables draggable LogReader if DragDrop Utility is present.
  379. *
  380. * @property draggable
  381. * @type Boolean
  382. * @default true
  383. */
  384. draggable : true,
  385. /////////////////////////////////////////////////////////////////////////////
  386. //
  387. // Public methods
  388. //
  389. /////////////////////////////////////////////////////////////////////////////
  390. /**
  391. * Public accessor to the unique name of the LogReader instance.
  392. *
  393. * @method toString
  394. * @return {String} Unique name of the LogReader instance.
  395. */
  396. toString : function() {
  397. return "LogReader instance" + this._sName;
  398. },
  399. /**
  400. * Pauses output of log messages. While paused, log messages are not lost, but
  401. * get saved to a buffer and then output upon resume of LogReader.
  402. *
  403. * @method pause
  404. */
  405. pause : function() {
  406. this.isPaused = true;
  407. this._btnPause.value = "Resume";
  408. this._timeout = null;
  409. this.logReaderEnabled = false;
  410. },
  411. /**
  412. * Resumes output of log messages, including outputting any log messages that
  413. * have been saved to buffer while paused.
  414. *
  415. * @method resume
  416. */
  417. resume : function() {
  418. this.isPaused = false;
  419. this._btnPause.value = "Pause";
  420. this.logReaderEnabled = true;
  421. this._printBuffer();
  422. },
  423. /**
  424. * Hides UI of LogReader. Logging functionality is not disrupted.
  425. *
  426. * @method hide
  427. */
  428. hide : function() {
  429. this._elContainer.style.display = "none";
  430. },
  431. /**
  432. * Shows UI of LogReader. Logging functionality is not disrupted.
  433. *
  434. * @method show
  435. */
  436. show : function() {
  437. this._elContainer.style.display = "block";
  438. },
  439. /**
  440. * Collapses UI of LogReader. Logging functionality is not disrupted.
  441. *
  442. * @method collapse
  443. */
  444. collapse : function() {
  445. this._elConsole.style.display = "none";
  446. if(this._elFt) {
  447. this._elFt.style.display = "none";
  448. }
  449. this._btnCollapse.value = "Expand";
  450. this.isCollapsed = true;
  451. },
  452. /**
  453. * Expands UI of LogReader. Logging functionality is not disrupted.
  454. *
  455. * @method expand
  456. */
  457. expand : function() {
  458. this._elConsole.style.display = "block";
  459. if(this._elFt) {
  460. this._elFt.style.display = "block";
  461. }
  462. this._btnCollapse.value = "Collapse";
  463. this.isCollapsed = false;
  464. },
  465. /**
  466. * Returns related checkbox element for given filter (i.e., category or source).
  467. *
  468. * @method getCheckbox
  469. * @param {String} Category or source name.
  470. * @return {Array} Array of all filter checkboxes.
  471. */
  472. getCheckbox : function(filter) {
  473. return this._filterCheckboxes[filter];
  474. },
  475. /**
  476. * Returns array of enabled categories.
  477. *
  478. * @method getCategories
  479. * @return {String[]} Array of enabled categories.
  480. */
  481. getCategories : function() {
  482. return this._categoryFilters;
  483. },
  484. /**
  485. * Shows log messages associated with given category.
  486. *
  487. * @method showCategory
  488. * @param {String} Category name.
  489. */
  490. showCategory : function(sCategory) {
  491. var filtersArray = this._categoryFilters;
  492. // Don't do anything if category is already enabled
  493. // Use Array.indexOf if available...
  494. if(filtersArray.indexOf) {
  495. if(filtersArray.indexOf(sCategory) > -1) {
  496. return;
  497. }
  498. }
  499. // ...or do it the old-fashioned way
  500. else {
  501. for(var i=0; i<filtersArray.length; i++) {
  502. if(filtersArray[i] === sCategory){
  503. return;
  504. }
  505. }
  506. }
  507. this._categoryFilters.push(sCategory);
  508. this._filterLogs();
  509. var elCheckbox = this.getCheckbox(sCategory);
  510. if(elCheckbox) {
  511. elCheckbox.checked = true;
  512. }
  513. },
  514. /**
  515. * Hides log messages associated with given category.
  516. *
  517. * @method hideCategory
  518. * @param {String} Category name.
  519. */
  520. hideCategory : function(sCategory) {
  521. var filtersArray = this._categoryFilters;
  522. for(var i=0; i<filtersArray.length; i++) {
  523. if(sCategory == filtersArray[i]) {
  524. filtersArray.splice(i, 1);
  525. break;
  526. }
  527. }
  528. this._filterLogs();
  529. var elCheckbox = this.getCheckbox(sCategory);
  530. if(elCheckbox) {
  531. elCheckbox.checked = false;
  532. }
  533. },
  534. /**
  535. * Returns array of enabled sources.
  536. *
  537. * @method getSources
  538. * @return {Array} Array of enabled sources.
  539. */
  540. getSources : function() {
  541. return this._sourceFilters;
  542. },
  543. /**
  544. * Shows log messages associated with given source.
  545. *
  546. * @method showSource
  547. * @param {String} Source name.
  548. */
  549. showSource : function(sSource) {
  550. var filtersArray = this._sourceFilters;
  551. // Don't do anything if category is already enabled
  552. // Use Array.indexOf if available...
  553. if(filtersArray.indexOf) {
  554. if(filtersArray.indexOf(sSource) > -1) {
  555. return;
  556. }
  557. }
  558. // ...or do it the old-fashioned way
  559. else {
  560. for(var i=0; i<filtersArray.length; i++) {
  561. if(sSource == filtersArray[i]){
  562. return;
  563. }
  564. }
  565. }
  566. filtersArray.push(sSource);
  567. this._filterLogs();
  568. var elCheckbox = this.getCheckbox(sSource);
  569. if(elCheckbox) {
  570. elCheckbox.checked = true;
  571. }
  572. },
  573. /**
  574. * Hides log messages associated with given source.
  575. *
  576. * @method hideSource
  577. * @param {String} Source name.
  578. */
  579. hideSource : function(sSource) {
  580. var filtersArray = this._sourceFilters;
  581. for(var i=0; i<filtersArray.length; i++) {
  582. if(sSource == filtersArray[i]) {
  583. filtersArray.splice(i, 1);
  584. break;
  585. }
  586. }
  587. this._filterLogs();
  588. var elCheckbox = this.getCheckbox(sSource);
  589. if(elCheckbox) {
  590. elCheckbox.checked = false;
  591. }
  592. },
  593. /**
  594. * Does not delete any log messages, but clears all printed log messages from
  595. * the console. Log messages will be printed out again if user re-filters. The
  596. * static method YAHOO.widget.Logger.reset() should be called in order to
  597. * actually delete log messages.
  598. *
  599. * @method clearConsole
  600. */
  601. clearConsole : function() {
  602. // Clear the buffer of any pending messages
  603. this._timeout = null;
  604. this._buffer = [];
  605. this._consoleMsgCount = 0;
  606. var elConsole = this._elConsole;
  607. elConsole.innerHTML = '';
  608. },
  609. /**
  610. * Updates title to given string.
  611. *
  612. * @method setTitle
  613. * @param sTitle {String} New title.
  614. */
  615. setTitle : function(sTitle) {
  616. this._title.innerHTML = this.html2Text(sTitle);
  617. },
  618. /**
  619. * Gets timestamp of the last log.
  620. *
  621. * @method getLastTime
  622. * @return {Date} Timestamp of the last log.
  623. */
  624. getLastTime : function() {
  625. return this._lastTime;
  626. },
  627. formatMsg : function (entry) {
  628. var Static = YAHOO.widget.LogReader,
  629. entryFormat = this.entryFormat || (this.verboseOutput ?
  630. Static.VERBOSE_TEMPLATE : Static.BASIC_TEMPLATE),
  631. info = {
  632. category : entry.category,
  633. // Label for color-coded display
  634. label : entry.category.substring(0,4).toUpperCase(),
  635. sourceAndDetail : entry.sourceDetail ?
  636. entry.source + " " + entry.sourceDetail :
  637. entry.source,
  638. // Escape HTML entities in the log message itself for output
  639. // to console
  640. message : this.html2Text(entry.msg || entry.message || '')
  641. };
  642. // Add time info
  643. if (entry.time && entry.time.getTime) {
  644. info.localTime = entry.time.toLocaleTimeString ?
  645. entry.time.toLocaleTimeString() :
  646. entry.time.toString();
  647. // Calculate the elapsed time to be from the last item that
  648. // passed through the filter, not the absolute previous item
  649. // in the stack
  650. info.elapsedTime = entry.time.getTime() - this.getLastTime();
  651. info.totalTime = entry.time.getTime() -
  652. YAHOO.widget.Logger.getStartTime();
  653. }
  654. var msg = Static.ENTRY_TEMPLATE.cloneNode(true);
  655. if (this.verboseOutput) {
  656. msg.className += ' yui-log-verbose';
  657. }
  658. msg.innerHTML = YAHOO.lang.substitute(entryFormat, info);
  659. return msg;
  660. },
  661. /**
  662. * Converts input chars "<", ">", and "&" to HTML entities.
  663. *
  664. * @method html2Text
  665. * @param sHtml {String} String to convert.
  666. * @private
  667. */
  668. html2Text : function(sHtml) {
  669. if(sHtml) {
  670. sHtml += "";
  671. return sHtml.replace(/&/g, "&#38;").replace(/</g, "&#60;").replace(/>/g, "&#62;");
  672. }
  673. return "";
  674. },
  675. /////////////////////////////////////////////////////////////////////////////
  676. //
  677. // Private member variables
  678. //
  679. /////////////////////////////////////////////////////////////////////////////
  680. /**
  681. * Name of LogReader instance.
  682. *
  683. * @property _sName
  684. * @type String
  685. * @private
  686. */
  687. _sName : null,
  688. //TODO: remove
  689. /**
  690. * A class member shared by all LogReaders if a container needs to be
  691. * created during instantiation. Will be null if a container element never needs to
  692. * be created on the fly, such as when the implementer passes in their own element.
  693. *
  694. * @property _elDefaultContainer
  695. * @type HTMLElement
  696. * @private
  697. */
  698. //YAHOO.widget.LogReader._elDefaultContainer = null;
  699. /**
  700. * Buffer of log message objects for batch output.
  701. *
  702. * @property _buffer
  703. * @type Object[]
  704. * @private
  705. */
  706. _buffer : null,
  707. /**
  708. * Number of log messages output to console.
  709. *
  710. * @property _consoleMsgCount
  711. * @type Number
  712. * @default 0
  713. * @private
  714. */
  715. _consoleMsgCount : 0,
  716. /**
  717. * Date of last output log message.
  718. *
  719. * @property _lastTime
  720. * @type Date
  721. * @private
  722. */
  723. _lastTime : null,
  724. /**
  725. * Batched output timeout ID.
  726. *
  727. * @property _timeout
  728. * @type Number
  729. * @private
  730. */
  731. _timeout : null,
  732. /**
  733. * Hash of filters and their related checkbox elements.
  734. *
  735. * @property _filterCheckboxes
  736. * @type Object
  737. * @private
  738. */
  739. _filterCheckboxes : null,
  740. /**
  741. * Array of filters for log message categories.
  742. *
  743. * @property _categoryFilters
  744. * @type String[]
  745. * @private
  746. */
  747. _categoryFilters : null,
  748. /**
  749. * Array of filters for log message sources.
  750. *
  751. * @property _sourceFilters
  752. * @type String[]
  753. * @private
  754. */
  755. _sourceFilters : null,
  756. /**
  757. * LogReader container element.
  758. *
  759. * @property _elContainer
  760. * @type HTMLElement
  761. * @private
  762. */
  763. _elContainer : null,
  764. /**
  765. * LogReader header element.
  766. *
  767. * @property _elHd
  768. * @type HTMLElement
  769. * @private
  770. */
  771. _elHd : null,
  772. /**
  773. * LogReader collapse element.
  774. *
  775. * @property _elCollapse
  776. * @type HTMLElement
  777. * @private
  778. */
  779. _elCollapse : null,
  780. /**
  781. * LogReader collapse button element.
  782. *
  783. * @property _btnCollapse
  784. * @type HTMLElement
  785. * @private
  786. */
  787. _btnCollapse : null,
  788. /**
  789. * LogReader title header element.
  790. *
  791. * @property _title
  792. * @type HTMLElement
  793. * @private
  794. */
  795. _title : null,
  796. /**
  797. * LogReader console element.
  798. *
  799. * @property _elConsole
  800. * @type HTMLElement
  801. * @private
  802. */
  803. _elConsole : null,
  804. /**
  805. * LogReader footer element.
  806. *
  807. * @property _elFt
  808. * @type HTMLElement
  809. * @private
  810. */
  811. _elFt : null,
  812. /**
  813. * LogReader buttons container element.
  814. *
  815. * @property _elBtns
  816. * @type HTMLElement
  817. * @private
  818. */
  819. _elBtns : null,
  820. /**
  821. * Container element for LogReader category filter checkboxes.
  822. *
  823. * @property _elCategoryFilters
  824. * @type HTMLElement
  825. * @private
  826. */
  827. _elCategoryFilters : null,
  828. /**
  829. * Container element for LogReader source filter checkboxes.
  830. *
  831. * @property _elSourceFilters
  832. * @type HTMLElement
  833. * @private
  834. */
  835. _elSourceFilters : null,
  836. /**
  837. * LogReader pause button element.
  838. *
  839. * @property _btnPause
  840. * @type HTMLElement
  841. * @private
  842. */
  843. _btnPause : null,
  844. /**
  845. * Clear button element.
  846. *
  847. * @property _btnClear
  848. * @type HTMLElement
  849. * @private
  850. */
  851. _btnClear : null,
  852. /////////////////////////////////////////////////////////////////////////////
  853. //
  854. // Private methods
  855. //
  856. /////////////////////////////////////////////////////////////////////////////
  857. /**
  858. * Initializes the primary container element.
  859. *
  860. * @method _initContainerEl
  861. * @param elContainer {HTMLElement} Container element by reference or string ID.
  862. * @private
  863. */
  864. _initContainerEl : function(elContainer) {
  865. // Validate container
  866. elContainer = YAHOO.util.Dom.get(elContainer);
  867. // Attach to existing container...
  868. if(elContainer && elContainer.tagName && (elContainer.tagName.toLowerCase() == "div")) {
  869. this._elContainer = elContainer;
  870. YAHOO.util.Dom.addClass(this._elContainer,"yui-log");
  871. }
  872. // ...or create container from scratch
  873. else {
  874. this._elContainer = document.body.appendChild(document.createElement("div"));
  875. //this._elContainer.id = "yui-log" + this._sName;
  876. YAHOO.util.Dom.addClass(this._elContainer,"yui-log");
  877. YAHOO.util.Dom.addClass(this._elContainer,"yui-log-container");
  878. //YAHOO.widget.LogReader._elDefaultContainer = this._elContainer;
  879. // If implementer has provided container values, trust and set those
  880. var containerStyle = this._elContainer.style;
  881. if(this.width) {
  882. containerStyle.width = this.width;
  883. }
  884. if(this.right) {
  885. containerStyle.right = this.right;
  886. }
  887. if(this.top) {
  888. containerStyle.top = this.top;
  889. }
  890. if(this.left) {
  891. containerStyle.left = this.left;
  892. containerStyle.right = "auto";
  893. }
  894. if(this.bottom) {
  895. containerStyle.bottom = this.bottom;
  896. containerStyle.top = "auto";
  897. }
  898. if(this.fontSize) {
  899. containerStyle.fontSize = this.fontSize;
  900. }
  901. // For Opera
  902. if(navigator.userAgent.toLowerCase().indexOf("opera") != -1) {
  903. document.body.style += '';
  904. }
  905. }
  906. },
  907. /**
  908. * Initializes the header element.
  909. *
  910. * @method _initHeaderEl
  911. * @private
  912. */
  913. _initHeaderEl : function() {
  914. var oSelf = this;
  915. // Destroy header
  916. if(this._elHd) {
  917. // Unhook DOM events
  918. YAHOO.util.Event.purgeElement(this._elHd, true);
  919. // Remove DOM elements
  920. this._elHd.innerHTML = "";
  921. }
  922. // Create header
  923. this._elHd = this._elContainer.appendChild(document.createElement("div"));
  924. this._elHd.id = "yui-log-hd" + this._sName;
  925. this._elHd.className = "yui-log-hd";
  926. this._elCollapse = this._elHd.appendChild(document.createElement("div"));
  927. this._elCollapse.className = "yui-log-btns";
  928. this._btnCollapse = document.createElement("input");
  929. this._btnCollapse.type = "button";
  930. //this._btnCollapse.style.fontSize =
  931. // YAHOO.util.Dom.getStyle(this._elContainer,"fontSize");
  932. this._btnCollapse.className = "yui-log-button";
  933. this._btnCollapse.value = "Collapse";
  934. this._btnCollapse = this._elCollapse.appendChild(this._btnCollapse);
  935. YAHOO.util.Event.addListener(
  936. oSelf._btnCollapse,'click',oSelf._onClickCollapseBtn,oSelf);
  937. this._title = this._elHd.appendChild(document.createElement("h4"));
  938. this._title.innerHTML = "Logger Console";
  939. },
  940. /**
  941. * Initializes the console element.
  942. *
  943. * @method _initConsoleEl
  944. * @private
  945. */
  946. _initConsoleEl : function() {
  947. // Destroy console
  948. if(this._elConsole) {
  949. // Unhook DOM events
  950. YAHOO.util.Event.purgeElement(this._elConsole, true);
  951. // Remove DOM elements
  952. this._elConsole.innerHTML = "";
  953. }
  954. // Ceate console
  955. this._elConsole = this._elContainer.appendChild(document.createElement("div"));
  956. this._elConsole.className = "yui-log-bd";
  957. // If implementer has provided console, trust and set those
  958. if(this.height) {
  959. this._elConsole.style.height = this.height;
  960. }
  961. },
  962. /**
  963. * Initializes the footer element.
  964. *
  965. * @method _initFooterEl
  966. * @private
  967. */
  968. _initFooterEl : function() {
  969. var oSelf = this;
  970. // Don't create footer elements if footer is disabled
  971. if(this.footerEnabled) {
  972. // Destroy console
  973. if(this._elFt) {
  974. // Unhook DOM events
  975. YAHOO.util.Event.purgeElement(this._elFt, true);
  976. // Remove DOM elements
  977. this._elFt.innerHTML = "";
  978. }
  979. this._elFt = this._elContainer.appendChild(document.createElement("div"));
  980. this._elFt.className = "yui-log-ft";
  981. this._elBtns = this._elFt.appendChild(document.createElement("div"));
  982. this._elBtns.className = "yui-log-btns";
  983. this._btnPause = document.createElement("input");
  984. this._btnPause.type = "button";
  985. //this._btnPause.style.fontSize =
  986. // YAHOO.util.Dom.getStyle(this._elContainer,"fontSize");
  987. this._btnPause.className = "yui-log-button";
  988. this._btnPause.value = "Pause";
  989. this._btnPause = this._elBtns.appendChild(this._btnPause);
  990. YAHOO.util.Event.addListener(
  991. oSelf._btnPause,'click',oSelf._onClickPauseBtn,oSelf);
  992. this._btnClear = document.createElement("input");
  993. this._btnClear.type = "button";
  994. //this._btnClear.style.fontSize =
  995. // YAHOO.util.Dom.getStyle(this._elContainer,"fontSize");
  996. this._btnClear.className = "yui-log-button";
  997. this._btnClear.value = "Clear";
  998. this._btnClear = this._elBtns.appendChild(this._btnClear);
  999. YAHOO.util.Event.addListener(
  1000. oSelf._btnClear,'click',oSelf._onClickClearBtn,oSelf);
  1001. this._elCategoryFilters = this._elFt.appendChild(document.createElement("div"));
  1002. this._elCategoryFilters.className = "yui-log-categoryfilters";
  1003. this._elSourceFilters = this._elFt.appendChild(document.createElement("div"));
  1004. this._elSourceFilters.className = "yui-log-sourcefilters";
  1005. }
  1006. },
  1007. /**
  1008. * Initializes Drag and Drop on the header element.
  1009. *
  1010. * @method _initDragDrop
  1011. * @private
  1012. */
  1013. _initDragDrop : function() {
  1014. // If Drag and Drop utility is available...
  1015. // ...and draggable is true...
  1016. // ...then make the header draggable
  1017. if(YAHOO.util.DD && this.draggable && this._elHd) {
  1018. var ylog_dd = new YAHOO.util.DD(this._elContainer);
  1019. ylog_dd.setHandleElId(this._elHd.id);
  1020. //TODO: use class name
  1021. this._elHd.style.cursor = "move";
  1022. }
  1023. },
  1024. /**
  1025. * Initializes category filters.
  1026. *
  1027. * @method _initCategories
  1028. * @private
  1029. */
  1030. _initCategories : function() {
  1031. // Initialize category filters
  1032. this._categoryFilters = [];
  1033. var aInitialCategories = YAHOO.widget.Logger.categories;
  1034. for(var j=0; j < aInitialCategories.length; j++) {
  1035. var sCategory = aInitialCategories[j];
  1036. // Add category to the internal array of filters
  1037. this._categoryFilters.push(sCategory);
  1038. // Add checkbox element if UI is enabled
  1039. if(this._elCategoryFilters) {
  1040. this._createCategoryCheckbox(sCategory);
  1041. }
  1042. }
  1043. },
  1044. /**
  1045. * Initializes source filters.
  1046. *
  1047. * @method _initSources
  1048. * @private
  1049. */
  1050. _initSources : function() {
  1051. // Initialize source filters
  1052. this._sourceFilters = [];
  1053. var aInitialSources = YAHOO.widget.Logger.sources;
  1054. for(var j=0; j < aInitialSources.length; j++) {
  1055. var sSource = aInitialSources[j];
  1056. // Add source to the internal array of filters
  1057. this._sourceFilters.push(sSource);
  1058. // Add checkbox element if UI is enabled
  1059. if(this._elSourceFilters) {
  1060. this._createSourceCheckbox(sSource);
  1061. }
  1062. }
  1063. },
  1064. /**
  1065. * Creates the UI for a category filter in the LogReader footer element.
  1066. *
  1067. * @method _createCategoryCheckbox
  1068. * @param sCategory {String} Category name.
  1069. * @private
  1070. */
  1071. _createCategoryCheckbox : function(sCategory) {
  1072. var oSelf = this;
  1073. if(this._elFt) {
  1074. var elParent = this._elCategoryFilters;
  1075. var elFilter = elParent.appendChild(document.createElement("span"));
  1076. elFilter.className = "yui-log-filtergrp";
  1077. // Append el at the end so IE 5.5 can set "type" attribute
  1078. // and THEN set checked property
  1079. var chkCategory = document.createElement("input");
  1080. chkCategory.id = "yui-log-filter-" + sCategory + this._sName;
  1081. chkCategory.className = "yui-log-filter-" + sCategory;
  1082. chkCategory.type = "checkbox";
  1083. chkCategory.category = sCategory;
  1084. chkCategory = elFilter.appendChild(chkCategory);
  1085. chkCategory.checked = true;
  1086. // Subscribe to the click event
  1087. YAHOO.util.Event.addListener(chkCategory,'click',oSelf._onCheckCategory,oSelf);
  1088. // Create and class the text label
  1089. var lblCategory = elFilter.appendChild(document.createElement("label"));
  1090. lblCategory.htmlFor = chkCategory.id;
  1091. lblCategory.className = sCategory;
  1092. lblCategory.innerHTML = sCategory;
  1093. this._filterCheckboxes[sCategory] = chkCategory;
  1094. }
  1095. },
  1096. /**
  1097. * Creates a checkbox in the LogReader footer element to filter by source.
  1098. *
  1099. * @method _createSourceCheckbox
  1100. * @param sSource {String} Source name.
  1101. * @private
  1102. */
  1103. _createSourceCheckbox : function(sSource) {
  1104. var oSelf = this;
  1105. if(this._elFt) {
  1106. var elParent = this._elSourceFilters;
  1107. var elFilter = elParent.appendChild(document.createElement("span"));
  1108. elFilter.className = "yui-log-filtergrp";
  1109. // Append el at the end so IE 5.5 can set "type" attribute
  1110. // and THEN set checked property
  1111. var chkSource = document.createElement("input");
  1112. chkSource.id = "yui-log-filter" + sSource + this._sName;
  1113. chkSource.className = "yui-log-filter" + sSource;
  1114. chkSource.type = "checkbox";
  1115. chkSource.source = sSource;
  1116. chkSource = elFilter.appendChild(chkSource);
  1117. chkSource.checked = true;
  1118. // Subscribe to the click event
  1119. YAHOO.util.Event.addListener(chkSource,'click',oSelf._onCheckSource,oSelf);
  1120. // Create and class the text label
  1121. var lblSource = elFilter.appendChild(document.createElement("label"));
  1122. lblSource.htmlFor = chkSource.id;
  1123. lblSource.className = sSource;
  1124. lblSource.innerHTML = sSource;
  1125. this._filterCheckboxes[sSource] = chkSource;
  1126. }
  1127. },
  1128. /**
  1129. * Reprints all log messages in the stack through filters.
  1130. *
  1131. * @method _filterLogs
  1132. * @private
  1133. */
  1134. _filterLogs : function() {
  1135. // Reprint stack with new filters
  1136. if (this._elConsole !== null) {
  1137. this.clearConsole();
  1138. this._printToConsole(YAHOO.widget.Logger.getStack());
  1139. }
  1140. },
  1141. /**
  1142. * Sends buffer of log messages to output and clears buffer.
  1143. *
  1144. * @method _printBuffer
  1145. * @private
  1146. */
  1147. _printBuffer : function() {
  1148. this._timeout = null;
  1149. if(this._elConsole !== null) {
  1150. var thresholdMax = this.thresholdMax;
  1151. thresholdMax = (thresholdMax && !isNaN(thresholdMax)) ? thresholdMax : 500;
  1152. if(this._consoleMsgCount < thresholdMax) {
  1153. var entries = [];
  1154. for (var i=0; i<this._buffer.length; i++) {
  1155. entries[i] = this._buffer[i];
  1156. }
  1157. this._buffer = [];
  1158. this._printToConsole(entries);
  1159. }
  1160. else {
  1161. this._filterLogs();
  1162. }
  1163. if(!this.newestOnTop) {
  1164. this._elConsole.scrollTop = this._elConsole.scrollHeight;
  1165. }
  1166. }
  1167. },
  1168. /**
  1169. * Cycles through an array of log messages, and outputs each one to the console
  1170. * if its category has not been filtered out.
  1171. *
  1172. * @method _printToConsole
  1173. * @param aEntries {Object[]} Array of LogMsg objects to output to console.
  1174. * @private
  1175. */
  1176. _printToConsole : function(aEntries) {
  1177. // Manage the number of messages displayed in the console
  1178. var entriesLen = aEntries.length,
  1179. df = document.createDocumentFragment(),
  1180. msgHTML = [],
  1181. thresholdMin = this.thresholdMin,
  1182. sourceFiltersLen = this._sourceFilters.length,
  1183. categoryFiltersLen = this._categoryFilters.length,
  1184. entriesStartIndex,
  1185. i, j, msg, before;
  1186. if(isNaN(thresholdMin) || (thresholdMin > this.thresholdMax)) {
  1187. thresholdMin = 0;
  1188. }
  1189. entriesStartIndex = (entriesLen > thresholdMin) ? (entriesLen - thresholdMin) : 0;
  1190. // Iterate through all log entries
  1191. for(i=entriesStartIndex; i<entriesLen; i++) {
  1192. // Print only the ones that filter through
  1193. var okToPrint = false;
  1194. var okToFilterCats = false;
  1195. // Get log message details
  1196. var entry = aEntries[i];
  1197. var source = entry.source;
  1198. var category = entry.category;
  1199. for(j=0; j<sourceFiltersLen; j++) {
  1200. if(source == this._sourceFilters[j]) {
  1201. okToFilterCats = true;
  1202. break;
  1203. }
  1204. }
  1205. if(okToFilterCats) {
  1206. for(j=0; j<categoryFiltersLen; j++) {
  1207. if(category == this._categoryFilters[j]) {
  1208. okToPrint = true;
  1209. break;
  1210. }
  1211. }
  1212. }
  1213. if(okToPrint) {
  1214. msg = this.formatMsg(entry);
  1215. if (typeof msg === 'string') {
  1216. msgHTML[msgHTML.length] = msg;
  1217. } else {
  1218. df.insertBefore(msg, this.newestOnTop ?
  1219. df.firstChild || null : null);
  1220. }
  1221. this._consoleMsgCount++;
  1222. this._lastTime = entry.time.getTime();
  1223. }
  1224. }
  1225. if (msgHTML.length) {
  1226. msgHTML.splice(0,0,this._elConsole.innerHTML);
  1227. this._elConsole.innerHTML = this.newestOnTop ?
  1228. msgHTML.reverse().join('') :
  1229. msgHTML.join('');
  1230. } else if (df.firstChild) {
  1231. this._elConsole.insertBefore(df, this.newestOnTop ?
  1232. this._elConsole.firstChild || null : null);
  1233. }
  1234. },
  1235. /////////////////////////////////////////////////////////////////////////////
  1236. //
  1237. // Private event handlers
  1238. //
  1239. /////////////////////////////////////////////////////////////////////////////
  1240. /**
  1241. * Handles Logger's categoryCreateEvent.
  1242. *
  1243. * @method _onCategoryCreate
  1244. * @param sType {String} The event.
  1245. * @param aArgs {Object[]} Data passed from event firer.
  1246. * @param oSelf {Object} The LogReader instance.
  1247. * @private
  1248. */
  1249. _onCategoryCreate : function(sType, aArgs, oSelf) {
  1250. var category = aArgs[0];
  1251. // Add category to the internal array of filters
  1252. oSelf._categoryFilters.push(category);
  1253. if(oSelf._elFt) {
  1254. oSelf._createCategoryCheckbox(category);
  1255. }
  1256. },
  1257. /**
  1258. * Handles Logger's sourceCreateEvent.
  1259. *
  1260. * @method _onSourceCreate
  1261. * @param sType {String} The event.
  1262. * @param aArgs {Object[]} Data passed from event firer.
  1263. * @param oSelf {Object} The LogReader instance.
  1264. * @private
  1265. */
  1266. _onSourceCreate : function(sType, aArgs, oSelf) {
  1267. var source = aArgs[0];
  1268. // Add source to the internal array of filters
  1269. oSelf._sourceFilters.push(source);
  1270. if(oSelf._elFt) {
  1271. oSelf._createSourceCheckbox(source);
  1272. }
  1273. },
  1274. /**
  1275. * Handles check events on the category filter checkboxes.
  1276. *
  1277. * @method _onCheckCategory
  1278. * @param v {HTMLEvent} The click event.
  1279. * @param oSelf {Object} The LogReader instance.
  1280. * @private
  1281. */
  1282. _onCheckCategory : function(v, oSelf) {
  1283. var category = this.category;
  1284. if(!this.checked) {
  1285. oSelf.hideCategory(category);
  1286. }
  1287. else {
  1288. oSelf.showCategory(category);
  1289. }
  1290. },
  1291. /**
  1292. * Handles check events on the category filter checkboxes.
  1293. *
  1294. * @method _onCheckSource
  1295. * @param v {HTMLEvent} The click event.
  1296. * @param oSelf {Object} The LogReader instance.
  1297. * @private
  1298. */
  1299. _onCheckSource : function(v, oSelf) {
  1300. var source = this.source;
  1301. if(!this.checked) {
  1302. oSelf.hideSource(source);
  1303. }
  1304. else {
  1305. oSelf.showSource(source);
  1306. }
  1307. },
  1308. /**
  1309. * Handles click events on the collapse button.
  1310. *
  1311. * @method _onClickCollapseBtn
  1312. * @param v {HTMLEvent} The click event.
  1313. * @param oSelf {Object} The LogReader instance
  1314. * @private
  1315. */
  1316. _onClickCollapseBtn : function(v, oSelf) {
  1317. if(!oSelf.isCollapsed) {
  1318. oSelf.collapse();
  1319. }
  1320. else {
  1321. oSelf.expand();
  1322. }
  1323. },
  1324. /**
  1325. * Handles click events on the pause button.
  1326. *
  1327. * @method _onClickPauseBtn
  1328. * @param v {HTMLEvent} The click event.
  1329. * @param oSelf {Object} The LogReader instance.
  1330. * @private
  1331. */
  1332. _onClickPauseBtn : function(v, oSelf) {
  1333. if(!oSelf.isPaused) {
  1334. oSelf.pause();
  1335. }
  1336. else {
  1337. oSelf.resume();
  1338. }
  1339. },
  1340. /**
  1341. * Handles click events on the clear button.
  1342. *
  1343. * @method _onClickClearBtn
  1344. * @param v {HTMLEvent} The click event.
  1345. * @param oSelf {Object} The LogReader instance.
  1346. * @private
  1347. */
  1348. _onClickClearBtn : function(v, oSelf) {
  1349. oSelf.clearConsole();
  1350. },
  1351. /**
  1352. * Handles Logger's newLogEvent.
  1353. *
  1354. * @method _onNewLog
  1355. * @param sType {String} The event.
  1356. * @param aArgs {Object[]} Data passed from event firer.
  1357. * @param oSelf {Object} The LogReader instance.
  1358. * @private
  1359. */
  1360. _onNewLog : function(sType, aArgs, oSelf) {
  1361. var logEntry = aArgs[0];
  1362. oSelf._buffer.push(logEntry);
  1363. if (oSelf.logReaderEnabled === true && oSelf._timeout === null) {
  1364. oSelf._timeout = setTimeout(function(){oSelf._printBuffer();}, oSelf.outputBuffer);
  1365. }
  1366. },
  1367. /**
  1368. * Handles Logger's resetEvent.
  1369. *
  1370. * @method _onReset
  1371. * @param sType {String} The event.
  1372. * @param aArgs {Object[]} Data passed from event firer.
  1373. * @param oSelf {Object} The LogReader instance.
  1374. * @private
  1375. */
  1376. _onReset : function(sType, aArgs, oSelf) {
  1377. oSelf._filterLogs();
  1378. }
  1379. };
  1380. /**
  1381. * The Logger widget provides a simple way to read or write log messages in
  1382. * JavaScript code. Integration with the YUI Library's debug builds allow
  1383. * implementers to access under-the-hood events, errors, and debugging messages.
  1384. * Output may be read through a LogReader console and/or output to a browser
  1385. * console.
  1386. *
  1387. * @module logger
  1388. * @requires yahoo, event, dom
  1389. * @optional dragdrop
  1390. * @namespace YAHOO.widget
  1391. * @title Logger Widget
  1392. */
  1393. /****************************************************************************/
  1394. /****************************************************************************/
  1395. /****************************************************************************/
  1396. // Define once
  1397. if(!YAHOO.widget.Logger) {
  1398. /**
  1399. * The singleton Logger class provides core log management functionality. Saves
  1400. * logs written through the global YAHOO.log function or written by a LogWriter
  1401. * instance. Provides access to logs for reading by a LogReader instance or
  1402. * native browser console such as the Firebug extension to Firefox or Safari's
  1403. * JavaScript console through integration with the console.log() method.
  1404. *
  1405. * @class Logger
  1406. * @static
  1407. */
  1408. YAHOO.widget.Logger = {
  1409. // Initialize properties
  1410. loggerEnabled: true,
  1411. _browserConsoleEnabled: false,
  1412. categories: ["info","warn","error","time","window"],
  1413. sources: ["global"],
  1414. _stack: [], // holds all log msgs
  1415. maxStackEntries: 2500,
  1416. _startTime: new Date().getTime(), // static start timestamp
  1417. _lastTime: null, // timestamp of last logged message
  1418. _windowErrorsHandled: false,
  1419. _origOnWindowError: null
  1420. };
  1421. /////////////////////////////////////////////////////////////////////////////
  1422. //
  1423. // Public properties
  1424. //
  1425. /////////////////////////////////////////////////////////////////////////////
  1426. /**
  1427. * True if Logger is enabled, false otherwise.
  1428. *
  1429. * @property loggerEnabled
  1430. * @type Boolean
  1431. * @static
  1432. * @default true
  1433. */
  1434. /**
  1435. * Array of categories.
  1436. *
  1437. * @property categories
  1438. * @type String[]
  1439. * @static
  1440. * @default ["info","warn","error","time","window"]
  1441. */
  1442. /**
  1443. * Array of sources.
  1444. *
  1445. * @property sources
  1446. * @type String[]
  1447. * @static
  1448. * @default ["global"]
  1449. */
  1450. /**
  1451. * Upper limit on size of internal stack.
  1452. *
  1453. * @property maxStackEntries
  1454. * @type Number
  1455. * @static
  1456. * @default 2500
  1457. */
  1458. /////////////////////////////////////////////////////////////////////////////
  1459. //
  1460. // Private properties
  1461. //
  1462. /////////////////////////////////////////////////////////////////////////////
  1463. /**
  1464. * Internal property to track whether output to browser console is enabled.
  1465. *
  1466. * @property _browserConsoleEnabled
  1467. * @type Boolean
  1468. * @static
  1469. * @default false
  1470. * @private
  1471. */
  1472. /**
  1473. * Array to hold all log messages.
  1474. *
  1475. * @property _stack
  1476. * @type Array
  1477. * @static
  1478. * @private
  1479. */
  1480. /**
  1481. * Static timestamp of Logger initialization.
  1482. *
  1483. * @property _startTime
  1484. * @type Date
  1485. * @static
  1486. * @private
  1487. */
  1488. /**
  1489. * Timestamp of last logged message.
  1490. *
  1491. * @property _lastTime
  1492. * @type Date
  1493. * @static
  1494. * @private
  1495. */
  1496. /////////////////////////////////////////////////////////////////////////////
  1497. //
  1498. // Public methods
  1499. //
  1500. /////////////////////////////////////////////////////////////////////////////
  1501. /**
  1502. * Saves a log message to the stack and fires newLogEvent. If the log message is
  1503. * assigned to an unknown category, creates a new category. If the log message is
  1504. * from an unknown source, creates a new source. If browser console is enabled,
  1505. * outputs the log message to browser console.
  1506. *
  1507. * @method log
  1508. * @param sMsg {String} The log message.
  1509. * @param sCategory {String} Category of log message, or null.
  1510. * @param sSource {String} Source of LogWriter, or null if global.
  1511. */
  1512. YAHOO.widget.Logger.log = function(sMsg, sCategory, sSource) {
  1513. if(this.loggerEnabled) {
  1514. if(!sCategory) {
  1515. sCategory = "info"; // default category
  1516. }
  1517. else {
  1518. sCategory = sCategory.toLocaleLowerCase();
  1519. if(this._isNewCategory(sCategory)) {
  1520. this._createNewCategory(sCategory);
  1521. }
  1522. }
  1523. var sClass = "global"; // default source
  1524. var sDetail = null;
  1525. if(sSource) {
  1526. var spaceIndex = sSource.indexOf(" ");
  1527. if(spaceIndex > 0) {
  1528. // Substring until first space
  1529. sClass = sSource.substring(0,spaceIndex);
  1530. // The rest of the source
  1531. sDetail = sSource.substring(spaceIndex,sSource.length);
  1532. }
  1533. else {
  1534. sClass = sSource;
  1535. }
  1536. if(this._isNewSource(sClass)) {
  1537. this._createNewSource(sClass);
  1538. }
  1539. }
  1540. var timestamp = new Date();
  1541. var logEntry = new YAHOO.widget.LogMsg({
  1542. msg: sMsg,
  1543. time: timestamp,
  1544. category: sCategory,
  1545. source: sClass,
  1546. sourceDetail: sDetail
  1547. });
  1548. var stack = this._stack;
  1549. var maxStackEntries = this.maxStackEntries;
  1550. if(maxStackEntries && !isNaN(maxStackEntries) &&
  1551. (stack.length >= maxStackEntries)) {
  1552. stack.shift();
  1553. }
  1554. stack.push(logEntry);
  1555. this.newLogEvent.fire(logEntry);
  1556. if(this._browserConsoleEnabled) {
  1557. this._printToBrowserConsole(logEntry);
  1558. }
  1559. return true;
  1560. }
  1561. else {
  1562. return false;
  1563. }
  1564. };
  1565. /**
  1566. * Resets internal stack and startTime, enables Logger, and fires logResetEvent.
  1567. *
  1568. * @method reset
  1569. */
  1570. YAHOO.widget.Logger.reset = function() {
  1571. this._stack = [];
  1572. this._startTime = new Date().getTime();
  1573. this.loggerEnabled = true;
  1574. this.log("Logger reset");
  1575. this.logResetEvent.fire();
  1576. };
  1577. /**
  1578. * Public accessor to internal stack of log message objects.
  1579. *
  1580. * @method getStack
  1581. * @return {Object[]} Array of log message objects.
  1582. */
  1583. YAHOO.widget.Logger.getStack = function() {
  1584. return this._stack;
  1585. };
  1586. /**
  1587. * Public accessor to internal start time.
  1588. *
  1589. * @method getStartTime
  1590. * @return {Date} Internal date of when Logger singleton was initialized.
  1591. */
  1592. YAHOO.widget.Logger.getStartTime = function() {
  1593. return this._startTime;
  1594. };
  1595. /**
  1596. * Disables output to the browser's global console.log() function, which is used
  1597. * by the Firebug extension to Firefox as well as Safari.
  1598. *
  1599. * @method disableBrowserConsole
  1600. */
  1601. YAHOO.widget.Logger.disableBrowserConsole = function() {
  1602. YAHOO.log("Logger output to the function console.log() has been disabled.");
  1603. this._browserConsoleEnabled = false;
  1604. };
  1605. /**
  1606. * Enables output to the browser's global console.log() function, which is used
  1607. * by the Firebug extension to Firefox as well as Safari.
  1608. *
  1609. * @method enableBrowserConsole
  1610. */
  1611. YAHOO.widget.Logger.enableBrowserConsole = function() {
  1612. this._browserConsoleEnabled = true;
  1613. YAHOO.log("Logger output to the function console.log() has been enabled.");
  1614. };
  1615. /**
  1616. * Surpresses native JavaScript errors and outputs to console. By default,
  1617. * Logger does not handle JavaScript window error events.
  1618. * NB: Not all browsers support the window.onerror event.
  1619. *
  1620. * @method handleWindowErrors
  1621. */
  1622. YAHOO.widget.Logger.handleWindowErrors = function() {
  1623. if(!YAHOO.widget.Logger._windowErrorsHandled) {
  1624. // Save any previously defined handler to call
  1625. if(window.error) {
  1626. YAHOO.widget.Logger._origOnWindowError = window.onerror;
  1627. }
  1628. window.onerror = YAHOO.widget.Logger._onWindowError;
  1629. YAHOO.widget.Logger._windowErrorsHandled = true;
  1630. YAHOO.log("Logger handling of window.onerror has been enabled.");
  1631. }
  1632. else {
  1633. YAHOO.log("Logger handling of window.onerror had already been enabled.");
  1634. }
  1635. };
  1636. /**
  1637. * Unsurpresses native JavaScript errors. By default,
  1638. * Logger does not handle JavaScript window error events.
  1639. * NB: Not all browsers support the window.onerror event.
  1640. *
  1641. * @method unhandleWindowErrors
  1642. */
  1643. YAHOO.widget.Logger.unhandleWindowErrors = function() {
  1644. if(YAHOO.widget.Logger._windowErrorsHandled) {
  1645. // Revert to any previously defined handler to call
  1646. if(YAHOO.widget.Logger._origOnWindowError) {
  1647. window.onerror = YAHOO.widget.Logger._origOnWindowError;
  1648. YAHOO.widget.Logger._origOnWindowError = null;
  1649. }
  1650. else {
  1651. window.onerror = null;
  1652. }
  1653. YAHOO.widget.Logger._windowErrorsHandled = false;
  1654. YAHOO.log("Logger handling of window.onerror has been disabled.");
  1655. }
  1656. else {
  1657. YAHOO.log("Logger handling of window.onerror had already been disabled.");
  1658. }
  1659. };
  1660. /////////////////////////////////////////////////////////////////////////////
  1661. //
  1662. // Public events
  1663. //
  1664. /////////////////////////////////////////////////////////////////////////////
  1665. /**
  1666. * Fired when a new category has been created.
  1667. *
  1668. * @event categoryCreateEvent
  1669. * @param sCategory {String} Category name.
  1670. */
  1671. YAHOO.widget.Logger.categoryCreateEvent =
  1672. new YAHOO.util.CustomEvent("categoryCreate", this, true);
  1673. /**
  1674. * Fired when a new source has been named.
  1675. *
  1676. * @event sourceCreateEvent
  1677. * @param sSource {String} Source name.
  1678. */
  1679. YAHOO.widget.Logger.sourceCreateEvent =
  1680. new YAHOO.util.CustomEvent("sourceCreate", this, true);
  1681. /**
  1682. * Fired when a new log message has been created.
  1683. *
  1684. * @event newLogEvent
  1685. * @param sMsg {String} Log message.
  1686. */
  1687. YAHOO.widget.Logger.newLogEvent = new YAHOO.util.CustomEvent("newLog", this, true);
  1688. /**
  1689. * Fired when the Logger has been reset has been created.
  1690. *
  1691. * @event logResetEvent
  1692. */
  1693. YAHOO.widget.Logger.logResetEvent = new YAHOO.util.CustomEvent("logReset", this, true);
  1694. /////////////////////////////////////////////////////////////////////////////
  1695. //
  1696. // Private methods
  1697. //
  1698. /////////////////////////////////////////////////////////////////////////////
  1699. /**
  1700. * Creates a new category of log messages and fires categoryCreateEvent.
  1701. *
  1702. * @method _createNewCategory
  1703. * @param sCategory {String} Category name.
  1704. * @private
  1705. */
  1706. YAHOO.widget.Logger._createNewCategory = function(sCategory) {
  1707. this.categories.push(sCategory);
  1708. this.categoryCreateEvent.fire(sCategory);
  1709. };
  1710. /**
  1711. * Checks to see if a category has already been created.
  1712. *
  1713. * @method _isNewCategory
  1714. * @param sCategory {String} Category name.
  1715. * @return {Boolean} Returns true if category is unknown, else returns false.
  1716. * @private
  1717. */
  1718. YAHOO.widget.Logger._isNewCategory = function(sCategory) {
  1719. for(var i=0; i < this.categories.length; i++) {
  1720. if(sCategory == this.categories[i]) {
  1721. return false;
  1722. }
  1723. }
  1724. return true;
  1725. };
  1726. /**
  1727. * Creates a new source of log messages and fires sourceCreateEvent.
  1728. *
  1729. * @method _createNewSource
  1730. * @param sSource {String} Source name.
  1731. * @private
  1732. */
  1733. YAHOO.widget.Logger._createNewSource = function(sSource) {
  1734. this.sources.push(sSource);
  1735. this.sourceCreateEvent.fire(sSource);
  1736. };
  1737. /**
  1738. * Checks to see if a source already exists.
  1739. *
  1740. * @method _isNewSource
  1741. * @param sSource {String} Source name.
  1742. * @return {Boolean} Returns true if source is unknown, else returns false.
  1743. * @private
  1744. */
  1745. YAHOO.widget.Logger._isNewSource = function(sSource) {
  1746. if(sSource) {
  1747. for(var i=0; i < this.sources.length; i++) {
  1748. if(sSource == this.sources[i]) {
  1749. return false;
  1750. }
  1751. }
  1752. return true;
  1753. }
  1754. };
  1755. /**
  1756. * Outputs a log message to global console.log() function.
  1757. *
  1758. * @method _printToBrowserConsole
  1759. * @param oEntry {Object} Log entry object.
  1760. * @private
  1761. */
  1762. YAHOO.widget.Logger._printToBrowserConsole = function(oEntry) {
  1763. if(window.console && console.log) {
  1764. var category = oEntry.category;
  1765. var label = oEntry.category.substring(0,4).toUpperCase();
  1766. var time = oEntry.time;
  1767. var localTime;
  1768. if (time.toLocaleTimeString) {
  1769. localTime = time.toLocaleTimeString();
  1770. }
  1771. else {
  1772. localTime = time.toString();
  1773. }
  1774. var msecs = time.getTime();
  1775. var elapsedTime = (YAHOO.widget.Logger._lastTime) ?
  1776. (msecs - YAHOO.widget.Logger._lastTime) : 0;
  1777. YAHOO.widget.Logger._lastTime = msecs;
  1778. var output =
  1779. localTime + " (" +
  1780. elapsedTime + "ms): " +
  1781. oEntry.source + ": ";
  1782. console.log(output, oEntry.msg);
  1783. }
  1784. };
  1785. /////////////////////////////////////////////////////////////////////////////
  1786. //
  1787. // Private event handlers
  1788. //
  1789. /////////////////////////////////////////////////////////////////////////////
  1790. /**
  1791. * Handles logging of messages due to window error events.
  1792. *
  1793. * @method _onWindowError
  1794. * @param sMsg {String} The error message.
  1795. * @param sUrl {String} URL of the error.
  1796. * @param sLine {String} Line number of the error.
  1797. * @private
  1798. */
  1799. YAHOO.widget.Logger._onWindowError = function(sMsg,sUrl,sLine) {
  1800. // Logger is not in scope of this event handler
  1801. try {
  1802. YAHOO.widget.Logger.log(sMsg+' ('+sUrl+', line '+sLine+')', "window");
  1803. if(YAHOO.widget.Logger._origOnWindowError) {
  1804. YAHOO.widget.Logger._origOnWindowError();
  1805. }
  1806. }
  1807. catch(e) {
  1808. return false;
  1809. }
  1810. };
  1811. /////////////////////////////////////////////////////////////////////////////
  1812. //
  1813. // First log
  1814. //
  1815. /////////////////////////////////////////////////////////////////////////////
  1816. YAHOO.widget.Logger.log("Logger initialized");
  1817. }
  1818. YAHOO.register("logger", YAHOO.widget.Logger, {version: "2.5.1", build: "984"});