<html> <!-- NOTE: This file is used as both the disk logfile template, as well as the log window template. TODO: hide/show columns should use <col> or <colspan> rather than row iteration logTable's height & messageCol width should be liquid (stretch to fill window) update function should accept a single row & append it to the table (instead of re-drawing the entire table) Update func should get error & warning tallies from c++ rather than re-calc --> <head> <!-- No caching --> <meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Expires" content="0" /> <style type="text/css"> table { width:100%; } /* Mozilla / Firefox method of keeping the table header visible at all times: */ table>tbody { /* child selector syntax which IE6 and older do not support*/ overflow-y: scroll; overflow-x: hidden; width: 100%; height: 550px; } /* IE method of keeping the table header visible at all times: */ thead td { position: relative; top: expression(document.getElementById("tableContainer").scrollTop-2); /* IE 5+ method of getting header to stick */ } .header{ text-align: center; font-weight: bold; border-bottom: 2px solid black; background-color: white; } td{ font-family: 'courier new', courier, monospace; font-size: 0.8em; padding-left: 5px; padding-top: 0px; padding-bottom: 0px; vertical-align: text-top; } td:last-child {padding-right: 20px;} /*prevent Mozilla scrollbar from hiding cell content*/ } </style> <script type="text/javascript"> // var bLiveLoggingMode = false; var mnTotalMessages = 0; var mnTotalWarnings = 0; var mnTotalErrors = 0; var mnTotalEntries = 0; var mnTotalLost = 0; var mnTotalLogged = 0; // Count of entries passed through addLogEntry() var mnMaxDispCnt = 100; var mnRefreshTimerID = 0; var msClassFilter = ""; var bClassFilterExcludesOnly = false; function setWaitCursor(bShow) { document.getElementById('controlsContainer').style.cursor = bShow ? "wait" : "default"; } // wrapper function to hide/show a column of the logTable function setColVisibility(iColIndex, bVisable) { setWaitCursor(true); var sExpression = "doSetColVisibility(" + iColIndex + ", " + bVisable + ");"; setTimeout(sExpression, 5); } // actually hide/show a column of the logTable // TODO: see if we can do this with a <col> or <colgroup /> rather than row iteration... function doSetColVisibility(iColIndex, bVisable) { var tableFrame = document.frames['logTableFrame']; var sDisplay = (bVisable ? '' : 'none'); // NOTE: '' -> default visability ( firefox doesn't like display = 'block' for td ) var cells = null; var rows = tableFrame.document.getElementById('logTable').rows; for(var i=0; i<rows.length; i++) { rows[i].cells[iColIndex].style.display = sDisplay; } setWaitCursor(false); } // wrapper to hide/show all rows of a given message type function filterMessages() { setWaitCursor(true); var sExpression = "onLogEntryTableLoad();"; setTimeout(sExpression, 5); } // wrapper function to color every other visible table row function alternateRowColors(bColorRows) { setWaitCursor(true); var sExpression = "doAlternateRowColors(" + bColorRows + ");"; setTimeout(sExpression, 5); } // actually color every other _visible_ row in the table function doAlternateRowColors(bColorRows) { var rows = document.getElementById('logTable').rows; var nVisibleRowIdx = 0; for(var i=0; i<rows.length; i++) { if( bColorRows ) { // if coloring rows, only color visible rows if( rows[i].style.display != 'none' ) { rows[i].style.backgroundColor = ( (nVisibleRowIdx % 2) ? '#ffffff' : '#ffffdd' ); nVisibleRowIdx++; } } else { // if un-coloring rows, un-color all of 'em rows[i].style.backgroundColor = '#ffffff'; } } setWaitCursor(false); } /* Legacy from version of logger where C++ adds individual entries via script calls to an EADM window instead of external browser // this func is called by the EAD when the logTemplate is used in the loggerWindow // when called, we should show all the elements that are hidden for the disk log function setupForLoggerWindow(sPathToLogFile, nMaxDispCnt) { bLiveLoggingMode = true; // Errors and warnings only by default document.getElementById('cbIncType_Msgs').checked = false; document.getElementById('cbIncType_Errs').checked = true; document.getElementById('cbIncType_Wrns').checked = true; // setup log file link document.getElementById('logFileLink').href = "ealink:-eadcommand:?cmd=ead_open_path&showUI=1&fullPath=iexplore.exe&cmdArgs=file://" + unescape(sPathToLogFile); // show the command entry, count and external log link blocks document.getElementById('cmdContainer').style.display = "block"; document.getElementById('countContainer').style.display = "block"; document.getElementById('extLinkContainer').style.display = "block"; // Remember back buffer entry limit mnMaxDispCnt = nMaxDispCnt; // Refresh max buffer entries document.getElementById("maxEntriesShown").innerText = mnMaxDispCnt; } // New function to add new log entries instead of re-creating whole table every time function addLogTableEntry(nIndex, sTimeStamp, nType, sClass, sFunc, sMsg) { try { // Reject if adding a type being filtering out switch(nType) { case 1: // Errors if (!document.getElementById('cbIncType_Errs').checked) return; break; case 2: // Warnings if (!document.getElementById('cbIncType_Wrns').checked) return; break; case 3: // Messages if (!document.getElementById('cbIncType_Msgs').checked) return; break; } // Reject if filtered by class if (!testClassFilter(sClass)) newRow.style.display = 'none'; // Refs for speed var tableContainer = document.getElementById('tableContainer'); var tableBody = document.getElementById('logTableBody'); // Note scroller existing position var oldScrollPos = tableContainer.scrollTop; var bScrollToBottom = (oldScrollPos >= tableContainer.scrollHeight - tableContainer.clientHeight ); // Truncate row count if >= max back buffer capacity if (mnMaxDispCnt > 0) { while (tableBody.rows.length >= mnMaxDispCnt) { tableBody.deleteRow(0); } } // Add new row var newRow = tableBody.insertRow(-1); // Insert at end // Row columns var newCell_Idx, newCell_TimeStamp, newCell_Type, newCell_Class, newCell_Func, newCell_Msg; newCell_Idx = newRow.insertCell(0); if (nIndex >= 0) newCell_Idx.innerText = nIndex+1; // Convert to 1 based number to jive with counts newCell_TimeStamp = newRow.insertCell(1); newCell_TimeStamp.innerText = sTimeStamp; newCell_Type = newRow.insertCell(2); newCell_Class = newRow.insertCell(3); newCell_Class.innerText = sClass; newCell_Func = newRow.insertCell(4); newCell_Func.innerText = sFunc; newCell_Msg = newRow.insertCell(5); newCell_Msg.innerHTML = unescape(sMsg); // Use HTML here in case log entry has custom nested HTML // Colorize row, set visibility, tag by type and label type based on entry type switch(nType) { case 1: // Error newRow.className = "Err"; newRow.style.color = "#C00000"; newCell_Type.innerText = "Err"; break; case 2: // Warning newRow.className = "Wrn"; newRow.style.color = "#0000C0"; newCell_Type.innerText = "Wrn"; break; case 3: // Message newRow.className = "Msg"; newRow.style.color = "#000000"; newCell_Type.innerText = "Msg"; break; case 4: // Trace newRow.className = "Trc"; newRow.style.color = "#000000"; newCell_Type.innerText = "Trc"; break; case 5: // Help newRow.className = "Hlp"; newRow.style.color = "#000000"; newCell_Type.innerText = "Hlp"; break; } // Hide hidden columns if (!document.getElementById('cbDispCol_Timestamp').checked) newCell_TimeStamp.style.display = 'none'; if (!document.getElementById('cbDispCol_LogType').checked) newCell_Type.style.display = 'none'; if (!document.getElementById('cbDispCol_Class').checked) newCell_Class.style.display = 'none'; if (!document.getElementById('cbDispCol_Function').checked) newCell_Function.style.display = 'none'; // Restore/set scroller position if( bScrollToBottom ) tableContainer.scrollTop = 99999999; else tableContainer.scrollTop = oldScrollPos; // Alternate row background highlighting if (document.getElementById('cbAltRowColors').checked) { // Unknown how many rows are hidden so find last visible row and alternate from that var bPrevBtmRowHighlighted = false; var rows = document.getElementById('logTable').rows; for(var i=rows.length-1; i--; ) { if (rows[i].style.display != 'none') { bPrevBtmRowHighlighted = (rows[i].style.backgroundColor == "#ffffdd"); break; } } // Highlight new row if previous wasn't if (!bPrevBtmRowHighlighted) newRow.style.backgroundColor = "#ffffdd"; } // Another successful addition mnTotalLogged++; } catch (e1) {} } // delete filtered out rows function updateMessageFiltering_LiveLogging() { // TODO: Add callback to C++ layer to repopulate from cached entries var tableBody = document.getElementById('logTableBody'); var bDisplay_Msgs = (document.getElementById('cbIncType_Msgs').checked); var bDisplay_Wrns = (document.getElementById('cbIncType_Wrns').checked); var bDisplay_Errs = (document.getElementById('cbIncType_Errs').checked); for(var i=tableBody.rows.length-1; i >= 0; i--) // Possibly deleting rows so reverse order { // Show/hide based on filtering if (!testClassFilter(tableBody.rows[i].cells[3].innerText)) // Filtered out based on log entry class filtering tableBody.deleteRow(i); else // Delete rows based on log entry type filtering switch(tableBody.rows[i].className) { case 'Msg': if (!bDisplay_Msgs) tableBody.deleteRow(i); break; case 'Wrn': if (!bDisplay_Wrns) tableBody.deleteRow(i); break; case 'Err': if (!bDisplay_Errs) tableBody.deleteRow(i); break; } } setWaitCursor(false); } // Note lost entries function adjTotals(nLost, nMsg, nWrn, nErr, nHlp) { mnTotalLost += nLost; mnTotalMessages += nMsg; mnTotalWarnings += nWrn; mnTotalErrors += nErr; mnTotalEntries += nMsg + nWrn + nErr; updateLogEntryCounts(); } */ function updateLogEntryCounts() { document.getElementById('warningCount').innerText = mnTotalWarnings; document.getElementById('errorCount').innerText = mnTotalErrors; document.getElementById('messageCount').innerText = mnTotalMessages; document.getElementById('lostCount').innerText = mnTotalLost; } function clearLogTable() { // replace the old table with the new one var tableBody = document.getElementById('logTableBody'); while (tableBody.rows.length) tableBody.deleteRow(0); } function reset() { clearLogTable(); // update message type tallies mnTotalLost = 0; mnTotalMessages = 0; mnTotalWarnings = 0; mnTotalErrors = 0; mnTotalEntries = 0; mnTotalLogged = 0; updateLogEntryCounts(); } function setClassFilter(sFilter) { // Set filter msClassFilter = trimString(sFilter); // Determine if filter contains excludes only bClassFilterExcludesOnly = true; var arrTokens = msClassFilter.split(' '); for(var i = 0; i<arrTokens.length; i++) { // Not an exclude? if ( arrTokens[i].charAt(0) != '-') { bClassFilterExcludesOnly = false; break; // Only needed one } } // Apply filtering onLogEntryTableLoad(); } function trimString(sString) { var nLen = sString.length; // Find start point beyond spaces at start var nStartIdx = 0; while(nStartIdx < nLen && sString.charAt(nStartIdx) == ' ') nStartIdx++; // Empty? if (nStartIdx >= nLen) return ""; // Find end point before spaces at end var nEndIdx=sString.length-1; while(nEndIdx > nStartIdx && sString.charAt(nEndIdx) == ' ') nEndIdx -= 1; // Empty? if (nEndIdx < nStartIdx) return ""; // Return substring between spaces on either end return sString.substring(nStartIdx, nEndIdx+1); } function scrollLogToBottom() { var tableFrame = document.frames['logTableFrame']; tableFrame.document.getElementById('logTable').scrollTop = 99999999; } function onLogEntryTableLoad() { //alert("Table loaded"); var tableFrame = document.frames['logTableFrame']; var rows = tableFrame.document.getElementById('logTable').rows; // Hide table while we're updating it document.getElementById('logTableFrame').style.display = 'none'; // Filter table updateMessageFiltering(); // Display only last n rows var nDispCnt = (mnMaxDispCnt < rows.length) ? mnMaxDispCnt : rows.length; var nVisibleRowCnt = 0; var nRowIdx = rows.length; // find first entry to hide after skipping last n visible while (nRowIdx-- && nVisibleRowCnt < nDispCnt) // Row not filtered out? if (rows[nRowIdx].style.display != 'none') nVisibleRowCnt++; // hide everything before first entry to be shown if (nRowIdx > 0) while (nRowIdx--) try { rows[nRowIdx].style.display = 'none'; } catch(exception) {} // Show table document.getElementById('logTableFrame').style.display = ''; } // hide/show all rows of a given message type function updateMessageFiltering() { var tableFrame = document.frames['logTableFrame']; // TODO: Add callback to C++ layer to repopulate from cached entries var tableBody = tableFrame.document.getElementById('logTableBody'); var sDisplayMode_Msgs = (document.getElementById('cbIncType_Msgs').checked ? '' : 'none'); var sDisplayMode_Wrns = (document.getElementById('cbIncType_Wrns').checked ? '' : 'none'); var sDisplayMode_Errs = (document.getElementById('cbIncType_Errs').checked ? '' : 'none'); for(var i=0; i < tableBody.rows.length; i++) { // Show/hide based on filtering if (!testClassFilter(tableBody.rows[i].cells[3].innerText)) // Filtered out based on log entry class filtering tableBody.rows[i].style.display = 'none'; else // Delete rows based on log entry type filtering switch(tableBody.rows[i].className) { case 'Msg': tableBody.rows[i].style.display = sDisplayMode_Msgs; break; case 'Wrn': tableBody.rows[i].style.display = sDisplayMode_Wrns; break; case 'Err': tableBody.rows[i].style.display = sDisplayMode_Errs; break; } } setWaitCursor(false); } function testClassFilter(sClass) { // No class filter in force if (msClassFilter.length == 0) return true; // True if testing "" if (sClass.length == 0) return true; // Filter contains class? var nMatchIdx = msClassFilter.indexOf(sClass); // Not contained in filter class? if (nMatchIdx < 0) return bClassFilterExcludesOnly; // In filter but as an exclusion using leading -? if (nMatchIdx > 0 && msClassFilter.charAt(nMatchIdx-1) == '-') return false; // Inclued in filter string as an include return true; } function reloadLog() { document.frames('logTableFrame').document.location = "EACore.html"; } function onReloadLogClick() { // Hide table during load document.getElementById('logTableFrame').style.display = 'none'; // Reload log reloadLog(); } function onAutoReloadTimer() { reloadLog(); } function onLoad() { // Seed displayed line count maxEntriesShown.value = mnMaxDispCnt; // Start auto-refresh timer onAutoReloadIntervalChange(60); // Start with 1 minute updates // Initial log pull reloadLog(); } function onAutoReloadIntervalChange(nInterval_sec) { // cancel timer if (mnRefreshTimerID != 0) { clearTimeout(mnRefreshTimerID); mnRefreshTimerID = 0; } // setup a new timer //alert(Number(nInterval_sec)); if (Number(nInterval_sec) > 0) { mnRefreshTimerID = setTimeout("onAutoReloadTimer()", nInterval_sec * 1000); //alert("Automatic data reload interval set to " + nInterval_sec + " seconds"); } } function onMaxEntriesShownChange(nMaxDispCnt) { if (nMaxDispCnt > 0) { mnMaxDispCnt = nMaxDispCnt; onLogEntryTableLoad(); } } </script> </head> <body style="padding: 0px; margin: 0px;" onload="onLoad();"> <table style="padding:0px; margin:0px;" border="0" height="100%" width="100%"> <tr height="1px"> <!-- Shrink top row to fit --> <td> <table id="logTableHeader" width="100%"> <!-- HEADER --> <tr id="controlsContainer" style="padding: 0px; margin: 0px; border: 1px solid black; font: arial;" width="100%"> <td style="font-weight: bold;"> Filter by Message Type<br /> <input type="checkbox" checked onclick="filterMessages();" id="cbIncType_Msgs" name="cbIncType_Msgs"/> Messages<br /> <input type="checkbox" checked onclick="filterMessages();" id="cbIncType_Wrns" name="cbIncType_Wrns"/> Warnings<br /> <input type="checkbox" checked onclick="filterMessages();" id="cbIncType_Errs" name="cbIncType_Errs"/> Errors </td> <td style="font-weight: bold;"> Show Columns<br /> <input type="checkbox" checked onclick="setColVisibility(1, this.checked);" id="cbDispCol_Timestamp" name="cbDispCol_Timestamp"/> Timestamp<br /> <input type="checkbox" onclick="setColVisibility(2, this.checked);" id="cbDispCol_LogType" name="cbDispCol_LogType"/> Log Type<br /> <input type="checkbox" checked onclick="setColVisibility(3, this.checked);" id="cbDispCol_Class" name="cbDispCol_Class"/> C++ Class<br /> <input type="checkbox" checked onclick="setColVisibility(4, this.checked);" id="cbDispCol_Function" name="cbDispCol_Function"/> Function<br /> </td> <td style="font-weight: bold;"> Other Options<br /> <input type="checkbox" checked onclick="alternateRowColors(this.checked);" id="cbAltRowColors" name="cbAltRowColors"/> Alternate Row Colors </td> <td>&nbsp;</td> <td id="countContainer" style="font-weight: bold;" class="messageCount"> <table> <tr><td colspan="2">Totals</td></tr> <tr><td align="right">Warnings:</td><td><span id="warningCount">0</span></td></tr> <tr><td align="right">Errors:</td><td><span id="errorCount">0</span></td></tr> <tr><td align="right">Messages:</td><td><span id="messageCount">0</span></td></tr> <tr><td align="right">Lost:</td><td><span id="lostCount">0</span></td></tr> <tr><td align="right" nowrap>Max Shown:</td><td> <input id="maxEntriesShown" type="text" size="3" onkeydown="if (event.keyCode == 13) onMaxEntriesShownChange(this.value);" value="0" /> </td></tr> </table> </td> </tr> <!-- Note: Command block hidden for direct viewing and shown during direct logging usage --> <tr style="padding: 0px 0px 0px 20px; font-weight: bold;"> <!-- Command input box w/submit button and external log link --> <td id="cmdContainer" nowrap colspan="3"> <!-- EADM Command form --> <form id="Form1" method="get" action="ealink:-eadcommand:" name="cmdline"> Command: <input type="text" name="cmd" size="60" id="Text1" onkeypress="if (event.keyCode == 13) scrollLogToBottom();" /> <input type="submit" value="Go" name="login" id="Submit1" onclick="scrollLogToBottom();" /> </form> </td> <!-- Class filter --> <td nowrap> Class(s): <input type="text" size="30" name="tbClassFilter" id="tbClassFilter" onkeydown="if (event.keyCode == 13) setClassFilter(this.value);" /> </td> <!-- Reload --> <td nowrap align="right"> Auto Reload Interval: <input type="text" size="3" onkeydown="if (event.keyCode == 13) onAutoReloadIntervalChange(this.value);" value="60" /> <input type="button" onclick="onReloadLogClick()" value="Reload" /> </td> </tr> </table> </td> </tr> <tr> <td> <!-- LOG EVENTS --> <iframe id="logTableFrame" name="logTableFrame" onload="onLogEntryTableLoad()" marginwidth="0px" marginheight="0px" frameborder="0" src="" height="100%" width="100%" /> </td> </tr> </table> </body> </html>