User:Cpl.Bohater/ChatHacks.js

/*  * ChatHacks.js, by Monchoman45. * Version 5.dontUseThisYetBecauseItMightExplodeAndThatWouldBeBad *  * Features: *  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 *  Icons next to messages by staff and chat mods in the room *  Pings when someone mentions your name or any other specified phrases */ $(function { 	if(wgPageName == 'Special:Chat') { 		$('body').prepend('\n.stafficon {\n\tmargin-bottom:-4px;\n}\n.modicon {\n\tmargin-bottom:-2px;\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}\naudio {display:none;}\n#pingspan {\n\tposition:absolute;\n\tz-index:5;\n\ttop:23px;\n\tmargin-left:15px;\n\tfont-size:15px;\n\tfont-weight:normal;\n\tline-height:15px;\n}\n#pings {\n\tresize:none;\n\tmargin-left:0;\n\tfont-size:12px;\n\theight:100px;\n\tdisplay:block;\n}\n#pingspan div span {\n\tfont-size:55%;\n}\n '); 		//Add a 'go afk' button and a 'clear chat' button 		$('#Write').append('AFKClear'); //Unbind all of the window listeners that set your status to back $(window).unbind('mousemove').unbind('focus').unbind('keypress'); //Add the sound space $('body').append(' '); //Add the area for adding more pings /*$('#ChatHeader .wordmark').append(' Ping phrases (?) ' + ((readCookie('pingphrases')) ? readCookie('pingphrases').split('\\n').join('\n') : wgUserName) + ' '); document.getElementById('pingspan').onmouseover = function(event) {document.getElementById('pings').style.display = 'block';} document.getElementById('pingspan').onmouseout = function(event) {document.getElementById('pings').style.display = 'none'; createCookie('pingphrases', document.getElementById('pings').value.split('\n').join('\\n'), 99999);} window.canding = false; //to prevent pinging people with scrollback setTimeout('window.canding = true', 10000); //lazy load quick fix window.titleorig = document.title; function Unding { //for fixing the title after you've been dinged document.getElementsByTagName('title')[0].innerHTML = window.titleorig; clearInterval(window.ding); } 		$(window).bind('focus', Unding); window.ding = 0;*/ window.staff = []; window.mods = []; //Make a list of mods and staff NodeRoomController.prototype.onInitial = function(message) { if(!this.isInitialized){ _.each(this.model.chats.models, $.proxy(function(data) { this.model.chats.remove(data); },this)); this.model.chats.trigger('clear'); // On first connection, just update the entire model. this.model.mport(message.data); this.isInitialized = true; } else { // If this is a reconnect... go through the model that was given and selectively, only add ChatEntries that were not already in the collection of chats. var jsonObj = JSON.parse(message.data); var chatEntries = this.model.chats; _.each(jsonObj.collections.chats.models, function(item, index){ 					var match = chatEntries.get(item.id); 					if(typeof match == "undefined"){ 						$.log("Found a ChatEntry that must have occurred during reconnection. Adding it to the model..."); 						var additionalEntry = new models.ChatEntry; 						additionalEntry.mport( JSON.stringify(item) ); 						chatEntries.add(additionalEntry); 					} 				}); // TODO: update the entire userlist (if the server went down or something, you're not going to get "part" messages for the users who are gone). // See BugzId 6107 for more info & partially completed code. } 			for(var i in this.afterInitQueue) { this.socket.send(this.afterInitQueue[i]); } 			this.afterInitQueue = []; window.staff = []; window.mods = []; var list = document.getElementById('WikiChatList').getElementsByTagName('li'); for(var i in list) { if(list[i].className) { var classes = list[i].className.split(' '); var user = false; var isstaff = false; var mod = false; for(var j in classes) { if(classes[j] == 'User') {user = true;} if(classes[j] == 'staff') {isstaff = true;} if(classes[j] == 'chat-mod') {mod = true;} } 					if(isstaff && user) { staff.push(list[i].getElementsByTagName('span')[0].innerHTML); } 					else if(mod && user) { mods.push(list[i].getElementsByTagName('span')[0].innerHTML); } 				} 			} 			//window.canding = true; } 		//msgReceived = NodeChatController.view.msgReceived; //Store the big switch statement /*NodeChatController.view.msgReceived = function(message) { //Instead of putting the whole switch statement here just to change one small piece, we change the piece and if it isn't relevant, we run the original statement. if(message.event == 'initial') { if(!this.isInitialized){ // On first connection, just update the entire model. this.model.mport(message.data); this.isInitialized = true; } else { // If this is a reconnect... go through the model that was given and selectively, only add ChatEntries that were not already in the collection of chats. var jsonObj = JSON.parse(message.data); var chatEntries = this.model.chats; _.each(jsonObj.collections.chats.models, function(item, index){ 						var match = chatEntries.get(item.id); 						if(typeof match == "undefined"){ 							NodeChatHelper.log("Found a ChatEntry that must have occurred during reconnection. Adding it to the model..."); 							var additionalEntry = new models.ChatEntry; 							additionalEntry.mport( JSON.stringify(item) ); 							chatEntries.add(additionalEntry); 						} 					}); // TODO: update the entire userlist (if the server went down or something, you're not going to get "part" messages for the users who are gone). // See BugzId 6107 for more info & partially completed code. } 				window.staff = []; window.mods = []; var list = document.getElementById('Users').getElementsByTagName('ul')[0].getElementsByTagName('li'); for(var i in list) { if(list[i].className) { var classes = list[i].className.split(' '); var user = false; var isstaff = false; var mod = false; for(var j in classes) { if(classes[j] == 'User') {user = true;} if(classes[j] == 'staff') {isstaff = true;} if(classes[j] == 'chat-mod') {mod = true;} } 						if(isstaff && user) { staff.push(list[i].getElementsByTagName('span')[0].innerHTML); } 						else if(mod && user) { mods.push(list[i].getElementsByTagName('span')[0].innerHTML); } 					} 				} 				//window.canding = true; } 			else { //Run the giant switch statement msgReceived.apply(this, arguments); } 		}*/ 		//Add/remove mods when people join/leave NodeChatUsers.prototype.addUser = function (user) { if(user.attributes.isStaff == true) { var isstaff = true; for(var i in staff) {if(staff[i] == user.attributes.name) {isstaff = false;}} if(isstaff == true) {staff.push(user.attributes.name);} } 			else if(user.attributes.isModerator == true) { var mod = true; for(var i in mods) {if(mods[i] == user.attributes.name) {mod = false;}} if(mod == true) {mods.push(user.attributes.name);} } 			var view = new UserView({model: user}); var list = (user.attributes.isPrivate) ? $('#PrivateChatList') : $('#WikiChatList'); var el = $(view.render.el); // For private chats, show private headline and possibly select the chat if(user.get('isPrivate')) { $('#Rail h1.private').show; if(user.get('active')) { el.addClass('selected'); } 			} 			// Add users to list if (list.children.length) { // The list is not empty. Arrange alphabetically. var compareA = el.data('user').toUpperCase; var wasAdded = false; list.children.each(function(idx, itm) { 					compareB = $(itm).data('user').toUpperCase; 					if (compareA < compareB) { 						$(itm).before(el); 						wasAdded = true; 						return false; 					} 				}); if (!wasAdded) { list.append(el); } 			} else { // The list is empty. Append this user. list.append(el); } 			// Scroll the list down if a new private chat is being added if (user.get('isPrivate')) { $.log('UserView SCROLL DOWN!!!'); $('#Rail').scrollTop($('#Rail').get(0).scrollHeight); } 			// Only show chevron in public chat if there is anyone to talk to 			if (list.children.length > 1) { $('#Rail .public .chevron').show; } else { $('#Rail .public .chevron').hide; }		 		} 		NodeChatUsers.prototype.removeUser = function (user) { for(var i in mods) {if(mods[i] == user.attributes.name) {mods.splice(i, 1);}} for(var i in staff) {if(staff[i] == user.attributes.name) {staff.splice(i, 1);}} var view = new UserView({model: user}); view.getUserElement.remove; } 		/*NodeChatController.view.model.users._callbacks.add[0] = function(user) { if(user.attributes.isStaff == true) { var isstaff = true; for(var i in staff) {if(staff[i] == user.attributes.name) {isstaff = false;}} if(isstaff == true) {staff.push(user.attributes.name);} } 			else if(user.attributes.isModerator == true) { var mod = true; for(var i in mods) {if(mods[i] == user.attributes.name) {mod = false;}} if(mod == 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(var i in mods) {if(mods[i] == user.attributes.name) {mods.splice(i, 1);}} for(var i in staff) {if(staff[i] == user.attributes.name) {staff.splice(i, 1);}} $('[id="' + NodeChatHelper.liIdByUsername( user.get('name') ) + '"]').remove; }*/ 		//Put images on mod and staff posts when they're added, ping if you've been mentioned NodeChatDiscussion.prototype.addChat = function (chat) { // Determine if chat view is presently scrolled to the bottom var isAtBottom = false; if (( this.chatDiv.scrollTop + 1) >= (this.chatUL.outerHeight - this.chatDiv.height)) { isAtBottom = true; } 			// Add message to chat var view = new ChatView({model: chat}); this.chatUL.append(view.render.el); var icon = ''; for(var i in staff) {if(staff[i] == chat.attributes.name) {icon = ' '}} for(var i in mods) {if(mods[i] == chat.attributes.name) {icon = ' '}} if(icon) {$('#Chat ul li:last-child .username').html($('#Chat ul li:last-child .username').html + icon);} /*if(window.canding && chat.attributes.name != wgUserName && !chat.attributes.isInlineAlert) { var pings = document.getElementById('pings').value.split('\n'); for(var i = 0; i < pings.length; i++) { if(chat.attributes.text.toLowerCase.indexOf(pings[i].toLowerCase) != -1) { $('#sound').html(''); if(document.hasFocus == false) {window.ding = setInterval('FlashTitle', 500);} NodeChatHelper.scrollToBottom; var text = chat.attributes.text; var ref = text.toLowerCase.indexOf(pings[i].toLowerCase); var phrase = text.slice(ref, ref + pings[i].length); $('#Chat ul li:last-child .message').html(text.replace(phrase, ' ' + phrase + ' ')); } 				} 			}*/ 			// Scroll chat to bottom if (chat.attributes.name == wgUserName || isAtBottom) { this.scrollToBottom; } 		} 		/*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}); $('#Chat ul').append(view.render.el); var icon = ''; for(var i in staff) {if(staff[i] == chat.attributes.name) {icon = ' '}} for(var i in mods) {if(mods[i] == chat.attributes.name) {icon = ' '}} if(icon) {$('#Chat ul li:last-child .username').html($('#Chat ul li:last-child .username').html + icon);} if(window.canding && chat.attributes.name != wgUserName && !chat.attributes.isInlineAlert) { var pings = document.getElementById('pings').value.split('\n'); for(var i = 0; i < pings.length; i++) { if(chat.attributes.text.toLowerCase.indexOf(pings[i].toLowerCase) != -1) { $('#sound').html(''); if(document.hasFocus == false) {window.ding = setInterval('FlashTitle', 500);} NodeChatHelper.scrollToBottom; var text = chat.attributes.text; var ref = text.toLowerCase.indexOf(pings[i].toLowerCase); var phrase = text.slice(ref, ref + pings[i].length); $('#Chat ul li:last-child .message').html(text.replace(phrase, ' ' + phrase + ' ')); } 				} 			} 			// 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.prototype.setAway = function (msg){ if(!msg) {var msg = '';} $.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.prototype.setBack = function { if( ! this.comingBackFromAway){ // if we have sent this command (but just haven't finished coming back yet), don't keep spamming the server w/this command $.log("Telling the server that I'm back."); this.comingBackFromAway = true; 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 - fail for not working, but at least it doesn't bork anything NodeChatController.prototype.sendMessage = function (event) { if(!this.active) { return true; } 			if (event.which == 13 && !event.shiftKey) { event.preventDefault; var inputField = this.viewDiscussion.getTextInput; var send = Preparse(inputField.val); if (inputField.val && send) { var chatEntry = new models.ChatEntry({roomId: this.roomId, name: wgUserName, text: inputField.val}); if( this.mainController != null ) { //is prive if( this.afterInitQueue.length < 1 || this.model.users.length < 2 ){ this.mainController.socket.send( this.model.privateRoom.xport ); } 						if( !this.isInitialized ) { this.afterInitQueue.push(chatEntry.xport); //temp chat entry in case of slow connection time chatEntry.set({temp : true, avatarSrc: wgAvatarUrl }); this.model.chats.add(chatEntry); } else { this.socket.send(chatEntry.xport); } 					} else { this.socket.send(chatEntry.xport); } 					inputField.val(''); event.preventDefault; } 				$.log('submitting form'); inputField.focus; } 		} 		/*$('#Write [name="message"]').unbind('keypress'); $('#Write [name="message"]').keypress(function(event) { 			if (event.which == 13 && !event.shiftKey) { 				event.preventDefault; 				NodeChatHelper.resetActivityTimer; 				var send = Preparse(this.value); 				if(send == true) { 					NodeChatHelper.log('submitting form'); 					$(event.target).closest('form').submit; 				} 				this.value = ''; 			} 		});*/ } }); /*function InlineAlert(text) { 	for(var i = 0; i < $('.Chat').length; i++) { 		if($('.Chat')[i].style.display == 'block') {} 	} 	//NodeChatHelper.scrollToBottom; }*/ function FlashTitle { 	if(document.getElementsByTagName('title')[0].innerHTML == window.titleorig) { 		document.getElementsByTagName('title')[0].innerHTML = 'Activity - ' + wgSiteName + ' chat'; 	} 	else { 		document.getElementsByTagName('title')[0].innerHTML = window.titleorig; 	} } function Preparse(input) { 	var text = input.split(' '); 	switch(text[0]) { 		case '/away': 		case '/afk': 			if($('#ChatHeader .User').hasClass('away') == false) {ToggleAway;} //if you're away, hitting enter has already sent you back 			return false; 			break; 		case '/clear': 			ClearWindow; 			return false; 			break; 		case '/kickban': 			var mod = new models.KickBanCommand({userToBan: build(text, 1)}); 			this.socket.send(mod.xport); return false; break; /*case '/self': for(var i = 0; i < $('.Chat').length; i++) { if($('.Chat')[i].style.display == 'block') {var ref = i; break;} } 			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 + '</a>'; i = k; 							} break; default: newstr += str.charAt(i); break; } 				} 				$('.Chat ul').append('<li><img class="avatar" src="' + $('#ChatHeader .User img').attr('src') + '"> ' + wgUserName + ' (self) ' + newstr + ' </li>'); } 			else { $('.Chat ul').append('<li><img class="avatar" src="' + $('#ChatHeader .User img').attr('src') + '"> ' + wgUserName + ' (self) </li>'); } 			NodeChatHelper.scrollToBottom; return false; break;*/ case '/me': if(text[1] != undefined) {$('#Write [name="message"]').val('* ' + wgUserName + ' ' + build(text, 1));} else {$('#Write [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) { mainRoom.setBack; } 	else { mainRoom.setAway; } } function ClearWindow { for(var i = 0; i < $('.Chat').length; i++) { if($('.Chat')[i].style.display == 'block') {$('.Chat')[i].getElementsByTagName('ul')[0].innerHTML = '';} } 	InlineAlert('Window cleared.'); } function createCookie(name,value,days) { if (days) { var date = new Date; date.setTime(date.getTime+(days*24*60*60*1000)); var expires = "; expires="+date.toGMTString; } 	else var expires = ""; document.cookie = name+"="+value+expires+"; path=/"; } function readCookie(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for(var i=0;i < ca.length;i++) { var c = ca[i]; while (c.charAt(0)==' ') c = c.substring(1,c.length); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); } 	return null; }