User:SirComputer/wikia.js

importScriptPage( 'AjaxUndo/code.js', 'dev' ); importScriptPage('PurgeButton/code.js', 'dev'); importScriptPage('EditIntroButton/code.js', 'dev'); /************** Torus chat client ************** * A Wikia chat client that isn't Special:Chat * * --- * * Written and maintained by Monchoman45      * ***********************************************/ importScriptPage('MediaWiki:ChatSocket.js', 'monchbox'); importScriptPage('MediaWiki:Torus.js/Database.js', 'monchbox').onload = function { if(Torus.init) {Torus.log('Looking up local room...');} var domain = document.location.host.substring(0, document.location.host.indexOf('.wikia.com')); if(domain.indexOf('preview.') == 0) {domain = domain.substring(8);} if(Torus.data.domains[domain]) { if(Torus.init) {Torus.log('Found domain ' + domain + ' in DB.');} Torus.local = Torus.data.domains[domain]; }	else if(Torus.init) {Torus.log('Can\'t find ' + domain + ' in DB. Fetching from Special:Chat...');} if(!Torus.local) { var xhr = new XMLHttpRequest; xhr.open('GET', '/index.php?title=Special:Chat&useskin=wikia', true); xhr.onreadystatechange = function { if(this.readyState == 4 && this.status == 200) { var text = this.response; var id = text.substring(text.indexOf('roomId=') + 7, text.indexOf(',', text.indexOf('roomId='))); if(!isNaN(id * 1)) { if(Torus.init) {Torus.log('Found local room to be ' + id + '.');} if(Torus.data.domains) { if(Torus.init) {Torus.log('Adding to database...');} /*Torus.log('Would you like to add this wiki to the Torus database? Doing so will allow you to reference this wiki\'s chat room from anywhere without using the id. (Note: this will briefly connect you to another room)'); Torus.log(''); //creates a message, which we will turn into a JS link below var spans = Torus.ui.window.window.getElementsByTagName('span'); spans[spans.length - 1].innerHTML = 'Add to database';*/ Torus.open(28); Torus.ui.activate(0); Torus.chats[28].socket.addListener('connect', function {							Torus.io.sendMessage(28, '!db add ' + domain + ' ' + id);							Torus.close(28);						}); }					Torus.local = id * 1; Torus.ui.activate(0); }				else { if(Torus.init) {Torus.log('Couldn\'t find local room. Using Central instead.');} Torus.local = 10; }				if(wgCanonicalNamespace == 'Special' && wgTitle == 'Torus' && Torus.options.data['misc-connection-local'] && Torus.init) {Torus.open(Torus.local);} }		}		xhr.send; }	else if(wgCanonicalNamespace == 'Special' && wgTitle == 'Torus' && Torus.options.data['misc-connection-local'] && Torus.init) {Torus.open(Torus.local);} } window.Torus = { init: false, local: 0, chats: {}, listeners: { initial: [], 'chat:add': [], join: [], part: [], updateUser: [], openPrivateRoom: [], forceReconnect: [], disableReconnect: [] },	io: {}, ui: { window: document.createElement('div'), active: 0, viewing: [], },	options: { selected: 'messages', groups: { messages: {}, miscellaneous: {} },		data: { 'messages-timezone': 0, 'messages-pings': wgUserName, 'messages-pings-enabled': true, 'messages-pings-alert': 'Activity!', 'messages-pings-interval': 500, 'messages-pings-beep': true, 'messages-pings-beep-sound': 'http://images.wikia.com/monchbox/images/0/01/Beep-sound.ogg', 'misc-connection-defaultrooms': '', 'misc-connection-local': true, 'misc-usercolor-enabled': true, 'misc-usercolor-hue': 0, 'misc-usercolor-sat': .7, 'misc-usercolor-val': .6 }	},	commands: {}, util: {}, data: { titleflash: document.title, pinginterval: 0, history: [], histindex: 0, } } //Function for adding an event listener //Accepts the event name and the listener function Torus.addListener = function(type, func) { if(!Torus.listeners[type]) {Torus.listeners[type] = [];} Torus.listeners[type].push(func); return true; } //Function for removing an event listener //Accepts the event name and the listener function //Returns true if the listener is removed, otherwise false Torus.removeListener = function(type, func) { if(!Torus.listeners[type]) {return false;} for(var i = 0; i < Torus.listeners[type].length; i++) { if(Torus.listeners[type][i] == func) {Torus.listeners[type].splice(i, 1); return true;} }	return false; } //Function for calling listeners for an event //Accepts the event name //Returns false if the type is invalid, otherwise true Torus.callListeners = function(type) { if(!Torus.listeners[type]) {return false;} var args = []; for(var i = 1; i < arguments.length; i++) {args.push(arguments[i]);} for(var i = 0; i < Torus.listeners[type].length; i++) { Torus.listeners[type][i].apply(Torus, args); }	return true; } Torus.open = function(room, key) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(room <= 0) {throw new ReferenceError('Invalid room ' + room + '. (open)'); return;} if(!Torus.chats[room] && room > 0) { Torus.ui.addRoom(room); Torus.chats[room].socket = new ChatSocket(key); Torus.chats[room].socket.addListener('connect', function {			if(!Torus.chats[this.roomId]) {				Torus.ui.addRoom(this.roomId);				Torus.chats[this.roomId].socket = this;			}			Torus.ui.addLine(this.roomId, '== Connected.');			this.cajax('&method=getListOfBlockedPrivate', {}, function(data) { eval('data = ' + data); //convert to object Torus.data.blockedBy = data.blockedByChatUsers; Torus.data.blocked = data.blockedChatUsers; });		});		Torus.chats[room].socket.addListener('message', function(event) {			Torus.io.receive(this.roomId, event);		}); Torus.chats[room].socket.addListener('error', function(error) {			this.disconnect(error);		}); Torus.chats[room].socket.addListener('disconnect', function(message) {			if(message == 'reconnecting') {				Torus.ui.addLine(this.roomId, '== Reconnecting...');				Torus.chats[this.roomId].reconnecting = true;			}			else {				Torus.log('Disconnected from ' + (Torus.data.ids[this.roomId] ? Torus.data.ids[this.roomId] : this.roomId) + ': ' + message);				Torus.ui.removeRoom(this.roomId);			}		}); Torus.chats[room].socket.connect(room); Torus.log('Connecting to ' + (Torus.data.ids[room] ? Torus.data.ids[room] : room) + '...'); }	Torus.ui.activate(room); } Torus.close = function(room, message) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room] || room <= 0) {throw new ReferenceError('Invalid room ' + room + '. (close)'); return;} if(room > 0) {Torus.chats[room].socket.disconnect(message);} } Torus.log = function(text) { if(text.indexOf('\n') != -1) { var spl = text.split('\n'); for(var i = 0; i < spl.length; i++) { Torus.ui.addLine(0, '== ' + spl[i]); }	}	else {Torus.ui.addLine(0, '== ' + text);} } Torus.ui.activate = function(room) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room]) {throw new ReferenceError('Invalid room ' + room + '. (ui.activate)'); return;} if(Torus.ui.active != 0) {Torus.ui.show(Torus.ui.active);} var tabs = Torus.ui.window.tabs.children; for(var i = 0; i < tabs.length; i++) { if(tabs[i].id == 'torus-tab-' + Torus.ui.active) { var classes = tabs[i].className.split(' '); for(var j = 0; j < classes.length; j++) { if(classes[j] == 'torus-tab-active') {classes.splice(j, 1); break;} }			tabs[i].className = classes.join(' '); break; }	}	Torus.ui.active = room; for(var i = 0; i < tabs.length; i++) { if(tabs[i].id == 'torus-tab-' + room) {tabs[i].className += ' torus-tab-active'; break;} }	Torus.ui.window.sidebar.innerHTML = ''; if(room > 0) {Torus.ui.updateUser(room, wgUserName);} if(room > 0) { if(!Torus.chats[room].parent) {Torus.ui.window.info.innerHTML = 'Public room' + (Torus.data.ids[room] ? ' of ' + Torus.data.ids[room] + '' : '') + '. (' + room + ')';} else {Torus.ui.window.info.innerHTML = 'Private room of ' + (Torus.data.ids[Torus.chats[room].parent] ? '' + Torus.data.ids[Torus.chats[room].parent] + '' : Torus.chats[room].parent) + ', between ' + Torus.chats[room].users.slice(0, Torus.chats[room].users.length - 1).join(', ') + ' and ' + Torus.chats[room].users[Torus.chats[room].users.length - 1] + '. (' + room + ')';} }	else {Torus.ui.window.info.innerHTML = '';} for(var i = 0; i < Torus.ui.viewing.length; i++) { if(Torus.ui.viewing[i] == room) {return;} }	Torus.ui.show(room); } Torus.ui.show = function(room) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room]) {throw new ReferenceError('Invalid room ' + room + '. (ui.show)'); return;} var tabs = Torus.ui.window.tabs.children; for(var i = 0; i < Torus.ui.viewing.length; i++) { if(Torus.ui.viewing[i] == room) { Torus.ui.viewing.splice(i, 1); for(var j = 0; j < tabs.length; j++) { if(tabs[j].id == 'torus-tab-' + room) { var classes = tabs[j].className.split(' '); for(var k = 0; k < classes.length; k++) { if(classes[k] == 'torus-tab-viewing') {classes.splice(k, 1); break;} }					tabs[j].className = classes.join(' '); document.getElementById('torus-css-dynamic').innerHTML = document.getElementById('torus-css-dynamic').innerHTML.replace('\n.torus-room-' + room + ' {display:list-item !important;}', ''); break; }			}			return; }	}	Torus.ui.viewing.push(room); for(var i = 0; i < tabs.length; i++) { if(tabs[i].id == 'torus-tab-' + room) {tabs[i].className += ' torus-tab-viewing'; break;} }	document.getElementById('torus-css-dynamic').innerHTML += '\n.torus-room-' + room + ' {display:list-item !important;}'; Torus.ui.window.window.scrollTop = Torus.ui.window.window.scrollHeight - Torus.ui.window.window.offsetHeight; } Torus.ui.addRoom = function(room, name) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(Torus.chats[room]) {return;} Torus.ui.window.tabs.innerHTML += '' + (room <= 0 ? name : (Torus.data.ids[room] ? Torus.data.ids[room] : room)) + (room > 0 ? 'x ' : '') + ' '; Torus.chats[room] = { id: room, parent: false, //the source of a PM name: (room <= 0 ? name : (Torus.data.ids[room] ? Torus.data.ids[room] : room)), away: 0, reconnecting: false, userlist: {length:0} }; } Torus.ui.removeRoom = function(room) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room]) {return;} if(Torus.ui.active == room) { if(Torus.chats[room].parent) {Torus.ui.activate(Torus.chats[room].parent);} else {Torus.ui.activate(0);} }	else { for(var i = 0; i < Torus.ui.viewing.length; i++) { if(Torus.ui.viewing[i] == room) { Torus.ui.show(room); break; }		}	}	var tabs = Torus.ui.window.tabs; for(var i = 0; i < tabs.children.length; i++) { if(tabs.children[i].id == 'torus-tab-' + room) {tabs.removeChild(tabs.children[i]); break;} }	delete Torus.chats[room]; } Torus.ui.addLine = function(room, text, time) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room]) {throw new ReferenceError('Invalid room ' + room + '. (ui.addLine)'); return;} while(text.indexOf('\n') != -1) {text = text.replace('\n', ' ');} text = Torus.util.parseLinks((Torus.chats[room].parent ? Torus.chats[room].parent : room), text); var twindow = Torus.ui.window.window; var scroll = false; if(twindow.offsetHeight + twindow.scrollTop >= twindow.scrollHeight) {scroll = true;} twindow.innerHTML += '[ ' + Torus.util.timestamp(time) + ' ] ( ' + (Torus.data.ids[room] ? Torus.data.ids[room] : room) + ' ) ' + text + ' '; if(scroll) {twindow.scrollTop = twindow.scrollHeight;} } Torus.ui.updateUser = function(room, name, props) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room] || room <= 0) {throw new ReferenceError('Invalid room ' + room + '. (ui.updateUser)'); return;} if(!Torus.chats[room].userlist[name] && !props) {return;} else if(!Torus.chats[room].userlist[name] && props) {Torus.chats[room].userlist.length++;} if(props) { if(!Torus.chats[room].userlist[name]) {Torus.chats[room].userlist[name] = props;} else { for(var i in props) {Torus.chats[room].userlist[name][i] = props[i];} }	}	props = Torus.chats[room].userlist[name]; if(Torus.ui.active == room) { if(name == wgUserName) { Torus.ui.window.sidebar.innerHTML = ''; for(var i in Torus.chats[room].userlist) { if(i == 'length' || i == wgUserName) {continue;} Torus.ui.updateUser(room, i); }		}		var users = Torus.ui.window.sidebar.getElementsByTagName('li'); var changed = false; for(var i = 0; i < users.length; i++) { if(users[i].className.indexOf('torus-user-' + encodeURIComponent(name)) != -1) { //is encodeURIComponent sufficient for this? var user = users[i]; changed = true; break; }		}		if(!changed) { var user = document.createElement('li'); var sidebar = Torus.ui.window.sidebar; var added = false; for(var i = 0; i < sidebar.children.length; i++) { var child = sidebar.children[i].children[sidebar.children[i].children.length - 1].textContent; var before = true; for(var j = 0; j < child.length; j++) { if(child.charCodeAt(j) > name.charCodeAt(j)) {break;} else if(child.charCodeAt(j) != name.charCodeAt(j)) {before = false; break;} }				if(before) { sidebar.insertBefore(user, sidebar.children[i]); added = true; break; }			}			if(!added) {sidebar.appendChild(user);} //is at the end of the alphabet }		user.className = 'torus-user ' + (props.mod || props.staff ? 'torus-user-' + (props.staff ? 'staff' : 'mod') + ' ' : '') + 'torus-user-' + encodeURIComponent(name); user.innerHTML = '  ' + name + ' ' + (props.mod || props.staff ? ' ' + (!props.staff && props.givemod ? '+' : ) + ' ' : ) + ' ' + props.statusState + ' ' + props.statusMessage + ' Private messagePromote to mod<a class="torus-user-action' + (Torus.chats[room].userlist[wgUserName] && (Torus.chats[room].userlist[wgUserName].mod || Torus.chats[room].userlist[wgUserName].staff) ? '" onclick="Torus.io.kickban(' + room + ', \'' + name + '\')' : ' torus-user-action-disabled') + '">Kickban</a> ' + (props.mod || props.staff ? '<img class="torus-user-icon-' + (props.staff ? 'staff' : 'mod') + '" src="http://c.wikia.com/extensions/wikia/Chat/images/icon-' + (props.staff ? 'staff' : 'chatmod') + '.png">' : ) + ' <span class="torus-user-name' + (props.statusState.toLowerCase == 'away' ? ' torus-user-away' : ) + '">' + name + ' ';	} } Torus.ui.removeUser = function(room, name) {	if(isNaN(room * 1)) {room = Torus.data.domains[room];}	if(!Torus.chats[room] || room <= 0) {throw new ReferenceError('Invalid room ' + room + '. (ui.removeUser)'); return;}	delete Torus.chats[room].userlist[name];	Torus.chats[room].userlist.length--;	if(Torus.ui.active == room) {		var users = Torus.ui.window.sidebar.getElementsByTagName('li');		for(var i = 0; i < users.length; i++) {			if(users[i].className.indexOf('torus-user-' + encodeURIComponent(name)) != -1) {				users[i].parentNode.removeChild(users[i]);				break;			}		}	} } Torus.ui.ping = function {	if(Torus.options.data['messages-pings-enabled'] && Torus.ui.window.window.parentNode && Torus.data.pinginterval == 0) {		Torus.data.titleflash = document.title; document.title = Torus.options.data['messages-pings-alert']; Torus.data.pinginterval = setInterval('if(document.title != Torus.options.data[\'messages-pings-alert\']) {document.title = Torus.options.data[\'messages-pings-alert\'];} else {document.title = Torus.data.titleflash;}', Torus.options.data['messages-pings-interval']); if(Torus.options.data['messages-pings-beep']) { var beep = document.createElement('audio'); beep.src = Torus.options.data['messages-pings-beep-sound']; beep.play; }	} } Torus.ui.inputListener = function(event) { if(event.keyCode == 13 && !event.shiftKey) { event.preventDefault; if(Torus.data.history[1] != this.value) { Torus.data.history[0] = this.value; Torus.data.history.unshift(''); }		Torus.data.histindex = 0; while(this.value.charAt(0) == '/') { if(this.value.indexOf('\n') != -1) { var result = Torus.commands.eval(this.value.substring(1, this.value.indexOf('\n'))); if(result != undefined) {Torus.log(result);} this.value = this.value.substring(this.value.indexOf('\n') + 1); }			else { var result = Torus.commands.eval(this.value.substring(1)); if(result != undefined) {Torus.log(result);} this.value = ''; }		}		if(this.value) { if(this.value.indexOf('./') == 0) {Torus.io.sendMessage(Torus.ui.active, this.value.substring(1), false);} else {Torus.io.sendMessage(Torus.ui.active, this.value, false);} this.value = ''; }	}	else if(event.keyCode == 38 && Torus.data.histindex + 1 < Torus.data.history.length) { Torus.data.histindex++; this.value = Torus.data.history[Torus.data.histindex]; }	else if(event.keyCode == 40 && Torus.data.histindex > 0) { Torus.data.histindex--; this.value = Torus.data.history[Torus.data.histindex]; } } Torus.io.sendMessage = function(room, message, hist) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room] || room < 0) {throw new ReferenceError('Invalid room ' + room + '. (io.sendMessage)');} if(room == 0) {Torus.log(message);} else { if((hist || hist == undefined) && Torus.data.history[1] != message) { Torus.data.history[0] = message; Torus.data.history.unshift(''); }		Torus.data.histindex = 0; if(Torus.chats[room].parent) {Torus.chats[Torus.chats[room].parent].socket.sendCommand('openprivate', '"roomId":' + room + ',"users":["' + Torus.chats[room].users.join('","') + '"]');} Torus.chats[room].socket.sendMessage(message); } } Torus.io.setStatus = function(room, state, message) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room] || room <= 0) {throw new ReferenceError('Invalid room ' + room + '. (io.setStatus)'); return;} Torus.chats[room].socket.sendCommand('setstatus', '"statusState":"' + state + '","statusMessage":"' + message + '"'); } Torus.io.giveMod = function(room, user) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room] || room <= 0) {throw new ReferenceError('Invalid room ' + room + '. (io.giveMod)'); return;} Torus.chats[room].socket.sendCommand('givechatmod', '"userToPromote":"' + user + '"'); } Torus.io.kickban = function(room, user) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room] || room <= 0) {throw new ReferenceError('Invalid room ' + room + '. (io.kickvan)'); return;} Torus.chats[room].socket.sendCommand('kickban', '"userToBan":"' + user + '"'); } Torus.io.openPrivate = function(room, users, message, id) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room] || room <= 0) {throw new ReferenceError('Invalid room ' + room + '. (io.openPrivate)'); return;} if(!message || typeof message != 'string') {message = '';} var username = false; for(var i in users) { if(users[i] == wgUserName) {username = true; break;} }	if(!username) {users.push(wgUserName);} if(!id) { Torus.chats[room].socket.cajax('&method=getPrivateRoomId', {users: users.join(',')}, function(data) {			eval('data = ' + data);			return Torus.io.openPrivate(room, users, message, data.id);		}); }	else { if(!Torus.chats[id]) { Torus.open(id); Torus.chats[id].parent = room; Torus.chats[id].users = users; if(message) { Torus.chats[id].socket.addListener('connect', function {					Torus.io.sendMessage(id, message);				}); }		}		else { Torus.ui.activate(id); if(message) {Torus.io.sendMessage(id, message);} }	} } Torus.io.receive = function(room, event) { if(isNaN(room * 1)) {room = Torus.data.domains[room];} if(!Torus.chats[room] || room <= 0) {throw new ReferenceError('Invalid room ' + room + '. (io.receive)'); return;} var data = (event.event == 'join' ? event.joinData : event.data); //this seems like an oversight in the protocol, but it's there so meh eval('data = ' + data); //convert data string to object if(data) {data.roomId = room;} switch(event.event) { case 'initial': var users = data.collections.users; for(var i = 0; i < users.models.length; i++) { Torus.ui.updateUser(room, users.models[i].attrs.name, {					avatar: users.models[i].attrs.avatarSrc.replace('28px', '100px'),					mod: users.models[i].attrs.isModerator,					staff: users.models[i].attrs.isStaff,					givemod: users.models[i].attrs.isCanGiveChatMode, //apparently they typo'd mod and never fixed it					statusState: users.models[i].attrs.statusState,					statusMessage: users.models[i].attrs.statusMessage,				}); }			if(!Torus.chats[room].reconnecting) { //this may cause some messages to be lost on slow connections, but we'll fix that later var chats = data.collections.chats; for(var i = 0; i < chats.models.length; i++) { while(chats.models[i].attrs.text.indexOf('<') != -1) {chats.models[i].attrs.text = chats.models[i].attrs.text.replace('<', '&lt;');} Torus.ui.addLine(room, '&lt;<span class="torus-usercolor" style="color:' + Torus.util.colorHash(chats.models[i].attrs.name) + '">' + chats.models[i].attrs.name + ' &gt; ' + chats.models[i].attrs.text, chats.models[i].attrs.timeStamp); }			}			else {Torus.chats[room].reconnecting = false;} break; case 'chat:add': if(!data.attrs.name) {console.log(data);} if(!data.attrs.isInlineAlert) { var pingphrase = ''; if(data.attrs.name != wgUserName) { var pings = Torus.options.data['messages-pings'].split('\n'); for(var i = 0; i < pings.length; i++) { if(pings[i] && data.attrs.text.indexOf(pings[i].toLowerCase) != -1) {Torus.ui.ping; pingphrase = pings[i]; break;} }				}				while(data.attrs.text.indexOf('<') != -1) {data.attrs.text = data.attrs.text.replace('<', '&lt;');} if(data.attrs.text.indexOf('* ' + data.attrs.name) == 0) {Torus.ui.addLine(room, '* <span class="torus-usercolor" style="color:' + Torus.util.colorHash(data.attrs.name) + '">' + data.attrs.name + ' ' + (pingphrase ? data.attrs.text.substring(data.attrs.name.length + 2).replace(pingphrase, ' ' + pingphrase + ' ') : data.attrs.text.substring(data.attrs.name.length + 2)));} else {Torus.ui.addLine(room, '&lt;<span class="torus-usercolor" style="color:' + Torus.util.colorHash(data.attrs.name) + '">' + data.attrs.name + ' &gt; ' + (pingphrase ? data.attrs.text.replace(pingphrase, ' ' + pingphrase + ' ') : data.attrs.text));} }			else { if(data.attrs.wfMsg) { switch(data.attrs.wfMsg) { case 'chat-user-was-kickbanned': Torus.ui.addLine(room, '== <span class="torus-usercolor" style="color:' + Torus.util.colorHash(data.attrs.msgParams[0]) + '">' + data.attrs.msgParams[0] + ' was kickbanned from ' + (Torus.data.ids[room] ? Torus.data.ids[room] : room)); break; case 'chat-inlinealert-a-made-b-chatmod': Torus.ui.addLine(room, '== <span class="torus-usercolor" style="color:' + Torus.util.colorHash(data.attrs.msgParams[0]) + '">' + data.attrs.msgParams[0] + ' promoted <span class="torus-usercolor" style="color:' + Torus.util.colorHash(data.attrs.msgParams[0]) + '">' + data.attrs.msgParams[1] + ' to chatmod'); break; default: console.log(data); break; }				}				else {Torus.ui.addLine(room, '== ' + data.attrs.text);} }			if(Torus.chats[room].parent && data.attrs.name != wgUserName) {Torus.ui.ping;} break; case 'join': if(!Torus.chats[room].userlist[data.attrs.name]) {Torus.ui.addLine(room, '== <span class="torus-usercolor" style="color:' + Torus.util.colorHash(data.attrs.name) + '">' + data.attrs.name + ' joined ' + (Torus.data.ids[room] ? Torus.data.ids[room] : room));} else {Torus.ui.addLine(room, '== <span class="torus-usercolor" style="color:' + Torus.util.colorHash(data.attrs.name) + '">' + data.attrs.name + ' rejoined ' + (Torus.data.ids[room] ? Torus.data.ids[room] : room));} Torus.ui.updateUser(room, data.attrs.name, {				avatar: data.attrs.avatarSrc.replace('28px', '100px'),				mod: data.attrs.isModerator,				staff: data.attrs.isStaff,				givemod: data.attrs.isCanGiveChatMode,				statusState: data.attrs.statusState,				statusMessage: data.attrs.statusMessage,			}); break; case 'part': if(!Torus.chats[room].userlist[data.attrs.name]) {break;} Torus.ui.addLine(room, '== <span class="torus-usercolor" style="color:' + Torus.util.colorHash(data.attrs.name) + '">' + data.attrs.name + ' left ' + (Torus.data.ids[room] ? Torus.data.ids[room] : room)); Torus.ui.removeUser(room, data.attrs.name); break; case 'updateUser': Torus.ui.updateUser(room, data.attrs.name, {				avatar: data.attrs.avatarSrc.replace('28px', '100px'),				mod: data.attrs.isModerator,				staff: data.attrs.isStaff,				givemod: data.attrs.isCanGiveChatMode,				statusState: data.attrs.statusState,				statusMessage: data.attrs.statusMessage,			}); break; case 'openPrivateRoom': if(!Torus.chats[data.attrs.roomId]) { Torus.open(data.attrs.roomId, Torus.chats[room].socket.key); Torus.chats[data.attrs.roomId].parent = room; Torus.chats[data.attrs.roomId].users = data.attrs.users; }			break; case 'forceReconnect': Torus.chats[room].socket.reconnect; break; case 'disableReconnect': //this would be more accurately described as force disconnect Torus.close(room); break; default: console.log(event); break; }	Torus.callListeners(event.event, (data ? data : room)); } Torus.options.addGroup = function(group) { if(typeof group != 'string') {throw new TypeError('Parameter \'group\' must be a string. (options.addGroup)');} if(Torus.options.groups[group.toLowerCase]) {throw new ReferenceError('Group \'' + group + '\' already exists. (options.addGroup)');} Torus.options.groups[group.toLowerCase] = {}; Torus.ui.window.options.children[0].innerHTML += '' + group + '</li>'; var wind = document.createElement('div'); //use document.createElement instead of .innerHTML += to prevent text fields from resetting wind.id = 'torus-option-group-' + group.toLowerCase; Torus.ui.window.options.insertBefore(wind, Torus.ui.window.options.lastChild); } Torus.options.removeGroup = function(group) { if(typeof group != 'string') {throw new TypeError('Parameter \'group\' must be a string. (options.removeGroup)');} group = group.toLowerCase; if(!Torus.options.groups[group]) {throw new ReferenceError('Group \'' + group + '\' doesn\'t exist. (options.removeGroup)');} var options = Torus.ui.window.options.children[0].children; var windows = Torus.ui.window.options.children; for(var i = 0; i < options.length; i++) { if(options[i].textContent.toLowerCase == group) {options.removeChild(options[i]);} }	for(var i = 1; i < windows.length; i++) { if(windows[i].id == 'torus-option-group-' + group) {windows[i].removeChild(windows[i]);} } } Torus.options.showGroup = function(group) { if(typeof group != 'string') {throw new TypeError('Parameter \'group\' must be a string. (options.showGroup)');} group = group.toLowerCase; if(!Torus.options.groups[group]) {throw new ReferenceError('Invalid group name \'' + group + '\'. (options.showGroup)');} if(Torus.options.selected == group) {return;} else {Torus.options.selected = group;} var options = Torus.ui.window.options.children[0].children; var windows = Torus.ui.window.options.children; for(var i = 0; i < options.length; i++) { var classes = options[i].className.split(' '); for(var j = 0; j < classes.length; j++) { if(classes[j] == 'torus-option-group-selected') {classes.splice(j, 1); break;} }		options[i].className = classes.join(' '); if(options[i].textContent.toLowerCase == group) {options[i].className += ' torus-option-group-selected';} }	for(var i = 1; i < windows.length; i++) { if(windows[i].id != 'torus-option-group-' + group) {windows[i].style.display = 'none';} else {windows[i].style.display = 'block';} } } Torus.options.save = function { var str = ''; for(var i in Torus.options.data) { var option = Torus.options.data[i]; if(i.indexOf(':') == -1 && typeof option != 'object') {str += i + ':' + option + '{;}';} }	str = str.substring(0, str.length - 3); window.localStorage.setItem('torus-options', str); return str; } Torus.options.load = function { var options = window.localStorage.getItem('torus-options'); if(options) {options = options.split('{;}');} else {return;} for(var i = 0; i < options.length; i++) { var key = options[i].substring(0, options[i].indexOf(':')); var val = options[i].substring(options[i].indexOf(':') + 1); if(val == 'true') {Torus.options.data[key] = true;} else if(val == 'false') {Torus.options.data[key] = false;} else if(!isNaN(val * 1)) {Torus.options.data[key] = val * 1;} else {Torus.options.data[key] = val;} }	return Torus.options.data; } Torus.commands.eval = function(str, prop) { if(typeof str != 'string') {return false;} var com = str.split(' '); var ref = Torus.commands.commands; var i = 0; var cont = true; while(ref[com[i]]) { switch(typeof ref[com[i]]) { case 'string': if(ref[com[i]].charAt(0) == '/') {var line = ref[com[i]].substring(1) + ' ' + com.slice(i + 1).join(' ');} else {var line = com.slice(0, i).join(' ') + ' ' + ref[com[i]] + ' ' + com.slice(i + 1).join(' ');} return Torus.commands.eval(line, prop); case 'object': if(typeof ref[com[i]].func == 'function') {var command = ref[com[i]];} //is a command else { ref = ref[com[i]]; i++; if(!ref[com[i]] && ref.default && ref.default.func) {var command = ref.default;} }				if(command) {cont = false;} break; default: cont = false; break; }		if(cont == false) {break;} }	if(command) { if(prop == '*') {return ref;} else if(prop) {return command[prop];} else {return command.func.apply(ref, com.slice(i + 1));} } } Torus.commands.commands = { join: { help: 'Join a room. Accepts either the id of the room, or the domain name (for example, commmunity will take you to the room for <a href="http://community.wikia.com" onclick="event.preventDefault; window.open(this.href, \'torus\')">community.wikia.com</a>). Specifying 0 will part all rooms.', func: function(room) { if(isNaN(room * 1)) { if(!Torus.data.domains[room]) {return 'Unable to look up ' + room + ' in database. Try <a href="http://' + room + '.wikia.com/wiki/Special:Torus" onclick="event.preventDefault; window.open(this.href, \'torus\');">w:c:' + room + ':Special:Torus</a>.';} else {room = Torus.data.domains[room];} }			if(room <= 0) { for(var i in Torus.chats) { Torus.close(i); }				return true; }			else {Torus.open(room);} }	},	part: { help: 'Leave a room. If no room is specified, the current room is left.', func: function(room) { if(!room) {Torus.close(Torus.ui.active);} else { if(isNaN(room * 1) && !Torus.chats[Torus.data.domains[room]]) {return 'Invalid room ' + room + '.';} else {Torus.close(room);} }		}	},	kick: { help: 'Kicks a user from the current room.', func: function { var user = ''; for(var i = 0; i < arguments.length; i++) {user += ' ' + arguments[i];} user = user.substring(1); Torus.io.kickban(Torus.ui.active, user); }	},	mod: 'givemod', givemod: { help: 'Promotes a user to chatmod in the current room.', func: function { var user = ''; for(var i = 0; i < arguments.length; i++) {user += ' ' + arguments[i];} user = user.substring(1); Torus.io.giveMod(Torus.ui.active, user); }	},	query: 'private', priv: 'private', private: { help: 'Opens a private room. Users can be specified in a comma-separated list.', func: function { var users = ''; for(var i = 0; i < arguments.length; i++) {users += ' ' + arguments[i];} users = users.substring(1).split(', '); Torus.io.openPrivate(Torus.ui.active, users); }	},	away: '/status away', back: '/status here', status: { help: 'Changes your status state or message for the current room.', func: function(state) { var message = ''; for(var i = 0; i < arguments.length; i++) {message += ' ' + arguments[i];} Torus.io.setStatus(Torus.ui.active, state, message); }	},	me: { help: 'Emote yourself.', func: function { var str = ''; for(var i = 0; i < arguments.length; i++) {str += ' ' + arguments[i];} Torus.io.sendMessage(Torus.ui.active, '* ' + wgUserName + str, false); }	},	options: { help: 'View options.', func: function { Torus.ui.activate(-1); }	},	help: { help: 'Displays help data.', func: function { var str = ''; for(var i = 0; i < arguments.length; i++) {str += ' ' + arguments[i];} str = str.substring(1); if(str) { var help = Torus.commands.eval(str, 'help'); if(!help) {Torus.log('No help data for ' + str);} else {return 'Help: ' + str + ': ' + help;} }			else { var coms = ''; for(var i in Torus.commands.commands) { coms += ', ' + i;				} coms = coms.substring(2); return 'Commands:\n' + coms; }		}	} }; Torus.util.colorHash = function(str) { var hue = 0; var val = Torus.options.data['misc-usercolor-val']; var sat = Torus.options.data['misc-usercolor-sat']; for(var i = 0; i < str.length; i++) { hue += str.charCodeAt(i); }	hue = (hue % 360 + Torus.options.data['misc-usercolor-hue']) % 360; var c = val * sat; var m = val - c;	var C = Math.floor((c + m) * 255).toString(16); var X = Math.floor((c * (1 - Math.abs((hue / 60) % 2 - 1)) + m) * 255).toString(16); var O = Math.floor(m * 255).toString(16); if(C.length == 1) {C = '0' + C;} if(X.length == 1) {X = '0' + X;} if(O.length == 1) {O = '0' + O;} switch(Math.floor(hue / 60)) { case 0: return '#' + C + X + O;		case 1: return '#' + X + C + O;		case 2: return '#' + O + C + X;		case 3: return '#' + O + X + C;		case 4: return '#' + X + O + C;		case 5: return '#' + C + O + X;	} } Torus.util.parseLinks = function(wiki, text) { if(!isNaN(wiki * 1)) {wiki = Torus.data.ids[wiki];} var ref = 0; while(text.indexOf('http', ref) != -1) { if(text.charAt(text.indexOf('http', ref) - 1) != '[' && (text.indexOf('http://', ref) == text.indexOf('http', ref) || text.indexOf('https://', ref) == text.indexOf('http', ref))) { var start = text.indexOf('http', ref); var space = text.indexOf(' ', start); var line = text.indexOf(' ', start); if(space != -1 && line != -1) { if(space < line) {var end = space;} else {var end = line;} }			else if(space != -1) {var end = space;} else if(line != -1) {var end = line;} else {var end = text.length;} var url = text.substring(start, end); while(url.lastIndexOf('.') == url.length - 1) {url = url.substring(0, url.length - 1); end--;} var link = '<a href="' + url + '" onclick="event.preventDefault; window.open(this.href, \'torus\');">' + url + '</a>'; text = text.substring(0, start) + link + text.substring(end, text.length); }		ref = text.indexOf('http', ref) + (link ? link.length - 9 : 1); }	ref = 0; while(text.indexOf(, ref) != -1) {		if(text.indexOf(, text.indexOf(, open);			var close = text.indexOf(, open);			if(text.indexOf(' ', open) != -1 && text.indexOf(' ', open) < close) {ref = text.indexOf('display				var page = text.substring(open + 2, pipe);				if(page.indexOf('w:c:') == 0) {var domain = page.substring(4);}				else if(page.indexOf('w:') == 0) {var domain = 'community';}				else if(page.indexOf('c:') == 0) {var domain = page.substring(2);}				else if(wiki) {var domain = wiki;}				else {ref = text.indexOf('', ref) + 1; continue;} //no domain was specified and we don't know the local domain				if(pipe + 1 == close) {var link = '<a href="http://' + domain + '.wikia.com/wiki/' + encodeURIComponent(text.substring(open + 2, pipe)) + '" title="' + text.substring(open + 2, pipe) + '" onclick="event.preventDefault; window.open(this.href, \'torus\');">' + text.substring(text.indexOf(':', open) + 1, pipe) + '</a>'} //pipe trick				else {var link = '<a href="http://' + domain + '.wikia.com/wiki/' + encodeURIComponent(text.substring(open + 2, pipe)) + '" title="' + text.substring(open + 2, pipe) + '" onclick="event.preventDefault; window.open(this.href, \'torus\');">' + text.substring(pipe + 1, close) + '</a>';}			}			else { //is [[page				var page = text.substring(open + 2, close);				if(page.indexOf('w:c:') == 0) {var domain = page.substring(4);}				else if(page.indexOf('w:') == 0) {var domain = 'community';}				else if(page.indexOf('c:') == 0) {var domain = page.substring(2);}				else if(wiki) {var domain = wiki;}				else {ref = text.indexOf('[[', ref) + 1; continue;} //no domain was specified and we don't know the local domain				var link = '<a href="http://' + domain + '.wikia.com/wiki/' + encodeURIComponent(page) + '" title="' + page + '" onclick="event.preventDefault; window.open(this.href, \'torus\');">' + page + '</a>';			}			text = text.substring(0, open) + link + text.substring(close + 2, text.length);			if(text.indexOf('[[', ref) != -1) {ref = text.indexOf('[[', ref) + (link ? 0 : 1);}			else {break;}		}		else {break;}	}	ref = 0;	while(text.indexOf('[http', ref) != -1) {		if(text.indexOf('[http://', ref) == text.indexOf('[http', ref) || text.indexOf('[https://', ref) == text.indexOf('[http', ref)) {			var start = text.indexOf('[http', ref);			var space = text.indexOf(' ', start);			var end = text.indexOf(']', space);			if(end == -1) {break;}			if(space + 1 >= text.indexOf(']', start) || text.indexOf(' ', start) < end) {ref = text.indexOf('[http', ref) + 1; continue;}			var url = text.substring(start + 1, space);			while(url.lastIndexOf('.') == url.length - 1) {url = url.substring(0, url.length - 1); end--;}			var link = '<a href="' + url + '" onclick="event.preventDefault; window.open(this.href, \'torus\');">' + text.substring(space + 1, end) + '</a>';			text = text.substring(0, start) + link + text.substring(end + 1, text.length);		}		if(text.indexOf('[http', ref) != -1) {ref = text.indexOf('[http', ref) + (link ? 0 : 1);}		else {break;}	}	return text; } Torus.util.timestamp = function(time) {	var date = new Date;	if(time) {date.setTime(time);}	date.setUTCHours(date.getUTCHours + Torus.options.data['messages-timezone']);	var hours = date.getUTCHours;	if(hours < 10) {hours = '0' + hours;}	var minutes = date.getUTCMinutes;	if(minutes < 10) {minutes = '0' + minutes;}	var seconds = date.getUTCSeconds;	if(seconds < 10) {seconds = '0' + seconds;}	return hours + ':' + minutes + ':' + seconds; } addOnloadHook(function {	document.head.innerHTML += '<style id="torus-css" type="text/css">\n#torus {\n\tposition:relative;\n\theight:50em;\n\twidth:98%;\n\tmargin:1em; auto;\n\tborder:1px solid #000;\n\tfont-size:11px;\n\tcolor:#000;\n}\n#torus-tabs {\n\tposition:absolute;\n\ttop:0;\n\tleft:0;\n\tright:0;\n\theight:3em;\n\tbackground-color:#66f;\n}\n.torus-tab {\n\tposition:relative;\n\ttop:.4em;\n\tmargin:.3em;\n\tpadding:.1em .3em;\n\tborder-radius:.4em;\n\tbackground-color:#99f;\n\tborder:1px solid #ccc;\n\tfont-size:1.5em;\n\tcursor: pointer;\n}\n.torus-tab-viewing, .torus-tab:hover {\n\tbackground-color:#def;\n}\n.torus-tab-active, .torus-tab-active:hover {\n\tbackground-color:#fff;\n\tfont-weight:bold;\n}\n.torus-tab-close {\n\tfont-size:.65em;\n\tmargin-left:.6em;\n\tvertical-align:top;\n\tline-height:.8em;\n}\n.torus-tab-close:hover {\n\tcolor:red;\n}\n#torus-tab--1 {\n\tfloat:right;\n\ttop:0;\n}\n#torus-sidebar {\n\tposition:absolute;\n\ttop:3em;\n\tbottom:4em;\n\tright:0;\n\twidth:15em;\n\tmargin:0;\n\tpadding:.2em 0;\n\tbackground-color:#66f;\n\tborder-top:1px solid #000;\n\tlist-style:none;\n\twhite-space:nowrap;\n\t/*overflow-x:hidden;*/\n}\n.torus-user {\n\tpadding-left:1.5em;\n}\n.torus-user-popup {\n\tdisplay:none;\n\tmin-width:15em;\n\tposition:absolute;\n\tright:15em;\n\tz-index:10;\n\tbackground-color:#66f;\n\tborder:1px solid black;\n\tborder-right:1px solid #555;\n}\n.torus-user:hover .torus-user-popup {\n\tdisplay:block;\n\tpadding-top:.2em;\n}\n.torus-user-popup .torus-user-avatar {\n\tposition:absolute;\n\twidth:3.5em;\n\tmargin:.5em;\n\tmargin-left:.7em;\n\tborder:1px solid #ccc;\n}\n.torus-user-popup .torus-user-info {\n\theight:5em;\n\tmargin-left:4.7em;\n\tpadding-right:.5em;\n}\n.torus-user-popup .torus-user-name {\n\tfont-size:larger;\n\tfont-weight:bold;\n}\n.torus-user-popup .torus-user-access {\n\tcolor:#0f0;\n\tfont-size:1.5em;\n\tfont-weight:bold;\n}\n.torus-user-popup .torus-user-status-state {\n\tfont-size:larger;\n}\n.torus-user-popup .torus-user-status-message {\n\tfont-style:italic;\n}\n.torus-user-popup .torus-user-action {\n\tdisplay:block;\n\twidth:100%;\n\tborder-top:1px solid #ccc;\n\tbackground-color:#99f;\n\ttext-align:center;\n}\n.torus-user-popup .torus-user-action:hover {\n\ttext-decoration:none;\n\tbackground-color:#def;\n\tcursor:pointer;\n}\n.torus-user-popup .torus-user-action-disabled, .torus-user-popup .torus-user-action-disabled:hover {\n\tbackground-color:#ddd;\n\tcolor:#999;\n\tcursor:default;\n}\n.torus-user-away {\n\tcolor:#666;\n\tfont-style:italic;\n}\n.torus-user-mod, .torus-user-staff {\n\tpadding-left:.5em;\n}\n.torus-user-icon-staff, .torus-user-icon-mod {\n\theight:1em;\n\tvertical-align:top;\n\tmargin-top:.1em;\n}\n.torus-user-icon-staff {\n\tmargin-top:.2em;\n}\n#torus-info {\n\tposition:absolute;\n\ttop:3em;\n\tleft:0;\n\tright:15em;\n\theight:2em;\n\tbackground-color:#dde;\n\tborder-top:1px solid #000;\n\tborder-right:1px solid #000;\n\ttext-align:center;\n}\n#torus-window, #torus-options {\n\tposition:absolute;\n\ttop:5em;\n\tbottom:4em;\n\tleft:0;\n\tright:15em;\n\tbackground-color:#ccf;\n\tborder-top:1px solid #000;\n\tborder-right:1px solid #000;\n\tmargin:0;\n\tpadding:.3em .5em;\n\toverflow-y:scroll;\n\toverflow-x:hidden;\n\tlist-style:none;\n\tfont-family:monospace;\n\tword-wrap:break-word;\n}\n.torus-message, #torus-options {\n\tdisplay:none;\n}\n.torus-message-ping {\n\tcolor:red;\n}\n#torus-options input[type="checkbox"] {\n\tvertical-align:top;\n\tmargin:0;\n}\n#torus-options {\n\tpadding-left:0;\n}\n#torus-options-groups {\n\tmargin:0;\n\tmargin-right:1em;\n\tfloat:left;\n\theight:100%;\n\tborder-right:1px solid #000;\n}\n.torus-option-group {\n\tpadding:.1em .5em;\n\tbackground-color:#99f;\n\tcursor:pointer;\n}\n.torus-option-group:hover {\n\tbackground-color:#def;\n}\n.torus-option-group-selected, .torus-option-group-selected:hover {\n\tbackground-color:#fff;\n}\n#torus-input {\n\tposition:absolute;\n\tbottom:0;\n\tleft:0;\n\tright:0;\n\theight:4em;\n\tbackground-color:#66f;\n\tborder-top:1px solid #000;\n}\n#torus-input-box {\n\tposition:absolute;\n\ttop:.2em;\n\tbottom:.2em;\n\tleft:.2em;\n\tright:.2em;\n\twidth:auto;\n\tresize:none;\n}\n <style id="torus-css-dynamic" type="text/css"> ';	Torus.ui.window.id = 'torus';	Torus.ui.window.innerHTML = ' <span id="torus-tab--1" class="torus-tab" onclick="Torus.ui.activate(-1);"><img width="18" src="http://images2.wikia.nocookie.net/__cb20110812214252/monchbox/images/a/a1/Gear_icon.png" style="vertical-align:top;"> Options <span id="torus-tab-0" class="torus-tab" onclick="event.preventDefault; if(event.shiftKey && Torus.ui.active != 0) {Torus.ui.show(0);} else {Torus.ui.activate(0);}">Status  <ul id="torus-sidebar"></ul> <ul id="torus-window"></ul> <textarea id="torus-input-box"> ';	Torus.ui.window.tabs = Torus.ui.window.children[0];	Torus.ui.window.sidebar = Torus.ui.window.children[1];	Torus.ui.window.info = Torus.ui.window.children[2];	Torus.ui.window.window = Torus.ui.window.children[3];	Torus.ui.window.options = Torus.ui.window.children[4];	Torus.ui.window.input = Torus.ui.window.children[5];	Torus.ui.window.onmouseover = function {		if(Torus.data.pinginterval != 0) {			clearInterval(Torus.data.pinginterval);			Torus.data.pinginterval = 0;			document.title = Torus.data.titleflash;		}	}	Torus.ui.window.input.getElementsByTagName('textarea')[0].onkeydown = Torus.ui.inputListener;	Torus.chats[0] = Torus.chats[-1] = true;	Torus.ui.activate(0);	document.body.addEventListener('beforeunload', Torus.options.save);	Torus.options.load;	Torus.ui.window.options.innerHTML = '<ul id="torus-options-groups">Messages</li>Miscellaneous</li></ul> <fieldset id="torus-option-set-messages-pings"> Pings <input type="checkbox" checked="' + Torus.options.data['messages-pings-enabled'] + '" onchange="Torus.options.data[\'messages-pings-enabled\'] = this.checked;"> <textarea cols="20" rows="8" onkeyup="Torus.options.data[\'messages-pings\'] = this.value;">' + Torus.options.data['messages-pings'] + '  Message: <input onkeyup="Torus.options.data[\'messages-pings-alert\'] = this.value;" value="' + Torus.options.data['messages-pings-alert'] + '">  Interval: <input onkeyup="Torus.options.data[\'messages-pings-interval\'] = this.value / 1000" value="' + (Torus.options.data['messages-pings-interval'] / 1000) + '" style="width:2em;">sec  Beep: <input type="checkbox" checked="' + Torus.options.data['messages-pings-beep'] + '" onchange="Torus.options.data[\'messages-pings-beep\'] = this.checked;">  Sound: <input onkeyup="Torus.options.data[\'messages-pings-beep-sound\'] = this.value" value="' + Torus.options.data['messages-pings-beep-sound'] + '"> <fieldset id="torus-option-set-messages-misc"> Misc Timezone: UTC + <input onkeyup="Torus.options.data[\'messages-timezone\'] = this.value;" value="' + Torus.options.data['messages-timezone'] + '" style="width:2em;"> <fieldset id="torus-option-set-miscellaneous-connection"> Connection Default rooms<textarea onkeyup="Torus.options.data[\'misc-connection-defaultrooms\'] = this.value">' + Torus.options.data['misc-connection-defaultrooms'] + '  Open local: <input type="checkbox" checked="' + Torus.options.data['misc-connection-local'] + '" onchange="Torus.options.data[\'misc-connection-local\'] = this.checked"> <fieldset id="torus-option-set-miscellaneous-colors"> Colors <input type="checkbox" checked="' + Torus.options.data['misc-usercolor-enabled'] + '" onchange="Torus.options.data[\'misc-usercolor-enabled\'] = this.checked;"> Hue offset: <input onkeyup="Torus.options.data[\'misc-usercolor-hue\'] = this.value % 360;" style="width:3em;" value="' + Torus.options.data['misc-usercolor-hue'] + '">°  Saturation: <input onkeyup="Torus.options.data[\'misc-usercolor-sat\'] = this.value / 100;" style="width:3em;" value="' + (Torus.options.data['misc-usercolor-sat'] * 100) + '">%  Brightness: <input onkeyup="Torus.options.data[\'misc-usercolor-val\'] = this.value / 100;" style="width:3em;" value="' + (Torus.options.data['misc-usercolor-val'] * 100) + '">% ';	if(wgCanonicalNamespace == 'Special' && wgTitle == 'Torus') {		document.title = 'Torus - It\'s a donut - ' + wgSiteName;		if(skin == 'oasis') {			var body = 'WikiaArticle';			if(document.getElementById('WikiaPageHeader')) {				document.getElementById('WikiaPageHeader').getElementsByTagName('h1')[0].innerHTML = 'Torus';				document.getElementById('WikiaPageHeader').getElementsByTagName('h2')[0].innerHTML = 'It\'s a donut';			}		}		else {			var body = 'bodyContent';			document.getElementById('firstHeading').innerHTML = 'Torus';		}		document.getElementById(body).innerHTML = (document.getElementById('AdminDashboardHeader') ? ' Torus ' : '');		document.getElementById(body).appendChild(Torus.ui.window);		if(Torus.local) {Torus.open(Torus.local);}		if(Torus.options.data['misc-connection-defaultrooms']) {			var rooms = Torus.options.data['misc-connection-defaultrooms'].split('\n');			for(var i = 0; i < rooms.length; i++) {				Torus.open(rooms[i]);			}		}	}	Torus.init = true; });