diff --git a/pywb/static/default_banner.js b/pywb/static/default_banner.js
index 5def7ff2..58b43c2a 100644
--- a/pywb/static/default_banner.js
+++ b/pywb/static/default_banner.js
@@ -20,200 +20,211 @@ This file is part of pywb, https://github.com/webrecorder/pywb
// Creates the default pywb banner.
-(function () {
- if (window.top !== window) {
- return;
+(function() {
+ if (window.top !== window) {
+ return;
+ }
+
+ /**
+ * The default banner class
+ */
+ function DefaultBanner() {
+ if (!(this instanceof DefaultBanner)) return new DefaultBanner();
+ this.banner = null;
+ this.captureInfo = null;
+ this.last_state = {};
+ this.state = null;
+ this.title = '';
+ this.loadingId = 'bannerLoading';
+ this.onMessage = this.onMessage.bind(this);
+ }
+
+ // Functions required to be exposed by all banners
+
+ /**
+ * @desc Initialize (display) the banner
+ */
+ DefaultBanner.prototype.init = function() {
+ if (window.wbinfo) {
+ this.createBanner('_wb_plain_banner');
+ this.set_banner(
+ window.wbinfo.url,
+ window.wbinfo.timestamp,
+ window.wbinfo.is_live,
+ window.wbinfo.is_framed ? '' : document.title
+ );
+ } else {
+ this.createBanner('_wb_frame_top_banner');
+ }
+ };
+
+ /**
+ * @desc Called by ContentFrame to detect if the banner is still showing
+ * that the page is loading
+ * @returns {boolean}
+ */
+ DefaultBanner.prototype.stillIndicatesLoading = function() {
+ return document.getElementById(this.loadingId) != null;
+ };
+
+ /**
+ * @param {string} url - The URL of the replayed page
+ * @param {?string} ts - The timestamp of the replayed page.
+ * If we are in live mode this is undefined/empty string
+ * @param {boolean} is_live - A bool indicating if we are operating in live mode
+ */
+ DefaultBanner.prototype.updateCaptureInfo = function(url, ts, is_live) {
+ if (is_live && !ts) {
+ ts = new Date().toISOString().replace(/[-T:.Z]/g, '');
+ }
+ this.set_banner(url, ts, is_live, null);
+ };
+
+ /**
+ * @desc Called by ContentFrame when a message is received from the replay iframe
+ * @param {MessageEvent} event - The message event containing the message received
+ * from the replayed page
+ */
+ DefaultBanner.prototype.onMessage = function(event) {
+ var type = event.data.wb_type;
+
+ if (type === 'load' || type === 'replace-url') {
+ this.state = event.data;
+ this.last_state = this.state;
+ this.title = event.data.title || this.title;
+ } else if (type === 'title') {
+ this.state = this.last_state;
+ this.title = event.data.title;
+ } else {
+ return;
}
- /**
- * The default banner class
- */
- function DefaultBanner() {
- if (!(this instanceof DefaultBanner)) return new DefaultBanner();
- this.banner = null;
- this.captureInfo = null;
- this.last_state = {};
- this.state = null;
- this.title = "";
- this.loadingId = 'bannerLoading';
- this.onMessage = this.onMessage.bind(this);
+ // favicon update
+ if (type === 'load') {
+ var head = document.querySelector('head');
+ var oldLink = document.querySelectorAll("link[rel*='icon']");
+ var i = 0;
+ for (; i < oldLink.length; i++) {
+ head.removeChild(oldLink[i]);
+ }
+
+ if (this.state.icons) {
+ for (i = 0; i < this.state.icons.length; i++) {
+ var icon = this.state.icons[i];
+ var link = document.createElement('link');
+ link.rel = icon.rel;
+ link.href = icon.href;
+ head.appendChild(link);
+ }
+ }
}
- // Functions required to be exposed by all banners
+ this.set_banner(
+ this.state.url,
+ this.state.ts,
+ this.state.is_live,
+ this.title
+ );
+ };
- /**
- * @desc Initialize (display) the banner
- */
- DefaultBanner.prototype.init = function () {
- if (window.wbinfo) {
- this.createBanner('_wb_plain_banner');
- this.set_banner(
- window.wbinfo.url,
- window.wbinfo.timestamp,
- window.wbinfo.is_live,
- window.wbinfo.is_framed ? "" : document.title
- );
- } else {
- this.createBanner('_wb_frame_top_banner');
- }
- };
+ // Functions internal to the default banner
- /**
- * @desc Called by ContentFrame to detect if the banner is still showing
- * that the page is loading
- * @returns {boolean}
- */
- DefaultBanner.prototype.stillIndicatesLoading = function () {
- return document.getElementById(this.loadingId) != null;
- };
+ /**
+ * @desc Creates the underlying HTML elements comprising the banner
+ * @param {string} bid - The id for the banner
+ */
+ DefaultBanner.prototype.createBanner = function(bid) {
+ this.banner = document.createElement('wb_div', true);
+ this.banner.setAttribute('id', bid);
+ this.banner.setAttribute('lang', 'en');
+ this.captureInfo = document.createElement('span');
+ this.captureInfo.innerHTML =
+ 'Loading...';
+ this.captureInfo.id = '_wb_capture_info';
+ this.banner.appendChild(this.captureInfo);
+ document.body.insertBefore(this.banner, document.body.firstChild);
+ };
- /**
- * @param {string} url - The URL of the replayed page
- * @param {?string} ts - The timestamp of the replayed page.
- * If we are in live mode this is undefined/empty string
- * @param {boolean} is_live - A bool indicating if we are operating in live mode
- */
- DefaultBanner.prototype.updateCaptureInfo = function (url, ts, is_live) {
- if (is_live && !ts) {
- ts = new Date().toISOString().replace(/[-T:.Z]/g, '')
- }
- this.set_banner(url, ts, is_live, null);
- };
+ /**
+ * @desc Converts a timestamp to a date string. If is_gmt is truthy then
+ * the returned data string will be the results of date.toGMTString otherwise
+ * its date.toLocaleString()
+ * @param {?string} ts - The timestamp to receive the correct date string for
+ * @param {boolean} is_gmt - Is the returned date string to be in GMT time
+ * @returns {string}
+ */
+ DefaultBanner.prototype.ts_to_date = function(ts, is_gmt) {
+ if (!ts) {
+ return '';
+ }
- /**
- * @desc Called by ContentFrame when a message is received from the replay iframe
- * @param {MessageEvent} event - The message event containing the message received
- * from the replayed page
- */
- DefaultBanner.prototype.onMessage = function (event) {
- var type = event.data.wb_type;
+ if (ts.length < 14) {
+ ts += '00000000000000'.substr(ts.length);
+ }
- if (type === "load" || type === "replace-url") {
- this.state = event.data;
- this.last_state = this.state;
- this.title = event.data.title || this.title;
- } else if (type === "title") {
- this.state = this.last_state;
- this.title = event.data.title;
- } else {
- return;
- }
+ var datestr =
+ ts.substring(0, 4) +
+ '-' +
+ ts.substring(4, 6) +
+ '-' +
+ ts.substring(6, 8) +
+ 'T' +
+ ts.substring(8, 10) +
+ ':' +
+ ts.substring(10, 12) +
+ ':' +
+ ts.substring(12, 14) +
+ '-00:00';
- // favicon update
- if (type === 'load') {
- var head = document.querySelector('head');
- var oldLink = document.querySelectorAll("link[rel*='icon']");
- var i = 0;
- for (; i < oldLink.length; i++) {
- head.removeChild(oldLink[i]);
- }
+ var date = new Date(datestr);
- if (this.state.icons) {
- for (i = 0; i < this.state.icons.length; i++) {
- var icon = this.state.icons[i];
- var link = document.createElement('link');
- link.rel = icon.rel;
- link.href = icon.href;
- head.appendChild(link);
- }
- }
- }
+ if (is_gmt) {
+ return date.toGMTString();
+ } else {
+ return date.toLocaleString();
+ }
+ };
- this.set_banner(this.state.url, this.state.ts, this.state.is_live, this.title);
- };
+ /**
+ * @desc Updates the contents displayed by the banner
+ * @param {?string} url - The URL of the replayed page to be displayed in the banner
+ * @param {?string} ts - A timestamp to be displayed in the banner
+ * @param {boolean} is_live - Are we in live mode
+ * @param {?string} title - The title of the replayed page to be displayed in the banner
+ */
+ DefaultBanner.prototype.set_banner = function(url, ts, is_live, title) {
+ var capture_str;
+ var title_str;
- // Functions internal to the default banner
+ if (!ts) {
+ return;
+ }
- /**
- * @desc Creates the underlying HTML elements comprising the banner
- * @param {string} bid - The id for the banner
- */
- DefaultBanner.prototype.createBanner = function (bid) {
- this.banner = document.createElement("wb_div", true);
- this.banner.setAttribute("id", bid);
- this.banner.setAttribute("lang", "en");
- this.captureInfo = document.createElement('span');
- this.captureInfo.innerHTML = 'Loading...';
- this.captureInfo.id = '_wb_capture_info';
- this.banner.appendChild(this.captureInfo);
- document.body.insertBefore(this.banner, document.body.firstChild);
- };
+ var date_str = this.ts_to_date(ts, true);
- /**
- * @desc Converts a timestamp to a date string. If is_gmt is truthy then
- * the returned data string will be the results of date.toGMTString otherwise
- * its date.toLocaleString()
- * @param {?string} ts - The timestamp to receive the correct date string for
- * @param {boolean} is_gmt - Is the returned date string to be in GMT time
- * @returns {string}
- */
- DefaultBanner.prototype.ts_to_date = function (ts, is_gmt) {
- if (!ts) {
- return "";
- }
+ if (title) {
+ capture_str = title;
+ } else {
+ capture_str = url;
+ }
- if (ts.length < 14) {
- ts += "00000000000000".substr(ts.length);
- }
+ title_str = capture_str;
+ capture_str = "" + capture_str + '';
- var datestr = (ts.substring(0, 4) + "-" +
- ts.substring(4, 6) + "-" +
- ts.substring(6, 8) + "T" +
- ts.substring(8, 10) + ":" +
- ts.substring(10, 12) + ":" +
- ts.substring(12, 14) + "-00:00");
+ if (is_live) {
+ title_str = ' pywb Live: ' + title_str;
+ capture_str += 'Live on ';
+ } else {
+ title_str += 'pywb Archived: ' + title_str;
+ capture_str += 'Archived on ';
+ }
- var date = new Date(datestr);
+ title_str += ' (' + date_str + ')';
+ capture_str += date_str;
+ this.captureInfo.innerHTML = capture_str;
+ window.document.title = title_str;
+ };
- if (is_gmt) {
- return date.toGMTString();
- } else {
- return date.toLocaleString();
- }
- };
-
- /**
- * @desc Updates the contents displayed by the banner
- * @param {?string} url - The URL of the replayed page to be displayed in the banner
- * @param {?string} ts - A timestamp to be displayed in the banner
- * @param {boolean} is_live - Are we in live mode
- * @param {?string} title - The title of the replayed page to be displayed in the banner
- */
- DefaultBanner.prototype.set_banner = function (url, ts, is_live, title) {
- var capture_str;
- var title_str;
-
- if (!ts) {
- return;
- }
-
- var date_str = this.ts_to_date(ts, true);
-
- if (title) {
- capture_str = title;
- } else {
- capture_str = url;
- }
-
- title_str = capture_str;
- capture_str = "" + capture_str + "";
-
- if (is_live) {
- title_str = " pywb Live: " + title_str;
- capture_str += "Live on ";
- } else {
- title_str += "pywb Archived: " + title_str;
- capture_str += "Archived on ";
- }
-
- title_str += " (" + date_str + ")";
- capture_str += date_str;
- this.captureInfo.innerHTML = capture_str;
- window.document.title = title_str;
- };
-
- // all banners will expose themselves by adding themselves as WBBanner on window
- window.WBBanner = new DefaultBanner();
+ // all banners will expose themselves by adding themselves as WBBanner on window
+ window.WBBanner = new DefaultBanner();
})();
-
-
diff --git a/pywb/static/queryWorker.js b/pywb/static/queryWorker.js
index 464390d0..4e5cc04c 100644
--- a/pywb/static/queryWorker.js
+++ b/pywb/static/queryWorker.js
@@ -18,7 +18,7 @@ var decoder = new TextDecoder('utf-8');
*/
var bufferedPreviousChunk = null;
-self.onmessage = function (event) {
+self.onmessage = function(event) {
var data = event.data;
if (data.type === 'query') {
fetch(data.queryURL)
@@ -42,7 +42,8 @@ function defaultErrorCatcher(error) {
*/
function consumeResponseBodyAsStream(response) {
var reader = response.body.getReader();
- reader.read()
+ reader
+ .read()
.then(function consumeStream(result) {
if (result.done) {
if (bufferedPreviousChunk) {
@@ -58,7 +59,10 @@ function consumeResponseBodyAsStream(response) {
return;
}
transformChunk(result.value);
- reader.read().then(consumeStream).catch(defaultErrorCatcher);
+ reader
+ .read()
+ .then(consumeStream)
+ .catch(defaultErrorCatcher);
})
.catch(defaultErrorCatcher);
}
@@ -154,8 +158,11 @@ function handleCDXRecord(binaryCDXRecord) {
year: ts.substring(0, 4),
month: ts.substring(4, 6),
day: day.charAt(0) === '0' ? day.charAt(1) : day,
- time: ts.substring(8, 10) + colon +
- ts.substring(10, 12) + colon +
+ time:
+ ts.substring(8, 10) +
+ colon +
+ ts.substring(10, 12) +
+ colon +
ts.substring(12, 14)
},
wasError: false,
@@ -163,9 +170,3 @@ function handleCDXRecord(binaryCDXRecord) {
recordCountFormatted: recordCount.toLocaleString()
});
}
-
-
-
-
-
-
diff --git a/pywb/static/search.js b/pywb/static/search.js
index 99f7381c..92bae699 100644
--- a/pywb/static/search.js
+++ b/pywb/static/search.js
@@ -1,175 +1,191 @@
- var dtRE = /^\d{4,14}$/;
- var didSetWasValidated = false;
- var showBadDateTimeClass = 'show-optional-bad-input';
- var filterMods = {
- '=': 'Contains',
- '==': 'Matches Exactly',
- '=~': 'Matches Regex',
- '=!': 'Does Not Contains',
- '=!=': 'Is Not',
- '=!~': 'Does Not Begins With'
- };
+var dtRE = /^\d{4,14}$/;
+var didSetWasValidated = false;
+var showBadDateTimeClass = 'show-optional-bad-input';
+var filterMods = {
+ '=': 'Contains',
+ '==': 'Matches Exactly',
+ '=~': 'Matches Regex',
+ '=!': 'Does Not Contains',
+ '=!=': 'Is Not',
+ '=!~': 'Does Not Begins With'
+};
- var elemIds = {
- filtering: {
- by: 'filter-by',
- modifier: 'filter-modifier',
- expression: 'filter-expression',
- list: 'filter-list',
- nothing: 'filtering-nothing',
- add: 'add-filter',
- clear: 'clear-filters'
- },
- dateTime: {
- from: 'dt-from',
- fromBad: 'dt-from-bad',
- to: 'dt-to',
- toBad: 'dt-to-bad'
- },
- match: 'match-type-select',
- url: 'search-url',
- form: 'search-form',
- resultsNewWindow: 'open-results-new-window'
- };
+var elemIds = {
+ filtering: {
+ by: 'filter-by',
+ modifier: 'filter-modifier',
+ expression: 'filter-expression',
+ list: 'filter-list',
+ nothing: 'filtering-nothing',
+ add: 'add-filter',
+ clear: 'clear-filters'
+ },
+ dateTime: {
+ from: 'dt-from',
+ fromBad: 'dt-from-bad',
+ to: 'dt-to',
+ toBad: 'dt-to-bad'
+ },
+ match: 'match-type-select',
+ url: 'search-url',
+ form: 'search-form',
+ resultsNewWindow: 'open-results-new-window'
+};
-
- function makeCheckDateRangeChecker(dtInputId, dtBadNotice) {
- var dtInput = document.getElementById(dtInputId);
- dtInput.onblur = function () {
- if (dtInput.validity.valid && dtBadNotice.classList.contains(showBadDateTimeClass)) {
- return dtBadNotice.classList.remove(showBadDateTimeClass);
- }
- if (dtInput.validity.valueMissing) {
- if (dtBadNotice.classList.contains(showBadDateTimeClass)) {
- dtBadNotice.classList.remove(showBadDateTimeClass);
- }
- return;
- }
- if (dtInput.validity.badInput) {
- if (!dtBadNotice.classList.contains(showBadDateTimeClass)) {
- dtBadNotice.classList.add(showBadDateTimeClass);
- }
- return;
- }
- var validInput = dtRE.test(dtInput.value);
- if (validInput && dtBadNotice.classList.contains(showBadDateTimeClass)) {
+function makeCheckDateRangeChecker(dtInputId, dtBadNotice) {
+ var dtInput = document.getElementById(dtInputId);
+ dtInput.onblur = function() {
+ if (
+ dtInput.validity.valid &&
+ dtBadNotice.classList.contains(showBadDateTimeClass)
+ ) {
+ return dtBadNotice.classList.remove(showBadDateTimeClass);
+ }
+ if (dtInput.validity.valueMissing) {
+ if (dtBadNotice.classList.contains(showBadDateTimeClass)) {
dtBadNotice.classList.remove(showBadDateTimeClass);
- } else if (!validInput) {
+ }
+ return;
+ }
+ if (dtInput.validity.badInput) {
+ if (!dtBadNotice.classList.contains(showBadDateTimeClass)) {
dtBadNotice.classList.add(showBadDateTimeClass);
}
- };
- }
-
- function createAndAddNoFilter(filterList) {
- var nothing = document.createElement('li');
- nothing.innerText = 'No Filter';
- nothing.id = elemIds.filtering.nothing;
- filterList.appendChild(nothing);
- }
-
- function addFilter(event) {
- var by = document.getElementById(elemIds.filtering.by).value;
- if (!by) return;
- var modifier = document.getElementById(elemIds.filtering.modifier).value;
- var expr = document.getElementById(elemIds.filtering.expression).value;
- if (!expr) return;
- var filterExpr = 'filter' + modifier + by + ':' + expr;
- var filterList = document.getElementById(elemIds.filtering.list);
- var filterNothing = document.getElementById(elemIds.filtering.nothing);
- if (filterNothing) {
- filterList.removeChild(filterNothing);
+ return;
}
- var li = document.createElement('li');
- li.innerText = 'By ' + by[0].toUpperCase() + by.substr(1) + ' ' + filterMods[modifier] + ' ' + expr;
- li.dataset.filter = filterExpr;
- var nukeButton = document.createElement('button');
- nukeButton.type = 'button';
- nukeButton.role = 'button';
- nukeButton.className = 'btn btn-outline-danger close';
- nukeButton.setAttribute('aria-label', 'Remove Filter');
- var buttonX = document.createElement('span');
- buttonX.className = 'px-2';
- buttonX.innerHTML = '×';
- buttonX.setAttribute('aria-hidden', 'true');
- nukeButton.appendChild(buttonX);
- nukeButton.onclick = function () {
- filterList.removeChild(li);
- if (filterList.children.length === 0) {
- createAndAddNoFilter(filterList);
- }
- };
- li.appendChild(nukeButton);
- filterList.appendChild(li);
- }
-
- function clearFilters(event) {
- if (document.getElementById(elemIds.filtering.nothing)) return;
- var filterList = document.getElementById(elemIds.filtering.list);
- while (filterList.firstElementChild) {
- filterList.firstElementChild.onclick = null;
- filterList.removeChild(filterList.firstElementChild);
+ var validInput = dtRE.test(dtInput.value);
+ if (validInput && dtBadNotice.classList.contains(showBadDateTimeClass)) {
+ dtBadNotice.classList.remove(showBadDateTimeClass);
+ } else if (!validInput) {
+ dtBadNotice.classList.add(showBadDateTimeClass);
}
- createAndAddNoFilter(filterList);
- }
+ };
+}
- function performQuery(url) {
- var query = [window.wb_prefix + '*?url=' + url];
- var filterExpressions = document.getElementById(elemIds.filtering.list).children;
- if (filterExpressions.length) {
- for (var i = 0; i < filterExpressions.length; ++i) {
- var fexpr = filterExpressions[i];
- if (fexpr.dataset && fexpr.dataset.filter) {
- query.push(fexpr.dataset.filter.trim());
- }
+function createAndAddNoFilter(filterList) {
+ var nothing = document.createElement('li');
+ nothing.innerText = 'No Filter';
+ nothing.id = elemIds.filtering.nothing;
+ filterList.appendChild(nothing);
+}
+
+function addFilter(event) {
+ var by = document.getElementById(elemIds.filtering.by).value;
+ if (!by) return;
+ var modifier = document.getElementById(elemIds.filtering.modifier).value;
+ var expr = document.getElementById(elemIds.filtering.expression).value;
+ if (!expr) return;
+ var filterExpr = 'filter' + modifier + by + ':' + expr;
+ var filterList = document.getElementById(elemIds.filtering.list);
+ var filterNothing = document.getElementById(elemIds.filtering.nothing);
+ if (filterNothing) {
+ filterList.removeChild(filterNothing);
+ }
+ var li = document.createElement('li');
+ li.innerText =
+ 'By ' +
+ by[0].toUpperCase() +
+ by.substr(1) +
+ ' ' +
+ filterMods[modifier] +
+ ' ' +
+ expr;
+ li.dataset.filter = filterExpr;
+ var nukeButton = document.createElement('button');
+ nukeButton.type = 'button';
+ nukeButton.role = 'button';
+ nukeButton.className = 'btn btn-outline-danger close';
+ nukeButton.setAttribute('aria-label', 'Remove Filter');
+ var buttonX = document.createElement('span');
+ buttonX.className = 'px-2';
+ buttonX.innerHTML = '×';
+ buttonX.setAttribute('aria-hidden', 'true');
+ nukeButton.appendChild(buttonX);
+ nukeButton.onclick = function() {
+ filterList.removeChild(li);
+ if (filterList.children.length === 0) {
+ createAndAddNoFilter(filterList);
+ }
+ };
+ li.appendChild(nukeButton);
+ filterList.appendChild(li);
+}
+
+function clearFilters(event) {
+ if (document.getElementById(elemIds.filtering.nothing)) return;
+ var filterList = document.getElementById(elemIds.filtering.list);
+ while (filterList.firstElementChild) {
+ filterList.firstElementChild.onclick = null;
+ filterList.removeChild(filterList.firstElementChild);
+ }
+ createAndAddNoFilter(filterList);
+}
+
+function performQuery(url) {
+ var query = [window.wb_prefix + '*?url=' + url];
+ var filterExpressions = document.getElementById(elemIds.filtering.list)
+ .children;
+ if (filterExpressions.length) {
+ for (var i = 0; i < filterExpressions.length; ++i) {
+ var fexpr = filterExpressions[i];
+ if (fexpr.dataset && fexpr.dataset.filter) {
+ query.push(fexpr.dataset.filter.trim());
}
}
- var matchType = document.getElementById(elemIds.match).value;
- if (matchType) {
- query.push('matchType=' + matchType.trim());
- }
- var fromT = document.getElementById(elemIds.dateTime.from).value;
- if (fromT) {
- query.push('from=' + fromT.trim());
- }
- var toT = document.getElementById(elemIds.dateTime.to).value;
- if (toT) {
- query.push('to=' + toT.trim());
- }
- var builtQuery = query.join('&');
- if (document.getElementById(elemIds.resultsNewWindow).checked) {
- try {
- var win = window.open(builtQuery);
- win.focus();
- } catch (e) {
- document.location.href = builtQuery;
- }
- } else {
+ }
+ var matchType = document.getElementById(elemIds.match).value;
+ if (matchType) {
+ query.push('matchType=' + matchType.trim());
+ }
+ var fromT = document.getElementById(elemIds.dateTime.from).value;
+ if (fromT) {
+ query.push('from=' + fromT.trim());
+ }
+ var toT = document.getElementById(elemIds.dateTime.to).value;
+ if (toT) {
+ query.push('to=' + toT.trim());
+ }
+ var builtQuery = query.join('&');
+ if (document.getElementById(elemIds.resultsNewWindow).checked) {
+ try {
+ var win = window.open(builtQuery);
+ win.focus();
+ } catch (e) {
document.location.href = builtQuery;
}
+ } else {
+ document.location.href = builtQuery;
}
+}
- $(document).ready(function () {
- $('[data-toggle="tooltip"]').tooltip({
- container: 'body',
- delay: { show: 1000 }
- });
- makeCheckDateRangeChecker(elemIds.dateTime.from, document.getElementById(elemIds.dateTime.fromBad));
- makeCheckDateRangeChecker(elemIds.dateTime.to, document.getElementById(elemIds.dateTime.toBad));
- document.getElementById(elemIds.filtering.add).onclick = addFilter;
- document.getElementById(elemIds.filtering.clear).onclick = clearFilters;
- var searchURLInput = document.getElementById(elemIds.url);
- var form = document.getElementById(elemIds.form);
- form.addEventListener('submit', function (event) {
- event.preventDefault();
- event.stopPropagation();
- var url = searchURLInput.value;
- if (!url) {
- if (!didSetWasValidated) {
- form.classList.add('was-validated');
- didSetWasValidated = true;
- }
- return;
- }
- performQuery(url);
- });
+$(document).ready(function() {
+ $('[data-toggle="tooltip"]').tooltip({
+ container: 'body',
+ delay: { show: 1000 }
});
+ makeCheckDateRangeChecker(
+ elemIds.dateTime.from,
+ document.getElementById(elemIds.dateTime.fromBad)
+ );
+ makeCheckDateRangeChecker(
+ elemIds.dateTime.to,
+ document.getElementById(elemIds.dateTime.toBad)
+ );
+ document.getElementById(elemIds.filtering.add).onclick = addFilter;
+ document.getElementById(elemIds.filtering.clear).onclick = clearFilters;
+ var searchURLInput = document.getElementById(elemIds.url);
+ var form = document.getElementById(elemIds.form);
+ form.addEventListener('submit', function(event) {
+ event.preventDefault();
+ event.stopPropagation();
+ var url = searchURLInput.value;
+ if (!url) {
+ if (!didSetWasValidated) {
+ form.classList.add('was-validated');
+ didSetWasValidated = true;
+ }
+ return;
+ }
+ performQuery(url);
+ });
+});
diff --git a/pywb/static/wb_frame.js b/pywb/static/wb_frame.js
index e72f2c26..8a9f92da 100644
--- a/pywb/static/wb_frame.js
+++ b/pywb/static/wb_frame.js
@@ -17,88 +17,90 @@ This file is part of pywb, https://github.com/webrecorder/pywb
along with pywb. If not, see .
*/
-
/**
* @param {Object} content_info - Information about the contents to be replayed
*/
function ContentFrame(content_info) {
- if (!(this instanceof ContentFrame)) return new ContentFrame(content_info);
- this.last_inner_hash = window.location.hash;
- this.last_url = content_info.url;
- this.last_ts = content_info.request_ts;
- this.content_info = content_info;
- // bind event callbacks
- this.outer_hash_changed = this.outer_hash_changed.bind(this);
- this.handle_event = this.handle_event.bind(this);
- this.wbBanner = null;
- this.checkBannerToId = null;
+ if (!(this instanceof ContentFrame)) return new ContentFrame(content_info);
+ this.last_inner_hash = window.location.hash;
+ this.last_url = content_info.url;
+ this.last_ts = content_info.request_ts;
+ this.content_info = content_info;
+ // bind event callbacks
+ this.outer_hash_changed = this.outer_hash_changed.bind(this);
+ this.handle_event = this.handle_event.bind(this);
+ this.wbBanner = null;
+ this.checkBannerToId = null;
- window.addEventListener('hashchange', this.outer_hash_changed, false);
- window.addEventListener('message', this.handle_event);
+ window.addEventListener('hashchange', this.outer_hash_changed, false);
+ window.addEventListener('message', this.handle_event);
- if (document.readyState === 'complete') {
- this.init_iframe();
- } else {
- document.addEventListener('DOMContentLoaded', this.init_iframe.bind(this), {once: true});
- }
+ if (document.readyState === 'complete') {
+ this.init_iframe();
+ } else {
+ document.addEventListener('DOMContentLoaded', this.init_iframe.bind(this), {
+ once: true
+ });
+ }
- window.__WB_pmw = function (win) {
- this.pm_source = win;
- return this;
- };
+ window.__WB_pmw = function(win) {
+ this.pm_source = win;
+ return this;
+ };
}
/**
* @desc Initializes the replay iframe. If a banner exists (exposed on window as WBBanner)
* then the init function of the banner is called.
*/
-ContentFrame.prototype.init_iframe = function () {
- if (typeof (this.content_info.iframe) === 'string') {
- this.iframe = document.querySelector(this.content_info.iframe);
- } else {
- this.iframe = this.content_info.iframe;
- }
+ContentFrame.prototype.init_iframe = function() {
+ if (typeof this.content_info.iframe === 'string') {
+ this.iframe = document.querySelector(this.content_info.iframe);
+ } else {
+ this.iframe = this.content_info.iframe;
+ }
- if (!this.iframe) {
- console.warn('no iframe found ' + this.content_info.iframe + ' found');
- return;
- }
+ if (!this.iframe) {
+ console.warn('no iframe found ' + this.content_info.iframe + ' found');
+ return;
+ }
- this.extract_prefix();
- if (window.WBBanner) {
- this.wbBanner = window.WBBanner;
- this.wbBanner.init();
- }
- this.load_url(this.content_info.url, this.content_info.request_ts);
+ this.extract_prefix();
+ if (window.WBBanner) {
+ this.wbBanner = window.WBBanner;
+ this.wbBanner.init();
+ }
+ this.load_url(this.content_info.url, this.content_info.request_ts);
};
/**
* @desc Initializes the prefixes used to load the pages to be replayed
*/
-ContentFrame.prototype.extract_prefix = function () {
- this.app_prefix = this.content_info.app_prefix || this.content_info.prefix;
- this.content_prefix = this.content_info.content_prefix || this.content_info.prefix;
+ContentFrame.prototype.extract_prefix = function() {
+ this.app_prefix = this.content_info.app_prefix || this.content_info.prefix;
+ this.content_prefix =
+ this.content_info.content_prefix || this.content_info.prefix;
- if (this.app_prefix && this.content_prefix) {
- return;
+ if (this.app_prefix && this.content_prefix) {
+ return;
+ }
+
+ var inx = window.location.href.indexOf(this.content_info.url);
+
+ if (inx < 0) {
+ inx = window.location.href.indexOf('/http') + 1;
+ if (inx <= 0) {
+ inx = window.location.href.indexOf('///') + 1;
+ if (inx <= 0) {
+ console.warn('No Prefix Found!');
+ }
}
+ }
- var inx = window.location.href.indexOf(this.content_info.url);
+ this.prefix = window.location.href.substr(0, inx);
- if (inx < 0) {
- inx = window.location.href.indexOf('/http') + 1;
- if (inx <= 0) {
- inx = window.location.href.indexOf('///') + 1;
- if (inx <= 0) {
- console.warn('No Prefix Found!');
- }
- }
- }
-
- this.prefix = window.location.href.substr(0, inx);
-
- this.app_prefix = this.app_prefix || this.prefix;
- this.content_prefix = this.content_prefix || this.prefix;
+ this.app_prefix = this.app_prefix || this.prefix;
+ this.content_prefix = this.content_prefix || this.prefix;
};
/**
@@ -109,46 +111,46 @@ ContentFrame.prototype.extract_prefix = function () {
* @param {?boolean} content_url - Is the abs URL to be constructed using the content_prefix or app_prefix
* @returns {string}
*/
-ContentFrame.prototype.make_url = function (url, ts, content_url) {
- var mod, prefix;
+ContentFrame.prototype.make_url = function(url, ts, content_url) {
+ var mod, prefix;
- if (content_url) {
- mod = 'mp_';
- prefix = this.content_prefix;
- } else {
- mod = '';
- prefix = this.app_prefix;
- }
+ if (content_url) {
+ mod = 'mp_';
+ prefix = this.content_prefix;
+ } else {
+ mod = '';
+ prefix = this.app_prefix;
+ }
- if (ts || mod) {
- mod += '/';
- }
+ if (ts || mod) {
+ mod += '/';
+ }
- if (ts) {
- return prefix + ts + mod + url;
- } else {
- return prefix + mod + url;
- }
+ if (ts) {
+ return prefix + ts + mod + url;
+ } else {
+ return prefix + mod + url;
+ }
};
/**
* @desc Handles and routes all messages received from the replay iframe.
* @param {MessageEvent} event - A message event potentially containing a message from the replay iframe
*/
-ContentFrame.prototype.handle_event = function (event) {
- var frame_win = this.iframe.contentWindow;
- if (event.source === window.parent) {
- // Pass to replay frame
- frame_win.postMessage(event.data, '*');
- } else if (event.source === frame_win) {
- // Check if iframe url change message
- if (typeof (event.data) === 'object' && event.data['wb_type']) {
- this.handle_message(event);
- } else {
- // Pass to parent
- window.parent.postMessage(event.data, '*');
- }
+ContentFrame.prototype.handle_event = function(event) {
+ var frame_win = this.iframe.contentWindow;
+ if (event.source === window.parent) {
+ // Pass to replay frame
+ frame_win.postMessage(event.data, '*');
+ } else if (event.source === frame_win) {
+ // Check if iframe url change message
+ if (typeof event.data === 'object' && event.data['wb_type']) {
+ this.handle_message(event);
+ } else {
+ // Pass to parent
+ window.parent.postMessage(event.data, '*');
}
+ }
};
/**
@@ -156,33 +158,36 @@ ContentFrame.prototype.handle_event = function (event) {
* is exposed, calls the onMessage function of the exposed banner.
* @param {MessageEvent} event - The message event containing a message from the replay iframe
*/
-ContentFrame.prototype.handle_message = function (event) {
- if (this.wbBanner) {
- this.wbBanner.onMessage(event);
- }
- var state = event.data;
- var type = state.wb_type;
+ContentFrame.prototype.handle_message = function(event) {
+ if (this.wbBanner) {
+ this.wbBanner.onMessage(event);
+ }
+ var state = event.data;
+ var type = state.wb_type;
- if (type === 'load' || type === 'replace-url') {
- this.set_url(state);
- } else if (type === 'hashchange') {
- this.inner_hash_changed(state);
- }
+ if (type === 'load' || type === 'replace-url') {
+ this.set_url(state);
+ } else if (type === 'hashchange') {
+ this.inner_hash_changed(state);
+ }
};
/**
* @desc Updates the URL of the top frame
* @param {Object} state - The contents of a message rreceived from the replay iframe
*/
-ContentFrame.prototype.set_url = function (state) {
- if (state.url && (state.url !== this.last_url || state.request_ts !== this.last_ts)) {
- var new_url = this.make_url(state.url, state.request_ts, false);
+ContentFrame.prototype.set_url = function(state) {
+ if (
+ state.url &&
+ (state.url !== this.last_url || state.request_ts !== this.last_ts)
+ ) {
+ var new_url = this.make_url(state.url, state.request_ts, false);
- window.history.replaceState(state, '', new_url);
+ window.history.replaceState(state, '', new_url);
- this.last_url = state.url;
- this.last_ts = state.request_ts;
- }
+ this.last_url = state.url;
+ this.last_ts = state.request_ts;
+ }
};
/**
@@ -194,29 +199,28 @@ ContentFrame.prototype.set_url = function (state) {
* @param {?string} newTs - The new timestamp of the replay iframe. Is falsy if
* operating in live mode
*/
-ContentFrame.prototype.initBannerUpdateCheck = function (newUrl, newTs) {
- if (!this.wbBanner) return;
- var contentFrame = this;
- var replayIframeLoaded = function () {
- contentFrame.iframe.removeEventListener('load', replayIframeLoaded);
- contentFrame.checkBannerToId = setTimeout(function () {
- contentFrame.checkBannerToId = null;
- if (contentFrame.wbBanner.stillIndicatesLoading()) {
- contentFrame.wbBanner.updateCaptureInfo(
- newUrl,
- newTs,
- contentFrame.content_prefix.indexOf('/live') !== -1
- );
- }
- }, 2000);
- };
- if (this.checkBannerToId) {
- clearTimeout(this.checkBannerToId);
- }
- this.iframe.addEventListener('load', replayIframeLoaded);
+ContentFrame.prototype.initBannerUpdateCheck = function(newUrl, newTs) {
+ if (!this.wbBanner) return;
+ var contentFrame = this;
+ var replayIframeLoaded = function() {
+ contentFrame.iframe.removeEventListener('load', replayIframeLoaded);
+ contentFrame.checkBannerToId = setTimeout(function() {
+ contentFrame.checkBannerToId = null;
+ if (contentFrame.wbBanner.stillIndicatesLoading()) {
+ contentFrame.wbBanner.updateCaptureInfo(
+ newUrl,
+ newTs,
+ contentFrame.content_prefix.indexOf('/live') !== -1
+ );
+ }
+ }, 2000);
+ };
+ if (this.checkBannerToId) {
+ clearTimeout(this.checkBannerToId);
+ }
+ this.iframe.addEventListener('load', replayIframeLoaded);
};
-
/**
* @desc Navigates the replay iframe to a newURL and if a banner is exposed
* the initBannerUpdateCheck function is called.
@@ -224,44 +228,44 @@ ContentFrame.prototype.initBannerUpdateCheck = function (newUrl, newTs) {
* @param {?string} newTs - The new timestamp of the replay iframe. Is falsy if
* operating in live mode
*/
-ContentFrame.prototype.load_url = function (newUrl, newTs) {
- this.iframe.src = this.make_url(newUrl, newTs, true);
- if (this.wbBanner) {
- this.initBannerUpdateCheck(newUrl, newTs);
- }
+ContentFrame.prototype.load_url = function(newUrl, newTs) {
+ this.iframe.src = this.make_url(newUrl, newTs, true);
+ if (this.wbBanner) {
+ this.initBannerUpdateCheck(newUrl, newTs);
+ }
};
/**
* @desc Updates this frames hash to the one inside the replay iframe
* @param {Object} state - The contents of message received from the replay iframe
*/
-ContentFrame.prototype.inner_hash_changed = function (state) {
- if (window.location.hash !== state.hash) {
- window.location.hash = state.hash;
- }
- this.last_inner_hash = state.hash;
+ContentFrame.prototype.inner_hash_changed = function(state) {
+ if (window.location.hash !== state.hash) {
+ window.location.hash = state.hash;
+ }
+ this.last_inner_hash = state.hash;
};
/**
* @desc Updates the hash of the replay iframe on a hash change in this frame
* @param event
*/
-ContentFrame.prototype.outer_hash_changed = function (event) {
- if (window.location.hash === this.last_inner_hash) {
- return;
- }
+ContentFrame.prototype.outer_hash_changed = function(event) {
+ if (window.location.hash === this.last_inner_hash) {
+ return;
+ }
- if (this.iframe) {
- var message = {'wb_type': 'outer_hashchange', 'hash': window.location.hash};
+ if (this.iframe) {
+ var message = { wb_type: 'outer_hashchange', hash: window.location.hash };
- this.iframe.contentWindow.postMessage(message, '*', undefined, true);
- }
+ this.iframe.contentWindow.postMessage(message, '*', undefined, true);
+ }
};
/**
* @desc Cleans up any event listeners added by the content frame
*/
-ContentFrame.prototype.close = function () {
- window.removeEventListener('hashchange', this.outer_hash_changed);
- window.removeEventListener('message', this.handle_event);
+ContentFrame.prototype.close = function() {
+ window.removeEventListener('hashchange', this.outer_hash_changed);
+ window.removeEventListener('message', this.handle_event);
};