scrollToBottom option
This commit is contained in:
@ -1,53 +1,101 @@
|
||||
chrome.runtime.onMessage.addListener(
|
||||
function (request, sender, sendResponse) {
|
||||
if (!request.action) return;
|
||||
// console.log("Recieved request:",request);
|
||||
(function () {
|
||||
chrome.runtime.onMessage.addListener(
|
||||
function (request, sender, sendResponse) {
|
||||
if (!request.action) return;
|
||||
// console.log("Recieved request:",request);
|
||||
doAction(request, sender).then(r => sendResponse && sendResponse(r));
|
||||
// return true to indicate you wish to send a response asynchronously
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
async function doAction(request, sender) {
|
||||
switch (request.action) {
|
||||
case ACTION_EXTRACT:
|
||||
let data = extract(request.itemsSelector, request.fieldSelectors);
|
||||
if (sendResponse) sendResponse(data);
|
||||
break;
|
||||
return data;
|
||||
case ACTION_GOTO_URL:
|
||||
window.location.replace(request.url);
|
||||
if (sendResponse) sendResponse(request.url);
|
||||
break;
|
||||
return request.url;
|
||||
case ACTION_REPORT_IN:
|
||||
if (sendResponse) sendResponse(request.action);
|
||||
break;
|
||||
return request.action;
|
||||
case ACTION_QUERY_URL:
|
||||
if (sendResponse) sendResponse(window.location.href);
|
||||
break;
|
||||
return window.location.href;
|
||||
case ACTION_SCROLL_BOTTOM:
|
||||
return executeUntil(
|
||||
() => window.scrollTo(0, document.body.clientHeight),
|
||||
() => document.body.clientHeight - window.scrollY - window.innerHeight < 20,
|
||||
"Scroll to page bottom...",
|
||||
1000,
|
||||
10
|
||||
)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function extract(itemsSelector, fieldSelectors) {
|
||||
// since some elements may be loaded asynchronously.
|
||||
// if one field is never found, we should return undefined,
|
||||
// so that senders can detect to retry until elements loaded.
|
||||
// If user writes wrong selectors, the task retries infinitely.
|
||||
let fieldFound = {};
|
||||
let items = Array.from(document.querySelectorAll(itemsSelector));
|
||||
// items may not loaded yet, tell the sender to retry.
|
||||
if (!items.length) return MSG_ELEMENT_NOT_FOUND;
|
||||
let results = items.map(
|
||||
item => {
|
||||
return fieldSelectors.map(
|
||||
selector => {
|
||||
let [cls, attr] = selector.split('@').slice(0, 2);
|
||||
let fieldVals = Array.from(item.querySelectorAll(cls));
|
||||
if (!fieldVals.length) {
|
||||
return;
|
||||
function extract(itemsSelector, fieldSelectors) {
|
||||
// since some elements may be loaded asynchronously.
|
||||
// if one field is never found, we should return undefined,
|
||||
// so that senders can detect to retry until elements loaded.
|
||||
// If user writes wrong selectors, the task retries infinitely.
|
||||
let fieldFound = {};
|
||||
let items = Array.from(document.querySelectorAll(itemsSelector));
|
||||
// items may not loaded yet, tell the sender to retry.
|
||||
if (!items.length) return MSG_ELEMENT_NOT_FOUND;
|
||||
let results = items.map(
|
||||
item => {
|
||||
return fieldSelectors.map(
|
||||
selector => {
|
||||
let [cls, attr] = selector.split('@').slice(0, 2);
|
||||
let fieldVals = Array.from(item.querySelectorAll(cls));
|
||||
if (!fieldVals.length) {
|
||||
return;
|
||||
}
|
||||
fieldFound[selector] = true;
|
||||
return fieldVals.map(find => attr ? find[attr] : find.textContent.trim()).join('\n')
|
||||
}
|
||||
fieldFound[selector] = true;
|
||||
return fieldVals.map(find => attr ? find[attr] : find.textContent.trim()).join('\n')
|
||||
)
|
||||
}
|
||||
);
|
||||
// if it exists a field, which is not found in any row, the sender should retry.
|
||||
let shouldWait = fieldSelectors.reduce((p, c) => p || !fieldFound[c], false);
|
||||
return shouldWait ? MSG_ELEMENT_NOT_FOUND : results
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeatedly execute an function until the the detector returns true.
|
||||
* @param {object} fn the function to execute
|
||||
* @param {object} detector the detector.
|
||||
* @param {string} log messages logged to console.
|
||||
* @param {number} interval interval for detecting
|
||||
* @param {number} limit max execute times of a function
|
||||
* @return {Promise} a promise of the response.
|
||||
*/
|
||||
function executeUntil(fn, detector, log, interval, limit) {
|
||||
interval = interval || 500;
|
||||
let count = 0;
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
loop();
|
||||
|
||||
async function loop() {
|
||||
fn();
|
||||
limit++;
|
||||
if (limit && count >= limit) {
|
||||
reject(false);
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
// if it exists a field, which is not found in any row, the sender should retry.
|
||||
let shouldWait = fieldSelectors.reduce((p, c) => p || !fieldFound[c], false);
|
||||
return shouldWait ? MSG_ELEMENT_NOT_FOUND : results
|
||||
}
|
||||
setTimeout(() => {
|
||||
let flag = !detector || detector();
|
||||
if (log) console.log(log, flag ? '(OK)' : '(failed)');
|
||||
if (flag) {
|
||||
resolve(true);
|
||||
} else {
|
||||
loop();
|
||||
}
|
||||
}, interval);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user