// ==UserScript== // @name [HFR] Citation dans la reponse rapide // @version 0.1.4 // @namespace http://toyonos.info // @description Rajoute le systeme de citation dans la zone de réponse rapide via un double clic sur les icônes correspondantes // @include http://forum.hardware.fr/* // @exclude http://forum.hardware.fr/message.php* // ==/UserScript== var getElementByXpath = function (path, element) { var arr = Array(), xpr = document.evaluate(path, element, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); for (;item = xpr.iterateNext();) arr.push(item); return arr; } RegExp.escape = function(text) { if (!arguments.callee.sRE) { var specials = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\' ]; arguments.callee.sRE = new RegExp('(\\' + specials.join('|\\') + ')', 'g'); } return text.replace(arguments.callee.sRE, '\\$1'); } var trim = function (myString) { return myString.replace(/^\s+/g,'').replace(/\s+$/g,''); } var root = document.getElementById('mesdiscussions'); var delay = 300; getElementByXpath('//table//tr[starts-with(@class, "message")]//a[starts-with(@href, "/message.php" )]', root).filter(function(link) { return link.firstChild.alt == 'answer'; } ).forEach(function(link) { link.setAttribute('onclick', "return false;"); var timerQuote; var firstClickQuoteTime = null; link.addEventListener('click', function(event) { if (firstClickQuoteTime != null && new Date().getTime() - firstClickQuoteTime < delay) { clearTimeout(timerQuote); firstClickQuoteTime = null; toyoAjaxLib.loadDoc(this.href, 'get', null, function(pageContent) { var quote = html_entity_decode(pageContent.match(/([^þ]*)<\/textarea>/).pop()); var selection = RegExp.escape(trim(document.getSelection())); var regexpExists = new RegExp(selection); var regexpDebut = new RegExp('\\[quotemsg=[0-9]+,[0-9]+,[0-9]+\\]\\s*' + selection); var regexpFin = new RegExp(selection + '\\s*\\[/quotemsg\\]'); if (document.getSelection() && regexpExists.test(quote)) { document.getElementById('content_form').value = quote.match(/\[quotemsg=[0-9]+,[0-9]+,[0-9]+\]/).pop(); if (!regexpDebut.test(quote)) document.getElementById('content_form').value += '[…] '; document.getElementById('content_form').value += document.getSelection(); if (!regexpFin.test(quote)) document.getElementById('content_form').value += ' […]'; document.getElementById('content_form').value += "[/quotemsg]\n"; } else { document.getElementById('content_form').value = quote; } document.getElementById('content_form').focus(); }); } else { firstClickQuoteTime = new Date().getTime(); timerQuote = setTimeout("document.location = '" + this.href + "';", delay); } } , false); } ); getElementByXpath('//table//tr[starts-with(@class, "message")]//a[starts-with(@href, "/message.php" )]', root).filter(function(link) { return link.firstChild.alt == 'answer +'; } ).forEach(function(link) { var saveOnClick = link.getAttribute('onclick').replace(/return false;/, ''); link.setAttribute('onclick', "return false;"); var timerMultiQuote; var firstClickMultiQuoteTime = null; link.addEventListener('click', function(event) { if (firstClickMultiQuoteTime != null && new Date().getTime() - firstClickMultiQuoteTime < delay) { clearTimeout(timerMultiQuote); firstClickMultiQuoteTime = null; toyoAjaxLib.loadDoc(this.href, 'get', null, function(pageContent) { var quote = html_entity_decode(pageContent.match(/([^þ]*)<\/textarea>/).pop()); var selection = RegExp.escape(trim(document.getSelection())); var regexpExists = new RegExp(selection); var regexpDebut = new RegExp('\\[quotemsg=[0-9]+,[0-9]+,[0-9]+\\]\\s*' + selection); var regexpFin = new RegExp(selection + '\\s*\\[/quotemsg\\]'); if (document.getSelection() && regexpExists.test(quote)) { document.getElementById('content_form').value += quote.match(/\[quotemsg=[0-9]+,[0-9]+,[0-9]+\]/).pop(); if (!regexpDebut.test(quote)) document.getElementById('content_form').value += '[…] '; document.getElementById('content_form').value += document.getSelection(); if (!regexpFin.test(quote)) document.getElementById('content_form').value += ' […]'; document.getElementById('content_form').value += "[/quotemsg]\n"; } else { document.getElementById('content_form').value += quote; } }); } else { firstClickMultiQuoteTime = new Date().getTime(); timerMultiQuote = setTimeout(saveOnClick, delay); } } , false); } ); /******************************************************************/ var toyoAjaxLib = (function() { // Private members function loadPage(url, method, arguments, responseHandler) { var req; method = method.toUpperCase(); if (method == 'GET' && arguments != null) url += '?' + arguments; // branch for native XMLHttpRequest object if (window.XMLHttpRequest) { req = new XMLHttpRequest(); req.onreadystatechange = processReqChange(req, responseHandler); req.open(method, url, true); if (method == 'POST') req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); arguments = method == 'POST' ? arguments : null; req.send(arguments); } else if (window.ActiveXObject) { // branch for IE/Windows ActiveX version req = new ActiveXObject("Microsoft.XMLHTTP"); if (req) { req.onreadystatechange = processReqChange(req, responseHandler); req.open(method, url, true); if (method == 'POST') req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); if (method == 'POST') req.send(arguments); else req.send(); } } } function processReqChange(req, responseHandler) { return function () { try { // only if req shows "loaded" if (req.readyState == 4) { // only if "OK" if (req.status == 200) { var content = req.responseXML != null && req.responseXML.documentElement != null ? req.responseXML.documentElement : req.responseText; if (responseHandler != null) responseHandler(content); } else { alert("There was a problem retrieving the XML data:\n" + req.statusText); } } } catch(e){} } } // Public members return { "loadDoc" : function(url, method, arguments, responseHandler) { try { loadPage(url, method, arguments, responseHandler); } catch(e) { var msg = (typeof e == "string") ? e : ((e.message) ? e.message : "Unknown Error"); alert("Unable to get data:\n" + msg); return; } } }; })(); /******************************************************************/ var html_entity_decode = function (texte) { texte = texte.replace(/&#(\d+);/g, function() { return String.fromCharCode(RegExp.$1); }); texte = texte.replace(/"/g,'"'); // 34 22 texte = texte.replace(/&/g,'&'); // 38 26 texte = texte.replace(/'/g,"'"); // 39 27 texte = texte.replace(/</g,'<'); // 60 3C texte = texte.replace(/>/g,'>'); // 62 3E texte = texte.replace(/ˆ/g,'^'); // 94 5E texte = texte.replace(/‘/g,'‘'); // 145 91 texte = texte.replace(/’/g,'’'); // 146 92 texte = texte.replace(/“/g,'“'); // 147 93 texte = texte.replace(/”/g,'”'); // 148 94 texte = texte.replace(/•/g,'•'); // 149 95 texte = texte.replace(/–/g,'–'); // 150 96 texte = texte.replace(/—/g,'—'); // 151 97 texte = texte.replace(/˜/g,'˜'); // 152 98 texte = texte.replace(/™/g,'™'); // 153 99 texte = texte.replace(/š/g,'š'); // 154 9A texte = texte.replace(/›/g,'›'); // 155 9B texte = texte.replace(/œ/g,'œ'); // 156 9C texte = texte.replace(/ť/g,''); // 157 9D texte = texte.replace(/ž/g,'ž'); // 158 9E texte = texte.replace(/Ÿ/g,'Ÿ'); // 159 9F texte = texte.replace(/ /g,' '); // 160 A0 texte = texte.replace(/¡/g,'¡'); // 161 A1 texte = texte.replace(/¢/g,'¢'); // 162 A2 texte = texte.replace(/£/g,'£'); // 163 A3 texte = texte.replace(/¤/g,' '); // 164 A4 texte = texte.replace(/¥/g,'¥'); // 165 A5 texte = texte.replace(/¦/g,'¦'); // 166 A6 texte = texte.replace(/§/g,'§'); // 167 A7 texte = texte.replace(/¨/g,'¨'); // 168 A8 texte = texte.replace(/©/g,'©'); // 169 A9 texte = texte.replace(/ª/g,'ª'); // 170 AA texte = texte.replace(/«/g,'«'); // 171 AB texte = texte.replace(/¬/g,'¬'); // 172 AC texte = texte.replace(/­/g,'­'); // 173 AD texte = texte.replace(/®/g,'®'); // 174 AE texte = texte.replace(/¯/g,'¯'); // 175 AF texte = texte.replace(/°/g,'°'); // 176 B0 texte = texte.replace(/±/g,'±'); // 177 B1 texte = texte.replace(/²/g,'²'); // 178 B2 texte = texte.replace(/³/g,'³'); // 179 B3 texte = texte.replace(/´/g,'´'); // 180 B4 texte = texte.replace(/µ/g,'µ'); // 181 B5 texte = texte.replace(/¶/g,'¶'); // 182 B6 texte = texte.replace(/·/g,'·'); // 183 B7 texte = texte.replace(/¸/g,'¸'); // 184 B8 texte = texte.replace(/¹/g,'¹'); // 185 B9 texte = texte.replace(/º/g,'º'); // 186 BA texte = texte.replace(/»/g,'»'); // 187 BB texte = texte.replace(/¼/g,'¼'); // 188 BC texte = texte.replace(/½/g,'½'); // 189 BD texte = texte.replace(/¾/g,'¾'); // 190 BE texte = texte.replace(/¿/g,'¿'); // 191 BF texte = texte.replace(/À/g,'À'); // 192 C0 texte = texte.replace(/Á/g,'Á'); // 193 C1 texte = texte.replace(/Â/g,'Â'); // 194 C2 texte = texte.replace(/Ã/g,'Ã'); // 195 C3 texte = texte.replace(/Ä/g,'Ä'); // 196 C4 texte = texte.replace(/Å/g,'Å'); // 197 C5 texte = texte.replace(/Æ/g,'Æ'); // 198 C6 texte = texte.replace(/Ç/g,'Ç'); // 199 C7 texte = texte.replace(/È/g,'È'); // 200 C8 texte = texte.replace(/É/g,'É'); // 201 C9 texte = texte.replace(/Ê/g,'Ê'); // 202 CA texte = texte.replace(/Ë/g,'Ë'); // 203 CB texte = texte.replace(/Ì/g,'Ì'); // 204 CC texte = texte.replace(/Í/g,'Í'); // 205 CD texte = texte.replace(/Î/g,'Î'); // 206 CE texte = texte.replace(/Ï/g,'Ï'); // 207 CF texte = texte.replace(/Ð/g,'Ð'); // 208 D0 texte = texte.replace(/Ñ/g,'Ñ'); // 209 D1 texte = texte.replace(/Ò/g,'Ò'); // 210 D2 texte = texte.replace(/Ó/g,'Ó'); // 211 D3 texte = texte.replace(/Ô/g,'Ô'); // 212 D4 texte = texte.replace(/Õ/g,'Õ'); // 213 D5 texte = texte.replace(/Ö/g,'Ö'); // 214 D6 texte = texte.replace(/×/g,'×'); // 215 D7 texte = texte.replace(/Ø/g,'Ø'); // 216 D8 texte = texte.replace(/Ù/g,'Ù'); // 217 D9 texte = texte.replace(/Ú/g,'Ú'); // 218 DA texte = texte.replace(/Û/g,'Û'); // 219 DB texte = texte.replace(/Ü/g,'Ü'); // 220 DC texte = texte.replace(/Ý/g,'Ý'); // 221 DD texte = texte.replace(/Þ/g,'Þ'); // 222 DE texte = texte.replace(/ß/g,'ß'); // 223 DF texte = texte.replace(/à/g,'à'); // 224 E0 texte = texte.replace(/á/g,'á'); // 225 E1 texte = texte.replace(/â/g,'â'); // 226 E2 texte = texte.replace(/ã/g,'ã'); // 227 E3 texte = texte.replace(/ä/g,'ä'); // 228 E4 texte = texte.replace(/å/g,'å'); // 229 E5 texte = texte.replace(/æ/g,'æ'); // 230 E6 texte = texte.replace(/ç/g,'ç'); // 231 E7 texte = texte.replace(/è/g,'è'); // 232 E8 texte = texte.replace(/é/g,'é'); // 233 E9 texte = texte.replace(/ê/g,'ê'); // 234 EA texte = texte.replace(/ë/g,'ë'); // 235 EB texte = texte.replace(/ì/g,'ì'); // 236 EC texte = texte.replace(/í/g,'í'); // 237 ED texte = texte.replace(/î/g,'î'); // 238 EE texte = texte.replace(/ï/g,'ï'); // 239 EF texte = texte.replace(/ð/g,'ð'); // 240 F0 texte = texte.replace(/ñ/g,'ñ'); // 241 F1 texte = texte.replace(/ò/g,'ò'); // 242 F2 texte = texte.replace(/ó/g,'ó'); // 243 F3 texte = texte.replace(/ô/g,'ô'); // 244 F4 texte = texte.replace(/õ/g,'õ'); // 245 F5 texte = texte.replace(/ö/g,'ö'); // 246 F6 texte = texte.replace(/÷/g,'÷'); // 247 F7 texte = texte.replace(/ø/g,'ø'); // 248 F8 texte = texte.replace(/ù/g,'ù'); // 249 F9 texte = texte.replace(/ú/g,'ú'); // 250 FA texte = texte.replace(/û/g,'û'); // 251 FB texte = texte.replace(/ü/g,'ü'); // 252 FC texte = texte.replace(/ý/g,'ý'); // 253 FD texte = texte.replace(/þ/g,'þ'); // 254 FE texte = texte.replace(/ÿ/g,'ÿ'); // 255 FF return texte; }; // ============ Module d'auto update du script ============ ({ check4Update : function() { var autoUpdate = this; var mirrorUrl = GM_getValue('mirrorUrl', 'null'); if (mirrorUrl == 'null') autoUpdate.retrieveMirrorUrl(); var currentVersion = GM_getValue('currentVersion', '0.1.4'); // On met éventuellement la version stockée à jour avec la version courante, si la version courante est plus récente if (autoUpdate.isLater('0.1.4', currentVersion)) { GM_setValue('currentVersion', '0.1.4'); currentVersion = '0.1.4'; } // Par contre, si la version stockée est plus récente que la version courante -> création un menu d'update pour la dernière version else if (autoUpdate.isLater(currentVersion, '0.1.4')) { GM_registerMenuCommand("[HFR] Citation dans la reponse rapide -> Installer la version " + currentVersion, function() { GM_openInTab(mirrorUrl + 'citation_reponse_rapide.user.js'); } ); } // Si la version courante et la version stockée sont identiques, on ne fait rien if (GM_getValue('lastVersionCheck') == undefined || GM_getValue('lastVersionCheck') == '') GM_setValue('lastVersionCheck', new Date().getTime() + ''); // Pas eu de check depuis 24h, on vérifie... if ((new Date().getTime() - GM_getValue('lastVersionCheck')) > 86400000 && mirrorUrl != 'null') { var checkUrl = mirrorUrl + 'getLastVersion.php5?name=' + encodeURIComponent('[HFR] Citation dans la reponse rapide'); if (isNaN(currentVersion.substring(currentVersion.length - 1))) checkUrl += '&sversion=' + currentVersion.substring(currentVersion.length - 1); GM_xmlhttpRequest({ method: "GET", url: checkUrl, onload: function(response) { var regExpVersion = new RegExp('^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}[a-zA-Z]?$'); var lastVersion = response.responseText; // Pas d'erreur et nouvelle version plus récente if (lastVersion != '-1' && regExpVersion.test(lastVersion) && autoUpdate.isLater(lastVersion, currentVersion)) { if (confirm('Une nouvelle version de [HFR] Citation dans la reponse rapide est disponible : ' + lastVersion + '\nVoulez-vous l\'installer ?')) { GM_openInTab(mirrorUrl + 'citation_reponse_rapide.user.js'); } else { // Mémorisation de la version refusée : elle servira de version de référence GM_setValue('currentVersion', lastVersion); } } GM_setValue('lastVersionCheck', new Date().getTime() + ''); } }); } }, max : function(v1, v2) { var tabV1 = v1.split('.'); var tabV2 = v2.split('.'); if (isNaN(tabV1[2].substring(tabV1[2].length - 1))) tabV1[2] = tabV1[2].substring(0, tabV1[2].length - 1); if (isNaN(tabV2[2].substring(tabV2[2].length - 1))) tabV2[2] = tabV2[2].substring(0, tabV2[2].length - 1); if ((tabV1[0] > tabV2[0]) || (tabV1[0] == tabV2[0] && tabV1[1] > tabV2[1]) || (tabV1[0] == tabV2[0] && tabV1[1] == tabV2[1] && tabV1[2] > tabV2[2])) { return v1; } else { return v2; } }, isLater : function(v1, v2) { return v1 != v2 && this.max(v1, v2) == v1; }, retrieveMirrorUrl : function() { var mirrors = 'http://hfr.toyonos.info/gm/;http://hfr-mirror.toyonos.info/gm/'.split(';'); var checkMirror = function (i) { var mirror = mirrors[i]; GM_xmlhttpRequest({ url: mirror + 'getLastVersion.php5', method: "HEAD", onload: function(response) { // Dès qu'un miroir répond, on le mémorise. if (response.status == 200) { GM_setValue('mirrorUrl', mirror); } else { // Sinon on test le prochain if ((i + 1) < mirrors.length) { checkMirror(i + 1); } else { GM_setValue('mirrorUrl', 'null'); } } } }); }; checkMirror(0); }, }).check4Update();