[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/2in3/2.9.0/build/yui2-logger/ -> yui2-logger.js (source)

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1