Greasy Fork

Greasy Fork is available in English.

知乎新版添加快捷键

为新版知乎添加快捷键

当前为 2018-10-24 提交的版本,查看 最新版本

// ==UserScript==
// @name         知乎新版添加快捷键
// @namespace    [email protected]
// @version      1.4
// @description  为新版知乎添加快捷键
// @author       zhangolve
// @match        *://www.zhihu.com/*
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    let selectId = 0;
    let gFlag = false, scFlag = false, fxFlag = false;
    const observer = new MutationObserver(setAnswersitems);
    let listItems;
    let mainTag; // 问题列表
    let answerClass;
    document.onkeydown = hotkey;
    // add hotkey event
    addEvent();

    function addEvent() {
      answerClass = getAnswerClass();
      if (mainTag) {
        mainTag.removeEventListener('mouseover', mouseoverEvent, true);
        observer.disconnect();
      }
      if(/^(http|https):\/\/www.zhihu.com(\/)?$/.test(window.location.href)) { // 匹配主页
        mainTag = document.querySelector('.TopstoryItem');
      } else if (/^(http|https):\/\/www.zhihu.com\/question\/(\d)+\/answer\/*/.test(window.location.href)) { //匹配单个问题页面
        mainTag = document.querySelector('.List-item');
      } else if(/^(http|https):\/\/www.zhihu.com\/question\/*/.test(window.location.href)) {
        mainTag = document.querySelector('.List-item').parentElement;
      }
      mainTag.addEventListener('mouseover', mouseoverEvent, true);
      observer.observe(mainTag, { childList: true });
    }

    function setAnswersitems() {
      let items;
      items = document.querySelectorAll('.' + answerClass);
      if(!items) return -1;
      listItems = items;
    }

    function setSelectId(value){
      const newId = Number(value);
      if (isNaN(newId)) return;
      selectId = newId;
    }

    function getAnswerClass() {
      if(/^(http|https):\/\/www.zhihu.com(\/)?$/.test(window.location.href)) { // 匹配主页
        return 'TopstoryItem';
      }
      else if (/^(http|https):\/\/www.zhihu.com\/question\/*/.test(window.location.href)) { //匹配问题页面
        return 'List-item';
      }
    }

    function mouseoverEvent(e){
      mainTag.removeEventListener('mouseover', mouseoverEvent, true);
      let element = e.target;
      setSelectId(parents(element));
      setTimeout(function() {
        mainTag.addEventListener('mouseover', mouseoverEvent, true);
      }, 500);
    }

    function parents(element){
      let parent = element.parentNode;
      if(!parent || !listItems) {
        return NaN;
      }
      if(!parent.className || !parent.className.includes(answerClass)){
        return parents(parent);
      }
      const id =  Array.from(listItems).findIndex(elm=>elm === parent
      );
      if (id === -1) {
        return NaN;
      } else {
        return id;
      }
    }

    function findAnswers(count) {
      if(!listItems) {
        setAnswersitems();
      }
      return listItems[count];
    }

    function answersCount() {
      if(!listItems) {
        setAnswersitems();
      }
      return listItems.length-1;
    }

  function getElementTop(element){
      let actualTop = element.offsetTop;
      let current = element.offsetParent;
      while (current !== null){
        actualTop += current.offsetTop;
        current = current.offsetParent;
      }
      return actualTop;
  }
    // 设置位置
    function setLocation(id) {
      let element = findAnswers(id);
      const elementTop = getElementTop(element);
      window.scrollTo(0, elementTop-70);
    }

    function nextItem() {
      let length = answersCount();
      if(selectId !== length){
        setSelectId(selectId + 1);
      }
      setLocation(selectId);
    }

    function previousItem() {
      if(selectId !== 0){
        setSelectId(selectId - 1);
      }
      setLocation(selectId);
    }


    function moreOrFold() {
        let answers = findAnswers(selectId);
        let contentMoreBtn = answers.querySelector('.ContentItem-more');
        let contentFoldBtn =answers.querySelector('.ContentItem-rightButton');
        let actionBtn = contentMoreBtn || contentFoldBtn;
        actionBtn.click();   
    }
    
    function firstItem()
    {
      if(gFlag){
        gFlag = false;
        setSelectId(0);
        setLocation(selectId);
      }
      gFlag = true;
    }

    function lastItem(){
      setSelectId(answersCount());
      setLocation(selectId);
    }

    function voteButtonUp() {
      let answers = findAnswers(selectId);
      let voteButton = answers.getElementsByClassName('VoteButton--up')[0];
      voteButton.click();
    }

    function voteButtonDown() {
      let answers = findAnswers(selectId);
      let voteButton = answers.getElementsByClassName('VoteButton--down')[0];
      voteButton.click();
    }

    function search()
    {
      const searchInput = document.querySelector('.SearchBar-input input');
      searchInput.focus();
    }

    function openComment()
    {
      let answers = findAnswers(selectId);
      let comment = answers.getElementsByClassName('ContentItem-actions')[0].childNodes[1];
      comment.click();
    }

    function thank()
    {
      let answers = findAnswers(selectId);
      let thinkButton = answers.getElementsByClassName('ContentItem-actions')[0].childNodes[4];
      thinkButton.click();
    }

    function collection()
    {
      let answers = findAnswers(selectId);
      let thinkButton = answers.getElementsByClassName('ContentItem-actions')[0].childNodes[3];
      thinkButton.click();
    }

    function share()
    {
      let answers = findAnswers(selectId);
      let share = answers.getElementsByClassName('ContentItem-actions')[0].childNodes[2];
      let button = share.getElementsByTagName('button')[0];
      button.click();
    }

    function hotkey(event)
    {
      if(event.altKey || event.ctrlKey) return;

      const element = event.target;
      if(element.tagName === 'INPUT' || 
        element.tagName === 'TEXTAREA' || 
        element.className === 'public-DraftEditor-content'){
        return;
      }

      if(event.key =='s') {
        scFlag = true;
      } else if(event.key =='f') {
        fxFlag = true;
      } else if(scFlag && event.key=='c') {
        scFlag = fxFlag = false;
        collection();
        return;
      } else if(fxFlag && event.key=='x') {
        scFlag = fxFlag = false;
        share();
        return;
      }
      else {
        scFlag = fxFlag = 0;
      }

      switch (event.key) {
        case 'j':
          nextItem();
          break;
        case 'k':
          previousItem();
          break;
        case '/':
          search();
          break;
        case '?':
          break;
        case 'g':
          firstItem();
          break;
        case 'o':
          break;
        case 'c':
          openComment();
          break;
        case 'v':
          voteButtonUp();
          break;
        case 'd':
          voteButtonDown();
          break;
        case 't':
          thank();
          break;
        case 'w':
          moreOrFold();
          break;
        case 'G':
          lastItem();
          break;
        default:

      }
    }
})();