log4javascript-rails 1.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +25 -0
  3. data/lib/log4javascript-rails.rb +8 -0
  4. data/lib/log4javascript-rails/version.rb +5 -0
  5. data/vendor/assets/javascripts/log4javascript-1.4.6.tar.gz +0 -0
  6. data/vendor/assets/javascripts/log4javascript-1.4.6/changelog.txt +379 -0
  7. data/vendor/assets/javascripts/log4javascript-1.4.6/console.html +263 -0
  8. data/vendor/assets/javascripts/log4javascript-1.4.6/console_uncompressed.html +2279 -0
  9. data/vendor/assets/javascripts/log4javascript-1.4.6/demos/basic.html +159 -0
  10. data/vendor/assets/javascripts/log4javascript-1.4.6/demos/blank.html +4 -0
  11. data/vendor/assets/javascripts/log4javascript-1.4.6/demos/index.html +49 -0
  12. data/vendor/assets/javascripts/log4javascript-1.4.6/demos/inpage.html +174 -0
  13. data/vendor/assets/javascripts/log4javascript-1.4.6/demos/lite.html +148 -0
  14. data/vendor/assets/javascripts/log4javascript-1.4.6/docs/backwardsincompatibilities.html +90 -0
  15. data/vendor/assets/javascripts/log4javascript-1.4.6/docs/distribution.html +87 -0
  16. data/vendor/assets/javascripts/log4javascript-1.4.6/docs/index.html +190 -0
  17. data/vendor/assets/javascripts/log4javascript-1.4.6/docs/lite.html +182 -0
  18. data/vendor/assets/javascripts/log4javascript-1.4.6/docs/manual.html +3198 -0
  19. data/vendor/assets/javascripts/log4javascript-1.4.6/docs/manual_lite.html +383 -0
  20. data/vendor/assets/javascripts/log4javascript-1.4.6/docs/quickstart.html +230 -0
  21. data/vendor/assets/javascripts/log4javascript-1.4.6/docs/whatsnew.html +86 -0
  22. data/vendor/assets/javascripts/log4javascript-1.4.6/examples/demo.html +16 -0
  23. data/vendor/assets/javascripts/log4javascript-1.4.6/examples/example_manual.html +31 -0
  24. data/vendor/assets/javascripts/log4javascript-1.4.6/examples/example_quickstart_1.html +36 -0
  25. data/vendor/assets/javascripts/log4javascript-1.4.6/examples/myloggingservlet.do +0 -0
  26. data/vendor/assets/javascripts/log4javascript-1.4.6/js/console.html +263 -0
  27. data/vendor/assets/javascripts/log4javascript-1.4.6/js/console_uncompressed.html +2279 -0
  28. data/vendor/assets/javascripts/log4javascript-1.4.6/js/liteconsole.html +41 -0
  29. data/vendor/assets/javascripts/log4javascript-1.4.6/js/liteconsole_uncompressed.html +194 -0
  30. data/vendor/assets/javascripts/log4javascript-1.4.6/js/log4javascript.js +274 -0
  31. data/vendor/assets/javascripts/log4javascript-1.4.6/js/log4javascript_lite.js +55 -0
  32. data/vendor/assets/javascripts/log4javascript-1.4.6/js/log4javascript_lite_uncompressed.js +620 -0
  33. data/vendor/assets/javascripts/log4javascript-1.4.6/js/log4javascript_production.js +188 -0
  34. data/vendor/assets/javascripts/log4javascript-1.4.6/js/log4javascript_production_uncompressed.js +2290 -0
  35. data/vendor/assets/javascripts/log4javascript-1.4.6/js/log4javascript_uncompressed.js +5879 -0
  36. data/vendor/assets/javascripts/log4javascript-1.4.6/js/stubs/log4javascript.js +23 -0
  37. data/vendor/assets/javascripts/log4javascript-1.4.6/js/stubs/log4javascript_lite.js +21 -0
  38. data/vendor/assets/javascripts/log4javascript-1.4.6/js/stubs/log4javascript_lite_uncompressed.js +102 -0
  39. data/vendor/assets/javascripts/log4javascript-1.4.6/js/stubs/log4javascript_production.js +22 -0
  40. data/vendor/assets/javascripts/log4javascript-1.4.6/js/stubs/log4javascript_production_uncompressed.js +253 -0
  41. data/vendor/assets/javascripts/log4javascript-1.4.6/js/stubs/log4javascript_uncompressed.js +341 -0
  42. data/vendor/assets/javascripts/log4javascript-1.4.6/js/tests/log4javascript.js +32 -0
  43. data/vendor/assets/javascripts/log4javascript-1.4.6/js/tests/log4javascript_lite.js +16 -0
  44. data/vendor/assets/javascripts/log4javascript-1.4.6/js/tests/log4javascript_lite_uncompressed.js +16 -0
  45. data/vendor/assets/javascripts/log4javascript-1.4.6/js/tests/log4javascript_production.js +28 -0
  46. data/vendor/assets/javascripts/log4javascript-1.4.6/js/tests/log4javascript_production_uncompressed.js +728 -0
  47. data/vendor/assets/javascripts/log4javascript-1.4.6/js/tests/log4javascript_uncompressed.js +862 -0
  48. data/vendor/assets/javascripts/log4javascript-1.4.6/license.txt +201 -0
  49. data/vendor/assets/javascripts/log4javascript-1.4.6/log4javascript.js +274 -0
  50. data/vendor/assets/javascripts/log4javascript-1.4.6/log4javascript_uncompressed.js +5879 -0
  51. data/vendor/assets/javascripts/log4javascript-1.4.6/main.css +300 -0
  52. data/vendor/assets/javascripts/log4javascript-1.4.6/test/index.html +15 -0
  53. data/vendor/assets/javascripts/log4javascript-1.4.6/test/log4javascript.html +16 -0
  54. data/vendor/assets/javascripts/log4javascript-1.4.6/test/log4javascript_lite.html +16 -0
  55. data/vendor/assets/javascripts/log4javascript-1.4.6/test/log4javascript_lite_uncompressed.html +16 -0
  56. data/vendor/assets/javascripts/log4javascript-1.4.6/test/log4javascript_production.html +16 -0
  57. data/vendor/assets/javascripts/log4javascript-1.4.6/test/log4javascript_production_uncompressed.html +16 -0
  58. data/vendor/assets/javascripts/log4javascript-1.4.6/test/log4javascript_uncompressed.html +16 -0
  59. data/vendor/assets/javascripts/log4javascript-1.4.6/test/main.html +16 -0
  60. data/vendor/assets/javascripts/log4javascript-1.4.6/test/tests.css +88 -0
  61. data/vendor/assets/javascripts/log4javascript-1.4.6/test/xntest.js +739 -0
  62. data/vendor/assets/javascripts/log4javascript.js +1 -0
  63. data/vendor/assets/stylesheets/angular-ng-grid-rails.css +439 -0
  64. metadata +107 -0
@@ -0,0 +1,2279 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
3
+ <head>
4
+ <title>log4javascript</title>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+ <!-- Make IE8 behave like IE7, having gone to all the trouble of making IE work -->
7
+ <meta http-equiv="X-UA-Compatible" content="IE=7" />
8
+ <script type="text/javascript">var isIe = false, isIePre7 = false;</script>
9
+ <!--[if IE]><script type="text/javascript">isIe = true</script><![endif]-->
10
+ <!--[if lt IE 7]><script type="text/javascript">isIePre7 = true</script><![endif]-->
11
+ <script type="text/javascript">
12
+ //<![CDATA[
13
+ var loggingEnabled = true;
14
+ var logQueuedEventsTimer = null;
15
+ var logEntries = [];
16
+ var logEntriesAndSeparators = [];
17
+ var logItems = [];
18
+ var renderDelay = 100;
19
+ var unrenderedLogItemsExist = false;
20
+ var rootGroup, currentGroup = null;
21
+ var loaded = false;
22
+ var currentLogItem = null;
23
+ var logMainContainer;
24
+
25
+ function copyProperties(obj, props) {
26
+ for (var i in props) {
27
+ obj[i] = props[i];
28
+ }
29
+ }
30
+
31
+ /*----------------------------------------------------------------*/
32
+
33
+ function LogItem() {
34
+ }
35
+
36
+ LogItem.prototype = {
37
+ mainContainer: null,
38
+ wrappedContainer: null,
39
+ unwrappedContainer: null,
40
+ group: null,
41
+
42
+ appendToLog: function() {
43
+ for (var i = 0, len = this.elementContainers.length; i < len; i++) {
44
+ this.elementContainers[i].appendToLog();
45
+ }
46
+ this.group.update();
47
+ },
48
+
49
+ doRemove: function(doUpdate, removeFromGroup) {
50
+ if (this.rendered) {
51
+ for (var i = 0, len = this.elementContainers.length; i < len; i++) {
52
+ this.elementContainers[i].remove();
53
+ }
54
+ this.unwrappedElementContainer = null;
55
+ this.wrappedElementContainer = null;
56
+ this.mainElementContainer = null;
57
+ }
58
+ if (this.group && removeFromGroup) {
59
+ this.group.removeChild(this, doUpdate);
60
+ }
61
+ if (this === currentLogItem) {
62
+ currentLogItem = null;
63
+ }
64
+ },
65
+
66
+ remove: function(doUpdate, removeFromGroup) {
67
+ this.doRemove(doUpdate, removeFromGroup);
68
+ },
69
+
70
+ render: function() {},
71
+
72
+ accept: function(visitor) {
73
+ visitor.visit(this);
74
+ },
75
+
76
+ getUnwrappedDomContainer: function() {
77
+ return this.group.unwrappedElementContainer.contentDiv;
78
+ },
79
+
80
+ getWrappedDomContainer: function() {
81
+ return this.group.wrappedElementContainer.contentDiv;
82
+ },
83
+
84
+ getMainDomContainer: function() {
85
+ return this.group.mainElementContainer.contentDiv;
86
+ }
87
+ };
88
+
89
+ LogItem.serializedItemKeys = {LOG_ENTRY: 0, GROUP_START: 1, GROUP_END: 2};
90
+
91
+ /*----------------------------------------------------------------*/
92
+
93
+ function LogItemContainerElement() {
94
+ }
95
+
96
+ LogItemContainerElement.prototype = {
97
+ appendToLog: function() {
98
+ var insertBeforeFirst = (newestAtTop && this.containerDomNode.hasChildNodes());
99
+ if (insertBeforeFirst) {
100
+ this.containerDomNode.insertBefore(this.mainDiv, this.containerDomNode.firstChild);
101
+ } else {
102
+ this.containerDomNode.appendChild(this.mainDiv);
103
+ }
104
+ }
105
+ };
106
+
107
+ /*----------------------------------------------------------------*/
108
+
109
+ function SeparatorElementContainer(containerDomNode) {
110
+ this.containerDomNode = containerDomNode;
111
+ this.mainDiv = document.createElement("div");
112
+ this.mainDiv.className = "separator";
113
+ this.mainDiv.innerHTML = "&nbsp;";
114
+ }
115
+
116
+ SeparatorElementContainer.prototype = new LogItemContainerElement();
117
+
118
+ SeparatorElementContainer.prototype.remove = function() {
119
+ this.mainDiv.parentNode.removeChild(this.mainDiv);
120
+ this.mainDiv = null;
121
+ };
122
+
123
+ /*----------------------------------------------------------------*/
124
+
125
+ function Separator() {
126
+ this.rendered = false;
127
+ }
128
+
129
+ Separator.prototype = new LogItem();
130
+
131
+ copyProperties(Separator.prototype, {
132
+ render: function() {
133
+ var containerDomNode = this.group.contentDiv;
134
+ if (isIe) {
135
+ this.unwrappedElementContainer = new SeparatorElementContainer(this.getUnwrappedDomContainer());
136
+ this.wrappedElementContainer = new SeparatorElementContainer(this.getWrappedDomContainer());
137
+ this.elementContainers = [this.unwrappedElementContainer, this.wrappedElementContainer];
138
+ } else {
139
+ this.mainElementContainer = new SeparatorElementContainer(this.getMainDomContainer());
140
+ this.elementContainers = [this.mainElementContainer];
141
+ }
142
+ this.content = this.formattedMessage;
143
+ this.rendered = true;
144
+ }
145
+ });
146
+
147
+ /*----------------------------------------------------------------*/
148
+
149
+ function GroupElementContainer(group, containerDomNode, isRoot, isWrapped) {
150
+ this.group = group;
151
+ this.containerDomNode = containerDomNode;
152
+ this.isRoot = isRoot;
153
+ this.isWrapped = isWrapped;
154
+ this.expandable = false;
155
+
156
+ if (this.isRoot) {
157
+ if (isIe) {
158
+ this.contentDiv = logMainContainer.appendChild(document.createElement("div"));
159
+ this.contentDiv.id = this.isWrapped ? "log_wrapped" : "log_unwrapped";
160
+ } else {
161
+ this.contentDiv = logMainContainer;
162
+ }
163
+ } else {
164
+ var groupElementContainer = this;
165
+
166
+ this.mainDiv = document.createElement("div");
167
+ this.mainDiv.className = "group";
168
+
169
+ this.headingDiv = this.mainDiv.appendChild(document.createElement("div"));
170
+ this.headingDiv.className = "groupheading";
171
+
172
+ this.expander = this.headingDiv.appendChild(document.createElement("span"));
173
+ this.expander.className = "expander unselectable greyedout";
174
+ this.expander.unselectable = true;
175
+ var expanderText = this.group.expanded ? "-" : "+";
176
+ this.expanderTextNode = this.expander.appendChild(document.createTextNode(expanderText));
177
+
178
+ this.headingDiv.appendChild(document.createTextNode(" " + this.group.name));
179
+
180
+ this.contentDiv = this.mainDiv.appendChild(document.createElement("div"));
181
+ var contentCssClass = this.group.expanded ? "expanded" : "collapsed";
182
+ this.contentDiv.className = "groupcontent " + contentCssClass;
183
+
184
+ this.expander.onclick = function() {
185
+ if (groupElementContainer.group.expandable) {
186
+ groupElementContainer.group.toggleExpanded();
187
+ }
188
+ };
189
+ }
190
+ }
191
+
192
+ GroupElementContainer.prototype = new LogItemContainerElement();
193
+
194
+ copyProperties(GroupElementContainer.prototype, {
195
+ toggleExpanded: function() {
196
+ if (!this.isRoot) {
197
+ var oldCssClass, newCssClass, expanderText;
198
+ if (this.group.expanded) {
199
+ newCssClass = "expanded";
200
+ oldCssClass = "collapsed";
201
+ expanderText = "-";
202
+ } else {
203
+ newCssClass = "collapsed";
204
+ oldCssClass = "expanded";
205
+ expanderText = "+";
206
+ }
207
+ replaceClass(this.contentDiv, newCssClass, oldCssClass);
208
+ this.expanderTextNode.nodeValue = expanderText;
209
+ }
210
+ },
211
+
212
+ remove: function() {
213
+ if (!this.isRoot) {
214
+ this.headingDiv = null;
215
+ this.expander.onclick = null;
216
+ this.expander = null;
217
+ this.expanderTextNode = null;
218
+ this.contentDiv = null;
219
+ this.containerDomNode = null;
220
+ this.mainDiv.parentNode.removeChild(this.mainDiv);
221
+ this.mainDiv = null;
222
+ }
223
+ },
224
+
225
+ reverseChildren: function() {
226
+ // Invert the order of the log entries
227
+ var node = null;
228
+
229
+ // Remove all the log container nodes
230
+ var childDomNodes = [];
231
+ while ((node = this.contentDiv.firstChild)) {
232
+ this.contentDiv.removeChild(node);
233
+ childDomNodes.push(node);
234
+ }
235
+
236
+ // Put them all back in reverse order
237
+ while ((node = childDomNodes.pop())) {
238
+ this.contentDiv.appendChild(node);
239
+ }
240
+ },
241
+
242
+ update: function() {
243
+ if (!this.isRoot) {
244
+ if (this.group.expandable) {
245
+ removeClass(this.expander, "greyedout");
246
+ } else {
247
+ addClass(this.expander, "greyedout");
248
+ }
249
+ }
250
+ },
251
+
252
+ clear: function() {
253
+ if (this.isRoot) {
254
+ this.contentDiv.innerHTML = "";
255
+ }
256
+ }
257
+ });
258
+
259
+ /*----------------------------------------------------------------*/
260
+
261
+ function Group(name, isRoot, initiallyExpanded) {
262
+ this.name = name;
263
+ this.group = null;
264
+ this.isRoot = isRoot;
265
+ this.initiallyExpanded = initiallyExpanded;
266
+ this.elementContainers = [];
267
+ this.children = [];
268
+ this.expanded = initiallyExpanded;
269
+ this.rendered = false;
270
+ this.expandable = false;
271
+ }
272
+
273
+ Group.prototype = new LogItem();
274
+
275
+ copyProperties(Group.prototype, {
276
+ addChild: function(logItem) {
277
+ this.children.push(logItem);
278
+ logItem.group = this;
279
+ },
280
+
281
+ render: function() {
282
+ if (isIe) {
283
+ var unwrappedDomContainer, wrappedDomContainer;
284
+ if (this.isRoot) {
285
+ unwrappedDomContainer = logMainContainer;
286
+ wrappedDomContainer = logMainContainer;
287
+ } else {
288
+ unwrappedDomContainer = this.getUnwrappedDomContainer();
289
+ wrappedDomContainer = this.getWrappedDomContainer();
290
+ }
291
+ this.unwrappedElementContainer = new GroupElementContainer(this, unwrappedDomContainer, this.isRoot, false);
292
+ this.wrappedElementContainer = new GroupElementContainer(this, wrappedDomContainer, this.isRoot, true);
293
+ this.elementContainers = [this.unwrappedElementContainer, this.wrappedElementContainer];
294
+ } else {
295
+ var mainDomContainer = this.isRoot ? logMainContainer : this.getMainDomContainer();
296
+ this.mainElementContainer = new GroupElementContainer(this, mainDomContainer, this.isRoot, false);
297
+ this.elementContainers = [this.mainElementContainer];
298
+ }
299
+ this.rendered = true;
300
+ },
301
+
302
+ toggleExpanded: function() {
303
+ this.expanded = !this.expanded;
304
+ for (var i = 0, len = this.elementContainers.length; i < len; i++) {
305
+ this.elementContainers[i].toggleExpanded();
306
+ }
307
+ },
308
+
309
+ expand: function() {
310
+ if (!this.expanded) {
311
+ this.toggleExpanded();
312
+ }
313
+ },
314
+
315
+ accept: function(visitor) {
316
+ visitor.visitGroup(this);
317
+ },
318
+
319
+ reverseChildren: function() {
320
+ if (this.rendered) {
321
+ for (var i = 0, len = this.elementContainers.length; i < len; i++) {
322
+ this.elementContainers[i].reverseChildren();
323
+ }
324
+ }
325
+ },
326
+
327
+ update: function() {
328
+ var previouslyExpandable = this.expandable;
329
+ this.expandable = (this.children.length !== 0);
330
+ if (this.expandable !== previouslyExpandable) {
331
+ for (var i = 0, len = this.elementContainers.length; i < len; i++) {
332
+ this.elementContainers[i].update();
333
+ }
334
+ }
335
+ },
336
+
337
+ flatten: function() {
338
+ var visitor = new GroupFlattener();
339
+ this.accept(visitor);
340
+ return visitor.logEntriesAndSeparators;
341
+ },
342
+
343
+ removeChild: function(child, doUpdate) {
344
+ array_remove(this.children, child);
345
+ child.group = null;
346
+ if (doUpdate) {
347
+ this.update();
348
+ }
349
+ },
350
+
351
+ remove: function(doUpdate, removeFromGroup) {
352
+ for (var i = 0, len = this.children.length; i < len; i++) {
353
+ this.children[i].remove(false, false);
354
+ }
355
+ this.children = [];
356
+ this.update();
357
+ if (this === currentGroup) {
358
+ currentGroup = this.group;
359
+ }
360
+ this.doRemove(doUpdate, removeFromGroup);
361
+ },
362
+
363
+ serialize: function(items) {
364
+ items.push([LogItem.serializedItemKeys.GROUP_START, this.name]);
365
+ for (var i = 0, len = this.children.length; i < len; i++) {
366
+ this.children[i].serialize(items);
367
+ }
368
+ if (this !== currentGroup) {
369
+ items.push([LogItem.serializedItemKeys.GROUP_END]);
370
+ }
371
+ },
372
+
373
+ clear: function() {
374
+ for (var i = 0, len = this.elementContainers.length; i < len; i++) {
375
+ this.elementContainers[i].clear();
376
+ }
377
+ }
378
+ });
379
+
380
+ /*----------------------------------------------------------------*/
381
+
382
+ function LogEntryElementContainer() {
383
+ }
384
+
385
+ LogEntryElementContainer.prototype = new LogItemContainerElement();
386
+
387
+ copyProperties(LogEntryElementContainer.prototype, {
388
+ remove: function() {
389
+ this.doRemove();
390
+ },
391
+
392
+ doRemove: function() {
393
+ this.mainDiv.parentNode.removeChild(this.mainDiv);
394
+ this.mainDiv = null;
395
+ this.contentElement = null;
396
+ this.containerDomNode = null;
397
+ },
398
+
399
+ setContent: function(content, wrappedContent) {
400
+ if (content === this.formattedMessage) {
401
+ this.contentElement.innerHTML = "";
402
+ this.contentElement.appendChild(document.createTextNode(this.formattedMessage));
403
+ } else {
404
+ this.contentElement.innerHTML = content;
405
+ }
406
+ },
407
+
408
+ setSearchMatch: function(isMatch) {
409
+ var oldCssClass = isMatch ? "searchnonmatch" : "searchmatch";
410
+ var newCssClass = isMatch ? "searchmatch" : "searchnonmatch";
411
+ replaceClass(this.mainDiv, newCssClass, oldCssClass);
412
+ },
413
+
414
+ clearSearch: function() {
415
+ removeClass(this.mainDiv, "searchmatch");
416
+ removeClass(this.mainDiv, "searchnonmatch");
417
+ }
418
+ });
419
+
420
+ /*----------------------------------------------------------------*/
421
+
422
+ function LogEntryWrappedElementContainer(logEntry, containerDomNode) {
423
+ this.logEntry = logEntry;
424
+ this.containerDomNode = containerDomNode;
425
+ this.mainDiv = document.createElement("div");
426
+ this.mainDiv.appendChild(document.createTextNode(this.logEntry.formattedMessage));
427
+ this.mainDiv.className = "logentry wrapped " + this.logEntry.level;
428
+ this.contentElement = this.mainDiv;
429
+ }
430
+
431
+ LogEntryWrappedElementContainer.prototype = new LogEntryElementContainer();
432
+
433
+ LogEntryWrappedElementContainer.prototype.setContent = function(content, wrappedContent) {
434
+ if (content === this.formattedMessage) {
435
+ this.contentElement.innerHTML = "";
436
+ this.contentElement.appendChild(document.createTextNode(this.formattedMessage));
437
+ } else {
438
+ this.contentElement.innerHTML = wrappedContent;
439
+ }
440
+ };
441
+
442
+ /*----------------------------------------------------------------*/
443
+
444
+ function LogEntryUnwrappedElementContainer(logEntry, containerDomNode) {
445
+ this.logEntry = logEntry;
446
+ this.containerDomNode = containerDomNode;
447
+ this.mainDiv = document.createElement("div");
448
+ this.mainDiv.className = "logentry unwrapped " + this.logEntry.level;
449
+ this.pre = this.mainDiv.appendChild(document.createElement("pre"));
450
+ this.pre.appendChild(document.createTextNode(this.logEntry.formattedMessage));
451
+ this.pre.className = "unwrapped";
452
+ this.contentElement = this.pre;
453
+ }
454
+
455
+ LogEntryUnwrappedElementContainer.prototype = new LogEntryElementContainer();
456
+
457
+ LogEntryUnwrappedElementContainer.prototype.remove = function() {
458
+ this.doRemove();
459
+ this.pre = null;
460
+ };
461
+
462
+ /*----------------------------------------------------------------*/
463
+
464
+ function LogEntryMainElementContainer(logEntry, containerDomNode) {
465
+ this.logEntry = logEntry;
466
+ this.containerDomNode = containerDomNode;
467
+ this.mainDiv = document.createElement("div");
468
+ this.mainDiv.className = "logentry nonielogentry " + this.logEntry.level;
469
+ this.contentElement = this.mainDiv.appendChild(document.createElement("span"));
470
+ this.contentElement.appendChild(document.createTextNode(this.logEntry.formattedMessage));
471
+ }
472
+
473
+ LogEntryMainElementContainer.prototype = new LogEntryElementContainer();
474
+
475
+ /*----------------------------------------------------------------*/
476
+
477
+ function LogEntry(level, formattedMessage) {
478
+ this.level = level;
479
+ this.formattedMessage = formattedMessage;
480
+ this.rendered = false;
481
+ }
482
+
483
+ LogEntry.prototype = new LogItem();
484
+
485
+ copyProperties(LogEntry.prototype, {
486
+ render: function() {
487
+ var logEntry = this;
488
+ var containerDomNode = this.group.contentDiv;
489
+
490
+ // Support for the CSS attribute white-space in IE for Windows is
491
+ // non-existent pre version 6 and slightly odd in 6, so instead
492
+ // use two different HTML elements
493
+ if (isIe) {
494
+ this.formattedMessage = this.formattedMessage.replace(/\r\n/g, "\r"); // Workaround for IE's treatment of white space
495
+ this.unwrappedElementContainer = new LogEntryUnwrappedElementContainer(this, this.getUnwrappedDomContainer());
496
+ this.wrappedElementContainer = new LogEntryWrappedElementContainer(this, this.getWrappedDomContainer());
497
+ this.elementContainers = [this.unwrappedElementContainer, this.wrappedElementContainer];
498
+ } else {
499
+ this.mainElementContainer = new LogEntryMainElementContainer(this, this.getMainDomContainer());
500
+ this.elementContainers = [this.mainElementContainer];
501
+ }
502
+ this.content = this.formattedMessage;
503
+ this.rendered = true;
504
+ },
505
+
506
+ setContent: function(content, wrappedContent) {
507
+ if (content != this.content) {
508
+ if (isIe && (content !== this.formattedMessage)) {
509
+ content = content.replace(/\r\n/g, "\r"); // Workaround for IE's treatment of white space
510
+ }
511
+ for (var i = 0, len = this.elementContainers.length; i < len; i++) {
512
+ this.elementContainers[i].setContent(content, wrappedContent);
513
+ }
514
+ this.content = content;
515
+ }
516
+ },
517
+
518
+ getSearchMatches: function() {
519
+ var matches = [];
520
+ var i, len;
521
+ if (isIe) {
522
+ var unwrappedEls = getElementsByClass(this.unwrappedElementContainer.mainDiv, "searchterm", "span");
523
+ var wrappedEls = getElementsByClass(this.wrappedElementContainer.mainDiv, "searchterm", "span");
524
+ for (i = 0, len = unwrappedEls.length; i < len; i++) {
525
+ matches[i] = new Match(this.level, null, unwrappedEls[i], wrappedEls[i]);
526
+ }
527
+ } else {
528
+ var els = getElementsByClass(this.mainElementContainer.mainDiv, "searchterm", "span");
529
+ for (i = 0, len = els.length; i < len; i++) {
530
+ matches[i] = new Match(this.level, els[i]);
531
+ }
532
+ }
533
+ return matches;
534
+ },
535
+
536
+ setSearchMatch: function(isMatch) {
537
+ for (var i = 0, len = this.elementContainers.length; i < len; i++) {
538
+ this.elementContainers[i].setSearchMatch(isMatch);
539
+ }
540
+ },
541
+
542
+ clearSearch: function() {
543
+ for (var i = 0, len = this.elementContainers.length; i < len; i++) {
544
+ this.elementContainers[i].clearSearch();
545
+ }
546
+ },
547
+
548
+ accept: function(visitor) {
549
+ visitor.visitLogEntry(this);
550
+ },
551
+
552
+ serialize: function(items) {
553
+ items.push([LogItem.serializedItemKeys.LOG_ENTRY, this.level, this.formattedMessage]);
554
+ }
555
+ });
556
+
557
+ /*----------------------------------------------------------------*/
558
+
559
+ function LogItemVisitor() {
560
+ }
561
+
562
+ LogItemVisitor.prototype = {
563
+ visit: function(logItem) {
564
+ },
565
+
566
+ visitParent: function(logItem) {
567
+ if (logItem.group) {
568
+ logItem.group.accept(this);
569
+ }
570
+ },
571
+
572
+ visitChildren: function(logItem) {
573
+ for (var i = 0, len = logItem.children.length; i < len; i++) {
574
+ logItem.children[i].accept(this);
575
+ }
576
+ },
577
+
578
+ visitLogEntry: function(logEntry) {
579
+ this.visit(logEntry);
580
+ },
581
+
582
+ visitSeparator: function(separator) {
583
+ this.visit(separator);
584
+ },
585
+
586
+ visitGroup: function(group) {
587
+ this.visit(group);
588
+ }
589
+ };
590
+
591
+ /*----------------------------------------------------------------*/
592
+
593
+ function GroupFlattener() {
594
+ this.logEntriesAndSeparators = [];
595
+ }
596
+
597
+ GroupFlattener.prototype = new LogItemVisitor();
598
+
599
+ GroupFlattener.prototype.visitGroup = function(group) {
600
+ this.visitChildren(group);
601
+ };
602
+
603
+ GroupFlattener.prototype.visitLogEntry = function(logEntry) {
604
+ this.logEntriesAndSeparators.push(logEntry);
605
+ };
606
+
607
+ GroupFlattener.prototype.visitSeparator = function(separator) {
608
+ this.logEntriesAndSeparators.push(separator);
609
+ };
610
+
611
+ /*----------------------------------------------------------------*/
612
+
613
+ window.onload = function() {
614
+ // Sort out document.domain
615
+ if (location.search) {
616
+ var queryBits = unescape(location.search).substr(1).split("&"), nameValueBits;
617
+ for (var i = 0, len = queryBits.length; i < len; i++) {
618
+ nameValueBits = queryBits[i].split("=");
619
+ if (nameValueBits[0] == "log4javascript_domain") {
620
+ document.domain = nameValueBits[1];
621
+ break;
622
+ }
623
+ }
624
+ }
625
+
626
+ // Create DOM objects
627
+ logMainContainer = $("log");
628
+ if (isIePre7) {
629
+ addClass(logMainContainer, "oldIe");
630
+ }
631
+
632
+ rootGroup = new Group("root", true);
633
+ rootGroup.render();
634
+ currentGroup = rootGroup;
635
+
636
+ setCommandInputWidth();
637
+ setLogContainerHeight();
638
+ toggleLoggingEnabled();
639
+ toggleSearchEnabled();
640
+ toggleSearchFilter();
641
+ toggleSearchHighlight();
642
+ applyFilters();
643
+ checkAllLevels();
644
+ toggleWrap();
645
+ toggleNewestAtTop();
646
+ toggleScrollToLatest();
647
+ renderQueuedLogItems();
648
+ loaded = true;
649
+ $("command").value = "";
650
+ $("command").autocomplete = "off";
651
+ $("command").onkeydown = function(evt) {
652
+ evt = getEvent(evt);
653
+ if (evt.keyCode == 10 || evt.keyCode == 13) { // Return/Enter
654
+ evalCommandLine();
655
+ stopPropagation(evt);
656
+ } else if (evt.keyCode == 27) { // Escape
657
+ this.value = "";
658
+ this.focus();
659
+ } else if (evt.keyCode == 38 && commandHistory.length > 0) { // Up
660
+ currentCommandIndex = Math.max(0, currentCommandIndex - 1);
661
+ this.value = commandHistory[currentCommandIndex];
662
+ moveCaretToEnd(this);
663
+ } else if (evt.keyCode == 40 && commandHistory.length > 0) { // Down
664
+ currentCommandIndex = Math.min(commandHistory.length - 1, currentCommandIndex + 1);
665
+ this.value = commandHistory[currentCommandIndex];
666
+ moveCaretToEnd(this);
667
+ }
668
+ };
669
+
670
+ // Prevent the keypress moving the caret in Firefox
671
+ $("command").onkeypress = function(evt) {
672
+ evt = getEvent(evt);
673
+ if (evt.keyCode == 38 && commandHistory.length > 0 && evt.preventDefault) { // Up
674
+ evt.preventDefault();
675
+ }
676
+ };
677
+
678
+ // Prevent the keyup event blurring the input in Opera
679
+ $("command").onkeyup = function(evt) {
680
+ evt = getEvent(evt);
681
+ if (evt.keyCode == 27 && evt.preventDefault) { // Up
682
+ evt.preventDefault();
683
+ this.focus();
684
+ }
685
+ };
686
+
687
+ // Add document keyboard shortcuts
688
+ document.onkeydown = function keyEventHandler(evt) {
689
+ evt = getEvent(evt);
690
+ switch (evt.keyCode) {
691
+ case 69: // Ctrl + shift + E: re-execute last command
692
+ if (evt.shiftKey && (evt.ctrlKey || evt.metaKey)) {
693
+ evalLastCommand();
694
+ cancelKeyEvent(evt);
695
+ return false;
696
+ }
697
+ break;
698
+ case 75: // Ctrl + shift + K: focus search
699
+ if (evt.shiftKey && (evt.ctrlKey || evt.metaKey)) {
700
+ focusSearch();
701
+ cancelKeyEvent(evt);
702
+ return false;
703
+ }
704
+ break;
705
+ case 40: // Ctrl + shift + down arrow: focus command line
706
+ case 76: // Ctrl + shift + L: focus command line
707
+ if (evt.shiftKey && (evt.ctrlKey || evt.metaKey)) {
708
+ focusCommandLine();
709
+ cancelKeyEvent(evt);
710
+ return false;
711
+ }
712
+ break;
713
+ }
714
+ };
715
+
716
+ // Workaround to make sure log div starts at the correct size
717
+ setTimeout(setLogContainerHeight, 20);
718
+
719
+ setShowCommandLine(showCommandLine);
720
+ doSearch();
721
+ };
722
+
723
+ window.onunload = function() {
724
+ if (mainWindowExists()) {
725
+ appender.unload();
726
+ }
727
+ appender = null;
728
+ };
729
+
730
+ /*----------------------------------------------------------------*/
731
+
732
+ function toggleLoggingEnabled() {
733
+ setLoggingEnabled($("enableLogging").checked);
734
+ }
735
+
736
+ function setLoggingEnabled(enable) {
737
+ loggingEnabled = enable;
738
+ }
739
+
740
+ var appender = null;
741
+
742
+ function setAppender(appenderParam) {
743
+ appender = appenderParam;
744
+ }
745
+
746
+ function setShowCloseButton(showCloseButton) {
747
+ $("closeButton").style.display = showCloseButton ? "inline" : "none";
748
+ }
749
+
750
+ function setShowHideButton(showHideButton) {
751
+ $("hideButton").style.display = showHideButton ? "inline" : "none";
752
+ }
753
+
754
+ var newestAtTop = false;
755
+
756
+ /*----------------------------------------------------------------*/
757
+
758
+ function LogItemContentReverser() {
759
+ }
760
+
761
+ LogItemContentReverser.prototype = new LogItemVisitor();
762
+
763
+ LogItemContentReverser.prototype.visitGroup = function(group) {
764
+ group.reverseChildren();
765
+ this.visitChildren(group);
766
+ };
767
+
768
+ /*----------------------------------------------------------------*/
769
+
770
+ function setNewestAtTop(isNewestAtTop) {
771
+ var oldNewestAtTop = newestAtTop;
772
+ var i, iLen, j, jLen;
773
+ newestAtTop = Boolean(isNewestAtTop);
774
+ if (oldNewestAtTop != newestAtTop) {
775
+ var visitor = new LogItemContentReverser();
776
+ rootGroup.accept(visitor);
777
+
778
+ // Reassemble the matches array
779
+ if (currentSearch) {
780
+ var currentMatch = currentSearch.matches[currentMatchIndex];
781
+ var matchIndex = 0;
782
+ var matches = [];
783
+ var actOnLogEntry = function(logEntry) {
784
+ var logEntryMatches = logEntry.getSearchMatches();
785
+ for (j = 0, jLen = logEntryMatches.length; j < jLen; j++) {
786
+ matches[matchIndex] = logEntryMatches[j];
787
+ if (currentMatch && logEntryMatches[j].equals(currentMatch)) {
788
+ currentMatchIndex = matchIndex;
789
+ }
790
+ matchIndex++;
791
+ }
792
+ };
793
+ if (newestAtTop) {
794
+ for (i = logEntries.length - 1; i >= 0; i--) {
795
+ actOnLogEntry(logEntries[i]);
796
+ }
797
+ } else {
798
+ for (i = 0, iLen = logEntries.length; i < iLen; i++) {
799
+ actOnLogEntry(logEntries[i]);
800
+ }
801
+ }
802
+ currentSearch.matches = matches;
803
+ if (currentMatch) {
804
+ currentMatch.setCurrent();
805
+ }
806
+ } else if (scrollToLatest) {
807
+ doScrollToLatest();
808
+ }
809
+ }
810
+ $("newestAtTop").checked = isNewestAtTop;
811
+ }
812
+
813
+ function toggleNewestAtTop() {
814
+ var isNewestAtTop = $("newestAtTop").checked;
815
+ setNewestAtTop(isNewestAtTop);
816
+ }
817
+
818
+ var scrollToLatest = true;
819
+
820
+ function setScrollToLatest(isScrollToLatest) {
821
+ scrollToLatest = isScrollToLatest;
822
+ if (scrollToLatest) {
823
+ doScrollToLatest();
824
+ }
825
+ $("scrollToLatest").checked = isScrollToLatest;
826
+ }
827
+
828
+ function toggleScrollToLatest() {
829
+ var isScrollToLatest = $("scrollToLatest").checked;
830
+ setScrollToLatest(isScrollToLatest);
831
+ }
832
+
833
+ function doScrollToLatest() {
834
+ var l = logMainContainer;
835
+ if (typeof l.scrollTop != "undefined") {
836
+ if (newestAtTop) {
837
+ l.scrollTop = 0;
838
+ } else {
839
+ var latestLogEntry = l.lastChild;
840
+ if (latestLogEntry) {
841
+ l.scrollTop = l.scrollHeight;
842
+ }
843
+ }
844
+ }
845
+ }
846
+
847
+ var closeIfOpenerCloses = true;
848
+
849
+ function setCloseIfOpenerCloses(isCloseIfOpenerCloses) {
850
+ closeIfOpenerCloses = isCloseIfOpenerCloses;
851
+ }
852
+
853
+ var maxMessages = null;
854
+
855
+ function setMaxMessages(max) {
856
+ maxMessages = max;
857
+ pruneLogEntries();
858
+ }
859
+
860
+ var showCommandLine = false;
861
+
862
+ function setShowCommandLine(isShowCommandLine) {
863
+ showCommandLine = isShowCommandLine;
864
+ if (loaded) {
865
+ $("commandLine").style.display = showCommandLine ? "block" : "none";
866
+ setCommandInputWidth();
867
+ setLogContainerHeight();
868
+ }
869
+ }
870
+
871
+ function focusCommandLine() {
872
+ if (loaded) {
873
+ $("command").focus();
874
+ }
875
+ }
876
+
877
+ function focusSearch() {
878
+ if (loaded) {
879
+ $("searchBox").focus();
880
+ }
881
+ }
882
+
883
+ function getLogItems() {
884
+ var items = [];
885
+ for (var i = 0, len = logItems.length; i < len; i++) {
886
+ logItems[i].serialize(items);
887
+ }
888
+ return items;
889
+ }
890
+
891
+ function setLogItems(items) {
892
+ var loggingReallyEnabled = loggingEnabled;
893
+ // Temporarily turn logging on
894
+ loggingEnabled = true;
895
+ for (var i = 0, len = items.length; i < len; i++) {
896
+ switch (items[i][0]) {
897
+ case LogItem.serializedItemKeys.LOG_ENTRY:
898
+ log(items[i][1], items[i][2]);
899
+ break;
900
+ case LogItem.serializedItemKeys.GROUP_START:
901
+ group(items[i][1]);
902
+ break;
903
+ case LogItem.serializedItemKeys.GROUP_END:
904
+ groupEnd();
905
+ break;
906
+ }
907
+ }
908
+ loggingEnabled = loggingReallyEnabled;
909
+ }
910
+
911
+ function log(logLevel, formattedMessage) {
912
+ if (loggingEnabled) {
913
+ var logEntry = new LogEntry(logLevel, formattedMessage);
914
+ logEntries.push(logEntry);
915
+ logEntriesAndSeparators.push(logEntry);
916
+ logItems.push(logEntry);
917
+ currentGroup.addChild(logEntry);
918
+ if (loaded) {
919
+ if (logQueuedEventsTimer !== null) {
920
+ clearTimeout(logQueuedEventsTimer);
921
+ }
922
+ logQueuedEventsTimer = setTimeout(renderQueuedLogItems, renderDelay);
923
+ unrenderedLogItemsExist = true;
924
+ }
925
+ }
926
+ }
927
+
928
+ function renderQueuedLogItems() {
929
+ logQueuedEventsTimer = null;
930
+ var pruned = pruneLogEntries();
931
+
932
+ // Render any unrendered log entries and apply the current search to them
933
+ var initiallyHasMatches = currentSearch ? currentSearch.hasMatches() : false;
934
+ for (var i = 0, len = logItems.length; i < len; i++) {
935
+ if (!logItems[i].rendered) {
936
+ logItems[i].render();
937
+ logItems[i].appendToLog();
938
+ if (currentSearch && (logItems[i] instanceof LogEntry)) {
939
+ currentSearch.applyTo(logItems[i]);
940
+ }
941
+ }
942
+ }
943
+ if (currentSearch) {
944
+ if (pruned) {
945
+ if (currentSearch.hasVisibleMatches()) {
946
+ if (currentMatchIndex === null) {
947
+ setCurrentMatchIndex(0);
948
+ }
949
+ displayMatches();
950
+ } else {
951
+ displayNoMatches();
952
+ }
953
+ } else if (!initiallyHasMatches && currentSearch.hasVisibleMatches()) {
954
+ setCurrentMatchIndex(0);
955
+ displayMatches();
956
+ }
957
+ }
958
+ if (scrollToLatest) {
959
+ doScrollToLatest();
960
+ }
961
+ unrenderedLogItemsExist = false;
962
+ }
963
+
964
+ function pruneLogEntries() {
965
+ if ((maxMessages !== null) && (logEntriesAndSeparators.length > maxMessages)) {
966
+ var numberToDelete = logEntriesAndSeparators.length - maxMessages;
967
+ var prunedLogEntries = logEntriesAndSeparators.slice(0, numberToDelete);
968
+ if (currentSearch) {
969
+ currentSearch.removeMatches(prunedLogEntries);
970
+ }
971
+ var group;
972
+ for (var i = 0; i < numberToDelete; i++) {
973
+ group = logEntriesAndSeparators[i].group;
974
+ array_remove(logItems, logEntriesAndSeparators[i]);
975
+ array_remove(logEntries, logEntriesAndSeparators[i]);
976
+ logEntriesAndSeparators[i].remove(true, true);
977
+ if (group.children.length === 0 && group !== currentGroup && group !== rootGroup) {
978
+ array_remove(logItems, group);
979
+ group.remove(true, true);
980
+ }
981
+ }
982
+ logEntriesAndSeparators = array_removeFromStart(logEntriesAndSeparators, numberToDelete);
983
+ return true;
984
+ }
985
+ return false;
986
+ }
987
+
988
+ function group(name, startExpanded) {
989
+ if (loggingEnabled) {
990
+ initiallyExpanded = (typeof startExpanded === "undefined") ? true : Boolean(startExpanded);
991
+ var newGroup = new Group(name, false, initiallyExpanded);
992
+ currentGroup.addChild(newGroup);
993
+ currentGroup = newGroup;
994
+ logItems.push(newGroup);
995
+ if (loaded) {
996
+ if (logQueuedEventsTimer !== null) {
997
+ clearTimeout(logQueuedEventsTimer);
998
+ }
999
+ logQueuedEventsTimer = setTimeout(renderQueuedLogItems, renderDelay);
1000
+ unrenderedLogItemsExist = true;
1001
+ }
1002
+ }
1003
+ }
1004
+
1005
+ function groupEnd() {
1006
+ currentGroup = (currentGroup === rootGroup) ? rootGroup : currentGroup.group;
1007
+ }
1008
+
1009
+ function mainPageReloaded() {
1010
+ currentGroup = rootGroup;
1011
+ var separator = new Separator();
1012
+ logEntriesAndSeparators.push(separator);
1013
+ logItems.push(separator);
1014
+ currentGroup.addChild(separator);
1015
+ }
1016
+
1017
+ function closeWindow() {
1018
+ if (appender && mainWindowExists()) {
1019
+ appender.close(true);
1020
+ } else {
1021
+ window.close();
1022
+ }
1023
+ }
1024
+
1025
+ function hide() {
1026
+ if (appender && mainWindowExists()) {
1027
+ appender.hide();
1028
+ }
1029
+ }
1030
+
1031
+ var mainWindow = window;
1032
+ var windowId = "log4javascriptConsoleWindow_" + new Date().getTime() + "_" + ("" + Math.random()).substr(2);
1033
+
1034
+ function setMainWindow(win) {
1035
+ mainWindow = win;
1036
+ mainWindow[windowId] = window;
1037
+ // If this is a pop-up, poll the opener to see if it's closed
1038
+ if (opener && closeIfOpenerCloses) {
1039
+ pollOpener();
1040
+ }
1041
+ }
1042
+
1043
+ function pollOpener() {
1044
+ if (closeIfOpenerCloses) {
1045
+ if (mainWindowExists()) {
1046
+ setTimeout(pollOpener, 500);
1047
+ } else {
1048
+ closeWindow();
1049
+ }
1050
+ }
1051
+ }
1052
+
1053
+ function mainWindowExists() {
1054
+ try {
1055
+ return (mainWindow && !mainWindow.closed &&
1056
+ mainWindow[windowId] == window);
1057
+ } catch (ex) {}
1058
+ return false;
1059
+ }
1060
+
1061
+ var logLevels = ["TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"];
1062
+
1063
+ function getCheckBox(logLevel) {
1064
+ return $("switch_" + logLevel);
1065
+ }
1066
+
1067
+ function getIeWrappedLogContainer() {
1068
+ return $("log_wrapped");
1069
+ }
1070
+
1071
+ function getIeUnwrappedLogContainer() {
1072
+ return $("log_unwrapped");
1073
+ }
1074
+
1075
+ function applyFilters() {
1076
+ for (var i = 0; i < logLevels.length; i++) {
1077
+ if (getCheckBox(logLevels[i]).checked) {
1078
+ addClass(logMainContainer, logLevels[i]);
1079
+ } else {
1080
+ removeClass(logMainContainer, logLevels[i]);
1081
+ }
1082
+ }
1083
+ updateSearchFromFilters();
1084
+ }
1085
+
1086
+ function toggleAllLevels() {
1087
+ var turnOn = $("switch_ALL").checked;
1088
+ for (var i = 0; i < logLevels.length; i++) {
1089
+ getCheckBox(logLevels[i]).checked = turnOn;
1090
+ if (turnOn) {
1091
+ addClass(logMainContainer, logLevels[i]);
1092
+ } else {
1093
+ removeClass(logMainContainer, logLevels[i]);
1094
+ }
1095
+ }
1096
+ }
1097
+
1098
+ function checkAllLevels() {
1099
+ for (var i = 0; i < logLevels.length; i++) {
1100
+ if (!getCheckBox(logLevels[i]).checked) {
1101
+ getCheckBox("ALL").checked = false;
1102
+ return;
1103
+ }
1104
+ }
1105
+ getCheckBox("ALL").checked = true;
1106
+ }
1107
+
1108
+ function clearLog() {
1109
+ rootGroup.clear();
1110
+ currentGroup = rootGroup;
1111
+ logEntries = [];
1112
+ logItems = [];
1113
+ logEntriesAndSeparators = [];
1114
+ doSearch();
1115
+ }
1116
+
1117
+ function toggleWrap() {
1118
+ var enable = $("wrap").checked;
1119
+ if (enable) {
1120
+ addClass(logMainContainer, "wrap");
1121
+ } else {
1122
+ removeClass(logMainContainer, "wrap");
1123
+ }
1124
+ refreshCurrentMatch();
1125
+ }
1126
+
1127
+ /* ------------------------------------------------------------------- */
1128
+
1129
+ // Search
1130
+
1131
+ var searchTimer = null;
1132
+
1133
+ function scheduleSearch() {
1134
+ try {
1135
+ clearTimeout(searchTimer);
1136
+ } catch (ex) {
1137
+ // Do nothing
1138
+ }
1139
+ searchTimer = setTimeout(doSearch, 500);
1140
+ }
1141
+
1142
+ function Search(searchTerm, isRegex, searchRegex, isCaseSensitive) {
1143
+ this.searchTerm = searchTerm;
1144
+ this.isRegex = isRegex;
1145
+ this.searchRegex = searchRegex;
1146
+ this.isCaseSensitive = isCaseSensitive;
1147
+ this.matches = [];
1148
+ }
1149
+
1150
+ Search.prototype = {
1151
+ hasMatches: function() {
1152
+ return this.matches.length > 0;
1153
+ },
1154
+
1155
+ hasVisibleMatches: function() {
1156
+ if (this.hasMatches()) {
1157
+ for (var i = 0; i < this.matches.length; i++) {
1158
+ if (this.matches[i].isVisible()) {
1159
+ return true;
1160
+ }
1161
+ }
1162
+ }
1163
+ return false;
1164
+ },
1165
+
1166
+ match: function(logEntry) {
1167
+ var entryText = String(logEntry.formattedMessage);
1168
+ var matchesSearch = false;
1169
+ if (this.isRegex) {
1170
+ matchesSearch = this.searchRegex.test(entryText);
1171
+ } else if (this.isCaseSensitive) {
1172
+ matchesSearch = (entryText.indexOf(this.searchTerm) > -1);
1173
+ } else {
1174
+ matchesSearch = (entryText.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1);
1175
+ }
1176
+ return matchesSearch;
1177
+ },
1178
+
1179
+ getNextVisibleMatchIndex: function() {
1180
+ for (var i = currentMatchIndex + 1; i < this.matches.length; i++) {
1181
+ if (this.matches[i].isVisible()) {
1182
+ return i;
1183
+ }
1184
+ }
1185
+ // Start again from the first match
1186
+ for (i = 0; i <= currentMatchIndex; i++) {
1187
+ if (this.matches[i].isVisible()) {
1188
+ return i;
1189
+ }
1190
+ }
1191
+ return -1;
1192
+ },
1193
+
1194
+ getPreviousVisibleMatchIndex: function() {
1195
+ for (var i = currentMatchIndex - 1; i >= 0; i--) {
1196
+ if (this.matches[i].isVisible()) {
1197
+ return i;
1198
+ }
1199
+ }
1200
+ // Start again from the last match
1201
+ for (var i = this.matches.length - 1; i >= currentMatchIndex; i--) {
1202
+ if (this.matches[i].isVisible()) {
1203
+ return i;
1204
+ }
1205
+ }
1206
+ return -1;
1207
+ },
1208
+
1209
+ applyTo: function(logEntry) {
1210
+ var doesMatch = this.match(logEntry);
1211
+ if (doesMatch) {
1212
+ logEntry.group.expand();
1213
+ logEntry.setSearchMatch(true);
1214
+ var logEntryContent;
1215
+ var wrappedLogEntryContent;
1216
+ var searchTermReplacementStartTag = "<span class=\"searchterm\">";
1217
+ var searchTermReplacementEndTag = "<" + "/span>";
1218
+ var preTagName = isIe ? "pre" : "span";
1219
+ var preStartTag = "<" + preTagName + " class=\"pre\">";
1220
+ var preEndTag = "<" + "/" + preTagName + ">";
1221
+ var startIndex = 0;
1222
+ var searchIndex, matchedText, textBeforeMatch;
1223
+ if (this.isRegex) {
1224
+ var flags = this.isCaseSensitive ? "g" : "gi";
1225
+ var capturingRegex = new RegExp("(" + this.searchRegex.source + ")", flags);
1226
+
1227
+ // Replace the search term with temporary tokens for the start and end tags
1228
+ var rnd = ("" + Math.random()).substr(2);
1229
+ var startToken = "%%s" + rnd + "%%";
1230
+ var endToken = "%%e" + rnd + "%%";
1231
+ logEntryContent = logEntry.formattedMessage.replace(capturingRegex, startToken + "$1" + endToken);
1232
+
1233
+ // Escape the HTML to get rid of angle brackets
1234
+ logEntryContent = escapeHtml(logEntryContent);
1235
+
1236
+ // Substitute the proper HTML back in for the search match
1237
+ var result;
1238
+ var searchString = logEntryContent;
1239
+ logEntryContent = "";
1240
+ wrappedLogEntryContent = "";
1241
+ while ((searchIndex = searchString.indexOf(startToken, startIndex)) > -1) {
1242
+ var endTokenIndex = searchString.indexOf(endToken, searchIndex);
1243
+ matchedText = searchString.substring(searchIndex + startToken.length, endTokenIndex);
1244
+ textBeforeMatch = searchString.substring(startIndex, searchIndex);
1245
+ logEntryContent += preStartTag + textBeforeMatch + preEndTag;
1246
+ logEntryContent += searchTermReplacementStartTag + preStartTag + matchedText +
1247
+ preEndTag + searchTermReplacementEndTag;
1248
+ if (isIe) {
1249
+ wrappedLogEntryContent += textBeforeMatch + searchTermReplacementStartTag +
1250
+ matchedText + searchTermReplacementEndTag;
1251
+ }
1252
+ startIndex = endTokenIndex + endToken.length;
1253
+ }
1254
+ logEntryContent += preStartTag + searchString.substr(startIndex) + preEndTag;
1255
+ if (isIe) {
1256
+ wrappedLogEntryContent += searchString.substr(startIndex);
1257
+ }
1258
+ } else {
1259
+ logEntryContent = "";
1260
+ wrappedLogEntryContent = "";
1261
+ var searchTermReplacementLength = searchTermReplacementStartTag.length +
1262
+ this.searchTerm.length + searchTermReplacementEndTag.length;
1263
+ var searchTermLength = this.searchTerm.length;
1264
+ var searchTermLowerCase = this.searchTerm.toLowerCase();
1265
+ var logTextLowerCase = logEntry.formattedMessage.toLowerCase();
1266
+ while ((searchIndex = logTextLowerCase.indexOf(searchTermLowerCase, startIndex)) > -1) {
1267
+ matchedText = escapeHtml(logEntry.formattedMessage.substr(searchIndex, this.searchTerm.length));
1268
+ textBeforeMatch = escapeHtml(logEntry.formattedMessage.substring(startIndex, searchIndex));
1269
+ var searchTermReplacement = searchTermReplacementStartTag +
1270
+ preStartTag + matchedText + preEndTag + searchTermReplacementEndTag;
1271
+ logEntryContent += preStartTag + textBeforeMatch + preEndTag + searchTermReplacement;
1272
+ if (isIe) {
1273
+ wrappedLogEntryContent += textBeforeMatch + searchTermReplacementStartTag +
1274
+ matchedText + searchTermReplacementEndTag;
1275
+ }
1276
+ startIndex = searchIndex + searchTermLength;
1277
+ }
1278
+ var textAfterLastMatch = escapeHtml(logEntry.formattedMessage.substr(startIndex));
1279
+ logEntryContent += preStartTag + textAfterLastMatch + preEndTag;
1280
+ if (isIe) {
1281
+ wrappedLogEntryContent += textAfterLastMatch;
1282
+ }
1283
+ }
1284
+ logEntry.setContent(logEntryContent, wrappedLogEntryContent);
1285
+ var logEntryMatches = logEntry.getSearchMatches();
1286
+ this.matches = this.matches.concat(logEntryMatches);
1287
+ } else {
1288
+ logEntry.setSearchMatch(false);
1289
+ logEntry.setContent(logEntry.formattedMessage, logEntry.formattedMessage);
1290
+ }
1291
+ return doesMatch;
1292
+ },
1293
+
1294
+ removeMatches: function(logEntries) {
1295
+ var matchesToRemoveCount = 0;
1296
+ var currentMatchRemoved = false;
1297
+ var matchesToRemove = [];
1298
+ var i, iLen, j, jLen;
1299
+
1300
+ // Establish the list of matches to be removed
1301
+ for (i = 0, iLen = this.matches.length; i < iLen; i++) {
1302
+ for (j = 0, jLen = logEntries.length; j < jLen; j++) {
1303
+ if (this.matches[i].belongsTo(logEntries[j])) {
1304
+ matchesToRemove.push(this.matches[i]);
1305
+ if (i === currentMatchIndex) {
1306
+ currentMatchRemoved = true;
1307
+ }
1308
+ }
1309
+ }
1310
+ }
1311
+
1312
+ // Set the new current match index if the current match has been deleted
1313
+ // This will be the first match that appears after the first log entry being
1314
+ // deleted, if one exists; otherwise, it's the first match overall
1315
+ var newMatch = currentMatchRemoved ? null : this.matches[currentMatchIndex];
1316
+ if (currentMatchRemoved) {
1317
+ for (i = currentMatchIndex, iLen = this.matches.length; i < iLen; i++) {
1318
+ if (this.matches[i].isVisible() && !array_contains(matchesToRemove, this.matches[i])) {
1319
+ newMatch = this.matches[i];
1320
+ break;
1321
+ }
1322
+ }
1323
+ }
1324
+
1325
+ // Remove the matches
1326
+ for (i = 0, iLen = matchesToRemove.length; i < iLen; i++) {
1327
+ array_remove(this.matches, matchesToRemove[i]);
1328
+ matchesToRemove[i].remove();
1329
+ }
1330
+
1331
+ // Set the new match, if one exists
1332
+ if (this.hasVisibleMatches()) {
1333
+ if (newMatch === null) {
1334
+ setCurrentMatchIndex(0);
1335
+ } else {
1336
+ // Get the index of the new match
1337
+ var newMatchIndex = 0;
1338
+ for (i = 0, iLen = this.matches.length; i < iLen; i++) {
1339
+ if (newMatch === this.matches[i]) {
1340
+ newMatchIndex = i;
1341
+ break;
1342
+ }
1343
+ }
1344
+ setCurrentMatchIndex(newMatchIndex);
1345
+ }
1346
+ } else {
1347
+ currentMatchIndex = null;
1348
+ displayNoMatches();
1349
+ }
1350
+ }
1351
+ };
1352
+
1353
+ function getPageOffsetTop(el, container) {
1354
+ var currentEl = el;
1355
+ var y = 0;
1356
+ while (currentEl && currentEl != container) {
1357
+ y += currentEl.offsetTop;
1358
+ currentEl = currentEl.offsetParent;
1359
+ }
1360
+ return y;
1361
+ }
1362
+
1363
+ function scrollIntoView(el) {
1364
+ var logContainer = logMainContainer;
1365
+ // Check if the whole width of the element is visible and centre if not
1366
+ if (!$("wrap").checked) {
1367
+ var logContainerLeft = logContainer.scrollLeft;
1368
+ var logContainerRight = logContainerLeft + logContainer.offsetWidth;
1369
+ var elLeft = el.offsetLeft;
1370
+ var elRight = elLeft + el.offsetWidth;
1371
+ if (elLeft < logContainerLeft || elRight > logContainerRight) {
1372
+ logContainer.scrollLeft = elLeft - (logContainer.offsetWidth - el.offsetWidth) / 2;
1373
+ }
1374
+ }
1375
+ // Check if the whole height of the element is visible and centre if not
1376
+ var logContainerTop = logContainer.scrollTop;
1377
+ var logContainerBottom = logContainerTop + logContainer.offsetHeight;
1378
+ var elTop = getPageOffsetTop(el) - getToolBarsHeight();
1379
+ var elBottom = elTop + el.offsetHeight;
1380
+ if (elTop < logContainerTop || elBottom > logContainerBottom) {
1381
+ logContainer.scrollTop = elTop - (logContainer.offsetHeight - el.offsetHeight) / 2;
1382
+ }
1383
+ }
1384
+
1385
+ function Match(logEntryLevel, spanInMainDiv, spanInUnwrappedPre, spanInWrappedDiv) {
1386
+ this.logEntryLevel = logEntryLevel;
1387
+ this.spanInMainDiv = spanInMainDiv;
1388
+ if (isIe) {
1389
+ this.spanInUnwrappedPre = spanInUnwrappedPre;
1390
+ this.spanInWrappedDiv = spanInWrappedDiv;
1391
+ }
1392
+ this.mainSpan = isIe ? spanInUnwrappedPre : spanInMainDiv;
1393
+ }
1394
+
1395
+ Match.prototype = {
1396
+ equals: function(match) {
1397
+ return this.mainSpan === match.mainSpan;
1398
+ },
1399
+
1400
+ setCurrent: function() {
1401
+ if (isIe) {
1402
+ addClass(this.spanInUnwrappedPre, "currentmatch");
1403
+ addClass(this.spanInWrappedDiv, "currentmatch");
1404
+ // Scroll the visible one into view
1405
+ var elementToScroll = $("wrap").checked ? this.spanInWrappedDiv : this.spanInUnwrappedPre;
1406
+ scrollIntoView(elementToScroll);
1407
+ } else {
1408
+ addClass(this.spanInMainDiv, "currentmatch");
1409
+ scrollIntoView(this.spanInMainDiv);
1410
+ }
1411
+ },
1412
+
1413
+ belongsTo: function(logEntry) {
1414
+ if (isIe) {
1415
+ return isDescendant(this.spanInUnwrappedPre, logEntry.unwrappedPre);
1416
+ } else {
1417
+ return isDescendant(this.spanInMainDiv, logEntry.mainDiv);
1418
+ }
1419
+ },
1420
+
1421
+ setNotCurrent: function() {
1422
+ if (isIe) {
1423
+ removeClass(this.spanInUnwrappedPre, "currentmatch");
1424
+ removeClass(this.spanInWrappedDiv, "currentmatch");
1425
+ } else {
1426
+ removeClass(this.spanInMainDiv, "currentmatch");
1427
+ }
1428
+ },
1429
+
1430
+ isOrphan: function() {
1431
+ return isOrphan(this.mainSpan);
1432
+ },
1433
+
1434
+ isVisible: function() {
1435
+ return getCheckBox(this.logEntryLevel).checked;
1436
+ },
1437
+
1438
+ remove: function() {
1439
+ if (isIe) {
1440
+ this.spanInUnwrappedPre = null;
1441
+ this.spanInWrappedDiv = null;
1442
+ } else {
1443
+ this.spanInMainDiv = null;
1444
+ }
1445
+ }
1446
+ };
1447
+
1448
+ var currentSearch = null;
1449
+ var currentMatchIndex = null;
1450
+
1451
+ function doSearch() {
1452
+ var searchBox = $("searchBox");
1453
+ var searchTerm = searchBox.value;
1454
+ var isRegex = $("searchRegex").checked;
1455
+ var isCaseSensitive = $("searchCaseSensitive").checked;
1456
+ var i;
1457
+
1458
+ if (searchTerm === "") {
1459
+ $("searchReset").disabled = true;
1460
+ $("searchNav").style.display = "none";
1461
+ removeClass(document.body, "searching");
1462
+ removeClass(searchBox, "hasmatches");
1463
+ removeClass(searchBox, "nomatches");
1464
+ for (i = 0; i < logEntries.length; i++) {
1465
+ logEntries[i].clearSearch();
1466
+ logEntries[i].setContent(logEntries[i].formattedMessage, logEntries[i].formattedMessage);
1467
+ }
1468
+ currentSearch = null;
1469
+ setLogContainerHeight();
1470
+ } else {
1471
+ $("searchReset").disabled = false;
1472
+ $("searchNav").style.display = "block";
1473
+ var searchRegex;
1474
+ var regexValid;
1475
+ if (isRegex) {
1476
+ try {
1477
+ searchRegex = isCaseSensitive ? new RegExp(searchTerm, "g") : new RegExp(searchTerm, "gi");
1478
+ regexValid = true;
1479
+ replaceClass(searchBox, "validregex", "invalidregex");
1480
+ searchBox.title = "Valid regex";
1481
+ } catch (ex) {
1482
+ regexValid = false;
1483
+ replaceClass(searchBox, "invalidregex", "validregex");
1484
+ searchBox.title = "Invalid regex: " + (ex.message ? ex.message : (ex.description ? ex.description : "unknown error"));
1485
+ return;
1486
+ }
1487
+ } else {
1488
+ searchBox.title = "";
1489
+ removeClass(searchBox, "validregex");
1490
+ removeClass(searchBox, "invalidregex");
1491
+ }
1492
+ addClass(document.body, "searching");
1493
+ currentSearch = new Search(searchTerm, isRegex, searchRegex, isCaseSensitive);
1494
+ for (i = 0; i < logEntries.length; i++) {
1495
+ currentSearch.applyTo(logEntries[i]);
1496
+ }
1497
+ setLogContainerHeight();
1498
+
1499
+ // Highlight the first search match
1500
+ if (currentSearch.hasVisibleMatches()) {
1501
+ setCurrentMatchIndex(0);
1502
+ displayMatches();
1503
+ } else {
1504
+ displayNoMatches();
1505
+ }
1506
+ }
1507
+ }
1508
+
1509
+ function updateSearchFromFilters() {
1510
+ if (currentSearch) {
1511
+ if (currentSearch.hasMatches()) {
1512
+ if (currentMatchIndex === null) {
1513
+ currentMatchIndex = 0;
1514
+ }
1515
+ var currentMatch = currentSearch.matches[currentMatchIndex];
1516
+ if (currentMatch.isVisible()) {
1517
+ displayMatches();
1518
+ setCurrentMatchIndex(currentMatchIndex);
1519
+ } else {
1520
+ currentMatch.setNotCurrent();
1521
+ // Find the next visible match, if one exists
1522
+ var nextVisibleMatchIndex = currentSearch.getNextVisibleMatchIndex();
1523
+ if (nextVisibleMatchIndex > -1) {
1524
+ setCurrentMatchIndex(nextVisibleMatchIndex);
1525
+ displayMatches();
1526
+ } else {
1527
+ displayNoMatches();
1528
+ }
1529
+ }
1530
+ } else {
1531
+ displayNoMatches();
1532
+ }
1533
+ }
1534
+ }
1535
+
1536
+ function refreshCurrentMatch() {
1537
+ if (currentSearch && currentSearch.hasVisibleMatches()) {
1538
+ setCurrentMatchIndex(currentMatchIndex);
1539
+ }
1540
+ }
1541
+
1542
+ function displayMatches() {
1543
+ replaceClass($("searchBox"), "hasmatches", "nomatches");
1544
+ $("searchBox").title = "" + currentSearch.matches.length + " matches found";
1545
+ $("searchNav").style.display = "block";
1546
+ setLogContainerHeight();
1547
+ }
1548
+
1549
+ function displayNoMatches() {
1550
+ replaceClass($("searchBox"), "nomatches", "hasmatches");
1551
+ $("searchBox").title = "No matches found";
1552
+ $("searchNav").style.display = "none";
1553
+ setLogContainerHeight();
1554
+ }
1555
+
1556
+ function toggleSearchEnabled(enable) {
1557
+ enable = (typeof enable == "undefined") ? !$("searchDisable").checked : enable;
1558
+ $("searchBox").disabled = !enable;
1559
+ $("searchReset").disabled = !enable;
1560
+ $("searchRegex").disabled = !enable;
1561
+ $("searchNext").disabled = !enable;
1562
+ $("searchPrevious").disabled = !enable;
1563
+ $("searchCaseSensitive").disabled = !enable;
1564
+ $("searchNav").style.display = (enable && ($("searchBox").value !== "") &&
1565
+ currentSearch && currentSearch.hasVisibleMatches()) ?
1566
+ "block" : "none";
1567
+ if (enable) {
1568
+ removeClass($("search"), "greyedout");
1569
+ addClass(document.body, "searching");
1570
+ if ($("searchHighlight").checked) {
1571
+ addClass(logMainContainer, "searchhighlight");
1572
+ } else {
1573
+ removeClass(logMainContainer, "searchhighlight");
1574
+ }
1575
+ if ($("searchFilter").checked) {
1576
+ addClass(logMainContainer, "searchfilter");
1577
+ } else {
1578
+ removeClass(logMainContainer, "searchfilter");
1579
+ }
1580
+ $("searchDisable").checked = !enable;
1581
+ } else {
1582
+ addClass($("search"), "greyedout");
1583
+ removeClass(document.body, "searching");
1584
+ removeClass(logMainContainer, "searchhighlight");
1585
+ removeClass(logMainContainer, "searchfilter");
1586
+ }
1587
+ setLogContainerHeight();
1588
+ }
1589
+
1590
+ function toggleSearchFilter() {
1591
+ var enable = $("searchFilter").checked;
1592
+ if (enable) {
1593
+ addClass(logMainContainer, "searchfilter");
1594
+ } else {
1595
+ removeClass(logMainContainer, "searchfilter");
1596
+ }
1597
+ refreshCurrentMatch();
1598
+ }
1599
+
1600
+ function toggleSearchHighlight() {
1601
+ var enable = $("searchHighlight").checked;
1602
+ if (enable) {
1603
+ addClass(logMainContainer, "searchhighlight");
1604
+ } else {
1605
+ removeClass(logMainContainer, "searchhighlight");
1606
+ }
1607
+ }
1608
+
1609
+ function clearSearch() {
1610
+ $("searchBox").value = "";
1611
+ doSearch();
1612
+ }
1613
+
1614
+ function searchNext() {
1615
+ if (currentSearch !== null && currentMatchIndex !== null) {
1616
+ currentSearch.matches[currentMatchIndex].setNotCurrent();
1617
+ var nextMatchIndex = currentSearch.getNextVisibleMatchIndex();
1618
+ if (nextMatchIndex > currentMatchIndex || confirm("Reached the end of the page. Start from the top?")) {
1619
+ setCurrentMatchIndex(nextMatchIndex);
1620
+ }
1621
+ }
1622
+ }
1623
+
1624
+ function searchPrevious() {
1625
+ if (currentSearch !== null && currentMatchIndex !== null) {
1626
+ currentSearch.matches[currentMatchIndex].setNotCurrent();
1627
+ var previousMatchIndex = currentSearch.getPreviousVisibleMatchIndex();
1628
+ if (previousMatchIndex < currentMatchIndex || confirm("Reached the start of the page. Continue from the bottom?")) {
1629
+ setCurrentMatchIndex(previousMatchIndex);
1630
+ }
1631
+ }
1632
+ }
1633
+
1634
+ function setCurrentMatchIndex(index) {
1635
+ currentMatchIndex = index;
1636
+ currentSearch.matches[currentMatchIndex].setCurrent();
1637
+ }
1638
+
1639
+ /* ------------------------------------------------------------------------- */
1640
+
1641
+ // CSS Utilities
1642
+
1643
+ function addClass(el, cssClass) {
1644
+ if (!hasClass(el, cssClass)) {
1645
+ if (el.className) {
1646
+ el.className += " " + cssClass;
1647
+ } else {
1648
+ el.className = cssClass;
1649
+ }
1650
+ }
1651
+ }
1652
+
1653
+ function hasClass(el, cssClass) {
1654
+ if (el.className) {
1655
+ var classNames = el.className.split(" ");
1656
+ return array_contains(classNames, cssClass);
1657
+ }
1658
+ return false;
1659
+ }
1660
+
1661
+ function removeClass(el, cssClass) {
1662
+ if (hasClass(el, cssClass)) {
1663
+ // Rebuild the className property
1664
+ var existingClasses = el.className.split(" ");
1665
+ var newClasses = [];
1666
+ for (var i = 0, len = existingClasses.length; i < len; i++) {
1667
+ if (existingClasses[i] != cssClass) {
1668
+ newClasses[newClasses.length] = existingClasses[i];
1669
+ }
1670
+ }
1671
+ el.className = newClasses.join(" ");
1672
+ }
1673
+ }
1674
+
1675
+ function replaceClass(el, newCssClass, oldCssClass) {
1676
+ removeClass(el, oldCssClass);
1677
+ addClass(el, newCssClass);
1678
+ }
1679
+
1680
+ /* ------------------------------------------------------------------------- */
1681
+
1682
+ // Other utility functions
1683
+
1684
+ function getElementsByClass(el, cssClass, tagName) {
1685
+ var elements = el.getElementsByTagName(tagName);
1686
+ var matches = [];
1687
+ for (var i = 0, len = elements.length; i < len; i++) {
1688
+ if (hasClass(elements[i], cssClass)) {
1689
+ matches.push(elements[i]);
1690
+ }
1691
+ }
1692
+ return matches;
1693
+ }
1694
+
1695
+ // Syntax borrowed from Prototype library
1696
+ function $(id) {
1697
+ return document.getElementById(id);
1698
+ }
1699
+
1700
+ function isDescendant(node, ancestorNode) {
1701
+ while (node != null) {
1702
+ if (node === ancestorNode) {
1703
+ return true;
1704
+ }
1705
+ node = node.parentNode;
1706
+ }
1707
+ return false;
1708
+ }
1709
+
1710
+ function isOrphan(node) {
1711
+ var currentNode = node;
1712
+ while (currentNode) {
1713
+ if (currentNode == document.body) {
1714
+ return false;
1715
+ }
1716
+ currentNode = currentNode.parentNode;
1717
+ }
1718
+ return true;
1719
+ }
1720
+
1721
+ function escapeHtml(str) {
1722
+ return str.replace(/&/g, "&amp;").replace(/[<]/g, "&lt;").replace(/>/g, "&gt;");
1723
+ }
1724
+
1725
+ function getWindowWidth() {
1726
+ if (window.innerWidth) {
1727
+ return window.innerWidth;
1728
+ } else if (document.documentElement && document.documentElement.clientWidth) {
1729
+ return document.documentElement.clientWidth;
1730
+ } else if (document.body) {
1731
+ return document.body.clientWidth;
1732
+ }
1733
+ return 0;
1734
+ }
1735
+
1736
+ function getWindowHeight() {
1737
+ if (window.innerHeight) {
1738
+ return window.innerHeight;
1739
+ } else if (document.documentElement && document.documentElement.clientHeight) {
1740
+ return document.documentElement.clientHeight;
1741
+ } else if (document.body) {
1742
+ return document.body.clientHeight;
1743
+ }
1744
+ return 0;
1745
+ }
1746
+
1747
+ function getToolBarsHeight() {
1748
+ return $("switches").offsetHeight;
1749
+ }
1750
+
1751
+ function getChromeHeight() {
1752
+ var height = getToolBarsHeight();
1753
+ if (showCommandLine) {
1754
+ height += $("commandLine").offsetHeight;
1755
+ }
1756
+ return height;
1757
+ }
1758
+
1759
+ function setLogContainerHeight() {
1760
+ if (logMainContainer) {
1761
+ var windowHeight = getWindowHeight();
1762
+ $("body").style.height = getWindowHeight() + "px";
1763
+ logMainContainer.style.height = "" +
1764
+ Math.max(0, windowHeight - getChromeHeight()) + "px";
1765
+ }
1766
+ }
1767
+
1768
+ function setCommandInputWidth() {
1769
+ if (showCommandLine) {
1770
+ $("command").style.width = "" + Math.max(0, $("commandLineContainer").offsetWidth -
1771
+ ($("evaluateButton").offsetWidth + 13)) + "px";
1772
+ }
1773
+ }
1774
+
1775
+ window.onresize = function() {
1776
+ setCommandInputWidth();
1777
+ setLogContainerHeight();
1778
+ };
1779
+
1780
+ if (!Array.prototype.push) {
1781
+ Array.prototype.push = function() {
1782
+ for (var i = 0, len = arguments.length; i < len; i++){
1783
+ this[this.length] = arguments[i];
1784
+ }
1785
+ return this.length;
1786
+ };
1787
+ }
1788
+
1789
+ if (!Array.prototype.pop) {
1790
+ Array.prototype.pop = function() {
1791
+ if (this.length > 0) {
1792
+ var val = this[this.length - 1];
1793
+ this.length = this.length - 1;
1794
+ return val;
1795
+ }
1796
+ };
1797
+ }
1798
+
1799
+ if (!Array.prototype.shift) {
1800
+ Array.prototype.shift = function() {
1801
+ if (this.length > 0) {
1802
+ var firstItem = this[0];
1803
+ for (var i = 0, len = this.length - 1; i < len; i++) {
1804
+ this[i] = this[i + 1];
1805
+ }
1806
+ this.length = this.length - 1;
1807
+ return firstItem;
1808
+ }
1809
+ };
1810
+ }
1811
+
1812
+ if (!Array.prototype.splice) {
1813
+ Array.prototype.splice = function(startIndex, deleteCount) {
1814
+ var itemsAfterDeleted = this.slice(startIndex + deleteCount);
1815
+ var itemsDeleted = this.slice(startIndex, startIndex + deleteCount);
1816
+ this.length = startIndex;
1817
+ // Copy the arguments into a proper Array object
1818
+ var argumentsArray = [];
1819
+ for (var i = 0, len = arguments.length; i < len; i++) {
1820
+ argumentsArray[i] = arguments[i];
1821
+ }
1822
+ var itemsToAppend = (argumentsArray.length > 2) ?
1823
+ itemsAfterDeleted = argumentsArray.slice(2).concat(itemsAfterDeleted) : itemsAfterDeleted;
1824
+ for (i = 0, len = itemsToAppend.length; i < len; i++) {
1825
+ this.push(itemsToAppend[i]);
1826
+ }
1827
+ return itemsDeleted;
1828
+ };
1829
+ }
1830
+
1831
+ function array_remove(arr, val) {
1832
+ var index = -1;
1833
+ for (var i = 0, len = arr.length; i < len; i++) {
1834
+ if (arr[i] === val) {
1835
+ index = i;
1836
+ break;
1837
+ }
1838
+ }
1839
+ if (index >= 0) {
1840
+ arr.splice(index, 1);
1841
+ return index;
1842
+ } else {
1843
+ return false;
1844
+ }
1845
+ }
1846
+
1847
+ function array_removeFromStart(array, numberToRemove) {
1848
+ if (Array.prototype.splice) {
1849
+ array.splice(0, numberToRemove);
1850
+ } else {
1851
+ for (var i = numberToRemove, len = array.length; i < len; i++) {
1852
+ array[i - numberToRemove] = array[i];
1853
+ }
1854
+ array.length = array.length - numberToRemove;
1855
+ }
1856
+ return array;
1857
+ }
1858
+
1859
+ function array_contains(arr, val) {
1860
+ for (var i = 0, len = arr.length; i < len; i++) {
1861
+ if (arr[i] == val) {
1862
+ return true;
1863
+ }
1864
+ }
1865
+ return false;
1866
+ }
1867
+
1868
+ function getErrorMessage(ex) {
1869
+ if (ex.message) {
1870
+ return ex.message;
1871
+ } else if (ex.description) {
1872
+ return ex.description;
1873
+ }
1874
+ return "" + ex;
1875
+ }
1876
+
1877
+ function moveCaretToEnd(input) {
1878
+ if (input.setSelectionRange) {
1879
+ input.focus();
1880
+ var length = input.value.length;
1881
+ input.setSelectionRange(length, length);
1882
+ } else if (input.createTextRange) {
1883
+ var range = input.createTextRange();
1884
+ range.collapse(false);
1885
+ range.select();
1886
+ }
1887
+ input.focus();
1888
+ }
1889
+
1890
+ function stopPropagation(evt) {
1891
+ if (evt.stopPropagation) {
1892
+ evt.stopPropagation();
1893
+ } else if (typeof evt.cancelBubble != "undefined") {
1894
+ evt.cancelBubble = true;
1895
+ }
1896
+ }
1897
+
1898
+ function getEvent(evt) {
1899
+ return evt ? evt : event;
1900
+ }
1901
+
1902
+ function getTarget(evt) {
1903
+ return evt.target ? evt.target : evt.srcElement;
1904
+ }
1905
+
1906
+ function getRelatedTarget(evt) {
1907
+ if (evt.relatedTarget) {
1908
+ return evt.relatedTarget;
1909
+ } else if (evt.srcElement) {
1910
+ switch(evt.type) {
1911
+ case "mouseover":
1912
+ return evt.fromElement;
1913
+ case "mouseout":
1914
+ return evt.toElement;
1915
+ default:
1916
+ return evt.srcElement;
1917
+ }
1918
+ }
1919
+ }
1920
+
1921
+ function cancelKeyEvent(evt) {
1922
+ evt.returnValue = false;
1923
+ stopPropagation(evt);
1924
+ }
1925
+
1926
+ function evalCommandLine() {
1927
+ var expr = $("command").value;
1928
+ evalCommand(expr);
1929
+ $("command").value = "";
1930
+ }
1931
+
1932
+ function evalLastCommand() {
1933
+ if (lastCommand != null) {
1934
+ evalCommand(lastCommand);
1935
+ }
1936
+ }
1937
+
1938
+ var lastCommand = null;
1939
+ var commandHistory = [];
1940
+ var currentCommandIndex = 0;
1941
+
1942
+ function evalCommand(expr) {
1943
+ if (appender) {
1944
+ appender.evalCommandAndAppend(expr);
1945
+ } else {
1946
+ var prefix = ">>> " + expr + "\r\n";
1947
+ try {
1948
+ log("INFO", prefix + eval(expr));
1949
+ } catch (ex) {
1950
+ log("ERROR", prefix + "Error: " + getErrorMessage(ex));
1951
+ }
1952
+ }
1953
+ // Update command history
1954
+ if (expr != commandHistory[commandHistory.length - 1]) {
1955
+ commandHistory.push(expr);
1956
+ // Update the appender
1957
+ if (appender) {
1958
+ appender.storeCommandHistory(commandHistory);
1959
+ }
1960
+ }
1961
+ currentCommandIndex = (expr == commandHistory[currentCommandIndex]) ? currentCommandIndex + 1 : commandHistory.length;
1962
+ lastCommand = expr;
1963
+ }
1964
+ //]]>
1965
+ </script>
1966
+ <style type="text/css">
1967
+ body {
1968
+ background-color: white;
1969
+ color: black;
1970
+ padding: 0;
1971
+ margin: 0;
1972
+ font-family: tahoma, verdana, arial, helvetica, sans-serif;
1973
+ overflow: hidden;
1974
+ }
1975
+
1976
+ div#switchesContainer input {
1977
+ margin-bottom: 0;
1978
+ }
1979
+
1980
+ div.toolbar {
1981
+ border-top: solid #ffffff 1px;
1982
+ border-bottom: solid #aca899 1px;
1983
+ background-color: #f1efe7;
1984
+ padding: 3px 5px;
1985
+ font-size: 68.75%;
1986
+ }
1987
+
1988
+ div.toolbar, div#search input {
1989
+ font-family: tahoma, verdana, arial, helvetica, sans-serif;
1990
+ }
1991
+
1992
+ div.toolbar input.button {
1993
+ padding: 0 5px;
1994
+ font-size: 100%;
1995
+ }
1996
+
1997
+ div.toolbar input.hidden {
1998
+ display: none;
1999
+ }
2000
+
2001
+ div#switches input#clearButton {
2002
+ margin-left: 20px;
2003
+ }
2004
+
2005
+ div#levels label {
2006
+ font-weight: bold;
2007
+ }
2008
+
2009
+ div#levels label, div#options label {
2010
+ margin-right: 5px;
2011
+ }
2012
+
2013
+ div#levels label#wrapLabel {
2014
+ font-weight: normal;
2015
+ }
2016
+
2017
+ div#search label {
2018
+ margin-right: 10px;
2019
+ }
2020
+
2021
+ div#search label.searchboxlabel {
2022
+ margin-right: 0;
2023
+ }
2024
+
2025
+ div#search input {
2026
+ font-size: 100%;
2027
+ }
2028
+
2029
+ div#search input.validregex {
2030
+ color: green;
2031
+ }
2032
+
2033
+ div#search input.invalidregex {
2034
+ color: red;
2035
+ }
2036
+
2037
+ div#search input.nomatches {
2038
+ color: white;
2039
+ background-color: #ff6666;
2040
+ }
2041
+
2042
+ div#search input.nomatches {
2043
+ color: white;
2044
+ background-color: #ff6666;
2045
+ }
2046
+
2047
+ div#searchNav {
2048
+ display: none;
2049
+ }
2050
+
2051
+ div#commandLine {
2052
+ display: none;
2053
+ }
2054
+
2055
+ div#commandLine input#command {
2056
+ font-size: 100%;
2057
+ font-family: Courier New, Courier;
2058
+ }
2059
+
2060
+ div#commandLine input#evaluateButton {
2061
+ }
2062
+
2063
+ *.greyedout {
2064
+ color: gray !important;
2065
+ border-color: gray !important;
2066
+ }
2067
+
2068
+ *.greyedout *.alwaysenabled { color: black; }
2069
+
2070
+ *.unselectable {
2071
+ -khtml-user-select: none;
2072
+ -moz-user-select: none;
2073
+ user-select: none;
2074
+ }
2075
+
2076
+ div#log {
2077
+ font-family: Courier New, Courier;
2078
+ font-size: 75%;
2079
+ width: 100%;
2080
+ overflow: auto;
2081
+ clear: both;
2082
+ position: relative;
2083
+ }
2084
+
2085
+ div.group {
2086
+ border-color: #cccccc;
2087
+ border-style: solid;
2088
+ border-width: 1px 0 1px 1px;
2089
+ overflow: visible;
2090
+ }
2091
+
2092
+ div.oldIe div.group, div.oldIe div.group *, div.oldIe *.logentry {
2093
+ height: 1%;
2094
+ }
2095
+
2096
+ div.group div.groupheading span.expander {
2097
+ border: solid black 1px;
2098
+ font-family: Courier New, Courier;
2099
+ font-size: 0.833em;
2100
+ background-color: #eeeeee;
2101
+ position: relative;
2102
+ top: -1px;
2103
+ color: black;
2104
+ padding: 0 2px;
2105
+ cursor: pointer;
2106
+ cursor: hand;
2107
+ height: 1%;
2108
+ }
2109
+
2110
+ div.group div.groupcontent {
2111
+ margin-left: 10px;
2112
+ padding-bottom: 2px;
2113
+ overflow: visible;
2114
+ }
2115
+
2116
+ div.group div.expanded {
2117
+ display: block;
2118
+ }
2119
+
2120
+ div.group div.collapsed {
2121
+ display: none;
2122
+ }
2123
+
2124
+ *.logentry {
2125
+ overflow: visible;
2126
+ display: none;
2127
+ white-space: pre;
2128
+ }
2129
+
2130
+ span.pre {
2131
+ white-space: pre;
2132
+ }
2133
+
2134
+ pre.unwrapped {
2135
+ display: inline !important;
2136
+ }
2137
+
2138
+ pre.unwrapped pre.pre, div.wrapped pre.pre {
2139
+ display: inline;
2140
+ }
2141
+
2142
+ div.wrapped pre.pre {
2143
+ white-space: normal;
2144
+ }
2145
+
2146
+ div.wrapped {
2147
+ display: none;
2148
+ }
2149
+
2150
+ body.searching *.logentry span.currentmatch {
2151
+ color: white !important;
2152
+ background-color: green !important;
2153
+ }
2154
+
2155
+ body.searching div.searchhighlight *.logentry span.searchterm {
2156
+ color: black;
2157
+ background-color: yellow;
2158
+ }
2159
+
2160
+ div.wrap *.logentry {
2161
+ white-space: normal !important;
2162
+ border-width: 0 0 1px 0;
2163
+ border-color: #dddddd;
2164
+ border-style: dotted;
2165
+ }
2166
+
2167
+ div.wrap #log_wrapped, #log_unwrapped {
2168
+ display: block;
2169
+ }
2170
+
2171
+ div.wrap #log_unwrapped, #log_wrapped {
2172
+ display: none;
2173
+ }
2174
+
2175
+ div.wrap *.logentry span.pre {
2176
+ overflow: visible;
2177
+ white-space: normal;
2178
+ }
2179
+
2180
+ div.wrap *.logentry pre.unwrapped {
2181
+ display: none;
2182
+ }
2183
+
2184
+ div.wrap *.logentry span.wrapped {
2185
+ display: inline;
2186
+ }
2187
+
2188
+ div.searchfilter *.searchnonmatch {
2189
+ display: none !important;
2190
+ }
2191
+
2192
+ div#log *.TRACE, label#label_TRACE {
2193
+ color: #666666;
2194
+ }
2195
+
2196
+ div#log *.DEBUG, label#label_DEBUG {
2197
+ color: green;
2198
+ }
2199
+
2200
+ div#log *.INFO, label#label_INFO {
2201
+ color: #000099;
2202
+ }
2203
+
2204
+ div#log *.WARN, label#label_WARN {
2205
+ color: #999900;
2206
+ }
2207
+
2208
+ div#log *.ERROR, label#label_ERROR {
2209
+ color: red;
2210
+ }
2211
+
2212
+ div#log *.FATAL, label#label_FATAL {
2213
+ color: #660066;
2214
+ }
2215
+
2216
+ div.TRACE#log *.TRACE,
2217
+ div.DEBUG#log *.DEBUG,
2218
+ div.INFO#log *.INFO,
2219
+ div.WARN#log *.WARN,
2220
+ div.ERROR#log *.ERROR,
2221
+ div.FATAL#log *.FATAL {
2222
+ display: block;
2223
+ }
2224
+
2225
+ div#log div.separator {
2226
+ background-color: #cccccc;
2227
+ margin: 5px 0;
2228
+ line-height: 1px;
2229
+ }
2230
+ </style>
2231
+ </head>
2232
+
2233
+ <body id="body">
2234
+ <div id="switchesContainer">
2235
+ <div id="switches">
2236
+ <div id="levels" class="toolbar">
2237
+ Filters:
2238
+ <input type="checkbox" id="switch_TRACE" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide trace messages" /><label for="switch_TRACE" id="label_TRACE">trace</label>
2239
+ <input type="checkbox" id="switch_DEBUG" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide debug messages" /><label for="switch_DEBUG" id="label_DEBUG">debug</label>
2240
+ <input type="checkbox" id="switch_INFO" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide info messages" /><label for="switch_INFO" id="label_INFO">info</label>
2241
+ <input type="checkbox" id="switch_WARN" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide warn messages" /><label for="switch_WARN" id="label_WARN">warn</label>
2242
+ <input type="checkbox" id="switch_ERROR" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide error messages" /><label for="switch_ERROR" id="label_ERROR">error</label>
2243
+ <input type="checkbox" id="switch_FATAL" onclick="applyFilters(); checkAllLevels()" checked="checked" title="Show/hide fatal messages" /><label for="switch_FATAL" id="label_FATAL">fatal</label>
2244
+ <input type="checkbox" id="switch_ALL" onclick="toggleAllLevels(); applyFilters()" checked="checked" title="Show/hide all messages" /><label for="switch_ALL" id="label_ALL">all</label>
2245
+ </div>
2246
+ <div id="search" class="toolbar">
2247
+ <label for="searchBox" class="searchboxlabel">Search:</label> <input type="text" id="searchBox" onclick="toggleSearchEnabled(true)" onkeyup="scheduleSearch()" size="20" />
2248
+ <input type="button" id="searchReset" disabled="disabled" value="Reset" onclick="clearSearch()" class="button" title="Reset the search" />
2249
+ <input type="checkbox" id="searchRegex" onclick="doSearch()" title="If checked, search is treated as a regular expression" /><label for="searchRegex">Regex</label>
2250
+ <input type="checkbox" id="searchCaseSensitive" onclick="doSearch()" title="If checked, search is case sensitive" /><label for="searchCaseSensitive">Match case</label>
2251
+ <input type="checkbox" id="searchDisable" onclick="toggleSearchEnabled()" title="Enable/disable search" /><label for="searchDisable" class="alwaysenabled">Disable</label>
2252
+ <div id="searchNav">
2253
+ <input type="button" id="searchNext" disabled="disabled" value="Next" onclick="searchNext()" class="button" title="Go to the next matching log entry" />
2254
+ <input type="button" id="searchPrevious" disabled="disabled" value="Previous" onclick="searchPrevious()" class="button" title="Go to the previous matching log entry" />
2255
+ <input type="checkbox" id="searchFilter" onclick="toggleSearchFilter()" title="If checked, non-matching log entries are filtered out" /><label for="searchFilter">Filter</label>
2256
+ <input type="checkbox" id="searchHighlight" onclick="toggleSearchHighlight()" title="Highlight matched search terms" /><label for="searchHighlight" class="alwaysenabled">Highlight all</label>
2257
+ </div>
2258
+ </div>
2259
+ <div id="options" class="toolbar">
2260
+ Options:
2261
+ <input type="checkbox" id="enableLogging" onclick="toggleLoggingEnabled()" checked="checked" title="Enable/disable logging" /><label for="enableLogging" id="enableLoggingLabel">Log</label>
2262
+ <input type="checkbox" id="wrap" onclick="toggleWrap()" title="Enable / disable word wrap" /><label for="wrap" id="wrapLabel">Wrap</label>
2263
+ <input type="checkbox" id="newestAtTop" onclick="toggleNewestAtTop()" title="If checked, causes newest messages to appear at the top" /><label for="newestAtTop" id="newestAtTopLabel">Newest at the top</label>
2264
+ <input type="checkbox" id="scrollToLatest" onclick="toggleScrollToLatest()" checked="checked" title="If checked, window automatically scrolls to a new message when it is added" /><label for="scrollToLatest" id="scrollToLatestLabel">Scroll to latest</label>
2265
+ <input type="button" id="clearButton" value="Clear" onclick="clearLog()" class="button" title="Clear all log messages" />
2266
+ <input type="button" id="hideButton" value="Hide" onclick="hide()" class="hidden button" title="Hide the console" />
2267
+ <input type="button" id="closeButton" value="Close" onclick="closeWindow()" class="hidden button" title="Close the window" />
2268
+ </div>
2269
+ </div>
2270
+ </div>
2271
+ <div id="log" class="TRACE DEBUG INFO WARN ERROR FATAL"></div>
2272
+ <div id="commandLine" class="toolbar">
2273
+ <div id="commandLineContainer">
2274
+ <input type="text" id="command" title="Enter a JavaScript command here and hit return or press 'Evaluate'" />
2275
+ <input type="button" id="evaluateButton" value="Evaluate" class="button" title="Evaluate the command" onclick="evalCommandLine()" />
2276
+ </div>
2277
+ </div>
2278
+ </body>
2279
+ </html>