@eclipse-scout/core
Version:
Eclipse Scout runtime
1,661 lines (1,449 loc) • 58.5 kB
JavaScript
// <BSI change>
// Our CSP rule prohibits inline scripts. That's why we refactored the original console_uncompressed.html
// from the log4javascript distribution, so it loads a regular script file. Because of this we also changed
// the IE and "old IE" detection used by log4javascript. We simply ask Scout what browser is used.
var isIe = window.opener.scout.Device.get().isInternetExplorer();
var isIePre7 = false; // not supported anymore, flag is always false
// Inline event handlers are not allowed -> attach them here
$('switch_TRACE').addEventListener('click', function() {
applyFilters(); checkAllLevels();
});
$('switch_DEBUG').addEventListener('click', function() {
applyFilters(); checkAllLevels();
});
$('switch_INFO').addEventListener('click', function() {
applyFilters(); checkAllLevels();
});
$('switch_WARN').addEventListener('click', function() {
applyFilters(); checkAllLevels();
});
$('switch_ERROR').addEventListener('click', function() {
applyFilters(); checkAllLevels();
});
$('switch_FATAL').addEventListener('click', function() {
applyFilters(); checkAllLevels();
});
$('switch_ALL').addEventListener('click', function() {
toggleAllLevels(); applyFilters();
});
$('searchBox').addEventListener('click', function() {
toggleSearchEnabled(true); applyFilters();
});
$('searchBox').addEventListener('keyup', scheduleSearch);
$('searchReset').addEventListener('click', clearSearch);
$('searchRegex').addEventListener('click', doSearch);
$('searchCaseSensitive').addEventListener('click', doSearch);
$('searchDisable').addEventListener('click', toggleSearchEnabled);
$('searchNext').addEventListener('click', searchNext);
$('searchPrevious').addEventListener('click', searchPrevious);
$('searchFilter').addEventListener('click', searchFilter);
$('searchHighlight').addEventListener('click', toggleSearchHighlight);
$('enableLogging').addEventListener('click', toggleLoggingEnabled);
$('wrap').addEventListener('click', toggleWrap);
$('newestAtTop').addEventListener('click', toggleNewestAtTop);
$('scrollToLatest').addEventListener('click', toggleScrollToLatest);
$('clearButton').addEventListener('click', clearLog);
$('hideButton').addEventListener('click', hide);
$('closeButton').addEventListener('click', closeWindow);
$('evaluateButton').addEventListener('click', evalCommandLine);
// </BSI change>
var loggingEnabled = true;
var logQueuedEventsTimer = null;
var logEntries = [];
var logEntriesAndSeparators = [];
var logItems = [];
var renderDelay = 100;
var unrenderedLogItemsExist = false;
var rootGroup, currentGroup = null;
var loaded = false;
var currentLogItem = null;
var logMainContainer;
function copyProperties(obj, props) {
for (var i in props) {
obj[i] = props[i];
}
}
/*----------------------------------------------------------------*/
function LogItem() {
}
LogItem.prototype = {
mainContainer: null,
wrappedContainer: null,
unwrappedContainer: null,
group: null,
appendToLog: function() {
for (var i = 0, len = this.elementContainers.length; i < len; i++) {
this.elementContainers[i].appendToLog();
}
this.group.update();
},
doRemove: function(doUpdate, removeFromGroup) {
if (this.rendered) {
for (var i = 0, len = this.elementContainers.length; i < len; i++) {
this.elementContainers[i].remove();
}
this.unwrappedElementContainer = null;
this.wrappedElementContainer = null;
this.mainElementContainer = null;
}
if (this.group && removeFromGroup) {
this.group.removeChild(this, doUpdate);
}
if (this === currentLogItem) {
currentLogItem = null;
}
},
remove: function(doUpdate, removeFromGroup) {
this.doRemove(doUpdate, removeFromGroup);
},
render: function() {},
accept: function(visitor) {
visitor.visit(this);
},
getUnwrappedDomContainer: function() {
return this.group.unwrappedElementContainer.contentDiv;
},
getWrappedDomContainer: function() {
return this.group.wrappedElementContainer.contentDiv;
},
getMainDomContainer: function() {
return this.group.mainElementContainer.contentDiv;
}
};
LogItem.serializedItemKeys = {LOG_ENTRY: 0, GROUP_START: 1, GROUP_END: 2};
/*----------------------------------------------------------------*/
function LogItemContainerElement() {
}
LogItemContainerElement.prototype = {
appendToLog: function() {
var insertBeforeFirst = (newestAtTop && this.containerDomNode.hasChildNodes());
if (insertBeforeFirst) {
this.containerDomNode.insertBefore(this.mainDiv, this.containerDomNode.firstChild);
} else {
this.containerDomNode.appendChild(this.mainDiv);
}
}
};
/*----------------------------------------------------------------*/
function SeparatorElementContainer(containerDomNode) {
this.containerDomNode = containerDomNode;
this.mainDiv = document.createElement("div");
this.mainDiv.className = "separator";
this.mainDiv.innerHTML = " ";
}
SeparatorElementContainer.prototype = new LogItemContainerElement();
SeparatorElementContainer.prototype.remove = function() {
this.mainDiv.parentNode.removeChild(this.mainDiv);
this.mainDiv = null;
};
/*----------------------------------------------------------------*/
function Separator() {
this.rendered = false;
}
Separator.prototype = new LogItem();
copyProperties(Separator.prototype, {
render: function() {
var containerDomNode = this.group.contentDiv;
if (isIe) {
this.unwrappedElementContainer = new SeparatorElementContainer(this.getUnwrappedDomContainer());
this.wrappedElementContainer = new SeparatorElementContainer(this.getWrappedDomContainer());
this.elementContainers = [this.unwrappedElementContainer, this.wrappedElementContainer];
} else {
this.mainElementContainer = new SeparatorElementContainer(this.getMainDomContainer());
this.elementContainers = [this.mainElementContainer];
}
this.content = this.formattedMessage;
this.rendered = true;
}
});
/*----------------------------------------------------------------*/
function GroupElementContainer(group, containerDomNode, isRoot, isWrapped) {
this.group = group;
this.containerDomNode = containerDomNode;
this.isRoot = isRoot;
this.isWrapped = isWrapped;
this.expandable = false;
if (this.isRoot) {
if (isIe) {
this.contentDiv = logMainContainer.appendChild(document.createElement("div"));
this.contentDiv.id = this.isWrapped ? "log_wrapped" : "log_unwrapped";
} else {
this.contentDiv = logMainContainer;
}
} else {
var groupElementContainer = this;
this.mainDiv = document.createElement("div");
this.mainDiv.className = "group";
this.headingDiv = this.mainDiv.appendChild(document.createElement("div"));
this.headingDiv.className = "groupheading";
this.expander = this.headingDiv.appendChild(document.createElement("span"));
this.expander.className = "expander unselectable greyedout";
this.expander.unselectable = true;
var expanderText = this.group.expanded ? "-" : "+";
this.expanderTextNode = this.expander.appendChild(document.createTextNode(expanderText));
this.headingDiv.appendChild(document.createTextNode(" " + this.group.name));
this.contentDiv = this.mainDiv.appendChild(document.createElement("div"));
var contentCssClass = this.group.expanded ? "expanded" : "collapsed";
this.contentDiv.className = "groupcontent " + contentCssClass;
this.expander.onclick = function() {
if (groupElementContainer.group.expandable) {
groupElementContainer.group.toggleExpanded();
}
};
}
}
GroupElementContainer.prototype = new LogItemContainerElement();
copyProperties(GroupElementContainer.prototype, {
toggleExpanded: function() {
if (!this.isRoot) {
var oldCssClass, newCssClass, expanderText;
if (this.group.expanded) {
newCssClass = "expanded";
oldCssClass = "collapsed";
expanderText = "-";
} else {
newCssClass = "collapsed";
oldCssClass = "expanded";
expanderText = "+";
}
replaceClass(this.contentDiv, newCssClass, oldCssClass);
this.expanderTextNode.nodeValue = expanderText;
}
},
remove: function() {
if (!this.isRoot) {
this.headingDiv = null;
this.expander.onclick = null;
this.expander = null;
this.expanderTextNode = null;
this.contentDiv = null;
this.containerDomNode = null;
this.mainDiv.parentNode.removeChild(this.mainDiv);
this.mainDiv = null;
}
},
reverseChildren: function() {
// Invert the order of the log entries
var node = null;
// Remove all the log container nodes
var childDomNodes = [];
while ((node = this.contentDiv.firstChild)) {
this.contentDiv.removeChild(node);
childDomNodes.push(node);
}
// Put them all back in reverse order
while ((node = childDomNodes.pop())) {
this.contentDiv.appendChild(node);
}
},
update: function() {
if (!this.isRoot) {
if (this.group.expandable) {
removeClass(this.expander, "greyedout");
} else {
addClass(this.expander, "greyedout");
}
}
},
clear: function() {
if (this.isRoot) {
this.contentDiv.innerHTML = "";
}
}
});
/*----------------------------------------------------------------*/
function Group(name, isRoot, initiallyExpanded) {
this.name = name;
this.group = null;
this.isRoot = isRoot;
this.initiallyExpanded = initiallyExpanded;
this.elementContainers = [];
this.children = [];
this.expanded = initiallyExpanded;
this.rendered = false;
this.expandable = false;
}
Group.prototype = new LogItem();
copyProperties(Group.prototype, {
addChild: function(logItem) {
this.children.push(logItem);
logItem.group = this;
},
render: function() {
if (isIe) {
var unwrappedDomContainer, wrappedDomContainer;
if (this.isRoot) {
unwrappedDomContainer = logMainContainer;
wrappedDomContainer = logMainContainer;
} else {
unwrappedDomContainer = this.getUnwrappedDomContainer();
wrappedDomContainer = this.getWrappedDomContainer();
}
this.unwrappedElementContainer = new GroupElementContainer(this, unwrappedDomContainer, this.isRoot, false);
this.wrappedElementContainer = new GroupElementContainer(this, wrappedDomContainer, this.isRoot, true);
this.elementContainers = [this.unwrappedElementContainer, this.wrappedElementContainer];
} else {
var mainDomContainer = this.isRoot ? logMainContainer : this.getMainDomContainer();
this.mainElementContainer = new GroupElementContainer(this, mainDomContainer, this.isRoot, false);
this.elementContainers = [this.mainElementContainer];
}
this.rendered = true;
},
toggleExpanded: function() {
this.expanded = !this.expanded;
for (var i = 0, len = this.elementContainers.length; i < len; i++) {
this.elementContainers[i].toggleExpanded();
}
},
expand: function() {
if (!this.expanded) {
this.toggleExpanded();
}
},
accept: function(visitor) {
visitor.visitGroup(this);
},
reverseChildren: function() {
if (this.rendered) {
for (var i = 0, len = this.elementContainers.length; i < len; i++) {
this.elementContainers[i].reverseChildren();
}
}
},
update: function() {
var previouslyExpandable = this.expandable;
this.expandable = (this.children.length !== 0);
if (this.expandable !== previouslyExpandable) {
for (var i = 0, len = this.elementContainers.length; i < len; i++) {
this.elementContainers[i].update();
}
}
},
flatten: function() {
var visitor = new GroupFlattener();
this.accept(visitor);
return visitor.logEntriesAndSeparators;
},
removeChild: function(child, doUpdate) {
array_remove(this.children, child);
child.group = null;
if (doUpdate) {
this.update();
}
},
remove: function(doUpdate, removeFromGroup) {
for (var i = 0, len = this.children.length; i < len; i++) {
this.children[i].remove(false, false);
}
this.children = [];
this.update();
if (this === currentGroup) {
currentGroup = this.group;
}
this.doRemove(doUpdate, removeFromGroup);
},
serialize: function(items) {
items.push([LogItem.serializedItemKeys.GROUP_START, this.name]);
for (var i = 0, len = this.children.length; i < len; i++) {
this.children[i].serialize(items);
}
if (this !== currentGroup) {
items.push([LogItem.serializedItemKeys.GROUP_END]);
}
},
clear: function() {
for (var i = 0, len = this.elementContainers.length; i < len; i++) {
this.elementContainers[i].clear();
}
}
});
/*----------------------------------------------------------------*/
function LogEntryElementContainer() {
}
LogEntryElementContainer.prototype = new LogItemContainerElement();
copyProperties(LogEntryElementContainer.prototype, {
remove: function() {
this.doRemove();
},
doRemove: function() {
this.mainDiv.parentNode.removeChild(this.mainDiv);
this.mainDiv = null;
this.contentElement = null;
this.containerDomNode = null;
},
setContent: function(content, wrappedContent) {
if (content === this.formattedMessage) {
this.contentElement.innerHTML = "";
this.contentElement.appendChild(document.createTextNode(this.formattedMessage));
} else {
this.contentElement.innerHTML = content;
}
},
setSearchMatch: function(isMatch) {
var oldCssClass = isMatch ? "searchnonmatch" : "searchmatch";
var newCssClass = isMatch ? "searchmatch" : "searchnonmatch";
replaceClass(this.mainDiv, newCssClass, oldCssClass);
},
clearSearch: function() {
removeClass(this.mainDiv, "searchmatch");
removeClass(this.mainDiv, "searchnonmatch");
}
});
/*----------------------------------------------------------------*/
function LogEntryWrappedElementContainer(logEntry, containerDomNode) {
this.logEntry = logEntry;
this.containerDomNode = containerDomNode;
this.mainDiv = document.createElement("div");
this.mainDiv.appendChild(document.createTextNode(this.logEntry.formattedMessage));
this.mainDiv.className = "logentry wrapped " + this.logEntry.level;
this.contentElement = this.mainDiv;
}
LogEntryWrappedElementContainer.prototype = new LogEntryElementContainer();
LogEntryWrappedElementContainer.prototype.setContent = function(content, wrappedContent) {
if (content === this.formattedMessage) {
this.contentElement.innerHTML = "";
this.contentElement.appendChild(document.createTextNode(this.formattedMessage));
} else {
this.contentElement.innerHTML = wrappedContent;
}
};
/*----------------------------------------------------------------*/
function LogEntryUnwrappedElementContainer(logEntry, containerDomNode) {
this.logEntry = logEntry;
this.containerDomNode = containerDomNode;
this.mainDiv = document.createElement("div");
this.mainDiv.className = "logentry unwrapped " + this.logEntry.level;
this.pre = this.mainDiv.appendChild(document.createElement("pre"));
this.pre.appendChild(document.createTextNode(this.logEntry.formattedMessage));
this.pre.className = "unwrapped";
this.contentElement = this.pre;
}
LogEntryUnwrappedElementContainer.prototype = new LogEntryElementContainer();
LogEntryUnwrappedElementContainer.prototype.remove = function() {
this.doRemove();
this.pre = null;
};
/*----------------------------------------------------------------*/
function LogEntryMainElementContainer(logEntry, containerDomNode) {
this.logEntry = logEntry;
this.containerDomNode = containerDomNode;
this.mainDiv = document.createElement("div");
this.mainDiv.className = "logentry nonielogentry " + this.logEntry.level;
this.contentElement = this.mainDiv.appendChild(document.createElement("span"));
this.contentElement.appendChild(document.createTextNode(this.logEntry.formattedMessage));
}
LogEntryMainElementContainer.prototype = new LogEntryElementContainer();
/*----------------------------------------------------------------*/
function LogEntry(level, formattedMessage) {
this.level = level;
this.formattedMessage = formattedMessage;
this.rendered = false;
}
LogEntry.prototype = new LogItem();
copyProperties(LogEntry.prototype, {
render: function() {
var logEntry = this;
var containerDomNode = this.group.contentDiv;
// Support for the CSS attribute white-space in IE for Windows is
// non-existent pre version 6 and slightly odd in 6, so instead
// use two different HTML elements
if (isIe) {
this.formattedMessage = this.formattedMessage.replace(/\r\n/g, "\r"); // Workaround for IE's treatment of white space
this.unwrappedElementContainer = new LogEntryUnwrappedElementContainer(this, this.getUnwrappedDomContainer());
this.wrappedElementContainer = new LogEntryWrappedElementContainer(this, this.getWrappedDomContainer());
this.elementContainers = [this.unwrappedElementContainer, this.wrappedElementContainer];
} else {
this.mainElementContainer = new LogEntryMainElementContainer(this, this.getMainDomContainer());
this.elementContainers = [this.mainElementContainer];
}
this.content = this.formattedMessage;
this.rendered = true;
},
setContent: function(content, wrappedContent) {
if (content != this.content) {
if (isIe && (content !== this.formattedMessage)) {
content = content.replace(/\r\n/g, "\r"); // Workaround for IE's treatment of white space
}
for (var i = 0, len = this.elementContainers.length; i < len; i++) {
this.elementContainers[i].setContent(content, wrappedContent);
}
this.content = content;
}
},
getSearchMatches: function() {
var matches = [];
var i, len;
if (isIe) {
var unwrappedEls = getElementsByClass(this.unwrappedElementContainer.mainDiv, "searchterm", "span");
var wrappedEls = getElementsByClass(this.wrappedElementContainer.mainDiv, "searchterm", "span");
for (i = 0, len = unwrappedEls.length; i < len; i++) {
matches[i] = new Match(this.level, null, unwrappedEls[i], wrappedEls[i]);
}
} else {
var els = getElementsByClass(this.mainElementContainer.mainDiv, "searchterm", "span");
for (i = 0, len = els.length; i < len; i++) {
matches[i] = new Match(this.level, els[i]);
}
}
return matches;
},
setSearchMatch: function(isMatch) {
for (var i = 0, len = this.elementContainers.length; i < len; i++) {
this.elementContainers[i].setSearchMatch(isMatch);
}
},
clearSearch: function() {
for (var i = 0, len = this.elementContainers.length; i < len; i++) {
this.elementContainers[i].clearSearch();
}
},
accept: function(visitor) {
visitor.visitLogEntry(this);
},
serialize: function(items) {
items.push([LogItem.serializedItemKeys.LOG_ENTRY, this.level, this.formattedMessage]);
}
});
/*----------------------------------------------------------------*/
function LogItemVisitor() {
}
LogItemVisitor.prototype = {
visit: function(logItem) {
},
visitParent: function(logItem) {
if (logItem.group) {
logItem.group.accept(this);
}
},
visitChildren: function(logItem) {
for (var i = 0, len = logItem.children.length; i < len; i++) {
logItem.children[i].accept(this);
}
},
visitLogEntry: function(logEntry) {
this.visit(logEntry);
},
visitSeparator: function(separator) {
this.visit(separator);
},
visitGroup: function(group) {
this.visit(group);
}
};
/*----------------------------------------------------------------*/
function GroupFlattener() {
this.logEntriesAndSeparators = [];
}
GroupFlattener.prototype = new LogItemVisitor();
GroupFlattener.prototype.visitGroup = function(group) {
this.visitChildren(group);
};
GroupFlattener.prototype.visitLogEntry = function(logEntry) {
this.logEntriesAndSeparators.push(logEntry);
};
GroupFlattener.prototype.visitSeparator = function(separator) {
this.logEntriesAndSeparators.push(separator);
};
/*----------------------------------------------------------------*/
window.onload = function() {
// Sort out document.domain
if (location.search) {
var queryBits = unescape(location.search).substr(1).split("&"), nameValueBits;
for (var i = 0, len = queryBits.length; i < len; i++) {
nameValueBits = queryBits[i].split("=");
if (nameValueBits[0] == "log4javascript_domain") {
document.domain = nameValueBits[1];
break;
}
}
}
// Create DOM objects
logMainContainer = $("log");
if (isIePre7) {
addClass(logMainContainer, "oldIe");
}
rootGroup = new Group("root", true);
rootGroup.render();
currentGroup = rootGroup;
setCommandInputWidth();
setLogContainerHeight();
toggleLoggingEnabled();
toggleSearchEnabled();
toggleSearchFilter();
toggleSearchHighlight();
applyFilters();
checkAllLevels();
toggleWrap();
toggleNewestAtTop();
toggleScrollToLatest();
renderQueuedLogItems();
loaded = true;
$("command").value = "";
$("command").autocomplete = "off";
$("command").onkeydown = function(evt) {
evt = getEvent(evt);
if (evt.keyCode == 10 || evt.keyCode == 13) { // Return/Enter
evalCommandLine();
stopPropagation(evt);
} else if (evt.keyCode == 27) { // Escape
this.value = "";
this.focus();
} else if (evt.keyCode == 38 && commandHistory.length > 0) { // Up
currentCommandIndex = Math.max(0, currentCommandIndex - 1);
this.value = commandHistory[currentCommandIndex];
moveCaretToEnd(this);
} else if (evt.keyCode == 40 && commandHistory.length > 0) { // Down
currentCommandIndex = Math.min(commandHistory.length - 1, currentCommandIndex + 1);
this.value = commandHistory[currentCommandIndex];
moveCaretToEnd(this);
}
};
// Prevent the keypress moving the caret in Firefox
$("command").onkeypress = function(evt) {
evt = getEvent(evt);
if (evt.keyCode == 38 && commandHistory.length > 0 && evt.preventDefault) { // Up
evt.preventDefault();
}
};
// Prevent the keyup event blurring the input in Opera
$("command").onkeyup = function(evt) {
evt = getEvent(evt);
if (evt.keyCode == 27 && evt.preventDefault) { // Up
evt.preventDefault();
this.focus();
}
};
// Add document keyboard shortcuts
document.onkeydown = function keyEventHandler(evt) {
evt = getEvent(evt);
switch (evt.keyCode) {
case 69: // Ctrl + shift + E: re-execute last command
if (evt.shiftKey && (evt.ctrlKey || evt.metaKey)) {
evalLastCommand();
cancelKeyEvent(evt);
return false;
}
break;
case 75: // Ctrl + shift + K: focus search
if (evt.shiftKey && (evt.ctrlKey || evt.metaKey)) {
focusSearch();
cancelKeyEvent(evt);
return false;
}
break;
case 40: // Ctrl + shift + down arrow: focus command line
case 76: // Ctrl + shift + L: focus command line
if (evt.shiftKey && (evt.ctrlKey || evt.metaKey)) {
focusCommandLine();
cancelKeyEvent(evt);
return false;
}
break;
}
};
// Workaround to make sure log div starts at the correct size
setTimeout(setLogContainerHeight, 20);
setShowCommandLine(showCommandLine);
doSearch();
};
window.onunload = function() {
if (mainWindowExists()) {
appender.unload();
}
appender = null;
};
/*----------------------------------------------------------------*/
function toggleLoggingEnabled() {
setLoggingEnabled($("enableLogging").checked);
}
function setLoggingEnabled(enable) {
loggingEnabled = enable;
}
var appender = null;
function setAppender(appenderParam) {
appender = appenderParam;
}
function setShowCloseButton(showCloseButton) {
$("closeButton").style.display = showCloseButton ? "inline" : "none";
}
function setShowHideButton(showHideButton) {
$("hideButton").style.display = showHideButton ? "inline" : "none";
}
var newestAtTop = false;
/*----------------------------------------------------------------*/
function LogItemContentReverser() {
}
LogItemContentReverser.prototype = new LogItemVisitor();
LogItemContentReverser.prototype.visitGroup = function(group) {
group.reverseChildren();
this.visitChildren(group);
};
/*----------------------------------------------------------------*/
function setNewestAtTop(isNewestAtTop) {
var oldNewestAtTop = newestAtTop;
var i, iLen, j, jLen;
newestAtTop = Boolean(isNewestAtTop);
if (oldNewestAtTop != newestAtTop) {
var visitor = new LogItemContentReverser();
rootGroup.accept(visitor);
// Reassemble the matches array
if (currentSearch) {
var currentMatch = currentSearch.matches[currentMatchIndex];
var matchIndex = 0;
var matches = [];
var actOnLogEntry = function(logEntry) {
var logEntryMatches = logEntry.getSearchMatches();
for (j = 0, jLen = logEntryMatches.length; j < jLen; j++) {
matches[matchIndex] = logEntryMatches[j];
if (currentMatch && logEntryMatches[j].equals(currentMatch)) {
currentMatchIndex = matchIndex;
}
matchIndex++;
}
};
if (newestAtTop) {
for (i = logEntries.length - 1; i >= 0; i--) {
actOnLogEntry(logEntries[i]);
}
} else {
for (i = 0, iLen = logEntries.length; i < iLen; i++) {
actOnLogEntry(logEntries[i]);
}
}
currentSearch.matches = matches;
if (currentMatch) {
currentMatch.setCurrent();
}
} else if (scrollToLatest) {
doScrollToLatest();
}
}
$("newestAtTop").checked = isNewestAtTop;
}
function toggleNewestAtTop() {
var isNewestAtTop = $("newestAtTop").checked;
setNewestAtTop(isNewestAtTop);
}
var scrollToLatest = true;
function setScrollToLatest(isScrollToLatest) {
scrollToLatest = isScrollToLatest;
if (scrollToLatest) {
doScrollToLatest();
}
$("scrollToLatest").checked = isScrollToLatest;
}
function toggleScrollToLatest() {
var isScrollToLatest = $("scrollToLatest").checked;
setScrollToLatest(isScrollToLatest);
}
function doScrollToLatest() {
var l = logMainContainer;
if (typeof l.scrollTop != "undefined") {
if (newestAtTop) {
l.scrollTop = 0;
} else {
var latestLogEntry = l.lastChild;
if (latestLogEntry) {
l.scrollTop = l.scrollHeight;
}
}
}
}
var closeIfOpenerCloses = true;
function setCloseIfOpenerCloses(isCloseIfOpenerCloses) {
closeIfOpenerCloses = isCloseIfOpenerCloses;
}
var maxMessages = null;
function setMaxMessages(max) {
maxMessages = max;
pruneLogEntries();
}
var showCommandLine = false;
function setShowCommandLine(isShowCommandLine) {
showCommandLine = isShowCommandLine;
if (loaded) {
$("commandLine").style.display = showCommandLine ? "block" : "none";
setCommandInputWidth();
setLogContainerHeight();
}
}
function focusCommandLine() {
if (loaded) {
$("command").focus();
}
}
function focusSearch() {
if (loaded) {
$("searchBox").focus();
}
}
function getLogItems() {
var items = [];
for (var i = 0, len = logItems.length; i < len; i++) {
logItems[i].serialize(items);
}
return items;
}
function setLogItems(items) {
var loggingReallyEnabled = loggingEnabled;
// Temporarily turn logging on
loggingEnabled = true;
for (var i = 0, len = items.length; i < len; i++) {
switch (items[i][0]) {
case LogItem.serializedItemKeys.LOG_ENTRY:
log(items[i][1], items[i][2]);
break;
case LogItem.serializedItemKeys.GROUP_START:
group(items[i][1]);
break;
case LogItem.serializedItemKeys.GROUP_END:
groupEnd();
break;
}
}
loggingEnabled = loggingReallyEnabled;
}
function log(logLevel, formattedMessage) {
if (loggingEnabled) {
var logEntry = new LogEntry(logLevel, formattedMessage);
logEntries.push(logEntry);
logEntriesAndSeparators.push(logEntry);
logItems.push(logEntry);
currentGroup.addChild(logEntry);
if (loaded) {
if (logQueuedEventsTimer !== null) {
clearTimeout(logQueuedEventsTimer);
}
logQueuedEventsTimer = setTimeout(renderQueuedLogItems, renderDelay);
unrenderedLogItemsExist = true;
}
}
}
function renderQueuedLogItems() {
logQueuedEventsTimer = null;
var pruned = pruneLogEntries();
// Render any unrendered log entries and apply the current search to them
var initiallyHasMatches = currentSearch ? currentSearch.hasMatches() : false;
for (var i = 0, len = logItems.length; i < len; i++) {
if (!logItems[i].rendered) {
logItems[i].render();
logItems[i].appendToLog();
if (currentSearch && (logItems[i] instanceof LogEntry)) {
currentSearch.applyTo(logItems[i]);
}
}
}
if (currentSearch) {
if (pruned) {
if (currentSearch.hasVisibleMatches()) {
if (currentMatchIndex === null) {
setCurrentMatchIndex(0);
}
displayMatches();
} else {
displayNoMatches();
}
} else if (!initiallyHasMatches && currentSearch.hasVisibleMatches()) {
setCurrentMatchIndex(0);
displayMatches();
}
}
if (scrollToLatest) {
doScrollToLatest();
}
unrenderedLogItemsExist = false;
}
function pruneLogEntries() {
if ((maxMessages !== null) && (logEntriesAndSeparators.length > maxMessages)) {
var numberToDelete = logEntriesAndSeparators.length - maxMessages;
var prunedLogEntries = logEntriesAndSeparators.slice(0, numberToDelete);
if (currentSearch) {
currentSearch.removeMatches(prunedLogEntries);
}
var group;
for (var i = 0; i < numberToDelete; i++) {
group = logEntriesAndSeparators[i].group;
array_remove(logItems, logEntriesAndSeparators[i]);
array_remove(logEntries, logEntriesAndSeparators[i]);
logEntriesAndSeparators[i].remove(true, true);
if (group.children.length === 0 && group !== currentGroup && group !== rootGroup) {
array_remove(logItems, group);
group.remove(true, true);
}
}
logEntriesAndSeparators = array_removeFromStart(logEntriesAndSeparators, numberToDelete);
return true;
}
return false;
}
function group(name, startExpanded) {
if (loggingEnabled) {
initiallyExpanded = (typeof startExpanded === "undefined") ? true : Boolean(startExpanded);
var newGroup = new Group(name, false, initiallyExpanded);
currentGroup.addChild(newGroup);
currentGroup = newGroup;
logItems.push(newGroup);
if (loaded) {
if (logQueuedEventsTimer !== null) {
clearTimeout(logQueuedEventsTimer);
}
logQueuedEventsTimer = setTimeout(renderQueuedLogItems, renderDelay);
unrenderedLogItemsExist = true;
}
}
}
function groupEnd() {
currentGroup = (currentGroup === rootGroup) ? rootGroup : currentGroup.group;
}
function mainPageReloaded() {
currentGroup = rootGroup;
var separator = new Separator();
logEntriesAndSeparators.push(separator);
logItems.push(separator);
currentGroup.addChild(separator);
}
function closeWindow() {
if (appender && mainWindowExists()) {
appender.close(true);
} else {
window.close();
}
}
function hide() {
if (appender && mainWindowExists()) {
appender.hide();
}
}
var mainWindow = window;
var windowId = "log4javascriptConsoleWindow_" + new Date().getTime() + "_" + ("" + Math.random()).substr(2);
function setMainWindow(win) {
mainWindow = win;
mainWindow[windowId] = window;
// If this is a pop-up, poll the opener to see if it's closed
if (opener && closeIfOpenerCloses) {
pollOpener();
}
}
function pollOpener() {
if (closeIfOpenerCloses) {
if (mainWindowExists()) {
setTimeout(pollOpener, 500);
} else {
closeWindow();
}
}
}
function mainWindowExists() {
try {
return (mainWindow && !mainWindow.closed &&
mainWindow[windowId] == window);
} catch (ex) {}
return false;
}
var logLevels = ["TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"];
function getCheckBox(logLevel) {
return $("switch_" + logLevel);
}
function getIeWrappedLogContainer() {
return $("log_wrapped");
}
function getIeUnwrappedLogContainer() {
return $("log_unwrapped");
}
function applyFilters() {
for (var i = 0; i < logLevels.length; i++) {
if (getCheckBox(logLevels[i]).checked) {
addClass(logMainContainer, logLevels[i]);
} else {
removeClass(logMainContainer, logLevels[i]);
}
}
updateSearchFromFilters();
}
function toggleAllLevels() {
var turnOn = $("switch_ALL").checked;
for (var i = 0; i < logLevels.length; i++) {
getCheckBox(logLevels[i]).checked = turnOn;
if (turnOn) {
addClass(logMainContainer, logLevels[i]);
} else {
removeClass(logMainContainer, logLevels[i]);
}
}
}
function checkAllLevels() {
for (var i = 0; i < logLevels.length; i++) {
if (!getCheckBox(logLevels[i]).checked) {
getCheckBox("ALL").checked = false;
return;
}
}
getCheckBox("ALL").checked = true;
}
function clearLog() {
rootGroup.clear();
currentGroup = rootGroup;
logEntries = [];
logItems = [];
logEntriesAndSeparators = [];
doSearch();
}
function toggleWrap() {
var enable = $("wrap").checked;
if (enable) {
addClass(logMainContainer, "wrap");
} else {
removeClass(logMainContainer, "wrap");
}
refreshCurrentMatch();
}
/* ------------------------------------------------------------------- */
// Search
var searchTimer = null;
function scheduleSearch() {
try {
clearTimeout(searchTimer);
} catch (ex) {
// Do nothing
}
searchTimer = setTimeout(doSearch, 500);
}
function Search(searchTerm, isRegex, searchRegex, isCaseSensitive) {
this.searchTerm = searchTerm;
this.isRegex = isRegex;
this.searchRegex = searchRegex;
this.isCaseSensitive = isCaseSensitive;
this.matches = [];
}
Search.prototype = {
hasMatches: function() {
return this.matches.length > 0;
},
hasVisibleMatches: function() {
if (this.hasMatches()) {
for (var i = 0; i < this.matches.length; i++) {
if (this.matches[i].isVisible()) {
return true;
}
}
}
return false;
},
match: function(logEntry) {
var entryText = String(logEntry.formattedMessage);
var matchesSearch = false;
if (this.isRegex) {
matchesSearch = this.searchRegex.test(entryText);
} else if (this.isCaseSensitive) {
matchesSearch = (entryText.indexOf(this.searchTerm) > -1);
} else {
matchesSearch = (entryText.toLowerCase().indexOf(this.searchTerm.toLowerCase()) > -1);
}
return matchesSearch;
},
getNextVisibleMatchIndex: function() {
for (var i = currentMatchIndex + 1; i < this.matches.length; i++) {
if (this.matches[i].isVisible()) {
return i;
}
}
// Start again from the first match
for (i = 0; i <= currentMatchIndex; i++) {
if (this.matches[i].isVisible()) {
return i;
}
}
return -1;
},
getPreviousVisibleMatchIndex: function() {
for (var i = currentMatchIndex - 1; i >= 0; i--) {
if (this.matches[i].isVisible()) {
return i;
}
}
// Start again from the last match
for (var i = this.matches.length - 1; i >= currentMatchIndex; i--) {
if (this.matches[i].isVisible()) {
return i;
}
}
return -1;
},
applyTo: function(logEntry) {
var doesMatch = this.match(logEntry);
if (doesMatch) {
logEntry.group.expand();
logEntry.setSearchMatch(true);
var logEntryContent;
var wrappedLogEntryContent;
var searchTermReplacementStartTag = "<span class=\"searchterm\">";
var searchTermReplacementEndTag = "<" + "/span>";
var preTagName = isIe ? "pre" : "span";
var preStartTag = "<" + preTagName + " class=\"pre\">";
var preEndTag = "<" + "/" + preTagName + ">";
var startIndex = 0;
var searchIndex, matchedText, textBeforeMatch;
if (this.isRegex) {
var flags = this.isCaseSensitive ? "g" : "gi";
var capturingRegex = new RegExp("(" + this.searchRegex.source + ")", flags);
// Replace the search term with temporary tokens for the start and end tags
var rnd = ("" + Math.random()).substr(2);
var startToken = "%%s" + rnd + "%%";
var endToken = "%%e" + rnd + "%%";
logEntryContent = logEntry.formattedMessage.replace(capturingRegex, startToken + "$1" + endToken);
// Escape the HTML to get rid of angle brackets
logEntryContent = escapeHtml(logEntryContent);
// Substitute the proper HTML back in for the search match
var result;
var searchString = logEntryContent;
logEntryContent = "";
wrappedLogEntryContent = "";
while ((searchIndex = searchString.indexOf(startToken, startIndex)) > -1) {
var endTokenIndex = searchString.indexOf(endToken, searchIndex);
matchedText = searchString.substring(searchIndex + startToken.length, endTokenIndex);
textBeforeMatch = searchString.substring(startIndex, searchIndex);
logEntryContent += preStartTag + textBeforeMatch + preEndTag;
logEntryContent += searchTermReplacementStartTag + preStartTag + matchedText +
preEndTag + searchTermReplacementEndTag;
if (isIe) {
wrappedLogEntryContent += textBeforeMatch + searchTermReplacementStartTag +
matchedText + searchTermReplacementEndTag;
}
startIndex = endTokenIndex + endToken.length;
}
logEntryContent += preStartTag + searchString.substr(startIndex) + preEndTag;
if (isIe) {
wrappedLogEntryContent += searchString.substr(startIndex);
}
} else {
logEntryContent = "";
wrappedLogEntryContent = "";
var searchTermReplacementLength = searchTermReplacementStartTag.length +
this.searchTerm.length + searchTermReplacementEndTag.length;
var searchTermLength = this.searchTerm.length;
var searchTermLowerCase = this.searchTerm.toLowerCase();
var logTextLowerCase = logEntry.formattedMessage.toLowerCase();
while ((searchIndex = logTextLowerCase.indexOf(searchTermLowerCase, startIndex)) > -1) {
matchedText = escapeHtml(logEntry.formattedMessage.substr(searchIndex, this.searchTerm.length));
textBeforeMatch = escapeHtml(logEntry.formattedMessage.substring(startIndex, searchIndex));
var searchTermReplacement = searchTermReplacementStartTag +
preStartTag + matchedText + preEndTag + searchTermReplacementEndTag;
logEntryContent += preStartTag + textBeforeMatch + preEndTag + searchTermReplacement;
if (isIe) {
wrappedLogEntryContent += textBeforeMatch + searchTermReplacementStartTag +
matchedText + searchTermReplacementEndTag;
}
startIndex = searchIndex + searchTermLength;
}
var textAfterLastMatch = escapeHtml(logEntry.formattedMessage.substr(startIndex));
logEntryContent += preStartTag + textAfterLastMatch + preEndTag;
if (isIe) {
wrappedLogEntryContent += textAfterLastMatch;
}
}
logEntry.setContent(logEntryContent, wrappedLogEntryContent);
var logEntryMatches = logEntry.getSearchMatches();
this.matches = this.matches.concat(logEntryMatches);
} else {
logEntry.setSearchMatch(false);
logEntry.setContent(logEntry.formattedMessage, logEntry.formattedMessage);
}
return doesMatch;
},
removeMatches: function(logEntries) {
var matchesToRemoveCount = 0;
var currentMatchRemoved = false;
var matchesToRemove = [];
var i, iLen, j, jLen;
// Establish the list of matches to be removed
for (i = 0, iLen = this.matches.length; i < iLen; i++) {
for (j = 0, jLen = logEntries.length; j < jLen; j++) {
if (this.matches[i].belongsTo(logEntries[j])) {
matchesToRemove.push(this.matches[i]);
if (i === currentMatchIndex) {
currentMatchRemoved = true;
}
}
}
}
// Set the new current match index if the current match has been deleted
// This will be the first match that appears after the first log entry being
// deleted, if one exists; otherwise, it's the first match overall
var newMatch = currentMatchRemoved ? null : this.matches[currentMatchIndex];
if (currentMatchRemoved) {
for (i = currentMatchIndex, iLen = this.matches.length; i < iLen; i++) {
if (this.matches[i].isVisible() && !array_contains(matchesToRemove, this.matches[i])) {
newMatch = this.matches[i];
break;
}
}
}
// Remove the matches
for (i = 0, iLen = matchesToRemove.length; i < iLen; i++) {
array_remove(this.matches, matchesToRemove[i]);
matchesToRemove[i].remove();
}
// Set the new match, if one exists
if (this.hasVisibleMatches()) {
if (newMatch === null) {
setCurrentMatchIndex(0);
} else {
// Get the index of the new match
var newMatchIndex = 0;
for (i = 0, iLen = this.matches.length; i < iLen; i++) {
if (newMatch === this.matches[i]) {
newMatchIndex = i;
break;
}
}
setCurrentMatchIndex(newMatchIndex);
}
} else {
currentMatchIndex = null;
displayNoMatches();
}
}
};
function getPageOffsetTop(el, container) {
var currentEl = el;
var y = 0;
while (currentEl && currentEl != container) {
y += currentEl.offsetTop;
currentEl = currentEl.offsetParent;
}
return y;
}
function scrollIntoView(el) {
var logContainer = logMainContainer;
// Check if the whole width of the element is visible and centre if not
if (!$("wrap").checked) {
var logContainerLeft = logContainer.scrollLeft;
var logContainerRight = logContainerLeft + logContainer.offsetWidth;
var elLeft = el.offsetLeft;
var elRight = elLeft + el.offsetWidth;
if (elLeft < logContainerLeft || elRight > logContainerRight) {
logContainer.scrollLeft = elLeft - (logContainer.offsetWidth - el.offsetWidth) / 2;
}
}
// Check if the whole height of the element is visible and centre if not
var logContainerTop = logContainer.scrollTop;
var logContainerBottom = logContainerTop + logContainer.offsetHeight;
var elTop = getPageOffsetTop(el) - getToolBarsHeight();
var elBottom = elTop + el.offsetHeight;
if (elTop < logContainerTop || elBottom > logContainerBottom) {
logContainer.scrollTop = elTop - (logContainer.offsetHeight - el.offsetHeight) / 2;
}
}
function Match(logEntryLevel, spanInMainDiv, spanInUnwrappedPre, spanInWrappedDiv) {
this.logEntryLevel = logEntryLevel;
this.spanInMainDiv = spanInMainDiv;
if (isIe) {
this.spanInUnwrappedPre = spanInUnwrappedPre;
this.spanInWrappedDiv = spanInWrappedDiv;
}
this.mainSpan = isIe ? spanInUnwrappedPre : spanInMainDiv;
}
Match.prototype = {
equals: function(match) {
return this.mainSpan === match.mainSpan;
},
setCurrent: function() {
if (isIe) {
addClass(this.spanInUnwrappedPre, "currentmatch");
addClass(this.spanInWrappedDiv, "currentmatch");
// Scroll the visible one into view
var elementToScroll = $("wrap").checked ? this.spanInWrappedDiv : this.spanInUnwrappedPre;
scrollIntoView(elementToScroll);
} else {
addClass(this.spanInMainDiv, "currentmatch");
scrollIntoView(this.spanInMainDiv);
}
},
belongsTo: function(logEntry) {
if (isIe) {
return isDescendant(this.spanInUnwrappedPre, logEntry.unwrappedPre);
} else {
return isDescendant(this.spanInMainDiv, logEntry.mainDiv);
}
},
setNotCurrent: function() {
if (isIe) {
removeClass(this.spanInUnwrappedPre, "currentmatch");
removeClass(this.spanInWrappedDiv, "currentmatch");
} else {
removeClass(this.spanInMainDiv, "currentmatch");
}
},
isOrphan: function() {
return isOrphan(this.mainSpan);
},
isVisible: function() {
return getCheckBox(this.logEntryLevel).checked;
},
remove: function() {
if (isIe) {
this.spanInUnwrappedPre = null;
this.spanInWrappedDiv = null;
} else {
this.spanInMainDiv = null;
}
}
};
var currentSearch = null;
var currentMatchIndex = null;
function doSearch() {
var searchBox = $("searchBox");
var searchTerm = searchBox.value;
var isRegex = $("searchRegex").checked;
var isCaseSensitive = $("searchCaseSensitive").checked;
var i;
if (searchTerm === "") {
$("searchReset").disabled = true;
$("searchNav").style.display = "none";
removeClass(document.body, "searching");
removeClass(searchBox, "hasmatches");
removeClass(searchBox, "nomatches");
for (i = 0; i < logEntries.length; i++) {
logEntries[i].clearSearch();
logEntries[i].setContent(logEntries[i].formattedMessage, logEntries[i].formattedMessage);
}
currentSearch = null;
setLogContainerHeight();
} else {
$("searchReset").disabled = false;
$("searchNav").style.display = "block";
var searchRegex;
var regexValid;
if (isRegex) {
try {
searchRegex = isCaseSensitive ? new RegExp(searchTerm, "g") : new RegExp(searchTerm, "gi");
regexValid = true;
replaceClass(searchBox, "validregex", "invalidregex");
searchBox.title = "Valid regex";
} catch (ex) {
regexValid = false;
replaceClass(searchBox, "invalidregex", "validregex");
searchBox.title = "Invalid regex: " + (ex.message ? ex.message : (ex.description ? ex.description : "unknown error"));
return;
}
} else {
searchBox.title = "";
removeClass(searchBox, "validregex");
removeClass(searchBox, "invalidregex");
}
addClass(document.body, "searching");
currentSearch = new Search(searchTerm, isRegex, searchRegex, isCaseSensitive);
for (i = 0; i < logEntries.length; i++) {
currentSearch.applyTo(logEntries[i]);
}
setLogContainerHeight();
// Highlight the first search match
if (currentSearch.hasVisibleMatches()) {
setCurrentMatchIndex(0);
displayMatches();
} else {
displayNoMatches();
}
}
}
function updateSearchFromFilters() {
if (currentSearch) {
if (currentSearch.hasMatches()) {
if (currentMatchIndex === null) {
currentMatchIndex = 0;
}
var currentMatch = currentSearch.matches[currentMatchIndex];
if (currentMatch.isVisible()) {
displayMatches();
setCurrentMatchIndex(currentMatchIndex);
} else {
currentMatch.setNotCurrent();
// Find the next visible match, if one exists
var nextVisibleMatchIndex = currentSearch.getNextVisibleMatchIndex();
if (nextVisibleMatchIndex > -1) {
setCurrentMatchIndex(nextVisibleMatchIndex);
displayMatches();
} else {
displayNoMatches();
}
}
} else {
displayNoMatches();
}
}
}
function refreshCurrentMatch() {
if (currentSearch && currentSearch.hasVisibleMatches()) {
setCurrentMatchIndex(currentMatchIndex);
}
}
function displayMatches() {
replaceClass($("searchBox"), "hasmatches", "nomatches");
$("searchBox").title = "" + currentSearch.matches.length + " matches found";
$("searchNav").style.display = "block";
setLogContainerHeight();
}
function displayNoMatches() {
replaceClass($("searchBox"), "nomatches", "hasmatches");
$("searchBox").title = "No matches found";
$("searchNav").style.display = "none";
setLogContainerHeight();
}
function toggleSearchEnabled(enable) {
enable = (typeof enable == "undefined") ? !$("searchDisable").checked : enable;
$("searchBox").disabled = !enable;
$("searchReset").disabled = !enable;
$("searchRegex").disabled = !enable;
$("searchNext").disabled = !enable;
$("searchPrevious").disabled = !enable;
$("searchCaseSensitive").disabled = !enable;
$("searchNav").style.display = (enable && ($("searchBox").value !== "") &&
currentSearch && currentSearch.hasVisibleMatches()) ?
"block" : "none";
if (enable) {
removeClass($("search"), "greyedout");
addClass(document.body, "searching");
if ($("searchHighlight").checked) {
addClass(logMainContainer, "searchhighlight");
} else {
removeClass(logMainContainer, "searchhighlight");
}
if ($("searchFilter").checked) {
addClass(logMainContainer, "searchfilter");
} else {
removeClass(logMainContainer, "searchfilter");
}
$("searchDisable").checked = !enable;
} else {
addClass($("search"), "greyedout");
removeClass(document.body, "searching");
removeClass(logMainContainer, "searchhighlight");
removeClass(logMainContainer, "searchfilter");
}
setLogContainerHeight();
}
function toggleSearchFilter() {
var enable = $("searchFilter").checked;
if (enable) {
addClass(logMainContainer, "searchfilter");
} else {
removeClass(logMainContainer, "searchfilter");
}
refreshCurrentMatch();
}
function toggleSearchHighlight() {
var enable = $("searchHighlight").checked;
if (enable) {
addClass(logMainContainer, "searchhighlight");
} else {
removeClass(logMainContainer, "searchhighlight");
}
}
function clearSearch() {
$("searchBox").value = "";
doSearch();
}
function searchNext() {
if (currentSearch !== null && currentMatchIndex !== null) {
currentSearch.matches[currentMatchIndex].setNotCurrent();
var nextMatchIndex = cur