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); } //*/ })();
WARNING!
Don’t use this on newer Vivaldi versions.
Too much was changed and this will cause an event emitter overflow!