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