Piazza - Archive with Delete Key

bind the delete key to quickly archive posts

当前为 2021-06-27 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Piazza - Archive with Delete Key
  3. // @namespace https://openuserjs.org/users/zachhardesty7
  4. // @author Zach Hardesty <zachhardesty7@users.noreply.github.com> (https://github.com/zachhardesty7)
  5. // @description bind the delete key to quickly archive posts
  6. // @copyright 2019, Zach Hardesty (https://zachhardesty.com/)
  7. // @license GPL-3.0-only; http://www.gnu.org/licenses/gpl-3.0.txt
  8. // @version 2.3.2
  9.  
  10. // @homepageURL https://github.com/zachhardesty7/tamper-monkey-scripts-collection/raw/master/piazza-archive-with-delete-key.user.js
  11. // @homepageURL https://openuserjs.org/scripts/zachhardesty7/Piazza_-_Archive_with_Delete_Key
  12. // @supportURL https://openuserjs.org/scripts/zachhardesty7/Piazza_-_Archive_with_Delete_Key/issues
  13.  
  14.  
  15. // @include https://piazza.com/class/*
  16. // ==/UserScript==
  17. /* global P */
  18.  
  19. // TODO: add undo shortcut
  20.  
  21. // let lastDeletedItemId
  22. let lastMovement = "down" // or 'up'
  23.  
  24. /**
  25. * ret prev item in cur week if exists or back up and move to prev week to get last item
  26. *
  27. * @see {getNextItem}
  28. * @param {Element} el - target
  29. * @returns {?HTMLElement} result
  30. */
  31. const getPrevItem = (el) => {
  32. if (el.previousElementSibling) return el.previousElementSibling
  33.  
  34. let parent = el.parentElement.parentElement.previousElementSibling
  35. while (parent) {
  36. if (parent.lastElementChild && parent.lastElementChild.lastElementChild) {
  37. return parent.lastElementChild.lastElementChild
  38. }
  39. parent = parent.previousElementSibling
  40. }
  41.  
  42. // must be at start of posts so force get next
  43. const item = getNextItem(el)
  44. if (!item) throw new Error("cannot find any other posts") // prevent inf loop
  45. return item
  46. }
  47.  
  48. /**
  49. * ret next item in cur week if exists or back up and move to next week to get first item
  50. *
  51. * @param {Element} el - target
  52. * @returns {?HTMLElement} result
  53. */
  54. const getNextItem = (el) => {
  55. // sibling from same week
  56. if (el.nextElementSibling) return el.nextElementSibling
  57.  
  58. // back up element to week div and select next week
  59. let parent = el.parentElement.parentElement.nextElementSibling
  60. // return first proceeding week with a post in it
  61. while (parent) {
  62. if (parent.lastElementChild && parent.lastElementChild.firstElementChild) {
  63. return parent.lastElementChild.firstElementChild
  64. }
  65. parent = parent.nextElementSibling // update to next week
  66. }
  67.  
  68. // must be at end of posts so force get prev
  69. const item = getPrevItem(el)
  70. if (!item) throw new Error("cannot find any other posts") // prevent inf loop
  71. return item
  72. }
  73.  
  74. /**
  75. * navigate posts on key press
  76. *
  77. * @param {KeyboardEvent} e - keydown event
  78. */
  79. const onKeydownHandler = (e) => {
  80. // move to prev feed item
  81. if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
  82. const prevItem = getPrevItem(document.querySelector(".feed_item.selected"))
  83. prevItem && prevItem.click()
  84. lastMovement = "up"
  85. }
  86.  
  87. // move to next feed item
  88. if (e.key === "ArrowRight" || e.key === "ArrowDown") {
  89. const nextItem = getNextItem(document.querySelector(".feed_item.selected"))
  90. nextItem && nextItem.click()
  91. lastMovement = "down"
  92. }
  93.  
  94. // del & move to next feed item
  95. if (e.key === "Delete") {
  96. const item = document.querySelector(".feed_item.selected")
  97. const newItem =
  98. lastMovement === "up" // change view
  99. ? getPrevItem(item)
  100. : getNextItem(item)
  101. newItem && newItem.click()
  102. // lastDeletedItemId = (item.id)
  103. P.feed.delFeedItem(item.id)
  104. }
  105.  
  106. // FIXME: cannot read property 'remove' of null
  107. // if (e.key === 'z' && e.ctrlKey) {
  108. // if (lastDeletedItemId) {
  109. // P.feed.addFeedItem(lastDeletedItemId)
  110. // }
  111. // }
  112. }
  113.  
  114. // update direction of last movement direction for each click
  115. document.addEventListener("click", (e) => {
  116. let clickedPost = /** @type {HTMLElement} */ (e.target)
  117.  
  118. // traverse up html until the post item is found or `null`
  119. while (clickedPost && !clickedPost.className.includes("feed_item")) {
  120. clickedPost = clickedPost.parentElement
  121. }
  122.  
  123. if (clickedPost) {
  124. const selected = document.querySelector(".feed_item.selected")
  125.  
  126. // id of week the post is in
  127. const bucketClicked = clickedPost.parentElement.id
  128. const bucketSelected = selected.parentElement.id
  129.  
  130. if (bucketClicked > bucketSelected) lastMovement = "down"
  131. else if (bucketClicked < bucketSelected) lastMovement = "up"
  132. else {
  133. // posts in the same week
  134. // get position within the week
  135. const positionClicked = [...clickedPost.parentElement.children].indexOf(
  136. clickedPost
  137. )
  138. const positionSelected = [...selected.parentElement.children].indexOf(
  139. selected
  140. )
  141.  
  142. if (positionClicked < positionSelected) lastMovement = "up"
  143. else if (positionClicked > positionSelected) lastMovement = "down"
  144. else {
  145. /* don't update lastMovement if already selected item is clicked */
  146. }
  147. }
  148. }
  149. })
  150.  
  151. document.addEventListener("keydown", onKeydownHandler)