多邻国选词快捷键

使用快捷键刷多邻国. 需要在vimium-c等快捷键相关插件中排除多邻国网站. 在主页面使用l键快速开始学习;在学习页使用ctrl键播放语音, 选词添加序号,退格键删除选词,删除键删除全部选词

目前为 2024-05-02 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name 多邻国选词快捷键
  3. // @namespace http://tampermonkey.net/
  4. // @version 2024-05-02
  5. // @description 使用快捷键刷多邻国. 需要在vimium-c等快捷键相关插件中排除多邻国网站. 在主页面使用l键快速开始学习;在学习页使用ctrl键播放语音, 选词添加序号,退格键删除选词,删除键删除全部选词
  6. // @author v
  7. // @match https://www.duolingo.cn/*
  8. // @license MIT
  9. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  10. // @require https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js
  11. // @require http://cdn.staticfile.org/jquery/1.8.3/jquery.min.js
  12. // @require https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js
  13. // @grant GM_log
  14. // @grant GM_addStyle
  15. // ==/UserScript==
  16.  
  17. // 序号样式
  18. GM_addStyle(".p_item_tip {position: absolute; color: dodgerblue; background-color: greenyellow; border-radius: 5px; !important;}")
  19.  
  20. (function() {
  21. 'use strict'
  22. // 选词键顺序
  23. var chars='abcdefghijklmnopqrstuvwxyz1234567890-=[],./'
  24. // 题目区元素相关数据对象
  25. // type -1: 无效 0: 选择题(自带[数字],不需要处理) 1: 组句题 2: 配对题(自带[数字],不需要处理) 3: 填空题(自带[首字母], 不需要处理)
  26. // el: 主要题目区元素
  27. // el2: 次要题目区元素
  28. var question = {type: -1}
  29. // 始初化题目数据对象方法
  30. var init_question = function() {
  31. if (question.type > -1) {
  32. return question
  33. }
  34. // 填空题(自带,不需要处理)
  35. question.el = document.querySelector('div[data-test="challenge challenge-tapComplete"]')
  36. if (question.el) {
  37. question.type = 3
  38. return
  39. }
  40. // 配对题(自带,不需要处理)
  41. question.el = document.querySelector('div[data-test="challenge challenge-listenMatch"]')
  42. if (question.el) {
  43. question.el = question.el.children[0].children[1].children[0]
  44. question.type = 2
  45. return
  46. }
  47. // 组句题
  48. question.el = document.querySelector('div[data-test="word-bank"]')
  49. if (question.el) {
  50. question.type = 1
  51. question.el2 = question.el.parentElement.previousElementSibling.children[0].children[0].children[1]
  52. return
  53. }
  54. // 选择题(自带,不需要处理)
  55. question.el = document.querySelector('div[aria-label="choice"]')
  56. if (question.el) {
  57. question.type = 0
  58. return
  59. }
  60. }
  61.  
  62. // 防抖方法
  63. function debounce(func, delay) {
  64. let timeout
  65. return function () {
  66. const _this = this
  67. const args = [...arguments]
  68. if (timeout) {
  69. clearTimeout(timeout)
  70. }
  71. timeout = setTimeout(() => {
  72. func.apply(_this, args)
  73. }, delay)
  74. }
  75. }
  76.  
  77. // 为单词/短语添加序号方法
  78. var process_order = function() {
  79. var play_btn = document.querySelector('button[data-test="player-next"]')
  80. if (play_btn.getAttribute('aria-disabled') != 'true') { return }
  81. init_question()
  82. if (question.type == 1) {
  83. for (var i=0; i< question.el.children.length; i++) {
  84. var item = question.el.children[i]
  85. let new_el = document.createElement('span')
  86. new_el.textContent = chars.charAt(i)
  87. new_el.className = 'p_item_tip';
  88. item.appendChild(new_el)
  89. }
  90. }
  91. }
  92. // 为单词/短语添加序号方法(防抖)
  93. var process_order_debounce = debounce(process_order, 500)
  94.  
  95. // 按键事件监听
  96. document.onkeydown = function(event) {
  97. // GM_log(event.key)
  98. // 回车键: 初始化题目数据对象, 同时延时为下一题单词/短语添加序号
  99. if (event.key == 'Enter') {
  100. question.type = -1
  101.  
  102. process_order_debounce()
  103. return
  104. }
  105. // Control键, 点击扬声器按钮播放语音
  106. if (event.key == 'Control') {
  107. var els = document.getElementsByClassName('fs-exclude')
  108. if (els) { els[0].click() }
  109. return
  110. }
  111. // 退格键, 删除最后一个选词
  112. if (event.key == 'Backspace') {
  113. if (question.el2) {
  114. var selects = question.el2.children
  115. var cnt = selects.length
  116. var last_select = selects[cnt - 1]
  117. last_select.querySelector('button').click()
  118. }
  119. return
  120. }
  121. // 删除键, 删除所有选词
  122. if (event.key == 'Delete') {
  123. if (question.el2) {
  124. var selects = question.el2.children
  125. var cnt = selects.length
  126. for (var i=cnt; cnt > 0; cnt--) {
  127. var select = selects[cnt - 1]
  128. select.querySelector('button').click()
  129. }
  130. }
  131. return
  132. }
  133.  
  134. // 将按键转为序号
  135. var idx = chars.indexOf(event.key)
  136. if (idx < 0) { return }
  137. // 在主页时 按l键直接学习(跳转/lesson页)
  138. var page_name = window.location.pathname.slice(1)
  139. if (page_name != 'lesson' && event.key == 'l') { window.location.href = 'lesson'; return }
  140.  
  141. // 在学习页时
  142. if (page_name == 'lesson') {
  143. init_question()
  144.  
  145. // 选择题
  146. if (question.type == 0 && question.el.children.length >= idx) {
  147. question.el.children[idx].click()
  148. return
  149. }
  150.  
  151. // 组句题
  152. if (question.type == 1 && question.el.children.length >= idx) {
  153. var el = question.el.children[idx]
  154. var item = el.children[0].children[0]
  155. if (item.getAttribute('aria-disabled') != 'true') {
  156. item.click()
  157. return
  158. }
  159. var text = item.querySelector('span[data-test="challenge-tap-token-text"').innerHTML
  160. var selects_div = question.el2
  161. var selects = selects_div.querySelectorAll('span[data-test="challenge-tap-token-text"]')
  162. for (var i= 0; i < selects.length; i++) {
  163. var select = selects[i]
  164. if (select.innerHTML == text) {
  165. select.parentElement.parentElement.click()
  166. return
  167. }
  168. }
  169. }
  170.  
  171. // 配对题(自带,不需要处理)
  172. // if (question.type == 2) {
  173. // var no = Number(event.key)
  174. // if (!isNaN(no)) {
  175. // idx = no - 1
  176. // var length = question.el.children.length
  177. // if (idx >=0 && idx < length) {
  178. // var el = question.el.children[idx].getElementsByClassName('fs-exclude')
  179. // if (el) {
  180. // el.click()
  181. // return
  182. // }
  183. // el = question.el.children[idx].querySelector('button').click()
  184. // }
  185. // }
  186. // return
  187. // }
  188. }
  189. }
  190.  
  191. })()

QingJ © 2025

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