read_mark

read mark

  1. // ==UserScript==
  2. // @name read_mark
  3. // @include *wikipedia*
  4. // @include http://readonlinefreebook.com/*
  5. // @include https://readonlinefreebook.com/*
  6. // @supportURL https://github.com/sxlgkxk/browser_script/issues
  7. // @version 0.2
  8. // @description read mark
  9. // @namespace http://sxlgkxk.github.io/
  10. // @author sxlgkxk
  11. // @icon http://sxlgkxk.github.io/im/avatar.jpg
  12. // @license MIT
  13. // @grant GM_getValue
  14. // @grant GM_setValue
  15. // @grant GM_xmlhttpRequest
  16. // ==/UserScript==
  17.  
  18. (function () {
  19.  
  20. //-------------------------------- common functions --------------------------------
  21.  
  22. function addScript(src) {
  23. var scripts_dom = document.createElement('script');
  24. scripts_dom.src = src;
  25. scripts_dom.type = 'text/javascript';
  26. document.getElementsByTagName('head')[0].appendChild(scripts_dom);
  27. }
  28. addScript('https://unpkg.com/axios/dist/axios.min.js')
  29.  
  30. function addStyle(html) {
  31. style = document.createElement("div")
  32. document.body.before(style)
  33. style.innerHTML = `<style>` + html + `</style>`
  34. }
  35.  
  36. //-------------------------------- code snippets --------------------------------
  37.  
  38. addStyle(`
  39. #markPanel{
  40. color: #fff;
  41. background-color: #333;
  42. position: fixed;
  43. bottom: 100px;
  44. right: 0px;
  45. width: 250px;
  46. opacity: 0.9;
  47. z-index: 3000;
  48. padding: 5px;
  49. }
  50. a.markUrl{
  51. font-weight: bold;
  52. color: #8bdb81;
  53. padding-right: 10px;
  54. font-size: 12px;
  55. }
  56. a:visited{
  57. color: #f5de19 !important;
  58. }
  59. button.markBtn, button.highlightBtn{
  60. background-color: #fff;
  61. color: #333;
  62. padding-top: 4px;
  63. padding-bottom: 4px;
  64. padding-left: 9px;
  65. padding-right: 9px;
  66. margin-right: 5px;
  67. margin-bottom: 3px;
  68. margin-top: 3px;
  69. border:0px;
  70. }
  71. [hidden] { display: none !important; }
  72. `)
  73.  
  74.  
  75. //-------------------------------- markPanel --------------------------------
  76.  
  77. mark_panel = document.createElement('div')
  78. document.body.before(mark_panel)
  79.  
  80. mark_panel_list_html = ""
  81. for (let i = 0; i < 10; i++) {
  82. data = localStorage.getItem("mark" + i)
  83. data = data ? JSON.parse(data) : {}
  84. url = data.url
  85. title = data.title
  86. mark_panel_list_html += `
  87. <div>
  88. <button onclick="document.setMark(`+ i + `)" class="markBtn">+</button>
  89. <a href="`+ url + `" class="markUrl" id="mark` + i + `">` + title + `</a>
  90. </div>
  91. `
  92. }
  93.  
  94. mark_panel.innerHTML = `<div id="markPanel" hidden>`
  95. + mark_panel_list_html
  96. + `<button class="highlightBtn" onclick="document.promptHighlight()">highlight</button>`
  97. + `<button class="highlightBtn" id="readlaterBtn" onclick="document.addToReadlater()">readlater</button>`
  98. + `</div>`
  99.  
  100. document.toggleMarkPanel = () => {
  101. markPanel = document.querySelector("#markPanel");
  102. if (markPanel.hidden) {
  103. markPanel.hidden = false
  104. } else {
  105. markPanel.hidden = true
  106. }
  107. }
  108. document.setMark = function (val) {
  109. data = { title: document.title.replace(" - Wikipedia", ''), url: window.location.href }
  110. localStorage.setItem("mark" + val, JSON.stringify(data))
  111. document.querySelector("#mark" + val).innerHTML = data.title
  112. document.querySelector("#mark" + val).href = data.url
  113. }
  114.  
  115. //-------------------------------- mark_button --------------------------------
  116.  
  117. body = document.querySelector('body')
  118. mark_button = document.createElement('button')
  119. document.body.before(mark_button)
  120.  
  121. // move button style
  122. mark_button.innerHTML = `<style>
  123. .float_btn{
  124. font-weight: bold;
  125. color: #fff;
  126. background-color: #333;
  127. position: fixed;
  128. width: 50px;
  129. height: 50px;
  130. opacity: 0.8;
  131. z-index: 1;
  132. }
  133. </style`
  134.  
  135. // mark_button
  136. mark_button.innerHTML += 'mark'
  137. mark_button.id = 'read_mark_btn'
  138. mark_button.classList.add("float_btn")
  139. mark_button.style.bottom = '50px'
  140. mark_button.style.right = '50px'
  141. mark_button.onclick = () => {
  142. document.toggleMarkPanel()
  143. }
  144.  
  145. //-------------------------------- highlight --------------------------------
  146.  
  147. // style
  148. function addStyle(html) {
  149. style = document.createElement("div")
  150. document.body.before(style)
  151. style.innerHTML = `<style>` + html + `</style>`
  152. }
  153. addStyle(`
  154. span.highlight{
  155. color: #555555;
  156. font-weight:bold;
  157. background-color: #8bdb81;
  158. }
  159. `)
  160.  
  161. function doHighlight(el = document.body) {
  162. var keywords = localStorage.getItem("highlight")
  163. if (!keywords) return;
  164. keywords = JSON.parse(keywords).join()
  165.  
  166. var rQuantifiers = /[-\/\\^$*+?.()|[\]{}]/g;
  167. keywords = keywords.replace(rQuantifiers, '\\$&').split(',').join('|');
  168. var pat = new RegExp('(' + keywords + ')', 'gi');
  169. var span = document.createElement('span');
  170. // getting all text nodes with a few exceptions
  171. var snapElements = document.evaluate(
  172. './/text()[normalize-space() != "" ' +
  173. 'and not(ancestor::style) ' +
  174. 'and not(ancestor::script) ' +
  175. 'and not(ancestor::textarea) ' +
  176. 'and not(ancestor::code) ' +
  177. 'and not(ancestor::pre)]',
  178. el, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  179.  
  180. if (!snapElements.snapshotItem(0)) { return; } // end execution if not found
  181.  
  182. for (var i = 0, len = snapElements.snapshotLength; i < len; i++) {
  183. var node = snapElements.snapshotItem(i);
  184. // check if it contains the keywords
  185. if (pat.test(node.nodeValue)) {
  186. // check that it isn't already highlighted
  187. if (node.className != "highlight" && node.parentNode.className != "highlight") {
  188. // create an element, replace the text node with an element
  189. var sp = span.cloneNode(true);
  190. sp.innerHTML = node.nodeValue.replace(pat, '<span class="highlight" title="highlight">$1</span>');
  191. node.parentNode.replaceChild(sp, node);
  192. }
  193. }
  194. }
  195. }
  196. doHighlight();
  197.  
  198. function promptHighlight() {
  199. text = prompt("请输入需要高亮的关键词")
  200. if (text) {
  201. keywords = [text]
  202. localStorage.setItem("highlight", JSON.stringify(keywords))
  203. doHighlight()
  204. }
  205. }
  206. document.promptHighlight = promptHighlight
  207.  
  208.  
  209. //-------------------------------- readlater --------------------------------
  210.  
  211. addStyle(`
  212. table#readlater_table {
  213. border-collapse: collapse;
  214. width: 100%;
  215. background-color: #222;
  216. }
  217. #readlater_table th, #readlater_table td {
  218. text-align: left;
  219. padding: 8px;
  220. }
  221. button.pagiBtn{
  222. background-color: #333;
  223. color: #fff;
  224. margin: 4px;
  225. padding-left: 15px;
  226. padding-right: 15px;
  227. padding-top: 9px;
  228. padding-bottom: 9px;
  229. }
  230. button#readlaterBtn.added{
  231. background-color: #8bdb81;
  232. }
  233. `)
  234.  
  235. for (let i = 1; i <= 31; i++) {
  236. addStyle(`td.readlaterDay` + i + `{background-color: rgba(` + Math.floor(Math.random() * 255) + `,` + Math.floor(Math.random() * 255) + `,` + Math.floor(Math.random() * 255) + `, 0.5);}`)
  237. }
  238.  
  239. function getReadlaterDateStr(date = null) {
  240. date = new Date(date)
  241. month = String(date.getMonth() + 1)
  242. day = String(date.getDate())
  243. return month + "." + day
  244. }
  245.  
  246. chapter_dom = document.querySelector("div.chapter-detail")
  247. if (!chapter_dom) chapter_dom = document.body
  248. readlater_panel = document.createElement("div")
  249. chapter_dom.before(readlater_panel)
  250. readlater_panel.innerHTML = `<div>
  251. <table id="readlater_table">
  252. </table>
  253. <button id="readlater_prev" class="pagiBtn">\<</button>
  254. <button id="readlater_next" class="pagiBtn">\></button>
  255. <input id="readlater_input" type="text" value="1" size="3">
  256. <button id="readlater_go" class="pagiBtn">go</button>
  257. </div>`
  258.  
  259. readlater_data = localStorage.getItem('readlater_data')
  260. readlater_data = readlater_data ? JSON.parse(readlater_data) : {}
  261. if (readlater_data[location.href]) {
  262. document.querySelector("#readlaterBtn").classList.add("added")
  263. }
  264.  
  265. function addToReadlater() {
  266. readlater_data=localStorage.getItem('readlater_data')
  267. readlater_data = readlater_data ? JSON.parse(readlater_data) : {}
  268. if (!readlater_data[location.href]) {
  269. readlater_data[location.href] = { date: new Date().getTime(), title: document.title.replace(" - Wikipedia", ''), url: location.href }
  270. localStorage.setItem('readlater_data', JSON.stringify(readlater_data))
  271. btn = document.querySelector('button#readlaterBtn')
  272. btn.classList.add('added')
  273. } else {
  274. delete readlater_data[location.href];
  275. localStorage.setItem('readlater_data', JSON.stringify(readlater_data))
  276. btn = document.querySelector('button#readlaterBtn')
  277. btn.classList.remove('added')
  278. }
  279. setReadlaterTable(1)
  280. }
  281. document.addToReadlater = addToReadlater
  282.  
  283. function setReadlaterTable(page) {
  284. page = page ? page : 1
  285. readlater_pageSize = 10
  286. readlater_table = document.querySelector("#readlater_table")
  287. readlater_table.innerHTML = ""
  288. readlater_list = Object.values(readlater_data).sort((a, b) => { return b.date - a.date })
  289.  
  290. start = (page - 1) * readlater_pageSize
  291. end = Math.min(start + readlater_pageSize, readlater_list.length)
  292.  
  293. for (i = start; i < end; i++) {
  294. day = new Date(readlater_list[i].date).getDate()
  295. readlater_table.innerHTML += `<tr>`
  296. // + `<td class="readlaterDay` + day + `">` + getReadlaterDateStr(readlater_list[i].date) + `</td>`
  297. + `<td><a href="` + readlater_list[i].url + `">` + readlater_list[i].title + `</a></td>
  298. </tr>`
  299. }
  300. }
  301. setReadlaterTable(1)
  302.  
  303. document.querySelector('#readlater_prev').onclick = () => {
  304. readlater_page = document.querySelector('#readlater_input').value;
  305. setReadlaterTable(--readlater_page);
  306. document.querySelector('#readlater_input').value = readlater_page
  307. }
  308. document.querySelector('#readlater_next').onclick = () => {
  309. readlater_page = document.querySelector('#readlater_input').value;
  310. setReadlaterTable(++readlater_page);
  311. document.querySelector('#readlater_input').value = readlater_page
  312. }
  313.  
  314. document.querySelector('#readlater_go').onclick = () => {
  315. readlater_page = document.querySelector('#readlater_input').value;
  316. setReadlaterTable(readlater_page);
  317. }
  318.  
  319. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址