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