2
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.net/yui/license.txt
7
/****************************************************************************/
8
/****************************************************************************/
9
/****************************************************************************/
12
* The LogMsg class defines a single log message.
16
* @param oConfigs {Object} Object literal of configuration params.
18
YAHOO.widget.LogMsg = function(oConfigs) {
44
* Log source. The first word passed in as the source argument.
52
* Log source detail. The remainder of the string passed in as the source argument, not
53
* including the first word (if any).
55
* @property sourceDetail
58
this.sourceDetail = null;
60
if (oConfigs && (oConfigs.constructor == Object)) {
61
for(var param in oConfigs) {
62
if (oConfigs.hasOwnProperty(param)) {
63
this[param] = oConfigs[param];
69
/****************************************************************************/
70
/****************************************************************************/
71
/****************************************************************************/
74
* The LogWriter class provides a mechanism to log messages through
75
* YAHOO.widget.Logger from a named source.
79
* @param sSource {String} Source of LogWriter instance.
81
YAHOO.widget.LogWriter = function(sSource) {
83
YAHOO.log("Could not instantiate LogWriter due to invalid source.",
84
"error", "LogWriter");
87
this._source = sSource;
90
/////////////////////////////////////////////////////////////////////////////
94
/////////////////////////////////////////////////////////////////////////////
97
* Public accessor to the unique name of the LogWriter instance.
100
* @return {String} Unique name of the LogWriter instance.
102
YAHOO.widget.LogWriter.prototype.toString = function() {
103
return "LogWriter " + this._sSource;
107
* Logs a message attached to the source of the LogWriter.
110
* @param sMsg {String} The log message.
111
* @param sCategory {String} Category name.
113
YAHOO.widget.LogWriter.prototype.log = function(sMsg, sCategory) {
114
YAHOO.widget.Logger.log(sMsg, sCategory, this._source);
118
* Public accessor to get the source name.
121
* @return {String} The LogWriter source.
123
YAHOO.widget.LogWriter.prototype.getSource = function() {
128
* Public accessor to set the source name.
131
* @param sSource {String} Source of LogWriter instance.
133
YAHOO.widget.LogWriter.prototype.setSource = function(sSource) {
135
YAHOO.log("Could not set source due to invalid source.", "error", this.toString());
139
this._source = sSource;
143
/////////////////////////////////////////////////////////////////////////////
145
// Private member variables
147
/////////////////////////////////////////////////////////////////////////////
150
* Source of the LogWriter instance.
156
YAHOO.widget.LogWriter.prototype._source = null;
161
/****************************************************************************/
162
/****************************************************************************/
163
/****************************************************************************/
166
* The LogReader class provides UI to read messages logged to YAHOO.widget.Logger.
170
* @param elContainer {HTMLElement} (optional) DOM element reference of an existing DIV.
171
* @param elContainer {String} (optional) String ID of an existing DIV.
172
* @param oConfigs {Object} (optional) Object literal of configuration params.
174
YAHOO.widget.LogReader = function(elContainer, oConfigs) {
175
this._sName = YAHOO.widget.LogReader._index;
176
YAHOO.widget.LogReader._index++;
179
this._buffer = []; // output buffer
180
this._filterCheckboxes = {}; // pointers to checkboxes
181
this._lastTime = YAHOO.widget.Logger.getStartTime(); // timestamp of last log message to console
183
// Parse config vars here
184
if (oConfigs && (oConfigs.constructor == Object)) {
185
for(var param in oConfigs) {
186
if (oConfigs.hasOwnProperty(param)) {
187
this[param] = oConfigs[param];
192
this._initContainerEl(elContainer);
193
if(!this._elContainer) {
194
YAHOO.log("Could not instantiate LogReader due to an invalid container element " +
195
elContainer, "error", this.toString());
199
this._initHeaderEl();
200
this._initConsoleEl();
201
this._initFooterEl();
203
this._initDragDrop();
205
this._initCategories();
208
// Subscribe to Logger custom events
209
YAHOO.widget.Logger.newLogEvent.subscribe(this._onNewLog, this);
210
YAHOO.widget.Logger.logResetEvent.subscribe(this._onReset, this);
212
YAHOO.widget.Logger.categoryCreateEvent.subscribe(this._onCategoryCreate, this);
213
YAHOO.widget.Logger.sourceCreateEvent.subscribe(this._onSourceCreate, this);
216
YAHOO.log("LogReader initialized", null, this.toString());
219
/////////////////////////////////////////////////////////////////////////////
221
// Static member variables
223
/////////////////////////////////////////////////////////////////////////////
224
YAHOO.lang.augmentObject(YAHOO.widget.LogReader, {
226
* Internal class member to index multiple LogReader instances.
228
* @property _memberName
237
* Node template for the log entries
238
* @property ENTRY_TEMPLATE
240
* @type {HTMLElement}
241
* @default PRE.yui-log-entry element
243
ENTRY_TEMPLATE : (function () {
244
var t = document.createElement('pre');
245
YAHOO.util.Dom.addClass(t,'yui-log-entry');
250
* Template used for innerHTML of verbose entry output.
251
* @property VERBOSE_TEMPLATE
253
* @default "<span class='{category}'>{label}</span>{totalTime}ms (+{elapsedTime}) {localTime}:</p><p>{sourceAndDetail}</p><p>{message}</p>"
255
VERBOSE_TEMPLATE : "<p><span class='{category}'>{label}</span> {totalTime}ms (+{elapsedTime}) {localTime}:</p><p>{sourceAndDetail}</p><p>{message}</p>",
258
* Template used for innerHTML of compact entry output.
259
* @property BASIC_TEMPLATE
261
* @default "<p><span class='{category}'>{label}</span>{totalTime}ms (+{elapsedTime}) {localTime}: {sourceAndDetail}: {message}</p>"
263
BASIC_TEMPLATE : "<p><span class='{category}'>{label}</span> {totalTime}ms (+{elapsedTime}) {localTime}: {sourceAndDetail}: {message}</p>"
266
/////////////////////////////////////////////////////////////////////////////
268
// Public member variables
270
/////////////////////////////////////////////////////////////////////////////
272
YAHOO.widget.LogReader.prototype = {
274
* Whether or not LogReader is enabled to output log messages.
276
* @property logReaderEnabled
280
logReaderEnabled : true,
283
* Public member to access CSS width of the LogReader container.
291
* Public member to access CSS height of the LogReader container.
299
* Public member to access CSS top position of the LogReader container.
307
* Public member to access CSS left position of the LogReader container.
315
* Public member to access CSS right position of the LogReader container.
323
* Public member to access CSS bottom position of the LogReader container.
331
* Public member to access CSS font size of the LogReader container.
339
* Whether or not the footer UI is enabled for the LogReader.
341
* @property footerEnabled
345
footerEnabled : true,
348
* Whether or not output is verbose (more readable). Setting to true will make
349
* output more compact (less readable).
351
* @property verboseOutput
355
verboseOutput : true,
358
* Custom output format for log messages. Defaults to null, which falls
359
* back to verboseOutput param deciding between LogReader.VERBOSE_TEMPLATE
360
* and LogReader.BASIC_TEMPLATE. Use bracketed place holders to mark where
361
* message info should go. Available place holder names include:
365
* <li>sourceAndDetail</li>
368
* <li>elapsedTime</li>
372
* @property entryFormat
379
* Whether or not newest message is printed on top.
381
* @property newestOnTop
387
* Output timeout buffer in milliseconds.
389
* @property outputBuffer
396
* Maximum number of messages a LogReader console will display.
398
* @property thresholdMax
405
* When a LogReader console reaches its thresholdMax, it will clear out messages
406
* and print out the latest thresholdMin number of messages.
408
* @property thresholdMin
415
* True when LogReader is in a collapsed state, false otherwise.
417
* @property isCollapsed
424
* True when LogReader is in a paused state, false otherwise.
433
* Enables draggable LogReader if DragDrop Utility is present.
435
* @property draggable
441
/////////////////////////////////////////////////////////////////////////////
445
/////////////////////////////////////////////////////////////////////////////
448
* Public accessor to the unique name of the LogReader instance.
451
* @return {String} Unique name of the LogReader instance.
453
toString : function() {
454
return "LogReader instance" + this._sName;
457
* Pauses output of log messages. While paused, log messages are not lost, but
458
* get saved to a buffer and then output upon resume of LogReader.
463
this.isPaused = true;
464
this._timeout = null;
465
this.logReaderEnabled = false;
466
if (this._btnPause) {
467
this._btnPause.value = "Resume";
472
* Resumes output of log messages, including outputting any log messages that
473
* have been saved to buffer while paused.
477
resume : function() {
478
this.isPaused = false;
479
this.logReaderEnabled = true;
481
if (this._btnPause) {
482
this._btnPause.value = "Pause";
487
* Hides UI of LogReader. Logging functionality is not disrupted.
492
this._elContainer.style.display = "none";
496
* Shows UI of LogReader. Logging functionality is not disrupted.
501
this._elContainer.style.display = "block";
505
* Collapses UI of LogReader. Logging functionality is not disrupted.
509
collapse : function() {
510
this._elConsole.style.display = "none";
512
this._elFt.style.display = "none";
514
this._btnCollapse.value = "Expand";
515
this.isCollapsed = true;
519
* Expands UI of LogReader. Logging functionality is not disrupted.
523
expand : function() {
524
this._elConsole.style.display = "block";
526
this._elFt.style.display = "block";
528
this._btnCollapse.value = "Collapse";
529
this.isCollapsed = false;
533
* Returns related checkbox element for given filter (i.e., category or source).
535
* @method getCheckbox
536
* @param {String} Category or source name.
537
* @return {Array} Array of all filter checkboxes.
539
getCheckbox : function(filter) {
540
return this._filterCheckboxes[filter];
544
* Returns array of enabled categories.
546
* @method getCategories
547
* @return {String[]} Array of enabled categories.
549
getCategories : function() {
550
return this._categoryFilters;
554
* Shows log messages associated with given category.
556
* @method showCategory
557
* @param {String} Category name.
559
showCategory : function(sCategory) {
560
var filtersArray = this._categoryFilters;
561
// Don't do anything if category is already enabled
562
// Use Array.indexOf if available...
563
if(filtersArray.indexOf) {
564
if(filtersArray.indexOf(sCategory) > -1) {
568
// ...or do it the old-fashioned way
570
for(var i=0; i<filtersArray.length; i++) {
571
if(filtersArray[i] === sCategory){
577
this._categoryFilters.push(sCategory);
579
var elCheckbox = this.getCheckbox(sCategory);
581
elCheckbox.checked = true;
586
* Hides log messages associated with given category.
588
* @method hideCategory
589
* @param {String} Category name.
591
hideCategory : function(sCategory) {
592
var filtersArray = this._categoryFilters;
593
for(var i=0; i<filtersArray.length; i++) {
594
if(sCategory == filtersArray[i]) {
595
filtersArray.splice(i, 1);
600
var elCheckbox = this.getCheckbox(sCategory);
602
elCheckbox.checked = false;
607
* Returns array of enabled sources.
610
* @return {Array} Array of enabled sources.
612
getSources : function() {
613
return this._sourceFilters;
617
* Shows log messages associated with given source.
620
* @param {String} Source name.
622
showSource : function(sSource) {
623
var filtersArray = this._sourceFilters;
624
// Don't do anything if category is already enabled
625
// Use Array.indexOf if available...
626
if(filtersArray.indexOf) {
627
if(filtersArray.indexOf(sSource) > -1) {
631
// ...or do it the old-fashioned way
633
for(var i=0; i<filtersArray.length; i++) {
634
if(sSource == filtersArray[i]){
639
filtersArray.push(sSource);
641
var elCheckbox = this.getCheckbox(sSource);
643
elCheckbox.checked = true;
648
* Hides log messages associated with given source.
651
* @param {String} Source name.
653
hideSource : function(sSource) {
654
var filtersArray = this._sourceFilters;
655
for(var i=0; i<filtersArray.length; i++) {
656
if(sSource == filtersArray[i]) {
657
filtersArray.splice(i, 1);
662
var elCheckbox = this.getCheckbox(sSource);
664
elCheckbox.checked = false;
669
* Does not delete any log messages, but clears all printed log messages from
670
* the console. Log messages will be printed out again if user re-filters. The
671
* static method YAHOO.widget.Logger.reset() should be called in order to
672
* actually delete log messages.
674
* @method clearConsole
676
clearConsole : function() {
677
// Clear the buffer of any pending messages
678
this._timeout = null;
680
this._consoleMsgCount = 0;
682
var elConsole = this._elConsole;
683
elConsole.innerHTML = '';
687
* Updates title to given string.
690
* @param sTitle {String} New title.
692
setTitle : function(sTitle) {
693
this._title.innerHTML = this.html2Text(sTitle);
697
* Gets timestamp of the last log.
699
* @method getLastTime
700
* @return {Date} Timestamp of the last log.
702
getLastTime : function() {
703
return this._lastTime;
706
formatMsg : function (entry) {
707
var Static = YAHOO.widget.LogReader,
708
entryFormat = this.entryFormat || (this.verboseOutput ?
709
Static.VERBOSE_TEMPLATE : Static.BASIC_TEMPLATE),
711
category : entry.category,
713
// Label for color-coded display
714
label : entry.category.substring(0,4).toUpperCase(),
716
sourceAndDetail : entry.sourceDetail ?
717
entry.source + " " + entry.sourceDetail :
720
// Escape HTML entities in the log message itself for output
722
message : this.html2Text(entry.msg || entry.message || '')
726
if (entry.time && entry.time.getTime) {
727
info.localTime = entry.time.toLocaleTimeString ?
728
entry.time.toLocaleTimeString() :
729
entry.time.toString();
731
// Calculate the elapsed time to be from the last item that
732
// passed through the filter, not the absolute previous item
734
info.elapsedTime = entry.time.getTime() - this.getLastTime();
736
info.totalTime = entry.time.getTime() -
737
YAHOO.widget.Logger.getStartTime();
740
var msg = Static.ENTRY_TEMPLATE.cloneNode(true);
741
if (this.verboseOutput) {
742
msg.className += ' yui-log-verbose';
745
// Bug 2061169: Workaround for YAHOO.lang.substitute()
746
msg.innerHTML = entryFormat.replace(/\{(\w+)\}/g, function (x, placeholder) { return (placeholder in info) ? info[placeholder] : ''; });
752
* Converts input chars "<", ">", and "&" to HTML entities.
755
* @param sHtml {String} String to convert.
758
html2Text : function(sHtml) {
761
return sHtml.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
766
/////////////////////////////////////////////////////////////////////////////
768
// Private member variables
770
/////////////////////////////////////////////////////////////////////////////
773
* Name of LogReader instance.
783
* A class member shared by all LogReaders if a container needs to be
784
* created during instantiation. Will be null if a container element never needs to
785
* be created on the fly, such as when the implementer passes in their own element.
787
* @property _elDefaultContainer
791
//YAHOO.widget.LogReader._elDefaultContainer = null;
794
* Buffer of log message objects for batch output.
803
* Number of log messages output to console.
805
* @property _consoleMsgCount
810
_consoleMsgCount : 0,
813
* Date of last output log message.
815
* @property _lastTime
822
* Batched output timeout ID.
831
* Hash of filters and their related checkbox elements.
833
* @property _filterCheckboxes
837
_filterCheckboxes : null,
840
* Array of filters for log message categories.
842
* @property _categoryFilters
846
_categoryFilters : null,
849
* Array of filters for log message sources.
851
* @property _sourceFilters
855
_sourceFilters : null,
858
* LogReader container element.
860
* @property _elContainer
867
* LogReader header element.
876
* LogReader collapse element.
878
* @property _elCollapse
885
* LogReader collapse button element.
887
* @property _btnCollapse
894
* LogReader title header element.
903
* LogReader console element.
905
* @property _elConsole
912
* LogReader footer element.
921
* LogReader buttons container element.
930
* Container element for LogReader category filter checkboxes.
932
* @property _elCategoryFilters
936
_elCategoryFilters : null,
939
* Container element for LogReader source filter checkboxes.
941
* @property _elSourceFilters
945
_elSourceFilters : null,
948
* LogReader pause button element.
950
* @property _btnPause
957
* Clear button element.
959
* @property _btnClear
965
/////////////////////////////////////////////////////////////////////////////
969
/////////////////////////////////////////////////////////////////////////////
972
* Initializes the primary container element.
974
* @method _initContainerEl
975
* @param elContainer {HTMLElement} Container element by reference or string ID.
978
_initContainerEl : function(elContainer) {
979
// Validate container
980
elContainer = YAHOO.util.Dom.get(elContainer);
981
// Attach to existing container...
982
if(elContainer && elContainer.tagName && (elContainer.tagName.toLowerCase() == "div")) {
983
this._elContainer = elContainer;
984
YAHOO.util.Dom.addClass(this._elContainer,"yui-log");
986
// ...or create container from scratch
988
this._elContainer = document.body.appendChild(document.createElement("div"));
989
//this._elContainer.id = "yui-log" + this._sName;
990
YAHOO.util.Dom.addClass(this._elContainer,"yui-log");
991
YAHOO.util.Dom.addClass(this._elContainer,"yui-log-container");
993
//YAHOO.widget.LogReader._elDefaultContainer = this._elContainer;
995
// If implementer has provided container values, trust and set those
996
var containerStyle = this._elContainer.style;
998
containerStyle.width = this.width;
1001
containerStyle.right = this.right;
1004
containerStyle.top = this.top;
1007
containerStyle.left = this.left;
1008
containerStyle.right = "auto";
1011
containerStyle.bottom = this.bottom;
1012
containerStyle.top = "auto";
1015
containerStyle.fontSize = this.fontSize;
1018
if(navigator.userAgent.toLowerCase().indexOf("opera") != -1) {
1019
document.body.style += '';
1025
* Initializes the header element.
1027
* @method _initHeaderEl
1030
_initHeaderEl : function() {
1035
// Unhook DOM events
1036
YAHOO.util.Event.purgeElement(this._elHd, true);
1038
// Remove DOM elements
1039
this._elHd.innerHTML = "";
1043
this._elHd = this._elContainer.appendChild(document.createElement("div"));
1044
this._elHd.id = "yui-log-hd" + this._sName;
1045
this._elHd.className = "yui-log-hd";
1047
this._elCollapse = this._elHd.appendChild(document.createElement("div"));
1048
this._elCollapse.className = "yui-log-btns";
1050
this._btnCollapse = document.createElement("input");
1051
this._btnCollapse.type = "button";
1052
//this._btnCollapse.style.fontSize =
1053
// YAHOO.util.Dom.getStyle(this._elContainer,"fontSize");
1054
this._btnCollapse.className = "yui-log-button";
1055
this._btnCollapse.value = "Collapse";
1056
this._btnCollapse = this._elCollapse.appendChild(this._btnCollapse);
1057
YAHOO.util.Event.addListener(
1058
oSelf._btnCollapse,'click',oSelf._onClickCollapseBtn,oSelf);
1060
this._title = this._elHd.appendChild(document.createElement("h4"));
1061
this._title.innerHTML = "Logger Console";
1065
* Initializes the console element.
1067
* @method _initConsoleEl
1070
_initConsoleEl : function() {
1072
if(this._elConsole) {
1073
// Unhook DOM events
1074
YAHOO.util.Event.purgeElement(this._elConsole, true);
1076
// Remove DOM elements
1077
this._elConsole.innerHTML = "";
1081
this._elConsole = this._elContainer.appendChild(document.createElement("div"));
1082
this._elConsole.className = "yui-log-bd";
1084
// If implementer has provided console, trust and set those
1086
this._elConsole.style.height = this.height;
1091
* Initializes the footer element.
1093
* @method _initFooterEl
1096
_initFooterEl : function() {
1099
// Don't create footer elements if footer is disabled
1100
if(this.footerEnabled) {
1103
// Unhook DOM events
1104
YAHOO.util.Event.purgeElement(this._elFt, true);
1106
// Remove DOM elements
1107
this._elFt.innerHTML = "";
1110
this._elFt = this._elContainer.appendChild(document.createElement("div"));
1111
this._elFt.className = "yui-log-ft";
1113
this._elBtns = this._elFt.appendChild(document.createElement("div"));
1114
this._elBtns.className = "yui-log-btns";
1116
this._btnPause = document.createElement("input");
1117
this._btnPause.type = "button";
1118
//this._btnPause.style.fontSize =
1119
// YAHOO.util.Dom.getStyle(this._elContainer,"fontSize");
1120
this._btnPause.className = "yui-log-button";
1121
this._btnPause.value = "Pause";
1122
this._btnPause = this._elBtns.appendChild(this._btnPause);
1123
YAHOO.util.Event.addListener(
1124
oSelf._btnPause,'click',oSelf._onClickPauseBtn,oSelf);
1126
this._btnClear = document.createElement("input");
1127
this._btnClear.type = "button";
1128
//this._btnClear.style.fontSize =
1129
// YAHOO.util.Dom.getStyle(this._elContainer,"fontSize");
1130
this._btnClear.className = "yui-log-button";
1131
this._btnClear.value = "Clear";
1132
this._btnClear = this._elBtns.appendChild(this._btnClear);
1133
YAHOO.util.Event.addListener(
1134
oSelf._btnClear,'click',oSelf._onClickClearBtn,oSelf);
1136
this._elCategoryFilters = this._elFt.appendChild(document.createElement("div"));
1137
this._elCategoryFilters.className = "yui-log-categoryfilters";
1138
this._elSourceFilters = this._elFt.appendChild(document.createElement("div"));
1139
this._elSourceFilters.className = "yui-log-sourcefilters";
1144
* Initializes Drag and Drop on the header element.
1146
* @method _initDragDrop
1149
_initDragDrop : function() {
1150
// If Drag and Drop utility is available...
1151
// ...and draggable is true...
1152
// ...then make the header draggable
1153
if(YAHOO.util.DD && this.draggable && this._elHd) {
1154
var ylog_dd = new YAHOO.util.DD(this._elContainer);
1155
ylog_dd.setHandleElId(this._elHd.id);
1156
//TODO: use class name
1157
this._elHd.style.cursor = "move";
1162
* Initializes category filters.
1164
* @method _initCategories
1167
_initCategories : function() {
1168
// Initialize category filters
1169
this._categoryFilters = [];
1170
var aInitialCategories = YAHOO.widget.Logger.categories;
1172
for(var j=0; j < aInitialCategories.length; j++) {
1173
var sCategory = aInitialCategories[j];
1175
// Add category to the internal array of filters
1176
this._categoryFilters.push(sCategory);
1178
// Add checkbox element if UI is enabled
1179
if(this._elCategoryFilters) {
1180
this._createCategoryCheckbox(sCategory);
1186
* Initializes source filters.
1188
* @method _initSources
1191
_initSources : function() {
1192
// Initialize source filters
1193
this._sourceFilters = [];
1194
var aInitialSources = YAHOO.widget.Logger.sources;
1196
for(var j=0; j < aInitialSources.length; j++) {
1197
var sSource = aInitialSources[j];
1199
// Add source to the internal array of filters
1200
this._sourceFilters.push(sSource);
1202
// Add checkbox element if UI is enabled
1203
if(this._elSourceFilters) {
1204
this._createSourceCheckbox(sSource);
1210
* Creates the UI for a category filter in the LogReader footer element.
1212
* @method _createCategoryCheckbox
1213
* @param sCategory {String} Category name.
1216
_createCategoryCheckbox : function(sCategory) {
1220
var elParent = this._elCategoryFilters;
1221
var elFilter = elParent.appendChild(document.createElement("span"));
1222
elFilter.className = "yui-log-filtergrp";
1224
// Append el at the end so IE 5.5 can set "type" attribute
1225
// and THEN set checked property
1226
var chkCategory = document.createElement("input");
1227
chkCategory.id = "yui-log-filter-" + sCategory + this._sName;
1228
chkCategory.className = "yui-log-filter-" + sCategory;
1229
chkCategory.type = "checkbox";
1230
chkCategory.category = sCategory;
1231
chkCategory = elFilter.appendChild(chkCategory);
1232
chkCategory.checked = true;
1234
// Subscribe to the click event
1235
YAHOO.util.Event.addListener(chkCategory,'click',oSelf._onCheckCategory,oSelf);
1237
// Create and class the text label
1238
var lblCategory = elFilter.appendChild(document.createElement("label"));
1239
lblCategory.htmlFor = chkCategory.id;
1240
lblCategory.className = sCategory;
1241
lblCategory.innerHTML = sCategory;
1243
this._filterCheckboxes[sCategory] = chkCategory;
1248
* Creates a checkbox in the LogReader footer element to filter by source.
1250
* @method _createSourceCheckbox
1251
* @param sSource {String} Source name.
1254
_createSourceCheckbox : function(sSource) {
1258
var elParent = this._elSourceFilters;
1259
var elFilter = elParent.appendChild(document.createElement("span"));
1260
elFilter.className = "yui-log-filtergrp";
1262
// Append el at the end so IE 5.5 can set "type" attribute
1263
// and THEN set checked property
1264
var chkSource = document.createElement("input");
1265
chkSource.id = "yui-log-filter" + sSource + this._sName;
1266
chkSource.className = "yui-log-filter" + sSource;
1267
chkSource.type = "checkbox";
1268
chkSource.source = sSource;
1269
chkSource = elFilter.appendChild(chkSource);
1270
chkSource.checked = true;
1272
// Subscribe to the click event
1273
YAHOO.util.Event.addListener(chkSource,'click',oSelf._onCheckSource,oSelf);
1275
// Create and class the text label
1276
var lblSource = elFilter.appendChild(document.createElement("label"));
1277
lblSource.htmlFor = chkSource.id;
1278
lblSource.className = sSource;
1279
lblSource.innerHTML = sSource;
1281
this._filterCheckboxes[sSource] = chkSource;
1286
* Reprints all log messages in the stack through filters.
1288
* @method _filterLogs
1291
_filterLogs : function() {
1292
// Reprint stack with new filters
1293
if (this._elConsole !== null) {
1294
this.clearConsole();
1295
this._printToConsole(YAHOO.widget.Logger.getStack());
1300
* Sends buffer of log messages to output and clears buffer.
1302
* @method _printBuffer
1305
_printBuffer : function() {
1306
this._timeout = null;
1308
if(this._elConsole !== null) {
1309
var thresholdMax = this.thresholdMax;
1310
thresholdMax = (thresholdMax && !isNaN(thresholdMax)) ? thresholdMax : 500;
1311
if(this._consoleMsgCount < thresholdMax) {
1313
for (var i=0; i<this._buffer.length; i++) {
1314
entries[i] = this._buffer[i];
1317
this._printToConsole(entries);
1323
if(!this.newestOnTop) {
1324
this._elConsole.scrollTop = this._elConsole.scrollHeight;
1330
* Cycles through an array of log messages, and outputs each one to the console
1331
* if its category has not been filtered out.
1333
* @method _printToConsole
1334
* @param aEntries {Object[]} Array of LogMsg objects to output to console.
1337
_printToConsole : function(aEntries) {
1338
// Manage the number of messages displayed in the console
1339
var entriesLen = aEntries.length,
1340
df = document.createDocumentFragment(),
1342
thresholdMin = this.thresholdMin,
1343
sourceFiltersLen = this._sourceFilters.length,
1344
categoryFiltersLen = this._categoryFilters.length,
1348
if(isNaN(thresholdMin) || (thresholdMin > this.thresholdMax)) {
1351
entriesStartIndex = (entriesLen > thresholdMin) ? (entriesLen - thresholdMin) : 0;
1353
// Iterate through all log entries
1354
for(i=entriesStartIndex; i<entriesLen; i++) {
1355
// Print only the ones that filter through
1356
var okToPrint = false;
1357
var okToFilterCats = false;
1359
// Get log message details
1360
var entry = aEntries[i];
1361
var source = entry.source;
1362
var category = entry.category;
1364
for(j=0; j<sourceFiltersLen; j++) {
1365
if(source == this._sourceFilters[j]) {
1366
okToFilterCats = true;
1370
if(okToFilterCats) {
1371
for(j=0; j<categoryFiltersLen; j++) {
1372
if(category == this._categoryFilters[j]) {
1379
msg = this.formatMsg(entry);
1380
if (typeof msg === 'string') {
1381
msgHTML[msgHTML.length] = msg;
1383
df.insertBefore(msg, this.newestOnTop ?
1384
df.firstChild || null : null);
1386
this._consoleMsgCount++;
1387
this._lastTime = entry.time.getTime();
1391
if (msgHTML.length) {
1392
msgHTML.splice(0,0,this._elConsole.innerHTML);
1393
this._elConsole.innerHTML = this.newestOnTop ?
1394
msgHTML.reverse().join('') :
1396
} else if (df.firstChild) {
1397
this._elConsole.insertBefore(df, this.newestOnTop ?
1398
this._elConsole.firstChild || null : null);
1402
/////////////////////////////////////////////////////////////////////////////
1404
// Private event handlers
1406
/////////////////////////////////////////////////////////////////////////////
1409
* Handles Logger's categoryCreateEvent.
1411
* @method _onCategoryCreate
1412
* @param sType {String} The event.
1413
* @param aArgs {Object[]} Data passed from event firer.
1414
* @param oSelf {Object} The LogReader instance.
1417
_onCategoryCreate : function(sType, aArgs, oSelf) {
1418
var category = aArgs[0];
1420
// Add category to the internal array of filters
1421
oSelf._categoryFilters.push(category);
1424
oSelf._createCategoryCheckbox(category);
1429
* Handles Logger's sourceCreateEvent.
1431
* @method _onSourceCreate
1432
* @param sType {String} The event.
1433
* @param aArgs {Object[]} Data passed from event firer.
1434
* @param oSelf {Object} The LogReader instance.
1437
_onSourceCreate : function(sType, aArgs, oSelf) {
1438
var source = aArgs[0];
1440
// Add source to the internal array of filters
1441
oSelf._sourceFilters.push(source);
1444
oSelf._createSourceCheckbox(source);
1449
* Handles check events on the category filter checkboxes.
1451
* @method _onCheckCategory
1452
* @param v {HTMLEvent} The click event.
1453
* @param oSelf {Object} The LogReader instance.
1456
_onCheckCategory : function(v, oSelf) {
1457
var category = this.category;
1459
oSelf.hideCategory(category);
1462
oSelf.showCategory(category);
1467
* Handles check events on the category filter checkboxes.
1469
* @method _onCheckSource
1470
* @param v {HTMLEvent} The click event.
1471
* @param oSelf {Object} The LogReader instance.
1474
_onCheckSource : function(v, oSelf) {
1475
var source = this.source;
1477
oSelf.hideSource(source);
1480
oSelf.showSource(source);
1485
* Handles click events on the collapse button.
1487
* @method _onClickCollapseBtn
1488
* @param v {HTMLEvent} The click event.
1489
* @param oSelf {Object} The LogReader instance
1492
_onClickCollapseBtn : function(v, oSelf) {
1493
if(!oSelf.isCollapsed) {
1502
* Handles click events on the pause button.
1504
* @method _onClickPauseBtn
1505
* @param v {HTMLEvent} The click event.
1506
* @param oSelf {Object} The LogReader instance.
1509
_onClickPauseBtn : function(v, oSelf) {
1510
if(!oSelf.isPaused) {
1519
* Handles click events on the clear button.
1521
* @method _onClickClearBtn
1522
* @param v {HTMLEvent} The click event.
1523
* @param oSelf {Object} The LogReader instance.
1526
_onClickClearBtn : function(v, oSelf) {
1527
oSelf.clearConsole();
1531
* Handles Logger's newLogEvent.
1534
* @param sType {String} The event.
1535
* @param aArgs {Object[]} Data passed from event firer.
1536
* @param oSelf {Object} The LogReader instance.
1539
_onNewLog : function(sType, aArgs, oSelf) {
1540
var logEntry = aArgs[0];
1541
oSelf._buffer.push(logEntry);
1543
if (oSelf.logReaderEnabled === true && oSelf._timeout === null) {
1544
oSelf._timeout = setTimeout(function(){oSelf._printBuffer();}, oSelf.outputBuffer);
1549
* Handles Logger's resetEvent.
1552
* @param sType {String} The event.
1553
* @param aArgs {Object[]} Data passed from event firer.
1554
* @param oSelf {Object} The LogReader instance.
1557
_onReset : function(sType, aArgs, oSelf) {
1558
oSelf._filterLogs();
1563
* The Logger widget provides a simple way to read or write log messages in
1564
* JavaScript code. Integration with the YUI Library's debug builds allow
1565
* implementers to access under-the-hood events, errors, and debugging messages.
1566
* Output may be read through a LogReader console and/or output to a browser
1570
* @requires yahoo, event, dom
1571
* @optional dragdrop
1572
* @namespace YAHOO.widget
1573
* @title Logger Widget
1576
/****************************************************************************/
1577
/****************************************************************************/
1578
/****************************************************************************/
1581
if(!YAHOO.widget.Logger) {
1583
* The singleton Logger class provides core log management functionality. Saves
1584
* logs written through the global YAHOO.log function or written by a LogWriter
1585
* instance. Provides access to logs for reading by a LogReader instance or
1586
* native browser console such as the Firebug extension to Firefox or Safari's
1587
* JavaScript console through integration with the console.log() method.
1592
YAHOO.widget.Logger = {
1593
// Initialize properties
1594
loggerEnabled: true,
1595
_browserConsoleEnabled: false,
1596
categories: ["info","warn","error","time","window"],
1597
sources: ["global"],
1598
_stack: [], // holds all log msgs
1599
maxStackEntries: 2500,
1600
_startTime: new Date().getTime(), // static start timestamp
1601
_lastTime: null, // timestamp of last logged message
1602
_windowErrorsHandled: false,
1603
_origOnWindowError: null
1606
/////////////////////////////////////////////////////////////////////////////
1608
// Public properties
1610
/////////////////////////////////////////////////////////////////////////////
1612
* True if Logger is enabled, false otherwise.
1614
* @property loggerEnabled
1621
* Array of categories.
1623
* @property categories
1626
* @default ["info","warn","error","time","window"]
1635
* @default ["global"]
1639
* Upper limit on size of internal stack.
1641
* @property maxStackEntries
1647
/////////////////////////////////////////////////////////////////////////////
1649
// Private properties
1651
/////////////////////////////////////////////////////////////////////////////
1653
* Internal property to track whether output to browser console is enabled.
1655
* @property _browserConsoleEnabled
1663
* Array to hold all log messages.
1671
* Static timestamp of Logger initialization.
1673
* @property _startTime
1679
* Timestamp of last logged message.
1681
* @property _lastTime
1686
/////////////////////////////////////////////////////////////////////////////
1690
/////////////////////////////////////////////////////////////////////////////
1692
* Saves a log message to the stack and fires newLogEvent. If the log message is
1693
* assigned to an unknown category, creates a new category. If the log message is
1694
* from an unknown source, creates a new source. If browser console is enabled,
1695
* outputs the log message to browser console.
1698
* @param sMsg {String} The log message.
1699
* @param sCategory {String} Category of log message, or null.
1700
* @param sSource {String} Source of LogWriter, or null if global.
1702
YAHOO.widget.Logger.log = function(sMsg, sCategory, sSource) {
1703
if(this.loggerEnabled) {
1705
sCategory = "info"; // default category
1708
sCategory = sCategory.toLocaleLowerCase();
1709
if(this._isNewCategory(sCategory)) {
1710
this._createNewCategory(sCategory);
1713
var sClass = "global"; // default source
1716
var spaceIndex = sSource.indexOf(" ");
1717
if(spaceIndex > 0) {
1718
// Substring until first space
1719
sClass = sSource.substring(0,spaceIndex);
1720
// The rest of the source
1721
sDetail = sSource.substring(spaceIndex,sSource.length);
1726
if(this._isNewSource(sClass)) {
1727
this._createNewSource(sClass);
1731
var timestamp = new Date();
1732
var logEntry = new YAHOO.widget.LogMsg({
1735
category: sCategory,
1737
sourceDetail: sDetail
1740
var stack = this._stack;
1741
var maxStackEntries = this.maxStackEntries;
1742
if(maxStackEntries && !isNaN(maxStackEntries) &&
1743
(stack.length >= maxStackEntries)) {
1746
stack.push(logEntry);
1747
this.newLogEvent.fire(logEntry);
1749
if(this._browserConsoleEnabled) {
1750
this._printToBrowserConsole(logEntry);
1760
* Resets internal stack and startTime, enables Logger, and fires logResetEvent.
1764
YAHOO.widget.Logger.reset = function() {
1766
this._startTime = new Date().getTime();
1767
this.loggerEnabled = true;
1768
this.log("Logger reset");
1769
this.logResetEvent.fire();
1773
* Public accessor to internal stack of log message objects.
1776
* @return {Object[]} Array of log message objects.
1778
YAHOO.widget.Logger.getStack = function() {
1783
* Public accessor to internal start time.
1785
* @method getStartTime
1786
* @return {Date} Internal date of when Logger singleton was initialized.
1788
YAHOO.widget.Logger.getStartTime = function() {
1789
return this._startTime;
1793
* Disables output to the browser's global console.log() function, which is used
1794
* by the Firebug extension to Firefox as well as Safari.
1796
* @method disableBrowserConsole
1798
YAHOO.widget.Logger.disableBrowserConsole = function() {
1799
YAHOO.log("Logger output to the function console.log() has been disabled.");
1800
this._browserConsoleEnabled = false;
1804
* Enables output to the browser's global console.log() function, which is used
1805
* by the Firebug extension to Firefox as well as Safari.
1807
* @method enableBrowserConsole
1809
YAHOO.widget.Logger.enableBrowserConsole = function() {
1810
this._browserConsoleEnabled = true;
1811
YAHOO.log("Logger output to the function console.log() has been enabled.");
1815
* Surpresses native JavaScript errors and outputs to console. By default,
1816
* Logger does not handle JavaScript window error events.
1817
* NB: Not all browsers support the window.onerror event.
1819
* @method handleWindowErrors
1821
YAHOO.widget.Logger.handleWindowErrors = function() {
1822
if(!YAHOO.widget.Logger._windowErrorsHandled) {
1823
// Save any previously defined handler to call
1825
YAHOO.widget.Logger._origOnWindowError = window.onerror;
1827
window.onerror = YAHOO.widget.Logger._onWindowError;
1828
YAHOO.widget.Logger._windowErrorsHandled = true;
1829
YAHOO.log("Logger handling of window.onerror has been enabled.");
1832
YAHOO.log("Logger handling of window.onerror had already been enabled.");
1837
* Unsurpresses native JavaScript errors. By default,
1838
* Logger does not handle JavaScript window error events.
1839
* NB: Not all browsers support the window.onerror event.
1841
* @method unhandleWindowErrors
1843
YAHOO.widget.Logger.unhandleWindowErrors = function() {
1844
if(YAHOO.widget.Logger._windowErrorsHandled) {
1845
// Revert to any previously defined handler to call
1846
if(YAHOO.widget.Logger._origOnWindowError) {
1847
window.onerror = YAHOO.widget.Logger._origOnWindowError;
1848
YAHOO.widget.Logger._origOnWindowError = null;
1851
window.onerror = null;
1853
YAHOO.widget.Logger._windowErrorsHandled = false;
1854
YAHOO.log("Logger handling of window.onerror has been disabled.");
1857
YAHOO.log("Logger handling of window.onerror had already been disabled.");
1861
/////////////////////////////////////////////////////////////////////////////
1865
/////////////////////////////////////////////////////////////////////////////
1868
* Fired when a new category has been created.
1870
* @event categoryCreateEvent
1871
* @param sCategory {String} Category name.
1873
YAHOO.widget.Logger.categoryCreateEvent =
1874
new YAHOO.util.CustomEvent("categoryCreate", this, true);
1877
* Fired when a new source has been named.
1879
* @event sourceCreateEvent
1880
* @param sSource {String} Source name.
1882
YAHOO.widget.Logger.sourceCreateEvent =
1883
new YAHOO.util.CustomEvent("sourceCreate", this, true);
1886
* Fired when a new log message has been created.
1888
* @event newLogEvent
1889
* @param sMsg {String} Log message.
1891
YAHOO.widget.Logger.newLogEvent = new YAHOO.util.CustomEvent("newLog", this, true);
1894
* Fired when the Logger has been reset has been created.
1896
* @event logResetEvent
1898
YAHOO.widget.Logger.logResetEvent = new YAHOO.util.CustomEvent("logReset", this, true);
1900
/////////////////////////////////////////////////////////////////////////////
1904
/////////////////////////////////////////////////////////////////////////////
1907
* Creates a new category of log messages and fires categoryCreateEvent.
1909
* @method _createNewCategory
1910
* @param sCategory {String} Category name.
1913
YAHOO.widget.Logger._createNewCategory = function(sCategory) {
1914
this.categories.push(sCategory);
1915
this.categoryCreateEvent.fire(sCategory);
1919
* Checks to see if a category has already been created.
1921
* @method _isNewCategory
1922
* @param sCategory {String} Category name.
1923
* @return {Boolean} Returns true if category is unknown, else returns false.
1926
YAHOO.widget.Logger._isNewCategory = function(sCategory) {
1927
for(var i=0; i < this.categories.length; i++) {
1928
if(sCategory == this.categories[i]) {
1936
* Creates a new source of log messages and fires sourceCreateEvent.
1938
* @method _createNewSource
1939
* @param sSource {String} Source name.
1942
YAHOO.widget.Logger._createNewSource = function(sSource) {
1943
this.sources.push(sSource);
1944
this.sourceCreateEvent.fire(sSource);
1948
* Checks to see if a source already exists.
1950
* @method _isNewSource
1951
* @param sSource {String} Source name.
1952
* @return {Boolean} Returns true if source is unknown, else returns false.
1955
YAHOO.widget.Logger._isNewSource = function(sSource) {
1957
for(var i=0; i < this.sources.length; i++) {
1958
if(sSource == this.sources[i]) {
1967
* Outputs a log message to global console.log() function.
1969
* @method _printToBrowserConsole
1970
* @param oEntry {Object} Log entry object.
1973
YAHOO.widget.Logger._printToBrowserConsole = function(oEntry) {
1974
if(window.console && console.log) {
1975
var category = oEntry.category;
1976
var label = oEntry.category.substring(0,4).toUpperCase();
1978
var time = oEntry.time;
1980
if (time.toLocaleTimeString) {
1981
localTime = time.toLocaleTimeString();
1984
localTime = time.toString();
1987
var msecs = time.getTime();
1988
var elapsedTime = (YAHOO.widget.Logger._lastTime) ?
1989
(msecs - YAHOO.widget.Logger._lastTime) : 0;
1990
YAHOO.widget.Logger._lastTime = msecs;
1994
elapsedTime + "ms): " +
1995
oEntry.source + ": ";
1998
if (YAHOO.env.ua.webkit) {
1999
output += oEntry.msg;
2002
console.log(output, oEntry.msg);
2006
/////////////////////////////////////////////////////////////////////////////
2008
// Private event handlers
2010
/////////////////////////////////////////////////////////////////////////////
2013
* Handles logging of messages due to window error events.
2015
* @method _onWindowError
2016
* @param sMsg {String} The error message.
2017
* @param sUrl {String} URL of the error.
2018
* @param sLine {String} Line number of the error.
2021
YAHOO.widget.Logger._onWindowError = function(sMsg,sUrl,sLine) {
2022
// Logger is not in scope of this event handler
2024
YAHOO.widget.Logger.log(sMsg+' ('+sUrl+', line '+sLine+')', "window");
2025
if(YAHOO.widget.Logger._origOnWindowError) {
2026
YAHOO.widget.Logger._origOnWindowError();
2034
/////////////////////////////////////////////////////////////////////////////
2038
/////////////////////////////////////////////////////////////////////////////
2040
YAHOO.widget.Logger.log("Logger initialized");
2044
YAHOO.register("logger", YAHOO.widget.Logger, {version: "2.7.0", build: "1799"});