save and load state
This commit is contained in:
		| @ -3,6 +3,7 @@ | |||||||
| <link> | <link> | ||||||
| <meta charset="utf-8"> | <meta charset="utf-8"> | ||||||
| <title>Data Extractor</title> | <title>Data Extractor</title> | ||||||
|  | <script charset="UTF-8" type="text/javascript" src="../scripts/shared/common.js"></script> | ||||||
| <script charset="UTF-8" type="text/javascript" src="tip.js"></script> | <script charset="UTF-8" type="text/javascript" src="tip.js"></script> | ||||||
|  |  | ||||||
| <link rel="stylesheet" href="styles/bootstrap.min.css"> | <link rel="stylesheet" href="styles/bootstrap.min.css"> | ||||||
| @ -32,7 +33,6 @@ | |||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|         <div class="row"> |         <div class="row"> | ||||||
|  |  | ||||||
|             <div class="col"> |             <div class="col"> | ||||||
|                 <h6>Quick Start</h6> |                 <h6>Quick Start</h6> | ||||||
|             </div> |             </div> | ||||||
| @ -42,22 +42,33 @@ | |||||||
|                 <div class="alert alert-success small"> |                 <div class="alert alert-success small"> | ||||||
|                     <p> |                     <p> | ||||||
|                         <b>Extract current page</b>: |                         <b>Extract current page</b>: | ||||||
|                         <br>new Extractor().task(".list-item", ["a.title", "p.content"]).start(); |                         <br>> $(".list-item", ["a.title", "p.content"]); | ||||||
|                     </p> |                     </p> | ||||||
|                     <p> |                     <p> | ||||||
|                         <b>Extract multiple pages (1-10, interval 1)</b>: |                         <b>Extract multiple pages (1-10, interval 1)</b>: | ||||||
|                         <br>new Extractor().task(".list-item", ["a.title", "p.content"], |                         <br>> job=new Extractor().task(".list-item", ["a.title", "p.content"], | ||||||
|                         "http://sample.com/?pn=${page}", 1, 10, 1).start(); |                         "http://sample.com/?pn=${page}", 1, 10, 1); | ||||||
|  |                         <br>> job.start(); | ||||||
|  |  | ||||||
|                     </p> |                     </p> | ||||||
|                     <p> |                     <p> | ||||||
|                         <b>Full document:</b> |                         <b>Full document at:</b> | ||||||
|                         <br> |                         <br> | ||||||
|                         <a href="#" id="link-document">https://git.jebbs.co/jebbs/data-extracter-extesion</a> |                         <a href="#" id="link-document">https://git.jebbs.co/jebbs/data-extracter-extesion</a> | ||||||
|                     </p> |                     </p> | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|  |         <div class="row"> | ||||||
|  |             <div class="col"> | ||||||
|  |                 <h6>Saved State</h6> | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  |         <div class="row"> | ||||||
|  |             <div class="col"> | ||||||
|  |                <input type="file" name="state" id="state-input"> | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|     </div> |     </div> | ||||||
| </body> | </body> | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								popup/tip.js
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								popup/tip.js
									
									
									
									
									
								
							| @ -11,4 +11,22 @@ window.onload = function () { | |||||||
|                 'url': `https://git.jebbs.co/jebbs/data-extracter-extesion` |                 'url': `https://git.jebbs.co/jebbs/data-extracter-extesion` | ||||||
|             }); |             }); | ||||||
|         }) |         }) | ||||||
|  |     document.querySelector('#state-input') | ||||||
|  |         .addEventListener('change', function (...args) { | ||||||
|  |             if (this.files.length == 1) { | ||||||
|  |                 var reader = new FileReader(); | ||||||
|  |                 let fileName = this.files[0].name; | ||||||
|  |                 reader.readAsText(this.files[0], "UTF-8"); | ||||||
|  |                 reader.onload = function (evt) { | ||||||
|  |                     var fileString = evt.target.result; | ||||||
|  |                     chrome.runtime.sendMessage({ | ||||||
|  |                         action: ACTION_UPLOAD_STATE, | ||||||
|  |                         state: fileString, | ||||||
|  |                         name: fileName | ||||||
|  |                     }, r => { | ||||||
|  |                         if (r) console.log('State sent:', r); | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }); | ||||||
| } | } | ||||||
| @ -1,9 +1,31 @@ | |||||||
|  | var __EXTRACTOR_STATE__ = ""; | ||||||
|  |  | ||||||
| class Extractor { | class Extractor { | ||||||
|     constructor(options) { |     constructor(options) { | ||||||
|         this._tasks = []; |         this._tasks = []; | ||||||
|         this._running = false; |         this._running = false; | ||||||
|         this._options = options; |         this._options = options; | ||||||
|     } |     } | ||||||
|  |     /** | ||||||
|  |      * Save current state, in case we restore it later. | ||||||
|  |      */ | ||||||
|  |     save() { | ||||||
|  |         saveFile(JSON.stringify(this), 'application/json', 'state.json'); | ||||||
|  |     } | ||||||
|  |     /** | ||||||
|  |      * Restore previous state by loading from saved state. | ||||||
|  |      */ | ||||||
|  |     load() { | ||||||
|  |         if (!__EXTRACTOR_STATE__) { | ||||||
|  |             console.log('No state found. \nPlease upload a saved state from the popup window first.'); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         let state = JSON.parse(__EXTRACTOR_STATE__); | ||||||
|  |         __EXTRACTOR_STATE__ = ""; | ||||||
|  |         this._options = state._options; | ||||||
|  |         this._tasks = state._tasks.map(t => new Task(this._options, 'whaterver', ['whaterver']).load(t)); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|     /** |     /** | ||||||
|      * Add a task to Extractor. \n |      * Add a task to Extractor. \n | ||||||
|      * One Extractor could has multiple tasks, which orgnized in a task chian. |      * One Extractor could has multiple tasks, which orgnized in a task chian. | ||||||
| @ -76,7 +98,7 @@ class Extractor { | |||||||
|         }, Promise.resolve(undefined)).then( |         }, Promise.resolve(undefined)).then( | ||||||
|             () => { |             () => { | ||||||
|                 this._running = false; |                 this._running = false; | ||||||
|                 this.save(); |                 this.export(); | ||||||
|             } |             } | ||||||
|         ).catch(err => { |         ).catch(err => { | ||||||
|             this._running = false; |             this._running = false; | ||||||
| @ -84,10 +106,10 @@ class Extractor { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|     /** |     /** | ||||||
|      * Save result of a task |      * export result of a task to CSV | ||||||
|      * @param {number} taskid which task id to save, begins with 0 |      * @param {number} taskid which task id to save, begins with 0 | ||||||
|      */ |      */ | ||||||
|     save(taskid) { |     export(taskid) { | ||||||
|         let id = this._checkTaskId(taskid, this._tasks.length - 1); |         let id = this._checkTaskId(taskid, this._tasks.length - 1); | ||||||
|         if (id < 0) return; |         if (id < 0) return; | ||||||
|         let results = this._tasks[id].results |         let results = this._tasks[id].results | ||||||
|  | |||||||
| @ -50,10 +50,18 @@ function sendMessage(tab, req, log, cond, interval, limit = 0) { | |||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
| chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) { | chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { | ||||||
|     if (!message.action || !message.action.startsWith(EXT_NAME)) { |     if (!request.action || !request.action.startsWith(EXT_NAME)) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     sendResponse("Calling from user pages is not allowed."); |     switch (request.action) { | ||||||
|     return; |         case ACTION_UPLOAD_STATE: | ||||||
|  |             sendResponse('recieved!'); | ||||||
|  |             __EXTRACTOR_STATE__ = request.state; | ||||||
|  |             console.log(`State (${request.name}) recieved. Use following to load it: \nsome_var = new Extractor().load()`); | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             sendResponse("Request not supported."); | ||||||
|  |             break; | ||||||
|  |     } | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -17,6 +17,15 @@ class Task { | |||||||
|         this._fieldSelectors = args.shift(); |         this._fieldSelectors = args.shift(); | ||||||
|         this._urls = parseUrls(...args); |         this._urls = parseUrls(...args); | ||||||
|     } |     } | ||||||
|  |     load(state) { | ||||||
|  |         this._itemsSelector = state._itemsSelector; | ||||||
|  |         this._data = state._data; | ||||||
|  |         this._data_keys = state._data_keys; | ||||||
|  |         this._itemsSelector = state._itemsSelector; | ||||||
|  |         this._fieldSelectors = state._fieldSelectors; | ||||||
|  |         this._urls = state._urls; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|     get urls() { |     get urls() { | ||||||
|         return this._urls; |         return this._urls; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -1,12 +1,8 @@ | |||||||
| const EXT_NAME = "DataExtracter"; | const EXT_NAME = "DataExtracter"; | ||||||
|  |  | ||||||
| const URL_REG = getWebUrl(); |  | ||||||
|  |  | ||||||
| const ACTION_EXTRACT = `${EXT_NAME}:Extract`; | const ACTION_EXTRACT = `${EXT_NAME}:Extract`; | ||||||
| const ACTION_GOTO_URL = `${EXT_NAME}:GoToTUL`; | const ACTION_GOTO_URL = `${EXT_NAME}:GoToTUL`; | ||||||
| const ACTION_REPORT_IN = `${EXT_NAME}:ReportIn`; | const ACTION_REPORT_IN = `${EXT_NAME}:ReportIn`; | ||||||
| const ACTION_QUERY_URL = `${EXT_NAME}:QueryURL`; | const ACTION_QUERY_URL = `${EXT_NAME}:QueryURL`; | ||||||
| const ACTION_SCROLL_BOTTOM = `${EXT_NAME}:ScrollToBottom`; | const ACTION_SCROLL_BOTTOM = `${EXT_NAME}:ScrollToBottom`; | ||||||
|  | const ACTION_UPLOAD_STATE = `${EXT_NAME}:UploadStateFile`; | ||||||
| const MSG_ELEMENT_NOT_FOUND = new ConstMessage(1, "No element found for at least one selector, maybe it's not loaded yet"); |  | ||||||
| const MSG_URL_SKIPPED = new ConstMessage(100, "Skipped current URL"); |  | ||||||
|  | |||||||
| @ -9,6 +9,10 @@ class ConstMessage { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | const URL_REG = getWebUrl(); | ||||||
|  | const MSG_ELEMENT_NOT_FOUND = new ConstMessage(1, "No element found for at least one selector, maybe it's not loaded yet"); | ||||||
|  | const MSG_URL_SKIPPED = new ConstMessage(100, "Skipped current URL"); | ||||||
|  |  | ||||||
| function saveFile(data, mimeType, fileName) { | function saveFile(data, mimeType, fileName) { | ||||||
|     fileName = fileName || document.title || "result"; |     fileName = fileName || document.title || "result"; | ||||||
|     var blob; |     var blob; | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user