Some quick Vivaldi Javascript hacks to add additional functions

Warning: Do not apply this code to a current version of Vivaldi. It will not work anymore because the Vivaldi code has changed!

 

As follow-up to the previous entry about Hacking the CSS, this time we add some new functions to Vivaldi. The Idea is based on the posts you can find at http://habrahabr.ru/users/23rd/topics/ (in Russian, Google translate helps if you don’t speak Russian). I changed them a bit to avoid some errors I saw in the debugging console and to make sure that they only do what they should (there were some minor glitches where unexpected things happened if you clicked in the wrong place – especially if you run the browser in UI debugging mode)

I ported 2 of the scripts:

“Click to minimize/hide the tab” which deactivates the current tab and shows the last active tab. (don’t click at the [x] – that still closes the tab ;))

“Right-click [+] button to paste and go in a new tab.

 

For testing reasons you can deactivate each of them by removing the first slash at the leading //*.

How to …?

Look in the application folder of Vivaldi for browser.html in the ressources/vivaldi folder and open it with a text editor.

Insert after the string and save it.

Create a folder in the same directory as browser.html and rename the folder to custom_ui . It should be already in the right place if you followed Method 2 in the previous entry about Hacking the CSS.

Save the following code as custom.js into the new folder:

 

(function () {     // get the whole browser UI. Do this only once!     var browser = document.body.querySelector('#browser');          // we need to emulate a click sometimes. Do this only once!     var dispatchMouseEvent = function (target, var_args) {         var e = document.createEvent("MouseEvents");         e.initEvent.apply(e, Array.prototype.slice.call(arguments, 1));         target.dispatchEvent(e);     };      /*     Single click on a tab to hide it and show the last active tab.      */ //*     var list = [];     function listTabs() {         var tabs = browser.querySelectorAll('#tabs>.tab');         list = [];         for (var i = 0; i < tabs.length; i++) {             list.push(tabs[i]);         }         list.sort(function (a, b) {             return recent(b) - recent(a);         });     }          function recent(tab) {         var page = document.querySelector('.webpageview webview[tab_id="' + tab.dataset.tabId + '"]');         if (page) {             page = page.parentNode.parentNode.parentNode.parentNode;             return parseInt(page.style.zIndex);         }         return 0;     };      function startAction(e) {         for (var i = 0; i < e.path.length; i++) {             // clicking on tab group switches should not fire, neither should clicking anywhere in the webpageview             if (e.path[i].classList && (e.path[i].classList.contains('tab-indicator') || e.path[i].classList.contains('webpageview'))) {                 break;             }             if (e.path[i].classList && e.path[i].classList.contains('active')) {                 var active = browser.querySelector('.tab.active');                 listTabs();                 dispatchMouseEvent(list[1], 'mousedown', true, true);                 break;             }         }     };          browser.addEventListener('mousedown', function (e) {         // Make sure that it fires on left mouse click only         //  e = e || window.event;         switch (e.which) {         case 1:             startAction(e);             break; // left         case 2:             break; // middle         case 3:             break; // right         }     }); //*/       /*     Right click on plus-button to paste and go      */ //*     var isItMouse = false; // Exclude responses from keyboard      //Tweak for paste in this input-field     var hiddenInput = document.createElement("input");     hiddenInput.type = "text";     browser.appendChild(hiddenInput);     hiddenInput.style.width = "0px";     hiddenInput.style.height = "0px";     hiddenInput.style.display = "none";      browser.addEventListener('contextmenu', function (e) {         // Area near square         if (e.target.className.toString().indexOf('newtab') > -1) {             isItMouse = true;             document.execCommand('paste');             return;         }         // Plus-symbol         // changed to parentElement instead of parentNode         if (e.target.parentElement.className.indexOf('newtab') > -1) {             initPaste();             return;         }         // Square         if (e.target.parentElement.parentElement.className.indexOf('newtab') > -1) {             initPaste();             return;         }     });      function initPaste() {         isItMouse = true;         hiddenInput.style.display = "block";         hiddenInput.focus();         document.execCommand('paste');     }      document.addEventListener('paste', function (e) {         if (isItMouse) {             isItMouse = false;             var url = e.clipboardData.getData('text/plain');             hiddenInput.style.display = "none"; //hide input-field for pasting              var re = new RegExp('\\r\\n', 'g'); // Delete newline characters             url = url.replace(re, '');                          // Search engines             var searchEngine = 'https://google.com/webhp?q=';             // var searchEngine = 'http://yandex.ru/search/?text=';             // var searchEngine = 'https://duckduckgo.com/?q=';             // ... or insert search string of your favorite search engine                          var active = browser.querySelector('.tab.active');             var webview = document.querySelector('#webview-container webview[tab_id="' + active.dataset.tabId + '"]');              if (url.length > 0) {                 if (checkUrl(url)) {                     webview.executeScript({                         code : "window.open('" + url + "','_blank')"                     });                 } else if (checkUrlWithoutProtocol(url)) {                     webview.executeScript({                         code : "window.open('http://" + url + "','_blank')"                     });                 } else {                     webview.executeScript({                         code : "window.open('" + searchEngine + url + "','_blank')"                     });                 }             }             //    console.log(url)         }     });          //Check url     var patternUrl = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?/#]\S*)?$/i;     var patternUrlWithout = /^(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,3})).?)(?::\d{2,5})?(?:[/?/#]\S*)?$/i;          //url with protocol     function checkUrl(str) {         return patternUrl.test(str);     }          //url without protocol     function checkUrlWithoutProtocol(str) {         return patternUrlWithout.test(str);     } //*/ })();

One reply on “Some quick Vivaldi Javascript hacks to add additional functions”

  1. WARNING!
    Don’t use this on newer Vivaldi versions.

    Too much was changed and this will cause an event emitter overflow!

Comments are closed.