Browse Source

logger: filter entries by tab

pull/2/head
gorhill 10 years ago
parent
commit
d7b6be4567
  1. 21
      src/css/logger-ui.css
  2. 9
      src/js/contentscript-end.js
  3. 165
      src/js/logger-ui.js
  4. 23
      src/js/messaging.js
  5. 2
      src/js/pagestats.js
  6. 5
      src/js/start.js
  7. 22
      src/logger-ui.html

21
src/css/logger-ui.css

@ -7,7 +7,6 @@ body {
margin: 0; margin: 0;
overflow-x: hidden; overflow-x: hidden;
padding: 0; padding: 0;
white-space: nowrap;
width: 100%; width: 100%;
} }
#toolbar { #toolbar {
@ -16,7 +15,7 @@ body {
box-sizing: border-box; box-sizing: border-box;
left: 0; left: 0;
margin: 0; margin: 0;
padding: 0 1em;
padding: 0.5em 1em;
position: fixed; position: fixed;
top: 0; top: 0;
width: 100%; width: 100%;
@ -28,7 +27,7 @@ body {
box-sizing: border-box; box-sizing: border-box;
cursor: pointer; cursor: pointer;
display: inline-block; display: inline-block;
font-size: 20px;
font-size: 150%;
margin: 0; margin: 0;
padding: 8px; padding: 8px;
} }
@ -39,6 +38,19 @@ body {
#toolbar .button:hover { #toolbar .button:hover {
background-color: #eee; background-color: #eee;
} }
#toolbar > div {
white-space: nowrap;
}
#toolbar > div:first-of-type {
font-size: 120%;
}
#toolbar > div > * {
vertical-align: middle;
}
#pageSelector {
max-width: 28em;
padding: 0.2em 0;
}
body #compactViewToggler.button:before { body #compactViewToggler.button:before {
content: '\f102'; content: '\f102';
} }
@ -55,14 +67,13 @@ body.f #filterButton {
background-color: #fee; background-color: #fee;
} }
#maxEntries { #maxEntries {
margin-left: 3em;
margin: 0 2em;
} }
input:focus { input:focus {
background-color: #ffe; background-color: #ffe;
} }
#content { #content {
font: 13px sans-serif; font: 13px sans-serif;
margin-top: 3.5em;
width: 100%; width: 100%;
} }

9
src/js/contentscript-end.js

@ -445,7 +445,8 @@ var nodeListsAddedHandler = function(nodeLists) {
what: 'contentScriptSummary', what: 'contentScriptSummary',
locationURL: window.location.href, locationURL: window.location.href,
inlineScript: false, inlineScript: false,
mustReport: true
mustReport: true,
title: ''
}; };
// https://github.com/gorhill/httpswitchboard/issues/25 // https://github.com/gorhill/httpswitchboard/issues/25
// & // &
@ -453,6 +454,12 @@ var nodeListsAddedHandler = function(nodeLists) {
// https://github.com/gorhill/httpswitchboard/issues/131 // https://github.com/gorhill/httpswitchboard/issues/131
hasInlineScript(document.querySelectorAll('a[href^="javascript:"],script'), summary); hasInlineScript(document.querySelectorAll('a[href^="javascript:"],script'), summary);
if ( window === window.top ) {
if ( document.title ) {
summary.title = document.title.trim();
}
}
//console.debug('contentscript-end.js > firstObservationHandler(): found %d script tags in "%s"', Object.keys(summary.scriptSources).length, window.location.href); //console.debug('contentscript-end.js > firstObservationHandler(): found %d script tags in "%s"', Object.keys(summary.scriptSources).length, window.location.href);
localMessager.send(summary); localMessager.send(summary);

165
src/js/logger-ui.js

@ -64,6 +64,15 @@ var dateOptions = {
/******************************************************************************/ /******************************************************************************/
// Adjust top padding of content table, to match that of toolbar height.
document.getElementById('content').style.setProperty(
'margin-top',
document.getElementById('toolbar').offsetHeight + 'px'
);
/******************************************************************************/
var escapeHTML = function(s) { var escapeHTML = function(s) {
return s.replace(reEscapeLeftBracket, '<') return s.replace(reEscapeLeftBracket, '<')
.replace(reEscapeRightBracket, '>'); .replace(reEscapeRightBracket, '>');
@ -74,6 +83,18 @@ var reEscapeRightBracket = />/g;
/******************************************************************************/ /******************************************************************************/
var classNameFromTabId = function(tabId) {
if ( tabId === noTabId ) {
return 'tab_bts';
}
if ( tabId !== '' ) {
return 'tab_' + tabId;
}
return '';
};
/******************************************************************************/
// Emphasize hostname and cookie name. // Emphasize hostname and cookie name.
var emphasizeCookie = function(s) { var emphasizeCookie = function(s) {
@ -261,11 +282,12 @@ var renderLogEntry = function(entry) {
if ( entry.tab ) { if ( entry.tab ) {
tr.classList.add('tab'); tr.classList.add('tab');
var className = classNameFromTabId(entry.tab);
if ( className !== '' ) {
tr.classList.add(className);
}
if ( entry.tab === noTabId ) { if ( entry.tab === noTabId ) {
tr.classList.add('tab_bts');
tr.cells[1].appendChild(createHiddenTextNode('bts')); tr.cells[1].appendChild(createHiddenTextNode('bts'));
} else if ( entry.tab !== '' ) {
tr.classList.add('tab_' + entry.tab);
} }
} }
if ( entry.cat !== '' ) { if ( entry.cat !== '' ) {
@ -329,6 +351,81 @@ var renderLogEntries = function(response) {
/******************************************************************************/ /******************************************************************************/
var synchronizeTabIds = function(newTabIds) {
var oldTabIds = allTabIds;
// Neuter rows for which a tab does not exist anymore
// TODO: sort to avoid using indexOf
var autoDeleteVoidRows = !!vAPI.localStorage.getItem('loggerAutoDeleteVoidRows');
var rowVoided = false;
var trs;
for ( var tabId in oldTabIds ) {
if ( oldTabIds.hasOwnProperty(tabId) === false ) {
continue;
}
if ( newTabIds.hasOwnProperty(tabId) ) {
continue;
}
// Mark or remove voided rows
trs = uDom('.tab_' + tabId);
if ( autoDeleteVoidRows ) {
toJunkyard(trs);
} else {
trs.removeClass('canMtx');
rowVoided = true;
}
// Remove popup if it is currently bound to a removed tab.
if ( tabId === popupManager.tabId ) {
popupManager.toggleOff();
}
}
var select = document.getElementById('pageSelector');
var selectValue = select.value;
var tabIds = Object.keys(newTabIds).sort(function(a, b) {
var sa = newTabIds[a].title || newTabIds[a].url;
var sb = newTabIds[b].title || newTabIds[b].url;
return sa.localeCompare(sb);
});
var option, entry;
for ( var i = 0, j = 2; i < tabIds.length; i++ ) {
tabId = tabIds[i];
if ( tabId === noTabId ) {
continue;
}
option = select.options[j];
j += 1;
if ( !option ) {
option = document.createElement('option');
select.appendChild(option);
}
entry = newTabIds[tabId];
option.textContent = entry.title || entry.url;
option.value = classNameFromTabId(tabId);
if ( option.value === selectValue ) {
option.setAttribute('selected', '');
} else {
option.removeAttribute('selected');
}
}
for ( ; j < select.options.length; j++ ) {
select.removeChild(select.options[j]);
}
if ( select.value !== selectValue ) {
select.selectedIndex = 0;
select.value = '';
select.options[0].setAttribute('selected', '');
pageSelectorChanged();
}
allTabIds = newTabIds;
return rowVoided;
};
/******************************************************************************/
var truncateLog = function(size) { var truncateLog = function(size) {
if ( size === 0 ) { if ( size === 0 ) {
size = 5000; size = 5000;
@ -356,28 +453,7 @@ var onLogBufferRead = function(response) {
// Neuter rows for which a tab does not exist anymore // Neuter rows for which a tab does not exist anymore
// TODO: sort to avoid using indexOf // TODO: sort to avoid using indexOf
var autoDeleteVoidRows = vAPI.localStorage.getItem('loggerAutoDeleteVoidRows');
var rowVoided = false, trs;
for ( var tabId in allTabIds ) {
if ( allTabIds.hasOwnProperty(tabId) === false ) {
continue;
}
if ( response.tabIds.hasOwnProperty(tabId) ) {
continue;
}
trs = uDom('.tab_' + tabId);
if ( autoDeleteVoidRows ) {
toJunkyard(trs);
} else {
trs.removeClass('canMtx');
rowVoided = true;
}
if ( tabId === popupManager.tabId ) {
popupManager.toggleOff();
}
}
allTabIds = response.tabIds;
var rowVoided = synchronizeTabIds(response.tabIds);
renderLogEntries(response); renderLogEntries(response);
if ( rowVoided ) { if ( rowVoided ) {
@ -408,6 +484,41 @@ var readLogBuffer = function() {
/******************************************************************************/ /******************************************************************************/
var pageSelectorChanged = function() {
var style = document.getElementById('tabFilterer');
var tabClass = document.getElementById('pageSelector').value;
var sheet = style.sheet;
while ( sheet.cssRules.length !== 0 ) {
sheet.deleteRule(0);
}
if ( tabClass !== '' ) {
sheet.insertRule(
'#content table tr:not(.' + tabClass + ') { display: none; }',
0
);
}
uDom('#refresh').toggleClass(
'disabled',
tabClass === '' || tabClass === 'tab_bts'
);
};
/******************************************************************************/
var refreshTab = function() {
var tabClass = document.getElementById('pageSelector').value;
var matches = tabClass.match(/^tab_(.+)$/);
if ( matches === null ) {
return;
}
if ( matches[1] === 'bts' ) {
return;
}
messager.send({ what: 'forceReloadTab', tabId: matches[1] });
};
/******************************************************************************/
var onMaxEntriesChanged = function() { var onMaxEntriesChanged = function() {
var raw = uDom(this).val(); var raw = uDom(this).val();
try { try {
@ -675,7 +786,7 @@ var popupManager = (function() {
popupObserver = new MutationObserver(resizePopup); popupObserver = new MutationObserver(resizePopup);
container.appendChild(popup); container.appendChild(popup);
style = document.querySelector('#content > style');
style = document.getElementById('popupFilterer');
style.textContent = styleTemplate.replace('{{tabId}}', localTabId); style.textContent = styleTemplate.replace('{{tabId}}', localTabId);
document.body.classList.add('popupOn'); document.body.classList.add('popupOn');
@ -727,6 +838,8 @@ var popupManager = (function() {
uDom.onLoad(function() { uDom.onLoad(function() {
readLogBuffer(); readLogBuffer();
uDom('#pageSelector').on('change', pageSelectorChanged);
uDom('#refresh').on('click', refreshTab);
uDom('#compactViewToggler').on('click', toggleCompactView); uDom('#compactViewToggler').on('click', toggleCompactView);
uDom('#clean').on('click', cleanBuffer); uDom('#clean').on('click', cleanBuffer);
uDom('#clear').on('click', clearBuffer); uDom('#clear').on('click', clearBuffer);

23
src/js/messaging.js

@ -390,17 +390,22 @@ var contentScriptSummaryHandler = function(tabId, details) {
if ( !details || !details.locationURL ) { if ( !details || !details.locationURL ) {
return; return;
} }
if ( details.inlineScript !== true ) {
return;
}
// scripts
// https://github.com/gorhill/httpswitchboard/issues/25 // https://github.com/gorhill/httpswitchboard/issues/25
var pageStore = µm.pageStoreFromTabId(tabId); var pageStore = µm.pageStoreFromTabId(tabId);
if ( pageStore === null ) { if ( pageStore === null ) {
return; return;
} }
if ( details.title ) {
pageStore.title = details.title;
}
// scripts
if ( details.inlineScript !== true ) {
return;
}
var pageHostname = pageStore.pageHostname; var pageHostname = pageStore.pageHostname;
var µmuri = µm.URI.set(details.locationURL); var µmuri = µm.URI.set(details.locationURL);
var frameURL = µmuri.normalizedURI(); var frameURL = µmuri.normalizedURI();
@ -904,10 +909,16 @@ var onMessage = function(request, sender, callback) {
switch ( request.what ) { switch ( request.what ) {
case 'readMany': case 'readMany':
var tabIds = {}; var tabIds = {};
var pageStore;
for ( var tabId in µm.pageStores ) { for ( var tabId in µm.pageStores ) {
if ( µm.pageStores.hasOwnProperty(tabId) ) {
tabIds[tabId] = true;
pageStore = µm.pageStoreFromTabId(tabId);
if ( pageStore === null ) {
continue;
} }
tabIds[tabId] = {
title: pageStore.title,
url: pageStore.pageUrl
};
} }
response = { response = {
colorBlind: false, colorBlind: false,

2
src/js/pagestats.js

@ -336,6 +336,7 @@ PageStore.prototype.init = function(tabContext) {
this.pageUrl = tabContext.normalURL; this.pageUrl = tabContext.normalURL;
this.pageHostname = tabContext.rootHostname; this.pageHostname = tabContext.rootHostname;
this.pageDomain = tabContext.rootDomain; this.pageDomain = tabContext.rootDomain;
this.title = '';
this.requests = µm.PageRequestStats.factory(); this.requests = µm.PageRequestStats.factory();
this.domains = {}; this.domains = {};
this.allHostnamesString = ' '; this.allHostnamesString = ' ';
@ -357,6 +358,7 @@ PageStore.prototype.dispose = function() {
this.pageUrl = ''; this.pageUrl = '';
this.pageHostname = ''; this.pageHostname = '';
this.pageDomain = ''; this.pageDomain = '';
this.title = '';
this.domains = {}; this.domains = {};
this.allHostnamesString = ' '; this.allHostnamesString = ' ';

5
src/js/start.js

@ -164,9 +164,8 @@ var onPSLReady = function() {
// rhill 2013-11-24: bind behind-the-scene virtual tab/url manually, since the // rhill 2013-11-24: bind behind-the-scene virtual tab/url manually, since the
// normal way forbid binding behind the scene tab. // normal way forbid binding behind the scene tab.
// https://github.com/gorhill/httpswitchboard/issues/67 // https://github.com/gorhill/httpswitchboard/issues/67
µm.pageStores[vAPI.noTabId] = µm.PageStore.factory(
µm.tabContextManager.mustLookup(vAPI.noTabId)
);
µm.pageStores[vAPI.noTabId] = µm.PageStore.factory(µm.tabContextManager.mustLookup(vAPI.noTabId));
µm.pageStores[vAPI.noTabId].title = vAPI.i18n('statsPageDetailedBehindTheScenePage');
vAPI.tabs.getAll(onTabsReady); vAPI.tabs.getAll(onTabsReady);
}; };

22
src/logger-ui.html

@ -9,15 +9,25 @@
<body class="compactView f"> <body class="compactView f">
<div id="toolbar"> <div id="toolbar">
<span id="compactViewToggler" class="button fa"></span>
<span id="clean" class="button fa disabled">&#xf00d;</span>
<span id="clear" class="button fa disabled">&#xf12d;</span>
<span id="filterButton" class="button fa">&#xf0b0;</span><input id="filterInput" type="text" placeholder="loggerFilterInputPlaceholder">
<input id="maxEntries" type="text" size="5" title="logMaxEntriesTip">
<div>
<select id="pageSelector">
<option value="" data-i18n="statsPageDetailedAllPages">
<option value="tab_bts" data-i18n="statsPageDetailedBehindTheScenePage">
</select>
<span id="refresh" class="button disabled fa">&#xf021;</span>
</div>
<div>
<span id="compactViewToggler" class="button fa"></span>
<span id="clean" class="button fa disabled">&#xf00d;</span>
<span id="clear" class="button fa disabled">&#xf12d;</span>
<span id="filterButton" class="button fa">&#xf0b0;</span><input id="filterInput" type="text" placeholder="loggerFilterInputPlaceholder">
<input id="maxEntries" type="text" size="5" title="logMaxEntriesTip">
</div>
</div> </div>
<div id="content"> <div id="content">
<style></style>
<style id="tabFilterer"></style>
<style id="popupFilterer"></style>
<table> <table>
<colgroup><col><col><col><col><col></colgroup> <colgroup><col><col><col><col><col></colgroup>
<tbody></tbody> <tbody></tbody>

Loading…
Cancel
Save