您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Pings you when specified words are said in the chat.
// ==UserScript== // @name IP.Chat Pings + Highlight // @namespace Makaze // @description Pings you when specified words are said in the chat. // @include * // @grant none // @version 2.4.0 // ==/UserScript== var titlePing, highlightPings, pingSound, audiblePingFile, audiblePingOnFocus, audiblePing, hasFocus = true, MakazeScriptStyles, IPChatMenuItems, pingMenu, menuButton, styleElem, defaultStyle = 'font-weight: bolder;\n' + 'font-size: 120%;\n' + 'color: #f24;\n' + 'text-shadow: 0px 1px #222;', opts, pingStyle, pings, userPings, userName, script_delay; // Global variable constructor function GlobalHandler() { var output; this.receiveEvent = function(event) { output = event.detail; }; this.dispatch = function(variable, name) { document.dispatchEvent( new CustomEvent('getGlobalVar_' + name, { detail: variable }) ); }; this.get = function(variable) { document.addEventListener('getGlobalVar_' + variable, this.receiveEvent, false); var getGlobalScript = document.createElement('script'); getGlobalScript.type = 'text/javascript'; getGlobalScript.id = 'getGlobalScript'; getGlobalScript.appendChild( document.createTextNode( '(' + this.dispatch.toString() + ')(' + variable + ', \'' + variable + '\');' + 'document.getElementById(\'getGlobalScript\').remove();' ) ); (document.body || document.documentElement).appendChild(getGlobalScript); document.removeEventListener('getGlobalVar_' + variable, this.receiveEvent, false); return output; }; this.set = function(variable, value) { switch (typeof value) { case 'string': value = '\'' + value + '\''; break; } var setGlobalScript = document.createElement('script'); setGlobalScript.type = 'text/javascript'; setGlobalScript.id = 'setGlobalScript'; setGlobalScript.appendChild( document.createTextNode( variable + ' = ' + value + ';' + 'document.getElementById(\'setGlobalScript\').remove();' ) ); (document.body || document.documentElement).appendChild(setGlobalScript); }; } // Initialize var Globals = new GlobalHandler(); // End global variable constructor // Classes constructor function ClassHandler() { var self = this; this.classList = function(elem) { return elem.className.trim().split(/[\b\s]/); }; this.hasClass = function(elem, className) { var classes = self.classList(elem), has = false, i = 0; for (i = 0; i < classes.length; i++) { if (classes[i] === className) { has = true; break; } } return (has); }; this.addClass = function(elem, className) { var classes; if (!self.hasClass(elem, className)) { classes = self.classList(elem); classes.push(className); elem.className = classes.join(' ').trim(); } return self; }; this.removeClass = function(elem, className) { var classes = self.classList(elem), i = 0; for (i = 0; i < classes.length; i++) { if (classes[i] === className) { classes.splice(i, 1); } } elem.className = classes.join(' ').trim(); return self; }; this.toggleClass = function(elem, className) { var classes; if (self.hasClass(elem, className)) { self.removeClass(elem, className); } else { classes = self.classList(elem); classes.push(className); elem.className = classes.join(' ').trim(); } return self; }; } // Initialize var Classes = new ClassHandler(); // End Classes constructor function fade(elem, type, speed) { var defaultOpacity, currentDisplay = elem.style.display || window.getComputedStyle(elem).display; elem.style.opacity = ''; defaultOpacity = window.getComputedStyle(elem).opacity; elem.style.opacity = 0; // Default values: switch (arguments.length) { case 1: type = 'toggle'; case 2: speed = 300; break; } switch (type) { case 'in': elem.style.display = ''; setTimeout(function() { elem.style.transition = 'all ' + speed + 'ms ease-in-out'; elem.style.opacity = defaultOpacity; setTimeout(function() { elem.style.transition = ''; elem.style.opacity = ''; }, speed + 10); }, 1); break; case 'out': elem.style.transition = ''; elem.style.opacity = defaultOpacity; elem.style.transition = 'all ' + speed + 'ms ease-in-out'; elem.style.opacity = 0; setTimeout(function() { elem.style.display = 'none'; elem.style.transition = ''; elem.style.opacity = ''; }, speed + 10); break; case 'toggle': default: if (currentDisplay === 'none') { elem.style.display = ''; setTimeout(function() { elem.style.transition = 'all ' + speed + 'ms ease-in-out'; elem.style.opacity = defaultOpacity; setTimeout(function() { elem.style.transition = ''; elem.style.opacity = ''; }, speed + 10); }, 1); } else { elem.style.transition = ''; elem.style.opacity = defaultOpacity; elem.style.transition = 'all ' + speed + 'ms ease-in-out'; elem.style.opacity = 0; setTimeout(function() { elem.style.display = 'none'; elem.style.transition = ''; elem.style.opacity = ''; }, speed + 10); } } } function createElement(type, callback) { var element = document.createElement(type); callback(element); return element; } function getUserName(context, userPings) { var userID = context.getElementsByClassName('ipsUserPhotoLink')[0].id.split('link_')[1], userName = context.getElementsByClassName('names')[0].getElementsByTagName('span')[0].title, newUserPings = [], i = 0, thisUserID, thisUserName; for (i = 0; i < userPings.length; i++) { newUserPings.push({'id': userPings[i].id, 'name': (userPings[i].hasOwnProperty('name')) ? userPings[i].name : null}); thisUserID = newUserPings[i].id; thisUserName = newUserPings[i].name; if (userID === thisUserID) { if (userName !== thisUserName) { newUserPings[i].name = userName; } } } return newUserPings; } function pingsInit() { var i = 0; userName = Globals.get('userName'); opts = (localStorage.getItem('MakazeScriptOptions')) ? JSON.parse(localStorage.getItem('MakazeScriptOptions')) : {}; pingStyle = (opts.hasOwnProperty('ipc_ping_style')) ? opts.ipc_ping_style : defaultStyle; pings = (opts.hasOwnProperty('ipc_pings')) ? opts.ipc_pings : [userName]; userPings = (opts.hasOwnProperty('ipc_user_pings')) ? opts.ipc_user_pings : []; audiblePing = (opts.hasOwnProperty('ipc_audible_ping')) ? opts.ipc_audible_ping : true; titlePing = (opts.hasOwnProperty('ipc_pings_in_title')) ? opts.ipc_pings_in_title : true; highlightPings = (opts.hasOwnProperty('ipc_highlight_pings')) ? opts.ipc_highlight_pings : true; audiblePingFile = (opts.hasOwnProperty('ipc_audible_ping_file')) ? opts.ipc_audible_ping_file : 'https://dl.dropboxusercontent.com/u/45569424/Saved_FE7.mp3'; audiblePingOnFocus = (opts.hasOwnProperty('ipc_audible_ping_on_focus')) ? opts.ipc_audible_ping_on_focus : false; pingSound = new Audio(audiblePingFile); // Styling if (document.getElementById('MakazeScriptStyles') == null) { MakazeScriptStyles = createElement('style', function(style) { style.id = 'MakazeScriptStyles'; style.type = 'text/css'; }); document.head.appendChild(MakazeScriptStyles); } styleElem = document.getElementById('MakazeScriptStyles'); if (styleElem.hasChildNodes()) { styleElem.childNodes[0].nodeValue += '\n\n'; } else { styleElem.appendChild(document.createTextNode('')); } if (!styleElem.childNodes[0].nodeValue.match('.MakazeScriptMenu')) { styleElem.childNodes[0].nodeValue += '.MakazeScriptMenu { position: fixed; z-index: 99999; top: 50%; left: 50%; padding: 10px; background-color: rgba(255, 255, 255, .85); box-shadow: 0px 0px 3px #888; border-radius: 5px; } .MakazeScriptMenu th { font-weight: bolder; } .MakazeScriptMenu th, .MakazeScriptMenu td { padding: 3px; } .MakazeScriptMenu .menu-save { text-align: center; margin-top: 6px; } .MakazeScriptMenu .menu-save > a { padding: 2px 10px; border: 1px solid #ccc; border-radius: 3px; font-weight: bolder; cursor: pointer; } .MakazeScriptMenu .menuTitle { margin-bottom: 10px; font-weight: bolder; } .MakazeScriptMenu .scrollableContent { width: 312px; height: 150px; overflow: auto; padding: 2px; } .MakazeScriptMenu textarea, .MakazeScriptMenu input[type=text], .MakazeScriptMenu input[type=number] { font-family: Consolas, Ubuntu Mono, sans-serif; font-size: 10px; color: #333; padding: 3px; box-sizing: border-box; }\n\n'; } styleElem.childNodes[0].nodeValue += '#pingsettings {\n' + 'margin-top: -174px;\n' + 'margin-left: -235px;\n' + '}\n\n' + '#pingsettings textarea {\n' + 'width: 144px;\n' + 'height: 144px;\n' + '}\n\n' + '#pingsettings input {\n' + 'vertical-align: middle;\n' + '}'; // Menu creation var pingMenu_options = createElement('table', function(table) { table.appendChild(createElement('thead', function(thead) { thead.appendChild(createElement('tr', function(row) { row.appendChild(createElement('th', function(cell) { cell.appendChild(document.createTextNode('Style')); })); row.appendChild(createElement('th', function(cell) { cell.appendChild(document.createTextNode('Pings')); })); row.appendChild(createElement('th', function(cell) { cell.appendChild(document.createTextNode('Pinged Users')); })); })); })); table.appendChild(createElement('tbody', function(tbody) { tbody.appendChild(createElement('tr', function(row) { row.appendChild(createElement('td', function(cell) { cell.appendChild(createElement('textarea', function(input) { input.id = 'pingStyle'; input.placeholder = 'Enter CSS for pinged word'; input.value = pingStyle; })); })); row.appendChild(createElement('td', function(cell) { cell.appendChild(createElement('textarea', function(input) { input.id = 'pingList'; input.placeholder = 'Enter words to ping seperated by newlines'; input.value = pings.join('\n'); })); })); row.appendChild(createElement('td', function(cell) { cell.appendChild(createElement('textarea', function(input) { input.id = 'userPingList'; input.placeholder = 'Enter users to ping on join seperated by newlines'; var tempUserPingList = []; for (i = 0; i < userPings.length; i++) { if (!userPings[i].hasOwnProperty('name') || userPings[i].name === null) { tempUserPingList.push(userPings[i].id); } else { tempUserPingList.push(userPings[i].id + '//' + userPings[i].name); } } input.value = tempUserPingList.join('\n'); })); })); })); tbody.appendChild(createElement('tr', function(row) { row.appendChild(createElement('td', function(cell) { cell.setAttribute('colspan', 3); cell.style.textAlign = 'center'; cell.appendChild(createElement('div', function(cont) { cont.style.display = 'inline-block'; cont.style.textAlign = 'left'; cont.appendChild(createElement('div', function(field) { field.appendChild(createElement('input', function(input) { input.id = 'audiblePingSwitch'; input.type = 'checkbox'; input.checked = audiblePing; })); field.appendChild(document.createTextNode(' Play sound when pinged')); })); cont.appendChild(createElement('div', function(field) { field.appendChild(createElement('input', function(input) { input.id = 'titlePingSwitch'; input.type = 'checkbox'; input.checked = titlePing; })); field.appendChild(document.createTextNode(' Change page title when pinged')); })); cont.appendChild(createElement('div', function(field) { field.appendChild(createElement('input', function(input) { input.id = 'highlightPingsSwitch'; input.type = 'checkbox'; input.checked = highlightPings; })); field.appendChild(document.createTextNode(' Highlight pings in the chat')); })); cont.appendChild(createElement('div', function(field) { field.appendChild(createElement('input', function(input) { input.id = 'audiblePingOnFocusSwitch'; input.type = 'checkbox'; input.checked = audiblePingOnFocus; })); field.appendChild(document.createTextNode(' Play audible ping when the page is focused')); })); cont.appendChild(createElement('div', function(field) { field.style.display = 'table'; field.style.width = '100%'; field.style.marginTop = '1em'; field.appendChild(createElement('span', function(name) { name.style.display = 'table-cell'; name.style.whiteSpace = 'pre'; name.appendChild(document.createTextNode('Audible ping file: ')); })); field.appendChild(createElement('span', function(content) { content.style.display = 'table-cell'; content.style.width = '100%'; content.appendChild(createElement('input', function(input) { input.id = 'audiblePingFile'; input.type = 'text'; input.placeholder = 'Enter a sound file to play when pinged'; input.style.width = '100%'; input.value = audiblePingFile; })); })); })); cont.appendChild(createElement('div', function(field) { field.style.display = 'table'; field.style.width = '100%'; field.style.marginTop = '1em'; field.appendChild(createElement('span', function(name) { name.style.display = 'table-cell'; name.style.whiteSpace = 'pre'; name.appendChild(document.createTextNode('Script delay (in ms): ')); })); field.appendChild(createElement('span', function(content) { content.style.display = 'table-cell'; content.style.width = '100%'; content.appendChild(createElement('input', function(input) { input.id = 'pingScriptDelay'; input.type = 'number'; input.placeholder = '0'; input.style.width = '100%'; input.value = (script_delay) ? script_delay : ''; })); })); })); })); })); })); })); }), pingMenu_save = createElement('div', function(cont) { cont.className = 'menu-save'; cont.appendChild(createElement('a', function(link) { link.href = 'javascript:void(0)'; link.id = 'pingsettings_save'; link.appendChild(document.createTextNode('Save')); link.onclick = function() { var opts = (localStorage.getItem('MakazeScriptOptions')) ? JSON.parse(localStorage.getItem('MakazeScriptOptions')) : {}, pingList = document.getElementById('pingList').value.split(/[\n\r]/), userPingList = document.getElementById('userPingList').value.split(/[\n\r]/), offset, split, elems, userElem, i = 0; if (styleElem.hasChildNodes()) { styleElem.childNodes[0].nodeValue += '\n\n'; } else { styleElem.appendChild(document.createTextNode('')); } styleElem.childNodes[0].nodeValue = styleElem.childNodes[0].nodeValue.replace(/\.ipc_highlight\s{[^]+?}/gi, '.ipc_highlight {\n' + document.getElementById('pingStyle').value + '\n' + '}'); for (i = 0, offset = 0; i < pingList.length; i++) { if (!pingList[i - offset].length) { pingList.splice(i - offset, 1); offset++; } } document.getElementById('pingList').value = pingList.join('\n'); // Make array of users for (i = 0, offset = 0; i < userPingList.length; i++) { if (!userPingList[i - offset].length) { userPingList.splice(i - offset, 1); offset++; } if (userPingList.length) { if (userPingList[i].match('//')) { split = userPingList[i].split('//'); userPingList[i] = {'id': split[0], 'name': split[1]}; } else { userPingList[i] = {'id': userPingList[i]}; } } } // Get usernames for (i = 0, elems = document.getElementById('chatters-online').getElementsByTagName('li'); i < elems.length; i++) { userElem = elems[i]; userPingList = getUserName(userElem, userPingList); } // Make array into list var tempUserPingList = []; for (i = 0; i < userPingList.length; i++) { if (!userPingList[i].hasOwnProperty('name') || userPingList[i].name === null) { tempUserPingList.push(userPingList[i].id); } else { tempUserPingList.push(userPingList[i].id + '//' + userPingList[i].name); } } // Output to menu document.getElementById('userPingList').value = tempUserPingList.join('\n'); opts.ipc_ping_style = document.getElementById('pingStyle').value; opts.ipc_pings = pingList; opts.ipc_user_pings = userPingList; opts.ipc_audible_ping = document.getElementById('audiblePingSwitch').checked; opts.ipc_pings_in_title = document.getElementById('titlePingSwitch').checked; opts.ipc_highlight_pings = document.getElementById('highlightPingsSwitch').checked; opts.ipc_audible_ping_on_focus = document.getElementById('audiblePingOnFocusSwitch').checked; opts.ipc_audible_ping_file = document.getElementById('audiblePingFile').value; opts.ipc_pings_script_delay = (document.getElementById('pingScriptDelay').value.length) ? parseInt(document.getElementById('pingScriptDelay').value) : 0; localStorage.setItem('MakazeScriptOptions', JSON.stringify(opts)); if (document.getElementById('audiblePingSwitch').checked) { pingSound = new Audio(document.getElementById('audiblePingFile').value); } fade(this.parentNode.parentNode, 'out'); }; })); cont.appendChild(createElement('a', function(link) { link.href = 'javascript:void(0)'; link.id = 'pingsettings_close'; link.style.marginLeft = '10px'; link.appendChild(document.createTextNode('Close')); link.onclick = function() { fade(this.parentNode.parentNode, 'out'); }; })); }); pingMenu = createElement('div', function(menu) { menu.id = 'pingsettings'; menu.className = 'MakazeScriptMenu'; menu.style.display = 'none'; menu.appendChild(pingMenu_options); menu.appendChild(pingMenu_save); }); document.body.appendChild(pingMenu); // Button creation if (document.getElementById('IPChatMenuItems') == null) { IPChatMenuItems = createElement('div', function(menu) { menu.id = 'IPChatMenuItems'; menu.style.textAlign = 'right'; }); document.getElementById('chatters-online-wrap').nextSibling.nextSibling.getElementsByTagName('ul')[0].appendChild(IPChatMenuItems); } if (document.getElementById('IPChatMenuItems').hasChildNodes()) { document.getElementById('IPChatMenuItems').appendChild(document.createElement('br')); } menuButton = createElement('a', function(button) { button.id = 'pingMenuButton'; button.className = 'ipsButton_secondary'; button.href = 'javascript:void(0)'; button.style.marginTop = '10px'; button.appendChild(document.createTextNode('Ping Settings')); button.onclick = function() { fade(document.getElementById('pingsettings')); }; }); document.getElementById('IPChatMenuItems').appendChild(menuButton); // Apply highlight style if (highlightPings) { if (styleElem.hasChildNodes()) { styleElem.childNodes[0].nodeValue += '\n\n'; } else { styleElem.appendChild(document.createTextNode('')); } styleElem.childNodes[0].nodeValue += '.ipc_highlight {\n' + pingStyle + '\n' + '}'; } document.addEventListener('DOMNodeInserted', function(event) { if (event.target.nodeType !== 1) { return false; } var opts, userPings; // Get usernames for user pings on joins if (event.target.id.substr(0, 5) === 'user_') { opts = (localStorage.getItem('MakazeScriptOptions')) ? JSON.parse(localStorage.getItem('MakazeScriptOptions')) : {}; userPings = (opts.hasOwnProperty('ipc_user_pings')) ? opts.ipc_user_pings : []; newUserPings = getUserName(event.target, userPings); opts.ipc_user_pings = newUserPings; localStorage.setItem('MakazeScriptOptions', JSON.stringify(opts)); return false; } if (event.target.id !== 'storage_chatroom') { return false; } opts = (localStorage.getItem('MakazeScriptOptions')) ? JSON.parse(localStorage.getItem('MakazeScriptOptions')) : {}; userPings = (opts.hasOwnProperty('ipc_user_pings')) ? opts.ipc_user_pings : []; var latestMessage, textToCheck, pings = (opts.hasOwnProperty('ipc_pings')) ? opts.ipc_pings : [userName], audiblePing = (opts.hasOwnProperty('ipc_audible_ping')) ? opts.ipc_audible_ping : true, titlePing = (opts.hasOwnProperty('ipc_pings_in_title')) ? opts.ipc_pings_in_title : true, highlightPings = (opts.hasOwnProperty('ipc_highlight_pings')) ? opts.ipc_highlight_pings : true, audiblePingOnFocus = (opts.hasOwnProperty('ipc_audible_ping_on_focus')) ? opts.ipc_audible_ping_on_focus : false, ping, userPing, newUserPings, nameToCheck, nameNode, playSound = false, i = 0; latestMessage = event.target.parentNode.getElementsByTagName('div')[event.target.parentNode.getElementsByTagName('div').length - 1]; if (!Classes.hasClass(latestMessage.parentNode, 'post')) { return false; } if (Classes.hasClass(latestMessage.parentNode, 'chat-myown')) { return false; } textToCheck = latestMessage.innerHTML; if (Classes.hasClass(latestMessage.parentNode, 'chat-notice')) { if (!userPings.length) { return false; } if (textToCheck !== ' has entered the room') { return false; } nameNode = latestMessage.parentNode.getElementsByTagName('label')[0]; while (typeof nameToCheck === 'undefined') { if (nameNode.hasChildNodes()) { nameNode = nameNode.lastChild; } else { nameToCheck = nameNode.nodeValue; } } for (i = 0; i < userPings.length; i++) { if (nameToCheck === userPings[i].name) { userPing = new RegExp('(' + userPings[i].name + ')', "g"); if (titlePing) { if (!hasFocus) { if (document.title.match(/\(P:/g)) { if (!document.title.match(userPing)) { document.title = document.title.replace(/\(P:\s(.*?)\)/g, '(P: $1 ' + userPings[i].name + ')'); } } else { document.title = '(P: ' + userPings[i].name + ') ' + document.title; } } } if (highlightPings) { latestMessage.parentNode.className += ' ipc_highlight'; } if (audiblePing) { playSound = true; } } } if (playSound) { if (!hasFocus || audiblePingOnFocus) { pingSound.play(); } } return false; } for (i = 0; i < pings.length; i++) { ping = new RegExp('(' + pings[i] + ')', "gi"); if (textToCheck.match(ping)) { if (titlePing) { if (!hasFocus) { if (document.title.match(/\(P:/g)) { if (!document.title.match(ping)) { document.title = document.title.replace(/\(P:\s(.*?)\)/g, '(P: $1 ' + pings[i] + ')'); } } else { document.title = '(P: ' + pings[i] + ') ' + document.title; } } } if (highlightPings) { Classes.addClass(latestMessage.parentNode, 'chat-myown'); latestMessage.innerHTML = latestMessage.innerHTML.replace(ping, '<span class="ipc_highlight">$1</span>'); } if (audiblePing) { playSound = true; } } } if (playSound) { if (!hasFocus || audiblePingOnFocus) { pingSound.play(); } } }); window.onblur = function() { hasFocus = false; }; window.onfocus = function() { hasFocus = true; if (document.title.match(/\(P:/gi)) { document.title = document.title.replace(/\(P:\s.*?\)\s/gi, ''); } }; } if (document.body.id === 'ipboard_body' && document.getElementById('storage_chatroom') != null) { opts = (localStorage.getItem('MakazeScriptOptions')) ? JSON.parse(localStorage.getItem('MakazeScriptOptions')) : {}; script_delay = (opts.hasOwnProperty('ipc_pings_script_delay')) ? opts.ipc_pings_script_delay : 0; if (script_delay) { setTimeout(function() { pingsInit(); }, script_delay); } else { pingsInit(); } }