User:Monchoman45/ChatHacks.js

/* * ChatHacks.js, by Monchoman45. * * For version 4a of chat. Or b or c, or whatever letter we're on. I don't think anyone really knows right now. * To do: Make preparser work again. The listener is different on the textarea than it was on the input box. * * Features: *  Imports all of your code files *  UTC timestamps on every message *  Ability to clear your chat window *  A message preparser with /me, /afk, /away, /clear, /self, and /kickban *  Inline alerts every time your away status changes *  Coloring for your username and the usernames of chat mods in the room */ $(function {	if(wgPageName == 'Special:Chat') {		$('body').prepend('\n.chat-mod,\n.mod,\n.mod::after {\n\tcolor:#da0;\n}\n.chat-mod.away {\n\tcolor:#eda;\n}\n.ChatHeader .username,\n.you .username,\n.you .username::after {\n\tcolor:#00c;\n}\n.UserStatsMenu {\n\tcolor:#000;\n}\n.Chat .continued {\n\ttop:0;\n\tmargin-bottom:0;\n}\n.Write [name="message"] {\n\twidth:93%;\n}\n ');

//Add a 'go afk' button and a 'clear chat' button $('#Write').append('AFKClear'); //Unbind all of the listeners that set your status to back $(window).unbind('mousemove').unbind('focus').unbind('keypress'); //Set status to back when you press enter in the textarea $('textarea[name="message"]').bind('keypress', function (event) {if(event.keyCode == 13) {NodeChatHelper.resetActivityTimer;}}); window.mods = []; window.list = document.getElementById('Users').getElementsByTagName('ul')[0].getElementsByTagName('li'); for(i = 0; i < list.length; i++) { if(list[i].className.split(' ')[1] == 'chat-mod') { mods.push(list[i].getElementsByTagName('span')[0].innerHTML); }		}

//Add/remove mods when people join/leave NodeChatController.view.model.users._callbacks.add[0] = function(user) { if(user.attributes.isModerator == true) { var add = true; for(i in mods) {if(mods[i] == user.attributes.name) {add = false;}} if(add == true) {mods.push(user.attributes.name)} }			var view = new UserView({model: user}); $('#Users > ul').append(view.render.el); }		NodeChatController.view.model.users._callbacks.remove[0] = function(user) { NodeChatHelper.log("Trying to remove " + user.get('name') + " from the list."); NodeChatHelper.log("Matches found: " + $('[id="' + NodeChatHelper.liIdByUsername( user.get('name') ) + '"]').length); for(i in mods) {if(mods[i] == user.attributes.name) {mods[i] = undefined;}} $('[id="' + NodeChatHelper.liIdByUsername( user.get('name') ) + '"]').remove; }		//Color mod posts when they're added, add timestamps to all non-inline alert messages NodeChatController.view.model.chats._callbacks.add[0] = function (chat) { // Determine if chat view is presently scrolled to the bottom var isAtBottom = false; if (($("#Chat").scrollTop + 1) >= ($("#Chat ul").outerHeight - $("#Chat").height)) { isAtBottom = true; }			// Add message to chat var view = new ChatView({model: chat}); for(i in mods) {if(mods[i] == view.model.attributes.name) {view.model.attributes.name = ' ' + view.model.attributes.name + ' '}} if(view.model.attributes.msgType == 'chat') { var date = new Date; if(date.getUTCHours >= 10) {var hours = date.getUTCHours;} else {var hours = '0' + date.getUTCHours;} if(date.getUTCMinutes >= 10) {var minutes = date.getUTCMinutes;} else {var minutes = '0' + date.getUTCMinutes;} view.model.attributes.text = ' [' + hours + ':' + minutes + '] ' + view.model.attributes.text; }			$('#Chat ul').append(view.render.el);

// Scroll chat to bottom if (chat.attributes.name == wgUserName || isAtBottom) { NodeChatHelper.scrollToBottom; }		}

//Add a custom inline alert that tells you when your status changes NodeChatController.view.setAway = function { var msg = ''; //var msg = $(e.target).parent.find('.user').html; //if(!msg){msg = '';} NodeChatHelper.log("Attempting to go away with message: " + msg); var setStatusCommand = new models.SetStatusCommand({				statusState: STATUS_STATE_AWAY,				statusMessage: msg			}); InlineAlert('You are now away.'); this.socket.send(setStatusCommand.xport); }		NodeChatController.view.setBack = function { NodeChatHelper.log("Attempting to come BACK from away."); var setStatusCommand = new models.SetStatusCommand({				statusState: STATUS_STATE_PRESENT,				statusMessage: ''			}); InlineAlert('You are no longer away.'); this.socket.send(setStatusCommand.xport); }

//Parse messages before they're sent //$('#Write textarea').unbind('keypress'); //unbind the default, because it uses 6 nested function calls that make it impossible to know what the object reference is		NodeChatController.view.sendMessage = function{ var inputField = $('[name=message]'); var nameField = $('input[name=user_name]'); if (inputField.val) { //Preparse message - will return true or false, based on whether the message should still be sent or not var send = Preparse(inputField.val); if(send == true) { chatEntry = new models.ChatEntry({name: nameField.val, text: inputField.val}); this.socket.send(chatEntry.xport); }				inputField.val(''); }			NodeChatHelper.focusTextInput; }		//$('#Write textarea').bind('keypress', function(event) {if(event.keyCode == 13) {NodeChatController.view.sendMessage.call(NodeChatController.view);}}); //rebind our new function, even though it'll throw an XHR POST error every time we send } });

function InlineAlert(text) { $('.Chat ul').append('' + text + ''); NodeChatHelper.scrollToBottom; }

function Preparse(input) { var text = input.split(' '); switch(text[0]) { case '/away': case '/afk': ToggleAway; return false; break; case '/clear': $('.Chat ul').html(''); InlineAlert('Window cleared.'); return false; break; case '/kickban': var mod = new models.KickBanCommand({userToBan: build(text, 1)}); NodeChatController.socket.send(mod.xport); return false; break; case '/self': if(text[1] != undefined) { str = build(text, 1); newstr = ''; for(var i = 0; i < str.length; i++) { switch(str.charAt(i)) { case '[': if(str.charAt(i + 1) == '[') { var k = str.indexOf(']', i); if(str.charAt(k + 1) == ']') { var substr = str.substring(i + 2, k); if(substr.indexOf('|') != -1) { var link = substr.substring(0, substr.indexOf('|')); var linktext = substr.substring(substr.indexOf('|') + 1, substr.length); }									else { var link = substr; var linktext = link; }									var linkspl = link.split(' '); link = ''; for(var j in linkspl) {link += linkspl[j] + '_';} link = link.substring(0, link.length - 1); newstr += '' + linktext + ''; i = k + 1; }							}							else if(str.substring(i + 1, i + 8) == 'http://') { var k = str.indexOf(']', i); var splstr = str.substring(i + 1, k).split(' '); if(splstr == str.substring(i + 1, k)) { var text = '[1]'; }								else { var text = build(splstr, 1); }								newstr += '' + text + ''; i = k;							} break; default: newstr += str.charAt(i); break; }				}				$('.Chat ul').append(' ' + wgUserName + '  (self) ' + newstr + ' '); }			else { $('.Chat ul').append(' ' + wgUserName + '  (self) </li>'); }			NodeChatHelper.scrollToBottom; return false; break; case '/me': if(text[1] != undefined) {$('input[name="message"]').val('* ' + wgUserName + ' ' + build(text, 1));} else {$('input[name="message"]').val('* ' + wgUserName);} return true; break; default: return true; break; } }

//Parser helping function - takes an array of text created with .split(' '), //and an index number for where to start, then rebuilds the string. //Can also accept an index value for where to stop. function build(text, index, stop) { var newtext = ''; if(stop == undefined || stop == 0) {stop = text.length} else if(stop < 0) {stop += text.length} if(index == stop || index == text.length - 1) {return text[index];} for(var i = index; i < stop; i++) { newtext += text[i] + ' '; }	return newtext; }

function ToggleAway { if($('#ChatHeader .User').hasClass('away') == true) { NodeChatController.view.setBack; }	else { NodeChatController.view.setAway; } }