annotation-board

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

目前為 2017-07-31 提交的版本,檢視 最新版本

// ==UserScript==
// ==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=208363
// @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?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) {
        console.log(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]);