Mouse Gestures like Opera

A Mouse Gestures script is the same as in the old Opera

Verze ze dne 04. 10. 2017. Zobrazit nejnovější verzi.

// ==UserScript==
// @name         Mouse Gestures like Opera
// @namespace    https://greasyfork.org/users/37096/
// @homepage     https://greasyfork.org/scripts/33398/
// @supportURL   https://greasyfork.org/scripts/33398/feedback
// @version      1.0.6
// @description  A Mouse Gestures script is the same as in the old Opera
// @author       Hồng Minh Tâm
// @require      https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js
// @icon         https://png.icons8.com/mouse-right-click/ultraviolet/40
// @include      *
// @compatible   chrome
// @license      GNU GPLv3
// @grant        GM_addStyle
// @grant        GM_openInTab
// @grant        window.close
// ==/UserScript==

(function () {
    'use strict';

    GM_addStyle([
        '.mouse-gestures { display: none; z-index: 9999999999; position: fixed; overflow: hidden; border: 1px solid #CCC; white-space: nowrap; font-family: sans-serif; background-color: rgba(0, 0, 0, 0.7); color: #333; border-radius: 50%; width: 400px; height: 400px; }',

        '.mouse-gestures .mouse-gestures-middle, .mouse-gestures .mouse-gestures-up, .mouse-gestures .mouse-gestures-down, .mouse-gestures .mouse-gestures-left, .mouse-gestures .mouse-gestures-right { display: table; position: absolute; height: 160px; width: 160px; padding: 0; margin: 0; }',
        '.mouse-gestures .mouse-gestures-middle { top: 50%; left: 50%; margin-top: -20px; margin-left: -80px; width: 160px; height: 160px; text-align: center; }',
        '.mouse-gestures .mouse-gestures-up { top: 0; left: 50%; margin-left: -80px; }',
        '.mouse-gestures .mouse-gestures-down { bottom: 0; left: 50%; margin-left: -80px; }',
        '.mouse-gestures .mouse-gestures-left { top: 50%; left: 0; margin-top: -80px; }',
        '.mouse-gestures .mouse-gestures-right { top: 50%; right: 0; margin-top: -80px; }',

        '.mouse-gestures .mouse-gestures-label { color: #fff; font-family: Arial,"Helvetica Neue",Helvetica,sans-serif; font-weight: 700; font-size: 16px; text-transform: none; letter-spacing: normal; white-space: pre-wrap; padding: 0; margin: 0; -webkit-transition: all .2s; -moz-transition: all .2s; transition: all .2s; line-height: 22px; }',
        '.mouse-gestures .mouse-gestures-up > .mouse-gestures-label { display: table-cell; vertical-align: bottom; text-align: center; padding-bottom: 50px; }',
        '.mouse-gestures .mouse-gestures-down > .mouse-gestures-label { display: table-cell; vertical-align: top; text-align: center; padding-top: 50px; }',
        '.mouse-gestures .mouse-gestures-left > .mouse-gestures-label { display: table-cell; vertical-align: middle; text-align: right; padding-right: 50px; }',
        '.mouse-gestures .mouse-gestures-right > .mouse-gestures-label { display: table-cell; vertical-align: middle; text-align: left; padding-left: 50px; }',

        '.mouse-gestures .mouse-gestures-icon { position: absolute; width: initial; }',
        '.mouse-gestures .mouse-gestures-middle > .mouse-gestures-icon { position: initial; }',
        '.mouse-gestures .mouse-gestures-up > .mouse-gestures-icon { bottom: 0; left: 50%; margin-left: -20px; }',
        '.mouse-gestures .mouse-gestures-down > .mouse-gestures-icon { top: 0; left: 50%; margin-left: -20px; }',
        '.mouse-gestures .mouse-gestures-left > .mouse-gestures-icon { top: 50%; right: 0; margin-top: -20px; }',
        '.mouse-gestures .mouse-gestures-right > .mouse-gestures-icon { top: 50%; left: 0; margin-top: -20px; }',

        '.mouse-gestures .active > .mouse-gestures-label { color: #ffff00; }',
        '.mouse-gestures .mouse-gestures-up.active > .mouse-gestures-label { padding-bottom: 10px; }',
        '.mouse-gestures .mouse-gestures-down.active > .mouse-gestures-label { padding-top: 10px; }',
        '.mouse-gestures .mouse-gestures-left.active > .mouse-gestures-label { padding-right: 10px; }',
        '.mouse-gestures .mouse-gestures-right.active > .mouse-gestures-label { padding-left: 10px; }',
        '.mouse-gestures .active > .mouse-gestures-icon { display: none; }',

        '.mouse-gestures .hide { display: none; }',
    ].join('\n'));

    const SENSITIVITY = 20;
    var startX;
    var startY;
    var gesture = '';
    var preventContextMenu = false;
    var mouseDownTriggered = false;
    var link;
    const defaultFn = {
        close: function() {
            window.top.close();
        },
        newTab: function() {
            defaultFn.openInNewTab();
        },
        duplicateTab: function() {
            defaultFn.openInNewTab(window.location.href);
        },
        openInNewTab: function(link) {
            GM_openInTab(link, false);
        },
        openInNewBackgroundTab: function(link) {
            GM_openInTab(link, true);
        },
        scrollToTop: function() {
            $('html, body').animate({
                scrollTop: 0
            }, 'slow');
        },
        scrollToBottom: function() {
            $('html, body').animate({
                scrollTop: $(document).height()
            }, 'slow');
        },
        back: function() {
            window.history.back();
        },
        forward: function() {
            window.history.forward();
        },
        reload: function() {
            window.location.reload();
        },
        reloadWithoutCache: function() {
            window.location.reload(true);
        }
    };
    const gestures = {
        u: {
            label: 'Scroll to top',
            fn: defaultFn.scrollToTop,
        },
        d: {
            label: 'Scroll to bottom',
            fn: defaultFn.scrollToBottom,
        },
        l: {
            label: 'Back',
            fn: defaultFn.back,
        },
        r: {
            label: 'Forward',
            fn: defaultFn.forward,
        },
        ud: {
            label: 'Reload',
            fn: defaultFn.reload,
        },
        du: {
            label: 'Duplicate tab',
            fn: defaultFn.duplicateTab,
        },
        dl: {
            label: 'Open link in new tab',
            fn: defaultFn.openInNewTab,
            onLink: true
        },
        dr: {
            label: 'Close tab',
            fn: defaultFn.close,
        },
        ru: {
            label: 'New tab',
            fn: defaultFn.newTab,
        },
        udu: {
            label: 'Reload without cache',
            fn: defaultFn.reloadWithoutCache,
        },
        dld: {
            label: 'Open link in new background tab',
            fn: defaultFn.openInNewBackgroundTab,
            onLink: true
        },
    };

    var $mouseGestures = $('<div/>', {
        class: 'mouse-gestures'
    }).appendTo($('body'));

    var $up = $('<div/>', {
        class: 'mouse-gestures-up'
    }).appendTo($mouseGestures);
    var $upIcon = $('<img/>', {
        class: 'mouse-gestures-icon',
        src: 'https://png.icons8.com/up/ultraviolet/40'
    }).appendTo($up);
    var $upLabel = $('<div/>', {
        class: 'mouse-gestures-label'
    }).text(gestures[gesture + 'u'].label).appendTo($up);

    var $down = $('<div/>', {
        class: 'mouse-gestures-down'
    }).appendTo($mouseGestures);
    var $downIcon = $('<img/>', {
        class: 'mouse-gestures-icon',
        src: 'https://png.icons8.com/down-arrow/ultraviolet/40'
    }).appendTo($down);
    var $downLabel = $('<div/>', {
        class: 'mouse-gestures-label'
    }).text(gestures[gesture + 'd'].label).appendTo($down);

    var $left = $('<div/>', {
        class: 'mouse-gestures-left'
    }).appendTo($mouseGestures);
    var $leftIcon = $('<img/>', {
        class: 'mouse-gestures-icon',
        src: 'https://png.icons8.com/left/ultraviolet/40'
    }).appendTo($left);
    var $leftLabel = $('<div/>', {
        class: 'mouse-gestures-label'
    }).text(gestures[gesture + 'l'].label).appendTo($left);

    var $right = $('<div/>', {
        class: 'mouse-gestures-right'
    }).appendTo($mouseGestures);
    var $rightIcon = $('<img/>', {
        class: 'mouse-gestures-icon',
        src: 'https://png.icons8.com/right/ultraviolet/40'
    }).appendTo($right);
    var $rightLabel = $('<div/>', {
        class: 'mouse-gestures-label'
    }).text(gestures[gesture + 'r'].label).appendTo($right);

    var $middle = $('<div/>', {
        class: 'mouse-gestures-middle'
    }).appendTo($mouseGestures);
    var $middleIcon = $('<img/>', {
        class: 'mouse-gestures-icon',
        src: 'https://png.icons8.com/mouse-right-click/ultraviolet/40'
    }).appendTo($middle);
    var $middleLabel = $('<div/>', {
        class: 'mouse-gestures-label'
    }).appendTo($middle);

    var timeoutDelay;
    $(document).mousedown(function (e) {
        if (e.which == 3) {
            var $target = $(e.target);
            if ($target.closest('a').length) {
                link = $target.closest('a').prop('href');
            } else {
                link = undefined;
            }
            preventContextMenu = false;
            mouseDownTriggered = true;
            startX = e.clientX;
            startY = e.clientY;
            gesture = '';
            $mouseGestures.css('background-image', '');
            loadMG();
            timeoutDelay = setTimeout(function () {
                showMG(e);
            }, 500);
            $(this).mousemove(function (e) {
                if (startY - e.clientY > 10 || e.clientY - startY > 10 || startX - e.clientX > 10 || e.clientX - startX > 10) {
                    preventContextMenu = false;
                    if (mouseDownTriggered) {
                        mouseDownTriggered = false;
                    } else {
                        clearTimeout(timeoutDelay);
                        showMG(e);
                        checkMG(e);
                    }
                }
            });
        }
    }).mouseup(function (e) {
        clearTimeout(timeoutDelay);
        $(this).unbind('mousemove');
        if (gestures[gesture]) {
            if (gestures[gesture].onLink === true) {
                if (typeof link !== 'undefined') {
                    gestures[gesture].fn(link);
                } else {
                    $mouseGestures.hide();
                }
            } else {
                gestures[gesture].fn();
            }
            switch (gesture.slice(-1)) {
                case 'u':
                    $down.addClass('hide');
                    $left.addClass('hide');
                    $right.addClass('hide');
                    break;
                case 'd':
                    $up.addClass('hide');
                    $left.addClass('hide');
                    $right.addClass('hide');
                    break;
                case 'l':
                    $up.addClass('hide');
                    $down.addClass('hide');
                    $right.addClass('hide');
                    break;
                case 'r':
                    $up.addClass('hide');
                    $down.addClass('hide');
                    $left.addClass('hide');
                    break;
            }
            $mouseGestures.delay(300).hide(0);
            gesture = '';
        } else {
            $mouseGestures.hide();
        }
    }).contextmenu(function (e) {
        if (preventContextMenu) e.preventDefault();
    });

    function showMG(e) {
        preventContextMenu = true;
        $mouseGestures.css({
            left: (e.clientX - $mouseGestures.width() / 2) + "px",
            top: (e.clientY - $mouseGestures.height() / 2) + "px"
        }).stop(true, true).show();
    }

    function checkMG(e) {
        checkMove(startY - e.clientY, 'u', e);
        checkMove(e.clientY - startY, 'd', e);
        checkMove(startX - e.clientX, 'l', e);
        checkMove(e.clientX - startX, 'r', e);
    }

    function checkMove(p, t, e) {
        if (p >= SENSITIVITY) {
            startX = e.clientX;
            startY = e.clientY;
            if (gesture[gesture.length - 1] != t) {
                gesture += t;
                loadMG();
            }
        }
    }

    function loadMG() {
        if (gestures[gesture + 'u'] ? (gestures[gesture + 'u'].onLink === true ? typeof link !== 'undefined' : true) : false) {
            $up.removeClass('active hide');
            $upLabel.text(gestures[gesture + 'u'].label);
        } else {
            $up.addClass('hide');
        }
        if (gestures[gesture + 'd'] ? (gestures[gesture + 'd'].onLink === true ? typeof link !== 'undefined' : true) : false) {
            $down.removeClass('active hide');
            $downLabel.text(gestures[gesture + 'd'].label);
        } else {
            $down.addClass('hide');
        }
        if (gestures[gesture + 'l'] ? (gestures[gesture + 'l'].onLink === true ? typeof link !== 'undefined' : true) : false) {
            $left.removeClass('active hide');
            $leftLabel.text(gestures[gesture + 'l'].label);
        } else {
            $left.addClass('hide');
        }
        if (gestures[gesture + 'r'] ? (gestures[gesture + 'r'].onLink === true ? typeof link !== 'undefined' : true) : false) {
            $right.removeClass('active hide');
            $rightLabel.text(gestures[gesture + 'r'].label);
        } else {
            $right.addClass('hide');
        }

        if (gestures[gesture] ? (gestures[gesture].onLink === true ? typeof link !== 'undefined' : true) : false) {
            switch (gesture.slice(-1)) {
                case 'u':
                    $up.removeClass('hide').addClass('active');
                    break;
                case 'd':
                    $down.removeClass('hide').addClass('active');
                    break;
                case 'l':
                    $left.removeClass('hide').addClass('active');
                    break;
                case 'r':
                    $right.removeClass('hide').addClass('active');
                    break;
            }
        }
    }
})();