wait for elements

This commit is contained in:
2020-01-10 15:35:18 +08:00
parent 4656e4ff64
commit c504942144
5 changed files with 38 additions and 19 deletions

View File

@ -16,7 +16,8 @@
}, },
"background": { "background": {
"scripts": [ "scripts": [
"scripts/shared.js", "scripts/shared/tools.js",
"scripts/shared/common.js",
"scripts/background/messaging.js", "scripts/background/messaging.js",
"scripts/background/result.js", "scripts/background/result.js",
"scripts/background/signiture.js", "scripts/background/signiture.js",
@ -29,7 +30,8 @@
"content_scripts": [{ "content_scripts": [{
"matches": ["*://*/*"], "matches": ["*://*/*"],
"js": [ "js": [
"scripts/shared.js", "scripts/shared/tools.js",
"scripts/shared/common.js",
"scripts/content/content.js" "scripts/content/content.js"
], ],
"run_at": "document_idle" "run_at": "document_idle"

View File

@ -105,7 +105,7 @@ function extractTabData(tab, itemsSelector, fieldSelectors) {
itemsSelector: itemsSelector, itemsSelector: itemsSelector,
fieldSelectors: fieldSelectors fieldSelectors: fieldSelectors
} }
let cond = r => r !== undefined; let cond = r => !MSG_ELEMENT_NOT_FOUND.isEqual(r);
return sendMessage(tab, req, 'Extract data from the tab...', cond); return sendMessage(tab, req, 'Extract data from the tab...', cond);
} }

View File

@ -24,26 +24,30 @@
); );
function extract(itemsSelector, fieldSelectors) { function extract(itemsSelector, fieldSelectors) {
// let fieldNotFound = false; // 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)); let items = Array.from(document.querySelectorAll(itemsSelector));
if (!items.length) return []; // items may not loaded yet, tell the sender to retry.
if (!items.length) return MSG_ELEMENT_NOT_FOUND;
let results = items.map( let results = items.map(
item => { item => {
return fieldSelectors.map( return fieldSelectors.map(
selector => { selector => {
let [cls, attr] = selector.split('@').slice(0, 2); let [cls, attr] = selector.split('@').slice(0, 2);
// TODO: close tab to cancel task tip
// if (fieldNotFound) return;
let fieldVals = Array.from(item.querySelectorAll(cls)); let fieldVals = Array.from(item.querySelectorAll(cls));
// if (!fieldVals.length) { if (!fieldVals.length) {
// fieldNotFound = true; return;
// return; }
// } fieldFound[selector] = true;
return fieldVals.map(find => attr ? find[attr] : find.textContent.trim()).join('\n') return fieldVals.map(find => attr ? find[attr] : find.textContent.trim()).join('\n')
} }
) )
} }
); );
// return fieldNotFound ? [] : results // if it exists a field, which is not found in any row, the sender should retry.
return results; let shouldWait = fieldSelectors.reduce((p, c) => p || !fieldFound[c], false);
return shouldWait ? MSG_ELEMENT_NOT_FOUND : results
} }

8
scripts/shared/common.js Normal file
View File

@ -0,0 +1,8 @@
const EXT_NAME = "DataExtracter";
const ACTION_EXTRACT = `${EXT_NAME}:Extract`;
const ACTION_GOTO_URL = `${EXT_NAME}:GoToTUL`;
const ACTION_REPORT_IN = `${EXT_NAME}:ReportIn`;
const ACTION_QUERY_URL = `${EXT_NAME}:QueryURL`;
const MSG_ELEMENT_NOT_FOUND = new ConstMessage(1, "No element found for at least one selector, maybe it's not loaded yet");

View File

@ -1,8 +1,13 @@
const EXT_NAME = "DataExtracter"; class ConstMessage {
const ACTION_EXTRACT = `${EXT_NAME}:Extract`; constructor(id, message) {
const ACTION_GOTO_URL = `${EXT_NAME}:GoToTUL`; this.id = id;
const ACTION_REPORT_IN = `${EXT_NAME}:ReportIn`; this.message = message;
const ACTION_QUERY_URL = `${EXT_NAME}:QueryURL`; }
isEqual(err) {
if (!err || !err.id) return false;
return this.id == err.id;
}
}
function saveFile(data, mimeType, fileName) { function saveFile(data, mimeType, fileName) {
fileName = fileName || document.title || "result"; fileName = fileName || document.title || "result";
@ -34,4 +39,4 @@ function saveFile(data, mimeType, fileName) {
} else { } else {
location.href = url location.href = url
} }
} }