NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Tab Titles for ticket system ManageEngine ServiceDesk Plus // @name:de-DE Tabtitel für Ticketsystem ManageEngine ServiceDesk Plus // @description Find the right tab instantly: Useful title with the ticket no and title or with information you choose // @description:de-DE Endlich sofort den richtigen Tab finden: Nützlicher Titel mit Ticketnr. und Betreff oder selbst gewählten Informationen // @namespace jandunker // @version 1.5 // @match http://servicedesk/* // @match http://servicedesk.hgroup.intra/* // @match https://servicedesk/* // @match https://servicedesk.hgroup.intra/* // @exclude */framework/html/blank.html // @noframes // @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt // @copyright 2020-2022, eckende (https://openuserjs.org/users/eckende) // @require https://openuserjs.org/src/libs/sizzle/GM_config.js // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @updateURL https://openuserjs.org/meta/eckende/Tab_Titles_for_ticket_system_ManageEngine_ServiceDesk_Plus.meta.js // @downloadURL https://openuserjs.org/install/eckende/Tab_Titles_for_ticket_system_ManageEngine_ServiceDesk_Plus.user.js // @icon data:image/gif;base64,R0lGODlhEAAQAHAAACH5BAkAAAMALAAAAAAQABAAgQAAAHSK///TdAAAAAI7nI85wIDtDhAiGhCCXXRj/XRP5nXNQp4TJX4ZuLKOS3KVmjK2V0smlGuYTKkUS0bLHYEvHUS3eCqmiAIAOw== // @icon64 data:image/gif;base64,R0lGODlhQABAAHAAACH5BAkAAAMALAAAAABAAEAAgQAAAHSK///TdAAAAAL/nI+py+0Po5y02ouzPqD7DwJUSHpjSZ4oqK7m5LJw/Ep0HX3Czu9fGwgKg79Zp9cr2jzDoTLnQfKekE9TSH3opIKsw3oNeBtb6ZgBvp4XZeRakW6+E+0krsoMzxH16V2bp/b3FcW1xxEoN0hWaLaIluj0yNboNgkXiXVJV2nXAaS3ydfpdzPaESZ2I4J4ZLh6CpC6ymrQ5wPbKhtqqsvVlWubSRQ8cPtr+ambyqypLOyKjPwU1yz4bEwq7VmbjWo9i3O8DYxdDe7cPb5NPYzeHk2erO4ODg8g/2peb32f77jvGzpFAfHpoxErXC9oBgEiXMbrIcNftBJGjBGLYrFzoMQWems4D9S1bnjicRNJkCQgk6VUEhKYsoVGbCV3jZR5kBZHVTpBzOzpDqjPnEAVCgXJTahRoT+PlVgalERTbeVAQIUpKcRUlrhCXLWZ0qlUoljT7SzxbxqJgc3QpiULlm1Yqmmfyr1I95/du3O16l0ll1ZdwGwF/70ReNVgxIVT6BIK6ajLj5ApSY58FHNlTJctZ94AOrTo0aRLmz5NoQAAOw== // @author Jan Dunker // ==/UserScript== // global variable declaration var tabtitlesucess = false; var ticketlinksuccess = false; var uiretrycounter = 0; // This script uses the GM_config library by sizzle to manage user settings GM_config.init( { 'id': 'ttmesdp', 'title': 'Einstellungen', 'events': { 'save': function (){ // automatically close dialog when saving GM_config.close(); // ask if settings should be applied now (page reload required) if (window.confirm('Soll der Tab jetzt neu geladen werden, um die Einstellungen zu übernehmen?')) { location.reload(); } }, 'open': function (doc, window, frame){ // add shadow to dialog and change border color GM_config.frame.style.border = '1px solid #888'; GM_config.frame.style.boxShadow = '0px 4px 15px 10px rgba(0, 0, 0, 0.3)'; // change button labels doc.getElementById('ttmesdp_saveBtn').textContent = 'Speichern'; doc.getElementById('ttmesdp_closeBtn').textContent = 'Abbrechen'; doc.getElementById('ttmesdp_resetLink').textContent = 'Felder zurücksetzen'; // give focus to settings dialog window.focus(); // prevent scrolling document.body.style.overflow = 'hidden'; }, 'close': function (){ // re-enable scrolling document.body.style.overflow = 'auto'; } }, 'css': '#ttmesdp_header:before {content: ""; display: block; background: url("data:image/gif;base64,R0lGODlhEAAQAHAAACH5BAkAAAMALAAAAAAQABAAgQAAAHSK///TdAAAAAI7nI85wIDtDhAiGhCCXXRj/XRP5nXNQp4TJX4ZuLKOS3KVmjK2V0smlGuYTKkUS0bLHYEvHUS3eCqmiAIAOw==") no-repeat; background-size: contain; width: 32px; height: 32px; image-rendering: crisp-edges; float: left; margin: 2px 15px 0 0; } #ttmesdp_buttons_holder .reset_holder.block {display: inline;} #ttmesdp_buttons_holder .saveclose_buttons, #ttmesdp_resetLink {margin: 10px 10px 10px 0px;} .section_header_holder, #ttmesdp #ttmesdp_header.config_header {margin: 15px} #ttmesdp_buttons_holder {position: sticky; bottom: 0px; width: 100%; background-color: #fffe; border-top: 1px solid #888; box-shadow: 0px -3px 5px 0px rgba(0, 0, 0, 0.3);} #ttmesdp_wrapper, body#ttmesdp {margin: 0px} .section_header center { margin-top: 10px; } .section_desc { margin-bottom: 10px; } #ttmesdp .center {text-align: left; padding: 5px; } body#ttmesdp * {font-family: Segoe UI, Arial, sans-serif; } #ttmesdp label.field_label { display: block; margin: 5px; font-size: 13px; font-weight: normal;} input { margin: 2px 5px 10px; font-size: 13px; font-weight: normal;} input[type=text]{padding: 3px; width: 90%;}', 'fields': { 'lang': { 'label': 'Sprache der Tabtitel / Language of tab titles', 'section': ['Tabtitel allgemein','Automatisch einen passenden Tabtitel setzen. Mehr Infos in den Tooltips.'], 'type': 'radio', 'options': ['Auto', 'DE', 'EN'], 'default': 'Auto', 'title': 'Sprache der Tabtitel. Bitte beachten, dass die Sprache der Texte, die aus der Seite stammen, ggf. abweichen kann.\n\ Language of the tab titles. Please note that the language of the texts coming from the site may differ.\n\ \u26A0\uFE0F Unfortunately the settings dialog is not translated yet. Please refer to the script source code starting around line 450.' }, 'updateinterval': { 'label': 'Aktualisierungsintervall des Titels (in ms)', 'type': 'int', 'default': 1000, 'min': 50, 'title': 'Desto niedriger die Zahl, desto häufiger wird der Tabtitel aktualisiert. Bei schlechter Performance sollte der Wert hochgesetzt werden.\nWenn der Tab sich im Hintergrund befindet, wird die Tabtitelaktualisierung pausiert, um die Systemressourcen zu schonen.' }, 'prefix': { 'label': 'Allgemeines Präfix (vor allen Titeln)', 'type': 'text', 'default': '', 'title': 'steht immer vor dem generierten Tabtitel' }, 'suffix': { 'label': 'Allgemeines Suffix (nach allen Titeln)', 'type': 'text', 'default': ' - Ticketsystem', 'title': 'steht immer hinter dem generierten Tabtitel' }, 'fallbacktitle': { 'label': 'Titel im Fall, dass keine spezifische Seite erkannt werden kann', 'type': 'text', 'default': 'Ticketsystem', 'title': 'Anhand der URL wird für fast alle Seiten ein Titel ermittelt. Sollte es mal Keinen geben, wird stattdessen diese Einstellung als Titel verwendet.' }, 'emptyfield': { 'label': 'Wert, der im Tabtitel benutzt wird, wenn ein %platzhalter% nicht gefunden werden kann', 'type': 'text', 'default': '[...]', 'title': 'Sollte beispielweise die Ticketnummer nicht auf der Seite gefunden werden können, wird der Platzhalter %ticket_id% stattdessen durch diesen Wert ersetzt.' }, 'ticketstring': { 'label': 'Ticketdetails', 'section': ['Tabtitel für Detailseiten','Hier kann der Tabtitel für bestimmte Seiten mit Platzhaltern gestaltet werden. Die verfügbaren Platzhalter sind im Tooltip zu finden.'], 'type': 'text', 'default': '%ticket_id% %ticket_title% - %ticket_requester%', 'title': '%ticket_id% - Ticketnummer\n\ %ticket_status% - Ticketstatus (Open/Closed/On Hold)\n\ %ticket_title% - Betreff\n%ticket_technician% Techniker/Bearbeiter\n\ %ticket_group% - Gruppe\n\ %ticket_requester% - Anforderer\n\ %ticket_site% - Standort\n\ %ticket_category% - Kategorie\n\ %ticket_subcategory% - Unterkategorie\n\ %ticket_element% - Element' }, 'taskstring': { 'label': 'Aufgabendetails', 'type': 'text', 'default': '%ticket_id% Task %task_title% (Task ID: %task_id%)', 'title': '%ticket_id% - Ticketnummer\n\ %ticket_status% - Ticketstatus (Open/Closed/On Hold)\n\ %task_status% - Aufgabenstatus\n\ %task_title% - Aufgabentitel\n\ %task_technician% - Techniker/Bearbeiter\n\ %task_group% - Gruppe\n\ %task_createdby% - Aufgabenersteller\n\ %task_type% - Aufgabentyp' }, 'problemstring': { 'label': 'Problemdetails', 'type': 'text', 'default': 'Problem %problem_id% %problem_title% - %problem_requester%', 'title': '%problem_id% - Problemnummer\n\ %problem_status% - Problemstatus\n\ %problem_title% - Problemtitel\n\ %problem_priority% - Priorität\n\ %problem_technician% - Techniker/Bearbeitern\n\ %problem_group% - Gruppe\n\ %problem_requester% - Anforderer\n\ %problem_category% - Kategorie\n\ %problem_subcategory% - Unterkategorie\n\ %problem_element% - Element\n\ %problem_site% - Standort' }, 'ticketliststring': { 'label': 'Ticketübersicht', 'section': ['Tabtitel für Übersichts-/Listenseiten','Hier kann der Tabtitel für bestimmte Seiten mit Platzhaltern gestaltet werden. Die verfügbaren Platzhalter sind im Tooltip zu finden.'], 'type': 'text', 'default': '%ticketlist_group%', 'title': '%ticketlist_group% - Gruppe' }, 'taskliststring': { 'label': 'Aufgabenübersicht', 'type': 'text', 'default': '%tasklist_filter%', 'title': '%tasklist_filter% - Aufgabenfilter' }, 'problemliststring': { 'label': 'Problemübersicht', 'type': 'text', 'default': '%problemlist_filter%', 'title': '%problemlist_filter% - Problemfilter' }, 'doAddTicketLinks': { 'label': 'Funktion aktivieren', 'section': ['Klickbare Ticketnummern', 'Wenn aktiviert, werden die Ticketseiten nach anderen Ticketnummern durchsucht und verlinkt.'], 'type': 'checkbox', 'default': true, 'title': 'Durchsucht werden Ticketbetreff, Ticketbeschreibung und Besprechungen (Notizen und E-Mails) auf Ticketseiten.' }, 'openLinksInNewTab': { 'label': 'Ticketlinks in neuem Tab öffnen', 'type': 'checkbox', 'default': true, 'title': 'Bei deaktivierter Einstellung wird der Link im aktuellen Tab geöffnet.' }, 'ticketregex': { 'label': 'Regex zur Erkennung von Ticketnummern', 'type': 'text', 'default': '\\b([4-6]\\d{5})\\b', 'title': 'Um die Ticketnummern zu erkennen, werden reguläre Ausdrücke verwendet.\n\ In der Standardeinstellung werden sechsstellige Nummern erkannt, die mit 4, 5 oder 6 anfangen.\n\ \\b(\\d{6})\\b - alle sechsstelligen Nummern erkennen\n\ \\b(\\d{4})\\b - alle vierstelligen Nummern erkennen\n\ Hilfreiches Tool: regexr.com' }, 'ticketlinksinterval': { 'label': 'Aktualisierungsintervall für klickbare Ticketnummern (in ms)', 'type': 'int', 'default': 5000, 'min': 0, 'title': 'Desto niedriger die Zahl, desto häufiger werden die Texte nach Ticketnummern durchsucht. Bei schlechter Performance sollte der Wert hochgesetzt werden.\nWenn der Tab sich im Hintergrund befindet, wird die Funktion pausiert, um die Systemressourcen zu schonen.', }, 'doEmbedSVG' : { 'label': 'Funktion aktivieren', 'section': ['SVG einbetten', '[Firmenspezifisch] Wenn aktiviert, wird bei Hilfebutton-Tickets der SVG-Screenshot-Anhang in die Seite eingebettet.'], 'type': 'checkbox', 'default': true, 'title': 'Der Screenshot erscheint unterhalb der Ticketbeschreibung.' }, 'hidenavbaricon': { 'label': 'Icon oben links in der Navigationsleiste ausblenden', 'section': ['UI Tweaks', 'Wenn aktiviert, werden kleine Anpassungen an der Benutzeroberfläche vorgenommen.'], 'type': 'checkbox', 'default': true, 'title': 'Beim Neuladen des Tabs kann es einen Moment dauern, bis das Element versteckt ist.' }, 'hidenavbartext': { 'label': 'Text oben links in der Navigationsleiste ausblenden', 'type': 'checkbox', 'default': true, 'title': 'Beim Neuladen des Tabs kann es einen Moment dauern, bis das Element versteckt ist.' }, 'hidetopbar': { 'label': 'Weiße Leiste unterhalb der Navigationsleiste ausblenden. Der Notizblockbutton wird dann in der Navigationsleiste neben dem Suchbutton angezeigt.', 'type': 'checkbox', 'default': false, 'title': 'Beim Neuladen des Tabs kann es einen Moment dauern, bis das Element versteckt ist.' }, 'hidedcdownmsg' : { 'label': 'Fehlermeldung "DC-Dienst ausgefallen. Bitte wenden Sie sich an Ihren Administrator" ausblenden.', 'type': 'checkbox', 'default': true, 'title': 'Beim Neuladen des Tabs kann es einen Moment dauern, bis das Element versteckt ist.' }, 'uicustomizinginterval': { 'label': 'Bei Fehlschlag erneut versuchen nach (in ms)', 'type': 'int', 'default': 500, 'min': 0, 'title': 'Klappt das Umsetzen der UI-Anpassungen nicht, wird der Vorgang ein paar Mal wiederholt. Meldungen dazu können in den Entwicklertools in der Konsole eingesehen werden.' }, 'logLevel': { 'label': 'Performancemessungen in Konsole ausgeben', 'section': ['Erweiterte Konfiguration', 'Weiterführende Einstellungen.'], 'type': 'radio', 'options': ['aus', 'einfach', 'detailliert'], 'default': 'aus', 'title': 'Wie lange dauert XY? Wenn aktiviert, können die Zeitmessungen in den Entwicklertools in der Konsole eingesehen werden.' }, 'defaulttabtitle': { 'label': 'Produktname/systemseitiger Standardtitel (nicht ändern, wenn es funktioniert)', 'type': 'text', 'size': 0, 'default': 'ManageEngine ServiceDesk Plus', 'title': 'Der Titel, der ohne das Skript angezeigt werden würde. Auch zu finden in der Variable sdp_app.PRODUCT_NAME. Der Wert wird intern benötigt und muss nur verändert werden, wenn er nicht passt.' } } }); // INFO ZU BENUTZERDEFINIERTEN FUNKTIONEN // information about custom functions // // Wenn das Skript nach Änderungen der Einstellungen oder benutzerdefinierten Funktionen nicht läuft, bitte einen Syntaxcheck durchführen (https://esprima.org/demo/validate.html). // If this script doesn't run after editing settings / custom functions, please perform a syntax check (https://esprima.org/demo/validate.html). // Benutzerdefinierte Funktionen sollen nicht arbeitsintensiv sein, da sie bei jeder Aktualisierung (Standard: ein Mal pro Sekunde) und bei jeder Platzhalterersetzung berechnet werden. // Do not make custom functions computing heavy as they run on every update (default: once per second) and as many times as a placeholder is substituted. // // Bei benutzerdefinierten Funktionen sollten folgende Funktionen verwendet werden, um Fehler abzufangen und Texte rückzugeben: // The following functions should be used because they do error handling and return strings: // getById('id') // document.getElementById('id') // querySel('CSS selector') // similar to document.querySelector('CSS selector') // getByDataName('name') // data-name='name' // DETAILSEITEN // detail pages /* Seitentitel für Tickets Page title for tickets %ticket_id% Ticketnummer %ticket_status% Ticketstatus (Open/Closed/On Hold) %ticket_title% Betreff %ticket_technician% Techniker/Bearbeiter %ticket_group% Gruppe %ticket_requester% Anforderer %ticket_site% Standort %ticket_category% Kategorie %ticket_subcategory% Unterkategorie %ticket_element% Element %custom1% Eigene Funktion 1 ... %custom5% Eigene Funktion 5 */ const ticketstring = GM_config.get('ticketstring'); //"%ticket_id% %ticket_title% - %ticket_requester%"; // Benutzerdefinierte Funktionen // custom functions function getFieldTicket_custom1(){let now = new Date(); return now.getHours().toString() + ":" + (now.getMinutes().toString()<10 ? "0" & now.getMinutes().toString() : now.getMinutes().toString());} function getFieldTicket_custom2(){return "";} function getFieldTicket_custom3(){return "";} function getFieldTicket_custom4(){return "";} function getFieldTicket_custom5(){return "";} /* Seitentitel für Aufgaben Page title for tasks %ticket_id% Ticketnummer %ticket_status% Ticketstatus (Open/Closed/On Hold) %task_status% Aufgabenstatus %task_title% Aufgabentitel %task_technician% Techniker/Bearbeiter %task_group% Gruppe %task_createdby% Aufgabenersteller %task_type% Aufgabentyp %custom1% Eigene Funktion 1 ... %custom5% Eigene Funktion 5 */ const taskstring = GM_config.get('taskstring'); //"%ticket_id% Task %task_title% (Task ID: %task_id%)"; // Benutzerdefinierte Funktionen // custom functions function getFieldTask_custom1(){return "";} function getFieldTask_custom2(){return "";} function getFieldTask_custom3(){return "";} function getFieldTask_custom4(){return "";} function getFieldTask_custom5(){return "";} /* Seitentitel für Probleme Page title for problems %problem_id% Problemnummer %problem_status% Problemstatus %problem_title% Problemtitel %problem_priority% Priorität %problem_technician% Techniker/Bearbeiter %problem_group% Gruppe %problem_requester% Anforderer %problem_category% Kategorie %problem_subcategory% Unterkategorie %problem_element% Element %problem_site% Standort %custom1% Eigene Funktion 1 ... %custom5% Eigene Funktion 5 */ const problemstring = GM_config.get('problemstring'); //"Problem %problem_id% %problem_title% - %problem_requester%"; // Benutzerdefinierte Funktionen // custom functions function getFieldProblem_custom1(){return "";} function getFieldProblem_custom2(){return "";} function getFieldProblem_custom3(){return "";} function getFieldProblem_custom4(){return "";} function getFieldProblem_custom5(){return "";} // LISTEN/ÜBERSICHTSSEITEN // lists /* Seitentitel für die Ticketübersicht Page title for the ticket list %ticketlist_group% Gruppe %custom1% Eigene Funktion 1 ... %custom5% Eigene Funktion 5 */ const ticketliststring = GM_config.get('ticketliststring'); //"%ticketlist_group%"; // Benutzerdefinierte Funktionen // custom functions function getFieldTicketList_custom1(){return "";} function getFieldTicketList_custom2(){return "";} function getFieldTicketList_custom3(){return "";} function getFieldTicketList_custom4(){return "";} function getFieldTicketList_custom5(){return "";} /* Seitentitel für die Aufgabenübersicht Page title for the task list %tasklist_filter% Aufgabenfilter %custom1% Eigene Funktion 1 ... %custom5% Eigene Funktion 5 */ const taskliststring = GM_config.get('taskliststring'); //"%tasklist_filter%"; // Benutzerdefinierte Funktionen // custom functions function getFieldTaskList_custom1(){return "";} function getFieldTaskList_custom2(){return "";} function getFieldTaskList_custom3(){return "";} function getFieldTaskList_custom4(){return "";} function getFieldTaskList_custom5(){return "";} /* Seitentitel für die Problemübersicht Page title for the problem list %problemlist_filter% Aufgabenfilter %custom1% Eigene Funktion 1 ... %custom5% Eigene Funktion 5 */ const problemliststring = GM_config.get('problemliststring'); //"%problemlist_filter%"; // Benutzerdefinierte Funktionen // custom functions function getFieldProblemList_custom1(){return "";} function getFieldProblemList_custom2(){return "";} function getFieldProblemList_custom3(){return "";} function getFieldProblemList_custom4(){return "";} function getFieldProblemList_custom5(){return "";} // Language // 0: de // 1: en var lang = GM_config.get('lang'); if (lang == 'DE') lang = 0; else if (lang == 'EN') lang = 1; else if (navigator.language == "de") lang = 0; else lang = 1; // debug mode var logLevel = GM_config.get('logLevel'); if (logLevel == 'einfach') logLevel = 1; else if (logLevel == 'detailliert') logLevel = 2; else logLevel = 0; // Prefix (before every title) const prefix = GM_config.get('prefix'); // Suffix (after every title) const suffix = GM_config.get('suffix'); // Empty field string const emptyfield = GM_config.get('emptyfield'); // Update interval for the title in ms // The smaller the number, the more often and more bad for performance const updateinterval = GM_config.get('updateinterval'); // 1 Sekunde // Fallback title, in case nothing is defined const fallbacktitle = GM_config.get('fallbacktitle'); // Product name/system-sided default title const defaulttabtitle = GM_config.get('defaulttabtitle'); // clickable ticket no. links // // If activated, the texts on ticket pages are searched for ticket no.. Results get replaced by links. const doAddTicketLinks = GM_config.get('doAddTicketLinks'); // Open ticket links in new tabs const openLinksInNewTab = GM_config.get('openLinksInNewTab'); // The search runs every x ms: const ticketlinksinterval = GM_config.get('ticketlinksinterval'); // Ticket no. detection const ticketregex = new RegExp(GM_config.get('ticketregex'), 'g'); // embed svg screenshot attachment // /!\ This is a company specific feature. You can disable this if you work for a different employer. const doEmbedSVG = GM_config.get('doEmbedSVG'); // ui customizing // retry after x milliseconds const uicustomizinginterval = GM_config.get('uicustomizinginterval') // Hide left icon in navbar const hidenavbaricon = GM_config.get('hidenavbaricon') // Hide left text in navbar const hidenavbartext = GM_config.get('hidenavbartext') // Hide white bar under navbar const hidetopbar = GM_config.get('hidetopbar') // hide dc-service down alert const hidedcdownmsg = GM_config.get('hidedcdownmsg') // getElementById with handling function getById(id){ var elem = document.getElementById(id); if (elem) { if (elem.innerText.trim() != "") return elem.innerText.trim(); else return elem.title.trim(); } else { console.log('[UserScript Tab Titles] "' + id + '" not found, returning "' + emptyfield + '" instead. Try document.getElementById("' + id + '")'); return emptyfield; } } // get using data-name with handling function getByDataName(name){ var elem = null; let data = document.querySelectorAll("[data-name]"); for (let i=0; i<data.length; i++) { if(name == data[i].dataset.name) { elem = data[i]; break; } } if (elem) { if (elem.innerText.trim() != "") return elem.innerText.trim(); else return elem.title.trim(); } else { console.log('[UserScript Tab Titles] "' + name + '" not found, returning "' + emptyfield + '" instead.'); return emptyfield; } } // document.querySelector with handling function querySel(selector){ var elem = document.querySelector(selector); if (elem) { if (elem.innerText.trim() != "") return elem.innerText.trim(); else return elem.title.trim(); } else { console.log('[UserScript Tab Titles] "' + selector + '" not found, returning "' + emptyfield + '" instead. Try document.querySelector("' + selector + '")'); return emptyfield; } } // Funktionen Ticket // lazy functions function getFieldTicket_ticket_id() {return getById("requestId");} //Ticketnummer function getFieldTicket_ticket_status() {return getById("status-right-panel");} //Ticketstatus (Open/Closed/On Hold) function getFieldTicket_ticket_title() {return getById("req_subject");} //Betreff function getFieldTicket_ticket_technician() {return getById("technician-right-panel");} //Techniker/Bearbeiter function getFieldTicket_ticket_group() {return getById("group-right-panel");} //Gruppe function getFieldTicket_ticket_requester() {return getById("userName");} //Anforderer function getFieldTicket_ticket_priority() {return getById("priority-right-panel");} //Priorität function getFieldTicket_ticket_site() {return getByDataName("site");} //Standort function getFieldTicket_ticket_category() {return getByDataName("category");} //Kategorie function getFieldTicket_ticket_subcategory() {return getByDataName("subcategory");} //Unterkategorie function getFieldTicket_ticket_element() {return getByDataName("item");} //Element function titleTicket(){ setTitle(ticketstring.replace("%ticket_id%",getFieldTicket_ticket_id).replace("%ticket_title%",getFieldTicket_ticket_title).replace("%ticket_technician%",getFieldTicket_ticket_technician).replace("%ticket_site%",getFieldTicket_ticket_site).replace("%ticket_group%",getFieldTicket_ticket_group).replace("%ticket_status%",getFieldTicket_ticket_status).replace("%ticket_requester%",getFieldTicket_ticket_requester).replace("%ticket_category%",getFieldTicket_ticket_category).replace("%ticket_subcategory%",getFieldTicket_ticket_subcategory).replace("%ticket_element%",getFieldTicket_ticket_element).replace("%ticket_priority%",getFieldTicket_ticket_priority).replace("%custom1%",getFieldTicket_custom1).replace("%custom2%",getFieldTicket_custom2).replace("%custom3%",getFieldTicket_custom3).replace("%custom4%",getFieldTicket_custom4).replace("%custom5%",getFieldTicket_custom5)); // add button to actionsbar if it's not already there //if (!document.getElementById('ttmesdp_opensettingsactionsbarbtn')) registerOpenSettingsActionsBar(); } // Funktionen Task // lazy functions function getFieldTask_ticket_id() {return getById("TaskEntityID").substring(2);} //Ticketnummer function getFieldTask_ticket_status() {return getById("TaskEntityStatus");} //Ticketstatus (Open/Closed/On Hold) function getFieldTask_task_id() {return getById("Hidden_TASKID");} //Aufgabennummer function getFieldTask_task_status() {return getById("Details_STATUSID");} //Aufgabenstatus function getFieldTask_task_title() {return getById("Task_TITLE");} //Aufgabentitel function getFieldTask_task_technician() {return getById("Details_OWNERID");} //Techniker/Bearbeiter function getFieldTask_task_group() {return getById("Details_GROUPID");} //Gruppe function getFieldTask_task_createdby() {return getById("Details_CREATEDBY");} //Aufgabenersteller function getFieldTask_task_type() {return getById("Details_taskType");} //Aufgabentyp function titleTask(){ setTitle(taskstring.replace("%ticket_id%",getFieldTask_ticket_id).replace("%ticket_status%",getFieldTask_ticket_status).replace("%task_id%",getFieldTask_task_id).replace("%task_title%",getFieldTask_task_title).replace("%task_createdby%",getFieldTask_task_createdby).replace("%task_group%",getFieldTask_task_group).replace("%task_status%",getFieldTask_task_status).replace("%task_technician%",getFieldTask_task_technician).replace("%task_type%",getFieldTask_task_type).replace("%custom1%",getFieldTask_custom1).replace("%custom2%",getFieldTask_custom2).replace("%custom3%",getFieldTask_custom3).replace("%custom4%",getFieldTask_custom4).replace("%custom5%",getFieldTask_custom5)); } // Funktionen Problem // lazy functions function getFieldProblem_problem_id() {return getById("problemid_ph");} //Problemnummer function getFieldProblem_problem_status() {return getById("STATUSID_CUR");} //Problemstatus function getFieldProblem_problem_title() {return getById("problemTitle");} //Problemtitel function getFieldProblem_problem_priority() {return getById("PRIORITYID_CUR");} //Priorität function getFieldProblem_problem_technician() {return getById("OWNERID_CUR");} //Techniker/Bearbeiter function getFieldProblem_problem_group() {return getById("QUEUEID_CUR");} //Gruppe function getFieldProblem_problem_requester() {return querySel(".reqtr-name");} //Anforderer function getFieldProblem_problem_category() {return getById("CATEGORYID_CUR");} //Kategorie function getFieldProblem_problem_subcategory() {return getById("SUBCATEGORYID_CUR");} //Unterkategorie function getFieldProblem_problem_element() {return getById("ITEMID_CUR");} //Element function getFieldProblem_problem_site() {return getById("SITEID_CUR");} //Standort function titleProblem(){ setTitle(problemstring.replace("%problem_id%",getFieldProblem_problem_id).replace("%problem_status%",getFieldProblem_problem_status).replace("%problem_title%",getFieldProblem_problem_title).replace("%problem_priority%",getFieldProblem_problem_priority).replace("%problem_technician%",getFieldProblem_problem_technician).replace("%problem_group%",getFieldProblem_problem_group).replace("%problem_requester%",getFieldProblem_problem_requester).replace("%problem_category%",getFieldProblem_problem_category).replace("%problem_subcategory%",getFieldProblem_problem_subcategory).replace("%problem_element%",getFieldProblem_problem_element).replace("%problem_site%",getFieldProblem_problem_site).replace("%custom1%",getFieldProblem_custom1).replace("%custom2%",getFieldProblem_custom2).replace("%custom3%",getFieldProblem_custom3).replace("%custom4%",getFieldProblem_custom4).replace("%custom5%",getFieldProblem_custom5)); } //Funktionen Ticketlist function titleTicketlist(){ setTitle(ticketliststring.replace("%ticketlist_group%",getById("listview_btn")).replace("%custom1%",getFieldTicketList_custom1).replace("%custom2%",getFieldTicketList_custom2).replace("%custom3%",getFieldTicketList_custom3).replace("%custom4%",getFieldTicketList_custom4).replace("%custom5%",getFieldTicketList_custom5)); } // Funktionen Tasklist function titleTasklist(){ setTitle(taskliststring.replace("%tasklist_filter%",getById("selected_tasklist_filter")).replace("%custom1%",getFieldTaskList_custom1).replace("%custom2%",getFieldTaskList_custom2).replace("%custom3%",getFieldTaskList_custom3).replace("%custom4%",getFieldTaskList_custom4).replace("%custom5%",getFieldTaskList_custom5)); } // Funktionen Problemlist function titleProblemlist(){ setTitle(problemliststring.replace("%problemlist_filter%",getById("ProListHdr")).replace("%custom1%",getFieldProblemList_custom1).replace("%custom2%",getFieldProblemList_custom2).replace("%custom3%",getFieldProblemList_custom3).replace("%custom4%",getFieldProblemList_custom4).replace("%custom5%",getFieldProblemList_custom5)); } // Titel mit Präfix und Suffix setzen function setTitle(str1, str2){ tabtitlesucess = true; if (str2) { if (lang == 0) window.document.title = prefix + str1 + suffix; else window.document.title = prefix + str2 + suffix; } else { window.document.title = prefix + str1 + suffix; } } // set tab title function tabTitles(){ if (logLevel > 0) console.time('tabTitles'); let url = location.href; if (url.match(/^https?:\/\/[\w\d.-]*\/WorkOrder\.do\?(?:.*&)?woMode=viewWO/)){ //Ticket titleTicket(); } else if (url.match(/^https?:\/\/[\w\d.-]*\/TaskDetails\.cc/)){ //Task if (document.getElementById("Task_TITLE")) titleTask(); else titleTasklist(); } else if (url.match(/^https?:\/\/[\w\d.-]*\/WOListView\.do/)){ //Ticketübersicht titleTicketlist(); } else if (url.match(/^https?:\/\/[\w\d.-]*\/SearchN\.do/)){ //Suche -> List/Ticket if (document.getElementById("requestId")) titleTicket(); else if (document.getElementById("Task_TITLE")) titleTask(); //Just in case else titleTicketlist(); } else if (url.match(/^https?:\/\/[\w\d.-]*\/WOAdvListView\.do/)){ setTitle("Erweiterte Ticketsuche","Advanced Ticket Search"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/WOAdvancedSearch\.do/)){ setTitle("Erweiterte Ticketsuche","Advanced Ticket Search"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/HomePage\.do/)){ setTitle("Home"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/DashBoard\.do/)){ setTitle("Dashboard"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/Problems\.cc/)){ titleProblemlist(); } else if (url.match(/^https?:\/\/[\w\d.-]*\/ProblemDetails\.cc/)){ titleProblem(); } else if (url.match(/^https?:\/\/[\w\d.-]*\/SolutionsHome\.do/)){ setTitle("Lösungen","Solutions"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/Templates\.do/)){ //Ticket-Vorlagen setTitle("Vorlagen","Templates"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/ShowTaskTemplateList\.cc/)){ setTitle("Vorlage auswählen","Select Template"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/SDArchiveWOListView\.do/)){ setTitle("Archivierte Anfragen","Archived Tickets"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/ReplyTemplate\.do/)){ setTitle("Antwortvorlagen","Reply Templates"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/AddNewProblem\.cc/)){ setTitle("Neues Problem erstellen","Create New Problem"); } else if (url.match(/https?:\/\/[\w\d.-]*\/WorkOrder\.do\?woMode=newWO/)){ setTitle("Neue Anforderung erstellen","Create New Request"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/TaskDefAction\.do/)){ //Neue Aufgabe erstellen setTitle("Neue Aufgabe erstellen","Create New Task"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/AddNewProblem\.cc/)){ setTitle("Neues Problem erstellen","Create New Problem"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/AddSolution\.do\\?.*submitaction=viewsolution/)){ setTitle("Lösung " + getById('solution_title'),"Solution " + getById('solution_title')); } else if (url.match(/^https?:\/\/[\w\d.-]*\/AddSolution\.do\\?.*submitaction=editsolution/)){ setTitle("Lösung bearbeiten","Edit Solution"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/AddSolution\.do/)){ setTitle("Lösung hinzufügen","Add Solution"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/showTopicDetails\.do/)){ setTitle("Lösungen","Solutions"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/ListRequests\.do/)){ setTitle(getById("defaultTitle")); } else if (url.match(/^https?:\/\/[\w\d.-]*\/CustomFilter\.do/)){ setTitle("Benutzerdefinierte Ansichten", "Custom Views"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/SearchRequester\.do/)){ setTitle("Anforderer auswählen","Select Requester"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/(?:AllReminders\.do|jsp\/Reminder\.jsp|ReminderDisplay\.do)/)){ setTitle("Erinnerungen","Reminders"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/(?:Announce|AnnounceShow)\.do/)){ setTitle("Ankündigungen","Announcements"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/calendar\//)){ setTitle("Kalender","Calendar"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/TopicAction\.do/)){ setTitle("Themen verwalten","Manage Topics"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/ImportXLSSolution\.do/)){ setTitle("Lösung importieren","Import Solution"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/AssociateCIList\.do/)){ setTitle("Assets auswählen","Select Assets"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/SiteLookup\.do/)){ setTitle("Standort auswählen","Select Site"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/ShowTaskTemplateList\.cc/)){ setTitle("Vorlage auswählen","Select Template"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/FilteredProblems\.cc/)){ setTitle("Problem auswählen","Select Problem"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/UserAssets\.do/)){ setTitle("Benutzer Assets","User Assets"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/SendNotification\.cc/)){ setTitle("Benachrichtigung senden", "Send Notification"); } else if (url.match(/^https?:\/\/[\w\d.-]*\/ShowTaskTemplateList\.cc/)){ setTitle("Vorlage auswählen","Select Template"); } else if (document.title === defaulttabtitle) { //Fallback nur Default setTitle(fallbacktitle); } else if (document.title.includes(defaulttabtitle + " - ")){ //Fallback Default mit Titel setTitle(document.title.replace(defaulttabtitle + " - ", "")); } if (logLevel > 0) console.timeEnd('tabTitles'); } // adding ticket links: where to look/replace depending on current page function addTicketLinks(){ // if tab is not open (page is not visible) do not waste computing power and skip the update // except if tab title has not been set yet (if the tab was opened in the background) or if the tab was just hidden (see event handler) if (document.visibilityState != 'visible' && ticketlinksuccess){ return; } let url = location.href; if (url.match(/^https?:\/\/[\w\d.-]*\/WorkOrder\.do\?(?:.*&)?woMode=viewWO/)) { addTicketLinksForTicket(); } else if (url.match(/^https?:\/\/[\w\d.-]*\/SearchN\.do/) && document.getElementById("requestId")) { addTicketLinksForTicket(); } } // adding ticket links: where to look/replace on ticket pages function addTicketLinksForTicket(){ ticketlinksuccess = true; if (logLevel > 0) console.time('addTicketLinksForTicket'); // Subject if (logLevel > 1) console.time('addTicketLinksForTicket_Subject'); addTicketLinksToId('req_subject'); if (logLevel > 1) console.timeEnd('addTicketLinksForTicket_Subject'); // Body if (logLevel > 1) console.time('addTicketLinksForTicket_Description'); addTicketLinksToId('req-desc-body'); if (logLevel > 1) console.timeEnd('addTicketLinksForTicket_Description'); // Conversations if (logLevel > 1) console.time('addTicketLinksForTicket_Conversations'); addTicketLinksToQuery('.panel-collapse.collapse'); if (logLevel > 1) console.timeEnd('addTicketLinksForTicket_Conversations'); if (logLevel > 0) console.timeEnd('addTicketLinksForTicket'); } // adding ticket links: call function for element function addTicketLinksToId(id){ // if not found log to console and return let elem = document.getElementById(id); if (!elem) { console.log('[UserScript Tab Titles] Adding ticket links failed: "' + id + '" not found. Try document.getElementById("' + id + '")'); return; } addTicketLinksToElem(elem); } // adding ticket links: call function for all elements function addTicketLinksToQuery(selector){ // if not found log to console and return let elems = document.querySelectorAll(selector); if (!elems) { console.log('[UserScript Tab Titles] Adding ticket links failed: "' + selector + '" not found. Try document.querySelectprAll("' + selector + '")'); return; } for (let i=0; i<elems.length; i++) { addTicketLinksToElem(elems[i]) } } // adding ticket links: the actual work function addTicketLinksToElem(elem){ if (elem) { // get all text nodes (within element) let iter = document.createNodeIterator(elem, NodeFilter.SHOW_TEXT); let textnode; // iterate through all text nodes while (textnode = iter.nextNode()) { // skip if parent is link to avoid nesting links if (textnode.parentNode.tagName != 'A') { // split text (e.g. ['My ticket is #', '123456', '. Thank you.']) let arr = textnode.nodeValue.split(ticketregex); for (let i = 0; i < arr.length; i++) { let a; if (ticketregex.test(arr[i]) && arr[i] != getFieldTicket_ticket_id()){ // if ticket number (and != current ticket) -> create a element a = document.createElement('a'); a.href = '/WorkOrder.do?woMode=viewWO&woID=' + arr[i]; if (openLinksInNewTab) a.target = '_blank'; a.innerText = arr[i]; } else { // else -> create text node a = document.createTextNode(arr[i]); } // insert replacement nodes textnode.parentNode.insertBefore(a, textnode); } // remove original text node textnode.parentNode.removeChild(textnode); } } } } // UI customizing function customizeUI(){ try { // hide navbar text if enabled if (hidenavbartext) document.getElementById("headinstanceicon").nextElementSibling.style.display = 'none'; // hide navbar icon if enabled if (hidenavbaricon) document.getElementById("headinstanceicon").style.display = 'none'; // hide topbar if enabled if (hidetopbar) { document.getElementById("top-subheader").style.display = 'none'; // create extra note button in the top right because the other one is now missing let elem = document.createElement("li"); elem.innerHTML = '<a id="custom-sticky-notes" onclick="$sticky_notes.load()" tab-name="Notizblock"><span><svg class="header-menu-icons" viewBox="0 0 24 24"> <g id="g33"> <rect style="stroke-width:0.8px;stroke-miterlimit:10" x="-9.4238186" y="18.841644" height="11.238" transform="rotate(-45)" id="rect27" /> <rect style="stroke-width:1.33094px;stroke-miterlimit:10" x="6.1109867" y="3.6965828" width="0.801" height="16.606834" id="rect29" /> <rect style="stroke-width:1.33094px;stroke-miterlimit:10" x="17.088013" y="3.6965828" width="0.801" height="16.606834" id="rect29-6" /> <rect style="stroke-width:1.12086px;stroke-miterlimit:10" x="6.1109862" y="19.502417" width="11.778027" height="0.801" id="rect31" /> <rect style="stroke-width:1.12086px;stroke-miterlimit:10" x="6.1109867" y="3.6965828" width="11.778027" height="0.801" id="rect31-7" /> <rect style="stroke-width:1.12086px;stroke-miterlimit:10" x="6.1109867" y="6.4593182" width="11.778027" height="0.801" id="rect31-7-2" /> </g></svg></span></a>'; let menu = document.querySelector(".header-icon-list"); menu.insertBefore(elem, menu.firstChild); } // hide dc service down message if enabled if (hidedcdownmsg) { if (document.getElementById('dc_down_msg')) { document.getElementById('dc_down_msg').style.display = 'none'; } } } catch { uiretrycounter++; if (uiretrycounter < 5) { // try again later console.log('[UserScript Tab Title] Failed to fully customize UI. Retrying in ' + uicustomizinginterval + ' ms'); if (uicustomizinginterval > 50) window.setTimeout(customizeUI, uicustomizinginterval); } else { console.log('[UserScript Tab Title] Failed to fully customize UI. Not retrying anymore, retry limit reached.'); } } } // SVG Embed // Embedding SVG can be done in many ways - here it's done by inserting the svg element into the html. This way, text can be selected and copied. function embedSVG(){ if (document.querySelector('a[download^=Screenshot_]') && document.getElementById('desc-content').innerText.match(/\[IK_SupportMail\]\s*$/) && !document.getElementById('ik_screenshot')) { if (logLevel > 0) console.time('embedSVG_all'); if (logLevel > 1) console.time('embedSVG_prepare'); // get screenshot attachment url let url = document.querySelector('a[download^=Screenshot_]').href; // prepare localized error messages just in case let embeddingErrorMsg; if (lang == 0) embeddingErrorMsg = 'Nachträgliches Einbetten des Screenshots fehlgeschlagen. Stattdessen den Anhang öffnen.' else embeddingErrorMsg = 'Dynamic embedding of the screenshot failed. Open the attachment instead.'; // create new ik_screenshot container let section = document.createElement('template'); section.innerHTML = '<div id="desc-ik_screenshot" class="atp-container-target atp-container m0 p10 clearfix"><p class="sb">Screenshot</p><hr class="mt0"><div id="ik_screenshot"></div></div>'; section = section.content.firstChild; // add at new position let att = document.getElementById('desc-attachments'); att.parentNode.insertBefore(section, att); // until SVG file is replaced, show 'Loading...' document.getElementById('ik_screenshot').innerHTML = 'Loading...'; if (logLevel > 1) console.time('embedSVG_download'); // fetch SVG file and insert contents into the container fetch(url).then( (response) => { response.text() .then( (text) => { if (logLevel > 1) console.timeEnd('embedSVG_download'); if (logLevel > 1) console.time('embedSVG_insert'); document.getElementById('ik_screenshot').innerHTML = text; if (logLevel > 1) console.timeEnd('embedSVG_insert'); if (logLevel > 0) console.timeEnd('embedSVG_all'); } ) .catch( (e) => { if (logLevel > 1) console.timeEnd('embedSVG_download'); console.log('Response failed: ' + e.message); document.getElementById('ik_screenshot').innerHTML = '[UserScript Tab Title] ' + embeddingErrorMsg + ' (Response, ' + e.message + ')'; if (logLevel > 1) console.timeEnd('embedSVG_insert'); if (logLevel > 0) console.timeEnd('embedSVG_all'); } ) } ) .catch( (e) => { if (logLevel > 1) console.timeEnd('embedSVG_download'); console.log('Fetch failed: ' + e.message); document.getElementById('ik_screenshot').innerHTML = '[UserScript Tab Title] ' + embeddingErrorMsg + ' (Fetch, ' + e.message + ')'; if (logLevel > 1) console.timeEnd('embedSVG_insert'); if (logLevel > 0) console.timeEnd('embedSVG_all'); } ); if (logLevel > 1) console.timeEnd('embedSVG_prepare'); } } // Hauptfunktion / Core Loop function update(){ // if tab is not open (page is not visible) do not waste computing power and skip the update // except if tab title has not been set yet (if the tab was opened in the background) or if the tab was just hidden (see event handler) if (document.visibilityState != 'visible' && tabtitlesucess){ return; } if (logLevel > 0) console.time('update'); // set tab titles tabTitles(); // embed SVG if available if (doEmbedSVG) embedSVG(); if (logLevel > 0) console.timeEnd('update'); } function openSettings(){ GM_config.open(); } function registerOpenSettings(){ if (logLevel > 1) console.time('registerOpenSettings'); GM_registerMenuCommand('Einstellungen', openSettings, 'e'); registerOpenSettingsProfile(); registerOpenSettingsTopbar(); if (logLevel > 1) console.timeEnd('registerOpenSettings'); } function registerOpenSettingsProfile(){ let a = document.getElementById('Pro-Personalize'); if (a) { let b = document.createElement('li'); a.parentElement.parentElement.appendChild(b); b.innerHTML = '<a href="javascript:void(0);" id="ttmesdp_opensettingsprofilebtn" name="Tabtitel-Einstellungen" class="p10"><span class="icon-md ml10" style="background-repeat: no-repeat; background-image: url(data:image/gif;base64,R0lGODlhEAAQAHAAACH5BAkAAAMALAAAAAAQABAAgQAAAHSK///TdAAAAAI7nI85wIDtDhAiGhCCXXRj/XRP5nXNQp4TJX4ZuLKOS3KVmjK2V0smlGuYTKkUS0bLHYEvHUS3eCqmiAIAOw==);"></span><span class="ml15">Tabtitel-Einstellungen</span></a>'; b.firstChild.addEventListener('click', openSettings); } } // currently unused function registerOpenSettingsActionsBar(){ let a = document.getElementById('actionsBar'); if (a) { let c = a.firstElementChild; if (c) { let b = document.createElement('a'); c.appendChild(b); b.href="javascript:void(0);"; b.id="ttmesdp_opensettingsactionsbarbtn"; b.name="Tabtitel-Einstellungen"; b.title="Tabtitel-Einstellungen"; b.className="btn btn-default btn-xs fl mr10"; b.style="top: 3px"; b.role = 'button'; b.innerHTML = '<span class="common-sprite icon-sm" style="top: 3px; background-repeat: no-repeat; background-image: url(data:image/gif;base64,R0lGODlhEAAQAHAAACH5BAkAAAMALAAAAAAQABAAgQAAAHSK///TdAAAAAI7nI85wIDtDhAiGhCCXXRj/XRP5nXNQp4TJX4ZuLKOS3KVmjK2V0smlGuYTKkUS0bLHYEvHUS3eCqmiAIAOw==);"></span>'; b.addEventListener('click', openSettings); } } } function registerOpenSettingsTopbar(){ //skip if this is not going to be shown anyways if (hidetopbar) return; let a = document.getElementById('subheader-show-menu'); if (a) { let b = document.createElement('div'); a.appendChild(b); b.id = 'ttmesdp_opensettingstopbarbtn'; b.className = 'vmiddle disp-ib bs-noconflict'; b.innerHTML = '<span aria-label="Tabtitel-Einstellungen" class="vmiddle cur-ptr" rel="uitooltip" title="Tabtitel-Einstellungen" style="border: solid #c8c7c8 1px; width: 24px; height: 23px; background-position: 3px 3px; display: inline-block; background-repeat: no-repeat; background-image: url(data:image/gif;base64,R0lGODlhEAAQAHAAACH5BAkAAAMALAAAAAAQABAAgQAAAHSK///TdAAAAAI7nI85wIDtDhAiGhCCXXRj/XRP5nXNQp4TJX4ZuLKOS3KVmjK2V0smlGuYTKkUS0bLHYEvHUS3eCqmiAIAOw==);"></span>'; b.addEventListener('click', openSettings); } } console.log('[UserScript Tab Title] Injected at \'' + window.location + '\''); // make settings available in several places registerOpenSettings(); // make sure update runs once after a page is hidden addEventListener('visibilitychange', event => { if (document.visibilityState == 'hidden') { tabtitlesucess = false; ticketlinksuccess = false; } }); // customize ui customizeUI(); // run first update update(); // schedule to run every x ms if (updateinterval > 50) window.setInterval(update, updateinterval); // add ticket links if (doAddTicketLinks && ticketlinksinterval > 50) window.setInterval(addTicketLinks, ticketlinksinterval);