annotation-board

allow you to add annotation after selected content and copy to clipboard and save to local server

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name                annotation-board
// @name:zh-CN          注释墙
// @description         allow you to add annotation after selected content and copy to clipboard and save to local server
// @description:zh-CN   选中内容后添加注释并复制到剪贴板, 同时在本地的服务其中新建一个副本, 参见 https://github.com/ezirmusitua/snippet-board
// @version             0.2.0
// @author              jferroal
// @license             GPL-3.0
// @require             https://greasyfork.org/scripts/31793-jmul/code/JMUL.js?version=209567
// @include             http://*
// @include             https://*
// @grant               GM_xmlhttpRequest
// @run-at              document-start
// @namespace           https://greasyfork.org/users/34556
// ==/UserScript==

(function e (t, n, r) { function s (o, u) { if (!n[o]) { if (!t[o]) { var a = typeof require === 'function' && require; if (!u && a) return a(o, !0); if (i) return i(o, !0); var f = new Error("Cannot find module '" + o + "'"); throw f.code = 'MODULE_NOT_FOUND', f } var l = n[o] = { exports: {} }; t[o][0].call(l.exports, function (e) { var n = t[o][1][e]; return s(n || e) }, l, l.exports, e, t, n, r) } return n[o].exports } var i = typeof require === 'function' && require; for (var o = 0; o < r.length; o++)s(r[o]); return s })({ 1: [function (require, module, exports) {
  const elements = require('./element');
  const request = require('./snippet.service');

  class AnnotationBoard {
    constructor () {
      this.request = request;
      this.container = new elements.Container();
      this.textarea = new elements.Textarea();
      this.saveBtn = new elements.Button();
      this.saveBtn.listenClick(() => {
        this.textarea.copyToClipboard();
        this.request.save({
          link: window.location.href,
          raw_content: this.textarea.value,
        });
        this.hide();
      });
      this.container.appendChild([this.textarea, this.saveBtn]);
      this.container.element.appendTo(document.body);
      this.isShowing = false;
    }

    show () {
      this.textarea.appendSelection();
      this.container.show();
      this.isShowing = true;
    }

    shouldShow () {
      const isEmptySelection = !!this.textarea.element.getSelection();
      return !this.isShowing && isEmptySelection;
    }

    hide () {
      this.isShowing = false;
      this.container.hide('display', 'none');
    }

    shouldHide (event) {
      const target = event && event.target;
      if (!target && this.isShowing) {
        return true;
      } else {
        const inContainer = elements.Container.isContainer(target.id);
        const inTextarea = elements.Textarea.isTextarea(target.id);
        const inButton = elements.Button.isButton(target.id);
        return !inContainer && !inTextarea && !inButton && this.isShowing;
      }
    }
  }

  module.exports = AnnotationBoard;
}, { './element': 2, './snippet.service': 4 }],
2: [function (require, module, exports) {
  const JMUL = window.JMUL || {};

  const AnnotationBoardId = {
    CONTAINER: 'annotation-container',
    TEXTAREA: 'annotation-textarea',
    BUTTON: 'annotation-button',
  };

  class BoardContainer {
    constructor () {
      this.element = new JMUL.Element('div');
      this.element.setId(AnnotationBoardId.CONTAINER);
      BoardContainer._initCss(this.element)
    }

    appendChild (children) {
      children.forEach((c) => {
        try {
          this.element.appendChild(c.element)
        } catch (er) {
          console.log(er);
        }
      });
    }

    show () {
      try {
        const pos = JMUL.Element.getSelectedPosition();
        this.element.setCss({
          display: 'flex',
          flexDirection: 'column',
          left: pos.x,
          top: pos.y,
        });
      } catch (err) {
        console.error(err);
      }
    }

    hide () {
      this.element.setCss({
        display: 'none',
      });
    }

    static isContainer (id) {
      return AnnotationBoardId.CONTAINER === id;
    }

    static _initCss (elem) {
      elem.setCss({
        display: 'none',
        fontFamily: 'Noto',
        border: '4px',
        boxShadow: '0px 3px 8px 1px rgba(0, 0, 0, 0.26)',
        position: 'absolute',
        backgroundColor: 'rgba(0, 0, 0, 0.56)',
        padding: '16px 4px 8px 4px',
      });
    }
  }

  class BoardEdit {
    constructor () {
      this.element = JMUL.Decorator.selectable(new JMUL.Element('textarea'));
      this.element.setId(AnnotationBoardId.TEXTAREA);
      BoardEdit._initCss(this.element);
    }

    appendSelection () {
      const prevVal = this.element.value();
      const selectedText = this.element.getSelection();
      const newVal = (!!prevVal && (prevVal + '\n') || '') + '========' + '\n' + selectedText + '\n';
      this.element.setValue(newVal)
    }

    hide () {
      this.element.setStyle('display', 'none');
    }

    copyToClipboard () {
      this.element.copyToClipboard();
    }

    get value () {
      return this.element.value();
    }

    static isTextarea (id) {
      return AnnotationBoardId.TEXTAREA === id;
    }

    static _initCss (elem) {
      elem.setCss({
        fontFamily: 'Noto',
        width: '240px',
        height: '128px',
        backgroundColor: 'rgba(255, 255, 255, 0.87)',
        marginBottom: '8px',
        borderRadius: '4px',
        color: 'rgba(0, 0, 0, 0.76)',
        fontSize: '12px',
      });
    }
  }

  class BoardButton {
    constructor () {
      this.element = new JMUL.Element('button');
      this.element.setId(AnnotationBoardId.BUTTON);
      this.element.setInnerHTML('复制到剪贴板');
      BoardButton._initCss(this.element);
    }

    listenClick (fn) {
      this.element.listen('click', (e) => fn());
    }

    static isButton (id) {
      return AnnotationBoardId.BUTTON === id;
    }

    static _initCss (elem) {
      elem.setCss({
        fontFamily: 'Noto',
        border: 'none',
        borderRadius: '4px',
        height: '24px',
        backgroundColor: 'rgba(255, 255, 255, 0.87)',
        color: 'rgba(0, 0, 0, 0.76)',
        fontSize: '14px',
      });
    }
  }

  module.exports = {
    Container: BoardContainer,
    Textarea: BoardEdit,
    Button: BoardButton,
  };
}, {}],
3: [function (require, module, exports) {
  const AnnotationBoard = require('./annotation-board');

  (function () {
    const annotationBoard = new AnnotationBoard();
    bindEvent();
    function bindEvent () {
      window.addEventListener('mouseup', (event) => {
        handleMouseUp(event);
      }, false);
    }

    function handleMouseUp (event) {
      if (annotationBoard.shouldShow()) {
        annotationBoard.show();
      } else if (annotationBoard.shouldHide(event)) {
        annotationBoard.hide();
      }
    }
  })();
}, { './annotation-board': 1 }],
4: [function (require, module, exports) {
  const JMUL = window.JMUL || {};

  class SnippetService {
    constructor (host = 'http://127.0.0.1', port = 5000, _options = {}) {
      if (!SnippetService.instance) {
        this.host = host;
        this.port = port;
        this.options = _options;
        if (!this.options.headers) {
          this.options.headers = { 'Content-Type': 'application/json' };
        }
        SnippetService.instance = this;
      }
      return SnippetService.instance;
    }

    save (data) {
      const request = new JMUL.Request(this.options);
      request.setMethod('POST');
      request.setUrl(this.host + ':' + this.port.toString() + '/snippet/api/v0.1.0');
      request.setData(data);
      request.send();
    }
  }

  SnippetService.instance = undefined;

  module.exports = new SnippetService();
}, {}] }, {}, [3]);