- // ==UserScript==
- // @name hipda-ID笔记
- // @namespace http://tampermonkey.net/
- // @version 0.2
- // @description 来自地板带着爱,记录上网冲浪的美好瞬间
- // @author 屋大维
- // @license MIT
- // @match https://www.hi-pda.com/forum/viewthread.php?tid*
- // @resource IMPORTED_CSS https://code.jquery.com/ui/1.13.0/themes/base/jquery-ui.css
- // @require https://code.jquery.com/jquery-3.4.1.min.js
- // @require https://code.jquery.com/ui/1.13.0/jquery-ui.js
- // @icon https://icons.iconarchive.com/icons/iconshock/real-vista-project-managment/64/task-notes-icon.png
- // @grant GM.setValue
- // @grant GM.getValue
- // @grant GM.deleteValue
- // @grant GM_getResourceText
- // @grant GM_addStyle
- // ==/UserScript==
-
- (async function() {
- 'use strict';
- // CSS
- const my_css = GM_getResourceText("IMPORTED_CSS");
- GM_addStyle(my_css);
- GM_addStyle(".no-close .ui-dialog-titlebar-close{display:none} textarea{height:100%;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}");
-
- // Your code here...
- // helpers
- function htmlToElement(html) {
- var template = document.createElement('template');
- html = html.trim(); // Never return a text node of whitespace as the result
- template.innerHTML = html;
- return template.content.firstChild;
- }
-
- // classes
- class HpPost {
- constructor() {
- }
-
- getPostTid() {
- return location.href.match(/tid=(\d+)/) ? parseInt(location.href.match(/tid=(\d+)/)[1]) : -999;
- }
-
- getUserUid() {
- return parseInt($("cite > a").attr("href").split("uid=")[1]);
- }
-
- getHpThreads() {
- let postTid = this.getPostTid();
- let divs = $('#postlist > div').get();
- return divs.map(d => new Hpthread(postTid, d));
- }
-
- addNoteManagementUI(_notebook) {
- var that = this;
- var button = htmlToElement(`
- <button id="noteButton_management">
- <span><img src="https://icons.iconarchive.com/icons/iconshock/real-vista-project-managment/32/task-notes-icon.png"></img></span>
- </button>
- `);
-
- // create dialog
- let dialog = htmlToElement(`
- <div id="noteDialog_management" style="display: none;">
- <h3>hipda-ID笔记 v${GM_info.script.version}</h3>
- <p style="margin: 10px auto 10px auto;">来自地板带着爱</p>
- <div>
- <button id="noteButton_import">导入</button>
- <button id="noteButton_export">导出</button>
- <button id="noteButton_reset">重置</button>
- </div>
- </div>
- `);
- $("body").append(dialog);
-
- $(document).ready( function () {
- $(document).on ("click", "#noteButton_import", function() {
- let r = confirm("确定要导入ID笔记吗?现有笔记将会被覆盖!");
- if (!r) {
- return;
- }
-
- // prompt cannot handle large file, extend it in the future
- let data = prompt("请将 id笔记.json 中的文本复制粘贴入文本框:");
- if (data !== null) {
- // try to load
- try {
- let j = JSON.parse(data);
- _notebook.importNotebook(j);
- } catch(err) {
- alert("格式错误!" + err);
- return;
- }
- alert("导入成功!");
- }
- });
- $(document).on ("click", "#noteButton_export", function() {
- let r = confirm("确定要导出ID笔记吗?");
- if (!r) {
- return;
- }
- let a = document.createElement("a");
- a.href = "data:text," + _notebook.exportNotebook();
- a.download = "id笔记.json";
- a.click();
- });
- $(document).on ("click", "#noteButton_reset", function() {
- let r = confirm("确定要清空ID笔记吗?");
- if (!r) {
- return;
- }
- _notebook.resetNotebook();
- alert("ID笔记已经清空!");
- });
- $(document).on ("click", `#noteButton_management`, function () {
- console.log("open notebook management dialog");
- $(`#noteDialog_management`).dialog({
- title: "ID笔记:管理面板",
- height: 150,
- width: 300,
- closeOnEscape: true,
- });
- });
- });
-
- // add UI
- let d = $("td.modaction").last();
- d.append(button);
-
- }
-
- }
-
- class Hpthread {
- constructor(postTid, threadDiv) {
- this.postTid = postTid;
- this._thread_div = threadDiv;
- }
-
- getThreadAuthorName() {
- return $(this._thread_div).find("div.postinfo > a").first().text();
- }
-
- getThreadAuthorUid() {
- return parseInt($(this._thread_div).find("div.postinfo > a").first().attr("href").split("uid=")[1]);
- }
-
- getThreadPid() {
- return parseInt($(this._thread_div).attr("id").split("_")[1]);
- }
-
- getGotoUrl() {
- return `https://www.hi-pda.com/forum/redirect.php?goto=findpost&ptid=${this.postTid}&pid=${this.getThreadPid()}`;
- }
-
- getThreadContent() {
- // get text without quotes
- return $(this._thread_div).find("td.t_msgfont").first().clone().children().remove().end().text().trim();
- }
-
- getThreadBrief(n) {
- let content = this.getThreadContent();
- if (content.length <= n) {
- return content;
- }
- return content.slice(0, n) + "\n\n【以上为截取片段】" ;
- }
-
- addNoteUI(_notebook) {
- let uid = this.getThreadAuthorUid();
- let index = $(this._thread_div).index();
- let userName = this.getThreadAuthorName();
-
- var that = this;
- // create an UI element which contains data and hooks
- // button
- let button = htmlToElement(`
- <button id="noteButton_${index}" style="color:grey; margin-left:20px;">
- ID笔记
- </button>
- `);
- // note dialog
- let dialog = htmlToElement(`
- <div id="noteDialog_${index}" style="display: none;">
- <textarea rows="10" wrap="hard" placeholder="暂时没有笔记">
- </div>
- `);
- $("body").append(dialog);
-
- // add event to button
- $(document).ready( function () {
- $(document).on ("click", `#noteButton_${index}`, function () {
- console.log("open note for", userName);
- // freshly fetched from DB
- $(`#noteDialog_${index}`).find('textarea').first().val(_notebook.get(uid));
- $(`#noteDialog_${index}`).dialog({
- title: `ID笔记:${userName}`,
- dialogClass: "no-close",
- closeText: "hide",
- closeOnEscape: true,
- height: 350,
- width: 600,
- buttons: [
- {
- text: "插入当前楼层",
- click: function() {
- let txt = $(`#noteDialog_${index}`).find('textarea').first();
- var caretPos = txt[0].selectionStart;
- var textAreaTxt = txt.val();
- var txtToAdd = `====\n引用: ${that.getGotoUrl()}\n${that.getThreadAuthorName()} 说:${that.getThreadBrief(200)}\n====`;
- txt.val(textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos) );
- }
- },
- {
- text: "确认",
- click: function() {
- // save the new note before close
- let newNote = $(`#noteDialog_${index}`).find('textarea').first().val();
- _notebook.put(uid, userName, newNote);
- $(this).dialog( "close" );
- }
- },
- {
- text: "取消",
- click: function() {
- // close without saving
- $(this).dialog( "close" );
- }
- }
- ]
- });
- });
- });
-
- // add UI
- let d = $(this._thread_div).find("td[rowspan='2'].postauthor").first();
- d.append(button);
- }
-
- }
-
- class Notebook {
- constructor(user_uid) {
- // initialization
- this._name = "hipda-notebook";
- this._user_uid = user_uid;
- this._notebook = {};
- return (async () => {
- this.loadFromLocalStorage();
- return this;
- })();
- }
-
- async loadFromLocalStorage() {
- console.log("load ID Notebook from Local Storage");
- let data = await GM.getValue(this._name, null);
- if (data !== null) {
- this._notebook = JSON.parse(data);
- }
- }
-
- async saveToLocalStorage() {
- console.log("save ID Notebook to Local Storage");
- await GM.setValue(this._name, JSON.stringify(this._notebook));
- }
-
- put(uid, userName, note) {
- // we need userName here, so user can analyze notes even after export
- this._notebook[uid] = {uid, userName, note};
- this.saveToLocalStorage();
- }
-
- get(uid) {
- if (uid in this._notebook) {
- return this._notebook[uid].note;
- }
- return "";
- }
-
- delete(uid) {
- if (uid in this._notebook) {
- delete this._notebook[uid];
- this.saveToLocalStorage();
- }
- }
-
- exportNotebook() {
- // can add meta data here
- let output = {
- notebook: this._notebook,
- version: GM_info.script.version,
- timestamp: + new Date()
- };
- return JSON.stringify(output);
- }
-
- importNotebook(input) {
- let attrs = ['notebook', 'version', 'timestamp'];
- for (let i=0; i<attrs.length; i++) {
- if (!input.hasOwnProperty(attrs[i])) {
- throw(`bad format: ${attrs[i]} does not exist`);
- }
- }
- this._notebook = {...input.notebook};
- this.saveToLocalStorage();
- }
-
- resetNotebook() {
- this._notebook = {};
- this.saveToLocalStorage();
- }
- }
-
-
-
-
- // get a post object
-
- var THIS_POST = new HpPost();
-
- // get tid and uid; uid for future extension
- var tid = THIS_POST.getPostTid();
- var uid = THIS_POST.getUserUid();
-
-
- var notebook = await new Notebook(uid);
-
- // render UI below
- // ID notes
- var hp_threads = THIS_POST.getHpThreads();
- for (let i=0; i<hp_threads.length; i++) {
- let hp_thread = hp_threads[i];
- hp_thread.addNoteUI(notebook);
- }
- // management panel
- THIS_POST.addNoteManagementUI(notebook);
-
-
- })();