// ==UserScript==
// @name Opera Browser Rocker+Mouse Gestures
// @namespace OperaBrowserGestures
// @description This script works on any browser and simulates the Opera Browser Mouse and Rocker Gestures, but with this script you can modify or disable them as you want.
// @version 0.0.6
// @author hacker09
// @include *
// @icon https://www.google.com/s2/favicons?domain=www.opera.com
// @require https://code.jquery.com/jquery-3.5.1.min.js
// @grant GM_registerMenuCommand
// @grant GM_openInTab
// @grant window.close
// @grant GM_setValue
// @grant GM_getValue
// @run-at document-end
// ==/UserScript==
// *** Mouse Gesture Settings Below *****************************************************************************************************************************************
GM_registerMenuCommand("Enable/Disable Mouse Gestures", MouseGestures); //Adds an option to the tampermonkey menu
if (GM_getValue("MouseGestures") !== true && GM_getValue("MouseGestures") !== false) { //If the value doesn't exist define as true
GM_setValue("MouseGestures", true); //Defines the variable as true
} //Finishes the if condition
function MouseGestures() //Function to enable or disable the MouseGestures
{ //Starts the function MouseGestures
if (GM_getValue("MouseGestures") === true) { //If the last config was true, set as false
GM_setValue("MouseGestures", false); //Defines the variable as false
} //Finishes the if condition
else { //If the last config was false, set as true
GM_setValue("MouseGestures", true); //Defines the variable as true
location.reload(); //Reloads the page
} //Finishes the else condition
} //Finishes the function MouseGestures
if (GM_getValue("MouseGestures") === true) //If the MouseGestures is enabled
{ //Starts the if condition
const SENSITIVITY = 3; // Adjust the script mouse senvity here between 1 ~ 5
const TOLERANCE = 3; // Adjust the script mouse tolerance here between 1 ~ 5
const funcs = { //Variable to store the functions
'DL': function() { //Function that will run when the mouse movement Down+Left is performed
GM_openInTab(location.href, { //Open the link
incognito: true, //Open the link on a New Incognito Window
}); //Finishes the GM_openInTab
window.top.close(); //Close the actual tab
}, //Finishes the mouse movement Down+Left
'L': function() { //Function that will run when the mouse movement Left is performed
window.history.back(); //Go Back
}, //Finishes the mouse movement Left
'R': function() { //Function that will run when the mouse movement Right is performed
window.history.forward(); //Go Foward
}, //Finishes the mouse movement Right
'D': function() { //Function that will run when the mouse movement Down is performed
if (IsShiftNotPressed) { //If the shift key isn't being pressed
GM_openInTab(link, { //Open the link on a new tab
active: true, //Focus on the new tab
insert: true, //Insert the new tab after the actual tab
setParent: true //Return to the tab the user was in
}); //Open the link that was hovered
setTimeout(function() { //Starts the settimeout function
link = 'about:newtab'; //Make the script open a new browser tab if no links were hovered
}, 100); //Finishes the settimeout function
} //Finishes the if condition
IsShiftNotPressed = true; //Variable to hold the shift key status
}, //Finishes the mouse movement Down
'UD': function() { //Function that will run when the mouse movement Up+Down is performed
window.location.reload(); //Reload the Tab
}, //Finishes the mouse movement Up+Down
'DR': function(e) { //Function that will run when the mouse movement Down+Right is performed
window.top.close(); //Close the tab
e.preventDefault(); //Prevent the default context menu from being opened
e.stopPropagation(); //Prevent the default context menu from being opened
}, //Finishes the mouse movement Down+Right
'DU': function() { //Function that will run when the mouse movement Down+Up is performed
GM_openInTab(link, { //Open the link that was hovered
active: false, //Don't focus on the new tab
insert: true, //Insert the new tab after the actual tab
setParent: true //Return to the tab the user was in
}); //Open the link that was hovered on a new background tab
setTimeout(function() { //Starts the setimeout function
link = 'about:newtab'; //Make the script open a browser tab if no links were hovered
}, 100); //Finishes the setimeout function
} //Finishes the mouse movement Down+Up
}; //Finishes the variable to store the functions
// *** Below this line is the math codes that track the mouse movement gestures *******************************************************************************************
const s = 1 << ((7 - SENSITIVITY) << 1);
const t1 = Math.tan(0.15708 * TOLERANCE),
t2 = 1 / t1;
let x, y, path;
const tracer = function(e) {
let cx = e.clientX,
cy = e.clientY,
deltaX = cx - x,
deltaY = cy - y,
distance = deltaX * deltaX + deltaY * deltaY;
if (distance > s) {
let slope = Math.abs(deltaY / deltaX),
direction = '';
if (slope > t1) {
direction = deltaY > 0 ? 'D' : 'U';
} else if (slope <= t2) {
direction = deltaX > 0 ? 'R' : 'L';
}
if (path.charAt(path.length - 1) !== direction) {
path += direction;
}
x = cx;
y = cy;
}
};
window.addEventListener('mousedown', function(e) { //Add an advent listener to the page to detect when the mouse is clicked
if (e.which === 3) { //Starts the if condition
x = e.clientX;
y = e.clientY;
path = "";
window.addEventListener('mousemove', tracer, false); //Add an advent listener to the page to detect the mouse position
} //Finishes the if condition
}, false); //Finishes the advent listener
window.addEventListener('contextmenu', function(e) { //When the right click button is released
window.removeEventListener('mousemove', tracer, false); //Stop tracking the mouse movements
if (path !== "") { //Starts the if condition
e.preventDefault(); //Prevent the default context menu from being opened
if (funcs.hasOwnProperty(path)) { //Starts the if condition
funcs[path]();
} //Finishes the if condition
} //Finishes the if condition
}, false); //Finishes the advent listener
var link; //Make the variable global
Array.from(document.querySelectorAll('a')).forEach(Element => Element.onmouseover = function() { //Get all the a link elements and add an advent listener to the link element
link = this.href; //Store the actual hovered link to a variable
}); //Finishes the forEach
var IsShiftNotPressed = true; //Variable to hold the shift key status
window.addEventListener("contextmenu", function(e) { //Adds an advent listener to the page to know when the shift key is pressed or not
if (e.shiftKey) { //If the shift key was pressed
window.open(link, '_blank', 'height=' + window.screen.height + ',width=' + window.screen.width); //Open the link on a new window
IsShiftNotPressed = false; //Variable to hold the shift key status
} //Finishes the if condition
if (LeftClicked) { //If Right was Clicked and then Left Click was released
e.preventDefault(); //Prevent the default context menu from being opened
e.stopPropagation(); //Prevent the default context menu from being opened
} //Finishes the if condition
}, false); //Finishes the advent listener
} //Finishes the if condition
// *** Rocker Mouse Gesture Settings Below ***************************************************************************************************************************
GM_registerMenuCommand("Enable/Disable Rocker Mouse Gestures", RockerMouseGestures); //Adds an option to the tampermonkey menu
if (GM_getValue("RockerMouseGestures") !== true && GM_getValue("RockerMouseGestures") !== false) { //If the value doesn't exist define as false
GM_setValue("RockerMouseGestures", false); //Defines the variable as false
} //Finishes the if condition
function RockerMouseGestures() //Function to enable or disable the RockerMouseGestures
{ //Starts the function RockerMouseGestures
if (GM_getValue("RockerMouseGestures") === true) { //If the last config was true, set as false
GM_setValue("RockerMouseGestures", false); //Defines the variable as false
} //Finishes the if condition
else { //If the last config was false, set as true
GM_setValue("RockerMouseGestures", true); //Defines the variable as true
location.reload(); //Reloads the page
} //Finishes the else condition
} //Finishes the function RockerMouseGestures
if (GM_getValue("RockerMouseGestures") === true) //If the RockerMouseGestures is enabled
{ //Starts the if condition
var LeftClicked, RightClicked; //Make these variables global
window.addEventListener("mousedown", function(e) { //Detect the right and left mouse clicks presses on the page
switch (e.button) { //Start the switch condition
case 0: //If Left Click was Pressed
LeftClicked = true; //Set the variable LeftClicked as true
break; //Don't execute the lines below if the Left Key was Pressed
case 2: //If Right Click was Pressed
RightClicked = true; //Set the variable RightClicked as true
break; //Don't execute the lines below if the Right Key was Pressed
} //Finishes the switch condition
}, false); //Finishes the adventlistener mousedown
window.addEventListener("mouseup", function(e) { //Detect the right and left mouse clicks releases on the page
switch (e.button) { //Start the switch condition
case 0: //If Left Click was released
LeftClicked = false; //Set the variable LeftClicked as false
break; //Don't execute the lines below if the Left Key was Pressed
case 2: //If Right Click was released
RightClicked = false; //Set the variable RightClicked as false
break; //Don't execute the lines below if the Left Key was Pressed
} //Finishes the switch condition
if (LeftClicked && RightClicked === false) { //If Left was Clicked and then Right Click was released
window.history.back(); //Go Back
} //Finishes the if condition
if (RightClicked && LeftClicked === false) { //If Right was Clicked and then Left Click was released
window.history.forward(); //Go Foward
} //Finishes the if condition
}, false); //Finishes the adventlistener mouseup
} //Finishes the if condition
// *** SearchHighLight Settings Below ***************************************************************************************************************************
GM_registerMenuCommand("Enable/Disable SearchHiLight", SearchHiLight); //Adds an option to the tampermonkey menu
if (GM_getValue("SearchHiLight") !== true && GM_getValue("SearchHiLight") !== false) { //If the value doesn't exist define as true
GM_setValue("SearchHiLight", true); //Defines the variable as true
} //Finishes the if condition
function SearchHiLight() //Function to enable or disable the SearchHiLight
{ //Starts the function SearchHiLight
if (GM_getValue("SearchHiLight") === true) { //If the last config was true, set as false
GM_setValue("SearchHiLight", false); //Defines the variable as false
} //Finishes the if condition
else { //If the last config was false, set as true
GM_setValue("SearchHiLight", true); //Defines the variable as true
location.reload(); //Reloads the page
} //Finishes the else condition
} //Finishes the function SearchHiLight
if (GM_getValue("SearchHiLight") === true) //If the SearchHiLight is enabled
{ //Starts the if condition
var $ = window.jQuery; //Defines That The Symbol $ Is A jQuery
$(function() { //Starts the function
var menu = $('#highlight_menu'); //Creates a variable to hold the menu element
$(document.body).on('mouseup', function() { //When the user releases the mouse click after selecting something
if (document.getSelection().toString() !== '') { //If the user selected something
var p = document.getSelection().getRangeAt(0).getBoundingClientRect(); //Create a new variable to get the positions later
menu.css({ //Set the menu css
left: (p.left + (p.width / 2)) - (menu.width() / 2), //Make the menu show on the correct left position
top: (p.top - menu.height() - 10), //Make the menu show on the correct top position
display: '' //Show the menu on the page
}).animate({ //Creates the animation animation
opacity: 1 //Set the animation opacity
}, 0); //Add an animation to the menu
menu.addClass('highlight_menu_animate'); //Add the class to animate the menu
$('head').append('<style>.highlight_menu_animate .popuptext::after { content: ""; height: 35px; top: 100%; left: 50%; margin-left: -10px; border-width: 10px; position: absolute; border-style: solid; border-color: #292929 transparent transparent transparent; }</style>'); //Create a class to animate the menu
return; //Keep displaying the menu box
} //Finishes the if condition
menu.animate({ //Creates the animation animation
opacity: 0 //Set the animation opacity
}); //Hide the menu If the user clicked on any of the options
}); //Finishes the mouseup advent listener
}); //Finishes the function
document.body.insertAdjacentHTML('beforeend', '<div id="highlight_menu" style="width: 110px; display:none; color: #fff; position: fixed; background-color: #292929; font-size: 13.4px; font-family: monospace;box-sizing: unset; z-index: 999;"> <ul style="cursor: pointer; margin-left: unset; margin-bottom: unset; margin-inline-end: unset; margin-inline-start: unset; margin-block-end: 10px; margin-block-start: unset; padding-left: 7px; padding-right: 7px; margin-top:10px;"><li class="popuptext" id="SearchBTN" style="display: inline;">Search</li><li class="popuptext" id="CopyBTN" style="cursor: pointer; display: inline;"> | Copy</li></ul></div>'); //Add the menu to the page
document.querySelector("#SearchBTN").onmousedown = function() { //When the user clicks on the Search button
var LinkfyOrSearch = 'https://www.google.com/search?q='; //Creates a variable to open google
if (window.getSelection().toString().match(/.org|.net|.co|.tv|.me|.biz|.club|.br|.gov|.io|.jp|.edu|.au|.in|.it|.ca|.mx|.fr|.tw|.il|.uk/) !== null) //If the selected text is a link
{ //Starts the if condition
var LinkfyOrSearch = 'https://'; //Make the non http and non https links able to be opened
} //Finishes the if condition
if (window.getSelection().toString().match(/http:|https:/) !== null) //If the selected text is a link that already has http or https
{ //Starts the if condition
var LinkfyOrSearch = ''; //Remove the https:// that was previsouly added to this variable
} //Finishes the if condition
window.open(LinkfyOrSearch + window.getSelection().toString()); //Open google and search for the selected word(s)
}; //Finishes the onmousedown advent listener
document.querySelector("#CopyBTN").onmousedown = function() { //When the user clicks on the copy button
navigator.clipboard.writeText(window.getSelection().toString()); //Copy the selected word(s)
document.querySelector("#CopyBTN").innerText = ' | Done'; //Change the button text to Done
setTimeout(function() { //Starts the setTimeout function
document.querySelector("#CopyBTN").innerText = ' | Copy'; //The next time that the menu is shown display the button text as Copy again, instead of Done
}, 400); //Finishes the setTimeout function
}; //Finishes the onmousedown advent listener
document.onclick = function() { //When the user clicks anywhwere on the page
if (document.querySelector("#highlight_menu").style.display !== '') { //If the menu is being displayed
document.querySelector("#highlight_menu").style.display = 'none'; //Hide the menu
} //Finishes the if condition
}; //Finishes the onclick advent listener
setTimeout(function() { //Starts the setTimeout function
var AllIframes = document.querySelectorAll("iframe"); //Get all iframes on the page
for (var i = AllIframes.length; i--;) { //Starts the for condition
if (AllIframes[i].allow.match('clipboard-write;') === null) //If the iframe doesn't have the clipboard-write attribute yet
{ //Starts the if condition
AllIframes[i].allow = AllIframes[i].allow + 'clipboard-write;'; //Add he permission to copy the iframe text
AllIframes[i].src = AllIframes[i].src; //Reload the iframe to make the iframe have the new permission
} //Finishes the if condition
} //Finishes the for condition
}, 2000); //Finishes the setTimeout function
} //Finishes the if condition