I did this tampermonkey script to parse my gmail inbox items and add a button linking to our Redmine Issue Tracker, so I can open the thread without having to open the email. This button I added, immediately open a new tab and switch focus to it.
It works fine, except that every time I click the button, it also opens the email on the Gmail page/browser tab. To fix this, I added a setTimeout(function() { window.history.go(-1); }, 1000)
to jump back after opening the link.
The problem is that this does not allow me to open several issues at once, i.e., by holding the Ctrl+Click
because it opens the email and jumps back (big flickering).
How could I stop the email from opening when I click on the button I added?
I tried setting the timeout to 0, i.e., setTimeout(function() { window.history.go(-1); }, 0)
, but this does not helps because GMail opens the email both, in the current browser tab/page and in a new page (along with my Redmine page), then I have 2 new pages opened when I click my button with Ctrl+Click
.
setTimeout(..., 0)
which could cancel the email opening before it starts? (So I can open several tabs at once by Holding the Ctrl
button)Ctrl
button)// ==UserScript==
// @name GMail Redmine Link to Redmine
// @namespace *
// @version 0.1
// @description Redmine button to jump directly to redmine thread
// @author user
//
// @include https://mail.google.com/*
// @require http://code.jquery.com/jquery-3.4.1.min.js
// ==/UserScript==
(function() {
'use strict';
let keepclosing = async () => {
let elementid = `div[role="link"] span[data-thread-id]`;
let viewedbar = $(elementid).not('span[data-donot-process-this-again]');
if(viewedbar.length)
{
$(viewedbar).each(function(index, item)
{
let newitem = $(item).text();
let redmineregex = /\#(\d+)/g;
let regeresult = redmineregex.exec(newitem);
if(regeresult && regeresult.length) {
let redminecase = regeresult[1];
let previousItem = function() {
window.open(`https://redmine.com/issues/${redminecase}`);
setTimeout(function() { window.history.go(-1); }, 1000);
return false;
};
let mybutt = document.createElement("input");
mybutt.type = "button";
mybutt.id = `OpenRedmineCaseButton${redminecase}`;
mybutt.value = `#${redminecase}`;
mybutt.onclick = previousItem;
$($($($(item).parent()).parent()).parent()).prepend(mybutt);
}
$(item).attr('data-donot-process-this-again', true);
})
}
setTimeout(keepclosing, 500);
}
setTimeout(keepclosing, 500);
})();
Observation: The image I posted has colors because the full code also has to part I removed to simplify the question:
let LatestIssues = 44000;
...
let casenumber = parseInt(redminecase);
if( casenumber > LatestIssues ) {
mybutt.style.background = '#ffe0e0';
}
else if( casenumber > LatestIssues - 2000 ) {
mybutt.style.background = '#faffd4';
}
else {
mybutt.style.background = '#cfe9ff';
}
// This is something I used to add the button more above, but did not worked
// $($($($($($($(item).parent()).parent()).parent()).parent()).parent()).parent()).prepend(mybutt);
Simply preventing the event from propagating up to Gmail's click listener on the row does the trick:
let previousItem = function(e) {
e.stopPropagation();
window.open(`https://redmine.com/issues/${redminecase}`);
};
IMO, a simpler approach would be:
'use strict';
const processed = new Set();
const addButtons = () => {
const parentSelector = `div[role="link"] > div`;
for (const parent of document.querySelectorAll(parentSelector)) {
const row = parent.children[0];
if (processed.has(row)) continue;
processed.add(row);
const caseNumber = row.querySelector('span[data-thread-id]')?.textContent.match(/$(\d+)/)?.[1];
if (!caseNumber) continue;
const button = row.insertAdjacentElement('afterbegin', document.createElement('input'));
button.type = 'button';
button.onclick = (e) => {
e.stopPropagation();
window.open(`https://redmine.com/issues/${caseNumber}`);
};
button.value = `#${caseNumber}`;
}
};
setInterval(addButtons, 500);