Skip to content

Instantly share code, notes, and snippets.

@hsayed21
Last active August 1, 2026 06:35
Show Gist options
  • Select an option

  • Save hsayed21/45dfe751d552ea9ce44386439ae8a5dc to your computer and use it in GitHub Desktop.

Select an option

Save hsayed21/45dfe751d552ea9ce44386439ae8a5dc to your computer and use it in GitHub Desktop.
Odoo Set Ticket to Open in a New Tab
// ==UserScript==
// @name Odoo Ticket Copy and Open New Tab
// @namespace http://tampermonkey.net/
// @version 3.0
// @description Copies ticket reference and attempts to open tickets using Odoo native navigation in a new tab
// @author @hsayed21
// @match https://www.posbank.me/web*
// @match https://posbankf346f.odoo.com/odoo/my-tickets*
// @grant none
// ==/UserScript==
(function () {
'use strict';
function copyText(text) {
if (navigator.clipboard?.writeText) {
return navigator.clipboard.writeText(text);
}
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
textarea.remove();
return Promise.resolve();
}
function makeOdooCellOpenInNewTab(nameCell) {
if (nameCell.dataset.blankClickEnabled === 'true') {
return;
}
nameCell.dataset.blankClickEnabled = 'true';
nameCell.style.cursor = 'pointer';
nameCell.title = 'Open ticket in a new tab';
let allowNativeClick = false;
nameCell.addEventListener(
'click',
function (event) {
if (allowNativeClick) {
allowNativeClick = false;
return;
}
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
allowNativeClick = true;
const newTabClick = new MouseEvent('click', {
bubbles: true,
cancelable: true,
composed: true,
view: window,
ctrlKey: true,
metaKey: true,
button: 0
});
nameCell.dispatchEvent(newTabClick);
// Safety reset in case Odoo does not receive the click.
setTimeout(() => {
allowNativeClick = false;
}, 100);
},
true
);
}
function processRows() {
const rows = document.querySelectorAll(
'tr.o_data_row:not([data-script-processed="true"])'
);
rows.forEach(row => {
const idCell = row.querySelector('td[name="ticket_ref"]');
const nameCell = row.querySelector('td[name="name"]');
if (!idCell || !nameCell) {
return;
}
row.dataset.scriptProcessed = 'true';
const ticketReference = idCell.textContent.trim();
/*
* Ticket reference copy badge
*/
idCell.innerHTML = '';
idCell.style.display = 'flex';
idCell.style.alignItems = 'center';
idCell.style.justifyContent = 'center';
const idLabel = document.createElement('span');
// Preserve the displayed reference, including leading zeros.
idLabel.textContent = `#${ticketReference}`;
idLabel.title = 'Click to copy ticket reference';
Object.assign(idLabel.style, {
fontWeight: 'bold',
cursor: 'pointer',
padding: '2px 6px',
backgroundColor: '#e9ecef',
border: '1px solid #dee2e6',
borderRadius: '4px',
fontSize: '0.9em',
color: '#495057',
transition: 'all 0.2s ease'
});
idLabel.addEventListener('click', function (event) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
copyText(ticketReference).then(() => {
const originalText = idLabel.textContent;
const originalBackground = idLabel.style.backgroundColor;
const originalColor = idLabel.style.color;
idLabel.textContent = 'Copied!';
idLabel.style.backgroundColor = '#28a745';
idLabel.style.color = '#ffffff';
setTimeout(() => {
idLabel.textContent = originalText;
idLabel.style.backgroundColor = originalBackground;
idLabel.style.color = originalColor;
}, 700);
});
});
idCell.appendChild(idLabel);
/*
* Keep the original Odoo name cell.
* Do not replace it with an incorrect generated URL.
*/
makeOdooCellOpenInNewTab(nameCell);
});
}
processRows();
const observer = new MutationObserver(() => {
processRows();
});
observer.observe(document.body, {
childList: true,
subtree: true
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment