NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name BBcode Reply // @namespace Anubys // @version 0.8.3 // @description Add bbcode on answer // @author Anubys // @copyright 2022, Anubys (https://openuserjs.org/users/Anubys) // @license MIT // @updateURL https://openuserjs.org/meta/Anubys/BBcode_Reply.meta.js // @downloadURL https://openuserjs.org/install/Anubys/BBcode_Reply.user.js // @include https://board.*.ogame.gameforge.com/* // @grant none // ==/UserScript== // @run-at document-end // var preview = document.querySelector('.formSubmit'), LengthPreview = document.querySelectorAll('.formSubmit').length, LastPreview = LengthPreview - 1, stock = localStorage.getItem('bbcode'), url = window.location.href, stock1 = localStorage.getItem('bbcodeFirst'), stock2 = localStorage.getItem('bbcodeLast'), stock3 = localStorage.getItem('bbcodeOption1'), stock4 = localStorage.getItem('bbcodeOption2'), stock5 = localStorage.getItem('SubmitOption'), PopupCreate = false; // Vérification de l'URL. var WordUrl = String(url), TestUrl = /thread-add/.test(WordUrl); // Chargement du module de traduction. const { changeLanguage, getAvailableLanguages, t } = loadTranslationModule() // Vérification des données stockées. if (!stock1 || stock1 === 'null' || !stock2 || stock2 === 'null') { alert('Entrez votre code dans les options ! Allez dans un sujet et cliquez sur option') } // Bouton d'ouverture des notifications. let ButtonNotif = document.querySelector('[data-tooltip=Notifications]'); ButtonNotif.addEventListener("click", function () { setTimeout(() => { let notif = document.querySelector('.interactiveDropdown.open'), buttonNotifIn = document.createElement('button'); notif.prepend(buttonNotifIn); buttonNotifIn.className = 'buttonNotif'; // Gestion de l'infobulle du bouton. /*tippy('.buttonNotif', { content: 'Ouvre toutes les notifications' });*/ buttonNotifIn.addEventListener('click', OpenNotif); },1); }) // Copie de la barre de navigation en bas. let Navigation = document.querySelector('.pageNavigation'), CloneNavigation = Navigation.cloneNode(true), Container = document.querySelector('.content'); CloneNavigation.style.display = 'block ruby'; CloneNavigation.style.marginTop = '10px'; CloneNavigation.style.background = 'rgba(127, 159, 180, 0.085) none repeat scroll 0 0'; CloneNavigation.id = "PageNavigationClone"; Container.appendChild(CloneNavigation); // Affichage du script si le button preview est présent. if (document.querySelector('#buttonMessagePreview')) { let button = document.createElement('button'), buttonOption = document.createElement('button'), buttonv2 = document.createElement('button'), buttonCloseWindow = document.createElement('button'); // Regex pour rechercher la couleur utilisée dans le code. var Testcolor = /#[a-z0-9]{6}/i.exec(stock1); if (Testcolor) { button.style.background = Testcolor[0]; buttonv2.style.background = Testcolor[0]; } else { button.style.background = '#ff8c00'; buttonv2.style.background = '#ff8c00'; } // Paramètres du bouton Beautify. if (stock3 === "true"){ document.querySelectorAll('.formSubmit')[LastPreview].prepend(button); } button.type ='button'; // Permet de ne pas activer le subit des autres bouttons du formulaire avec celui-ci button.addEventListener('click', texte); button.textContent = t('beautify'); button.className = 'button'; // Paramètres du bouton Beautify V2. if (stock4 === "true"){ document.querySelectorAll('.formSubmit')[LastPreview].prepend(buttonv2); } buttonv2.type ='button'; // Permet de ne pas activer le subit des autres bouttons du formulaire avec celui-ci buttonv2.addEventListener('click', textev3); buttonv2.innerHTML = t('beautify'); buttonv2.className = 'button'; buttonv2.id = 'buttonBeautify' // Paramètres du bouton Option. let lign = document.querySelector(('[class^="messageTabMenu"]')).querySelector('ul'); buttonOption.type = 'button'; // Permet de ne pas activer le subit des autres bouttons du formulaire avec celui-ci buttonOption.addEventListener('click', Popup); lign.appendChild(buttonOption); buttonOption.innerHTML = 'Option'; buttonOption.className = 'buttonOption' // Paramètre du bouton CloseWindows. if(TestUrl === false){ let Pagination = document.querySelector('.messageContent.messageQuickReplyContent'); buttonCloseWindow.type = 'button'; // Permet de ne pas activer le subit des autres bouttons du formulaire avec celui-ci buttonCloseWindow.addEventListener('click', CloseWindow); Pagination.parentNode.prepend(buttonCloseWindow); buttonCloseWindow.className = 'buttonCloseWindow'; } } // Suppression du bouton submit en fonction de l'URL. if (stock5 === "true"){ if(TestUrl){ let submit = document.querySelector('.formSubmit').getElementsByTagName('input')[0]; submit.style.display = 'none'; } else if (document.querySelectorAll('.buttonPrimary')[1]){ // Apparition seulement si nous sommes dans un sujet. let submit = document.querySelectorAll('.buttonPrimary'); submit[1].style.display = 'none'; } } // Ajout d'un bouton qui ouvre chaque nouveau sujet dans un onglet. var SubjectColumn = document.querySelector('.contentHeader'), NumberNewSubject = document.querySelectorAll('.tabularListRow > ol.new'); const htmlBuilder = { langSelect() { const currentLanguage = changeLanguage() const select = document.createElement('select') select.id = 'bbcodeReplyLangSelect' select.className = 'Input'; getAvailableLanguages().forEach(lang => { const option = document.createElement('option') option.value = lang option.textContent = lang if (lang === currentLanguage) { option.selected = true } select.appendChild(option) }) return select } } // Création du bouton. if (NumberNewSubject.length >= 1){ let buttonOpen = document.createElement('button'), content = document.querySelector('.contentHeaderTitle > h1'); buttonOpen.type ='button'; // Permet de ne pas activer le subit des autres bouttons du formulaire avec celui-ci buttonOpen.addEventListener('click', open); buttonOpen.className = "NewLecture"; content.appendChild(buttonOpen); function open(){ let i = 0; while(i < NumberNewSubject.length){ window.open(NumberNewSubject[i].querySelector('.messageGroupLink')); i = i + 1; } } } // Ajout d'un bouton qui ouvre chaque section comportant un message à lire (Exemple VDU). var NewSection = document.querySelectorAll('.wbbBoardContainer.wbbDepth1.tabularBox .badge.badgeUpdate:not(.badgeUpdateMobile)') if (NewSection.length >= 1){ let buttonOpenVDU = document.createElement('button'), contentVDU = document.querySelector('.contentHeaderTitle > h1'); buttonOpenVDU.type ='button'; // Permet de ne pas activer le subit des autres bouttons du formulaire avec celui-ci buttonOpenVDU.addEventListener('click', openVDU); buttonOpenVDU.className = "NewLecture"; contentVDU.appendChild(buttonOpenVDU); function openVDU(){ let i = 0; while(i < NewSection.length){ window.open(NewSection[i].parentElement.querySelector('a')); i = i + 1; } } } // Fonction validation du bouton submit au clic et suppression du bouton submit. function AutoSubmit(){ if (stock5 === "true"){ if(TestUrl){ let submit = document.querySelector('.formSubmit').getElementsByTagName('input')[0]; submit.click(); } else { let submit = document.querySelectorAll('.buttonPrimary'); submit[1].click(); } } } // Fonction d'implantation de texte. function texte(){ let Board = document.querySelector('#redactor-uuid-0'), Textbalise = document.createTextNode(stock1 + ' ' + stock2), Insert = Board.querySelectorAll('p'); Insert[Insert.length-1].appendChild(Textbalise); } // Fonction d'implantation de texte v2. function textev2(){ let Board = document.querySelector('#redactor-uuid-0').getElementsByTagName('p')[0], Board2 = document.querySelector('#redactor-uuid-0').querySelectorAll('p'), Board3 = Board2[Board2.length - 1]; Board.prepend(stock1); Board3.append(stock2); if(TestUrl){ setTimeout(() => { AutoSubmit(); }, "500") } else { AutoSubmit(); } } // Fonction d'implantation de texte v3. function textev3(){ let Board = document.querySelectorAll('#redactor-uuid-0 > p'), BoardUlLi = document.querySelectorAll('#redactor-uuid-0 > ul > li'), BoardOlLi = document.querySelectorAll('#redactor-uuid-0 > ol > li'), i = 0, j = 0, k = 0; while(i < Board.length){ Board[i].prepend(stock1); Board[i].append(stock2); i = i + 1; } while(j < BoardUlLi.length){ BoardUlLi[j].prepend(stock1); BoardUlLi[j].append(stock2); j = j + 1; } while(k < BoardOlLi.length){ BoardOlLi[k].prepend(stock1); BoardOlLi[k].append(stock2); k = k + 1; } if(TestUrl){ setTimeout(() => { AutoSubmit(); }, "500") } else { AutoSubmit(); } } // Fonction d'implantation de Color Letter. function ColorLetter() { document.querySelectorAll('#redactor-uuid-0 > p').forEach(paragraph => { paragraph.innerHTML = surroundFirstLetter(paragraph.innerHTML, stock1, stock2) }) AutoSubmit(); } function surroundFirstLetter(html, before, after) { const firstLetterIndex = findFirstLetterIndex(html) if (firstLetterIndex === -1) { return html } const firstPart = html.slice(0, firstLetterIndex) const lastPart = html.slice(firstLetterIndex + 1) return `${firstPart}${before}${html[firstLetterIndex]}${after}${lastPart}` } function findFirstLetterIndex(html) { let inHtmlTag = false let inBBCodeTag = false for (let index = 0; index < html.length; ++index) { if (inHtmlTag) { if (html[index] === '>') { inHtmlTag = false } } else if (inBBCodeTag) { if (html[index] === ']') { inBBCodeTag = false } } else if (html[index] === '<') { inHtmlTag = true } else if (html[index] === '[') { inBBCodeTag = true } else { return index } } return -1 } // Fonction réset des clés bbcode. function reset(){ localStorage.removeItem('bbcodeFirst'); localStorage.removeItem('bbcodeLast'); localStorage.removeItem('bbcodeOption1'); localStorage.removeItem('bbcodeOption2'); window.location.reload(); } // Fonction pour le pop-up des options. function Popup () { var popup1 = document.body, newDiv, newDiv1, newDiv2, newDiv3, newDiv4, newDiv5, newDiv6, newDiv7, newDiv8, newDiv9, exit = document.createElement('button'), valid = document.createElement('button'); if(PopupCreate === false){ newDiv = document.createElement('div'); const langDiv = document.createElement('div'); newDiv1 = document.createElement('div'); newDiv2 = document.createElement('div'); newDiv3 = document.createElement('div'); newDiv4 = document.createElement('div'); newDiv5 = document.createElement('div'); newDiv6 = document.createElement('div'); newDiv7 = document.createElement('div'); newDiv8 = document.createElement('div'); newDiv9 = document.createElement('div'); //Déclaration des classNames du popup. newDiv.className = 'popup'; newDiv1.className = 'Titre'; langDiv.className = 'ligne1'; newDiv2.className = 'ligne1'; newDiv3.className = 'ligne2'; newDiv4.className = 'ligne3'; newDiv5.className = 'ligne4'; newDiv6.className = 'ligne5'; newDiv7.className = 'ligne6'; newDiv8.className = 'ligne7'; newDiv9.className = 'ligne41'; popup1.appendChild(newDiv); newDiv.appendChild(newDiv1); newDiv.appendChild(langDiv); newDiv.appendChild(newDiv2); newDiv.appendChild(newDiv3); newDiv.appendChild(newDiv4); newDiv.appendChild(newDiv5); newDiv.appendChild(newDiv9); newDiv.appendChild(newDiv6); newDiv.appendChild(newDiv7); newDiv.appendChild(newDiv8); var newText = document.createTextNode("Options"), langText = document.createTextNode(`${t('lang')} : `), newText1 = document.createTextNode(`${t('begenning_bbcode')} : `), newText2 = document.createTextNode(`${t('bbcode_end')} : `), newText3 = document.createTextNode(`${t('beautify_before')} : `), newText4 = document.createTextNode(`${t('beautify_after')} : `), newText5 = document.createTextNode(`${t('RAZ')} : `), newText6 = document.createTextNode(`${t('automatically_post')} : `), newText7 = document.createTextNode("Premier lettre :"), Checkbox1 = document.createElement("input"), // Checkbox option poster avant. Checkbox2 = document.createElement("input"), // Checkbox option poster après. Checkbox3 = document.createElement("input"), // Checkbox option poster directement (autosubmit). Checkbox4 = document.createElement("input"); // Checkbox option première lettre seulement. langDiv.appendChild(langText); newDiv1.appendChild(newText); newDiv2.appendChild(newText1); newDiv3.appendChild(newText2); newDiv4.appendChild(newText3); newDiv5.appendChild(newText4); newDiv6.appendChild(newText6); newDiv7.appendChild(newText5); newDiv9.appendChild(newText7); // Implantation de l'option poster avant. Checkbox1.type = "checkbox"; Checkbox1.id = "checkboxOption1"; newDiv4.appendChild(Checkbox1); Checkbox1.style.position = 'fixed'; Checkbox1.style.right = '1em'; // Check de l'option décorer avant si l'opion est stocké ou non. Si stocké, la case se montre coché. if (stock3 === "true"){ document.getElementById('checkboxOption1').checked = true; } else { document.getElementById('checkboxOption1').checked = false; } // Implantation de l'option poster après. Checkbox2.type = "checkbox"; Checkbox2.id = "checkboxOption2"; newDiv5.appendChild(Checkbox2); Checkbox2.style.position = 'fixed'; Checkbox2.style.right = '1em'; //Check de l'option décorer après si l'opion est stocké ou non. Si stocké, la case se montre coché. if (stock4 === "true"){ document.getElementById('checkboxOption2').checked = true; } else { document.getElementById('checkboxOption2').checked = false; } // Implantation de l'option poster directement (autosubmit). Checkbox3.type = "checkbox"; Checkbox3.id = "checkboxOption3"; newDiv6.appendChild(Checkbox3); Checkbox3.style.position = 'fixed'; Checkbox3.style.right = '1em'; if (stock5 === "true"){ document.getElementById('checkboxOption3').checked = true; } else { document.getElementById('checkboxOption3').checked = false; } // Implantation de l'option première lettre seulement. Checkbox4.type = "checkbox"; Checkbox4.id = "checkboxOption4"; newDiv9.appendChild(Checkbox4); Checkbox4.style.position = 'fixed'; Checkbox4.style.right = '1em'; // Paramètres du bouton Reset. let buttonReset = document.createElement('button'); buttonReset.type = 'button'; // Permet de ne pas activer le subit des autres bouttons du formulaire avec celui-ci buttonReset.addEventListener('click', reset); newDiv7.appendChild(buttonReset); buttonReset.innerHTML = 'Reset'; buttonReset.className = 'Reset'; newDiv1.appendChild(exit); exit.addEventListener('click', close); exit.id = 'buttonExit' newDiv8.appendChild(valid); valid.addEventListener('click', buttonValid); valid.addEventListener('click', close); valid.id = "buttonValidation"; valid.innerHTML = 'Valider'; var langSelect = htmlBuilder.langSelect() var newInput1 = document.createElement("input") var newInput2 = document.createElement("input"); langDiv.appendChild(langSelect); newDiv2.appendChild(newInput1); newDiv3.appendChild(newInput2); newInput1.className = 'Input'; newInput1.id = 'Sitting1'; newInput1.value = stock1; newInput2.className = 'Input'; newInput2.id = 'Sitting2'; newInput2.value = stock2; function close (){ newDiv.style.display = 'none'; PopupCreate = true; console.log(PopupCreate); } function buttonValid (){ changeLanguage(document.getElementById('bbcodeReplyLangSelect').value) let stockon1 = document.getElementById('Sitting1').value, stockon2 = document.getElementById('Sitting2').value, stockon3 = document.getElementById('checkboxOption1').checked, stockon4 = document.getElementById('checkboxOption2').checked, stockon5 = document.getElementById('checkboxOption3').checked; localStorage.setItem('bbcodeFirst', stockon1); localStorage.setItem('bbcodeLast', stockon2); localStorage.setItem('bbcodeOption1', stockon3); localStorage.setItem('bbcodeOption2', stockon4); localStorage.setItem('SubmitOption', stockon5); window.location.reload(); } PopupCreate = true; } else { PopupOpen(); } } function PopupOpen (){ document.querySelector('.popup').style.display = 'inherit'; } function CloseWindow (){ window.close(); } function OpenNotif(){ let NewNotif = document.querySelectorAll('.notificationItem.interactiveDropdownItemOutstanding.interactiveDropdownItemOutstandingIcon.interactiveDropdownItemShadow'), k = 0; while(k < (NewNotif.length)){ let LastLink = NewNotif[k].querySelectorAll('div > div > h3 a'); window.open(NewNotif[k].querySelectorAll('div > div > h3 a')[LastLink.length - 1]); k = k + 1; } } // Code CSS. function addCss(cssString) { var head = document.getElementsByTagName('head')[0]; var newCss = document.createElement('style'); newCss.type = "text/css"; newCss.innerHTML = cssString; head.appendChild(newCss); } /*// Gestion des infobulles. tippy('.buttonOption', { content: 'Sélectionne tes options' }); tippy('.Reset', { content: 'Réinitialise toutes tes options' }); tippy('.NewLecture', { content: 'Ouvre les sujets non lus' }); tippy('.buttonCloseWindow', { content: 'Ferme l\'onglet' });*/ addCss(` .Titre{ text-align:center; color:orange; font-size:large; padding:5px; } .button{ padding:8px 10px; font-size:14px; } .buttonOption{ padding:1px 10px; font-size:10px; background-color:rgba(19, 18, 19, 0.78); margin:2px; } .popup{ margin:auto; position:fixed; top:50%; left:50%; transform:translate(-50%, -50%); z-index:99999; width:350px; height:auto; background-color:rgba(19, 18, 19, 0.78); border-radius:15px; } .Input{ position:fixed; right:1em; } .Reset{ margin:2px; position:fixed; padding:1px 10px; font-size:10px; background:#FF0000; right:1em; } .ligne1{ padding:10px; } .ligne2{ padding:10px; } .ligne3{ padding:10px; height:30px; } .ligne4{ padding:10px; height:30px; } .ligne41{ padding:10px; height:30px; } .ligne5{ padding:10px; height:30px; } .ligne6{ padding:10px; height:50px; } .ligne7{ padding:10px; height:50px; } .ligne8{ padding:10px; height:50px; } .buttonCloseWindow{ position:absolute; width:20px; height:20px; background:rgba(255,50,50,1); margin-left:212px; margin-top:8px; border-radius:300px; z-index:1; padding:0; box-shadow:-2px -2px 5px rgba(0,0,0,0.5) inset, 1px 1px 8px rgba(0,0,0,0.5); } .buttonCloseWindow:after { color:rgba(255,255,255,0.8); } .buttonCloseWindow:hover { background:rgba(50,255,50,1); } .NewLecture{ position:absolute; width:20px; height:20px; background:rgba(244, 102, 27, 1); border-radius:300px; padding:0; margin-top:7px; margin-left:20px; box-shadow:-2px -2px 5px rgba(0,0,0,0.5) inset, 1px 1px 8px rgba(0,0,0,0.5); } .NewLecture:after { color:rgba(255,255,255,0.8); } .NewLecture:hover { background:rgba(50,255,50,1); } .buttonNotif{ position:absolute; width:20px; height:20px; margin-top:1em; margin-left:10em; background:yellow; border-radius:300px; padding:0 !important; box-shadow : -2px -2px 5px rgba(0,0,0,0.5) inset, 1px 1px 8px rgba(0,0,0,0.5); } .buttonNotif:after { color : rgba(255,255,255,0.8); } .buttonNotif:hover { background: rgba(50,255,50,1); } #PageNavigationClone .breadcrumbs { margin-bottom: 0px; z-index: 0; } #PageNavigationClone.pageNavigation .pageNavigationIcons{ display : none; } section#main #content{padding-top : 30px;} .pageNavigation .breadcrumbs{ margin-bottom: -80px; } #buttonValidation{ position:fixed; right:40%; bottom:10px; width:60px; height:30px; padding:1px 10px; font-size:10px; background:#94e733; margin:2px; border-radius:15px; } #buttonExit{ float:right; padding:10px; border-radius:10px; background:#FF0000; } `); /***********************************************/ /******** Gestion des traductions - début ******/ /***********************************************/ function loadTranslationModule() { /** @typedef {keyof translations} Language */ /** @typedef {keyof translations[mainLanguage]} TranslationKey */ const translations = { fr: { lang: 'Langue', beautify: 'Décorer', begenning_bbcode: 'Début de votre bbcode', bbcode_end: 'Fin de votre bbcode', beautify_before: 'Décorer avant', beautify_after: 'Décorer après', RAZ: 'Remise à zéro', automatically_post: 'Poster automatiquement', }, en: { lang: 'Language', beautify: 'Beautify', begenning_bbcode: 'Begenning of your bbcode', bbcode_end: 'End of your bbcode', beautify_before: 'Beautify in first', beautify_after: 'Beautify after', RAZ: 'Reset', automatically_post: 'Post automatically', }, de: { lang: 'Sprache', beautify: '', begenning_bbcode: '', bbcode_end: '', beautify_before: '', beautify_after: '', RAZ: '', automatically_post: '', } } /** Langue principale, sera utilisé si une traduction n'existe pas dans une autre langue */ const mainLanguage = 'fr' /** * Langue Actuelle, choisie par l'utilisateur * @type {Language} */ let currentLanguage = localStorage.getItem('bbcodeReplyLanguage') || mainLanguage checkTranslationConsistency() /** * Renvoie la traduction demandée pour la langue selectionnée, * si celle ci n'est pas traduite renvoie la traduction pour la langue principale * @param {TranslationKey} translationKey * @returns {translations[mainLanguage][TranslationKey]} */ function t(translationKey) { return translations[currentLanguage][translationKey] || translations[mainLanguage][translationKey] } /** * Change la langue actuelle par celle fournie * Si aucune langue n'est fournie, ne change rien, mais renvoie la langue actuelle * @param {Language} [newLanguage] */ function changeLanguage(newLanguage) { if (newLanguage) { currentLanguage = newLanguage localStorage.setItem('bbcodeReplyLanguage', newLanguage) } return currentLanguage } /** * Renvoi la liste des langues disponibles * @returns {Language} */ function getAvailableLanguages() { return Object.keys(translations) } /** * Vérifie qu'il n'y a pas d'erreur dans la liste des traductions */ function checkTranslationConsistency() { const mainTranslationKeys = Object.keys(translations[mainLanguage]) Object.keys(translations) .filter(language => language !== mainLanguage) .forEach(language => { const currentTranslationKeys = Object.keys(translations[language]) mainTranslationKeys.forEach((translationKey, index) => { if (translationKey !== currentTranslationKeys[index]) { alert([ `There is an issue with the "${language}" Translation`, `"${translationKey}" should have been found but "${currentTranslationKeys[index]}" was found instead`, '', `To ensure consistency, check that the order is the same for "${mainLanguage}" and "${language}"`, '', `Note that it's fine if the translation is empty, for example ${translationKey}: ''`, ].join('\n')) } }) }); } return { changeLanguage, getAvailableLanguages, t, } } /*********************************************/ /******** Gestion des traductions - fin ******/ /*********************************************/