(function($) { var ConsoleRoom = this.ConsoleRoom = Room.extend({ constructor: function() { if (!this.events) this.events = {}; if (!this.events['click .ilink']) this.events['click .ilink'] = 'clickLink'; if (!this.events['click .username']) this.events['click .username'] = 'clickUsername'; if (!this.events['submit form']) this.events['submit form'] = 'submit'; if (!this.events['keydown textarea']) this.events['keydown textarea'] = 'keyPress'; if (!this.events['click .message-pm i']) this.events['click .message-pm i'] = 'openPM'; this.initializeTabComplete(); this.initializeChatHistory(); // this MUST set up this.$chatAdd Room.apply(this, arguments); app.user.on('change', this.updateUser, this); this.updateUser(); }, updateUser: function() { var name = app.user.get('name'); var userid = app.user.get('userid'); if (!name) { this.$chatAdd.html('Connecting...'); this.$chatbox = null; } else if (!app.user.get('named')) { this.$chatAdd.html('
'); this.$chatbox = null; } else { this.$chatAdd.html(''); this.$chatbox = this.$chatAdd.find('textarea'); this.$chatbox.autoResize({ animate: false, extraSpace: 0 }); if (this === app.curSideRoom || this === app.curRoom) { this.$chatbox.focus(); } } }, focus: function() { if (this.$chatbox) this.$chatbox.focus(); }, login: function() { app.addPopup(LoginPopup); }, submit: function(e) { e.preventDefault(); e.stopPropagation(); var text; if ((text = this.$chatbox.val())) { if (!$.trim(text)) { this.$chatbox.val(''); return; } this.tabComplete.reset(); this.chatHistory.push(text); text = this.parseCommand(text); if (text) { this.send(text); } this.$chatbox.val(''); } }, keyPress: function(e) { if (e.keyCode === 13 && !e.shiftKey) { // Enter key this.submit(e); } else if (e.keyCode === 33) { // Pg Up key this.$chatFrame.scrollTop(this.$chatFrame.scrollTop() - this.$chatFrame.height() + 60); } else if (e.keyCode === 34) { // Pg Dn key this.$chatFrame.scrollTop(this.$chatFrame.scrollTop() + this.$chatFrame.height() - 60); } else if (e.keyCode === 9 && !e.shiftKey && !e.ctrlKey) { // Tab key if (this.handleTabComplete(this.$chatbox)) { e.preventDefault(); e.stopPropagation(); } } else if (e.keyCode === 38 && !e.shiftKey && !e.altKey) { // Up key if (this.chatHistoryUp(this.$chatbox, e)) { e.preventDefault(); e.stopPropagation(); } } else if (e.keyCode === 40 && !e.shiftKey && !e.altKey) { // Down key if (this.chatHistoryDown(this.$chatbox, e)) { e.preventDefault(); e.stopPropagation(); } } }, clickUsername: function(e) { e.stopPropagation(); e.preventDefault(); var position; if (e.currentTarget.className === 'userbutton username') { position = 'right'; } var name = $(e.currentTarget).data('name'); app.addPopup(UserPopup, {name: name, sourceEl: e.currentTarget, position: position}); }, clickLink: function(e) { if (e.cmdKey || e.metaKey || e.ctrlKey) return; e.preventDefault(); e.stopPropagation(); var roomid = $(e.currentTarget).attr('href').substr(app.root.length); app.tryJoinRoom(roomid); }, openPM: function(e) { e.preventDefault(); e.stopPropagation(); app.focusRoom(''); app.rooms[''].focusPM($(e.currentTarget).data('name')); }, clear: function() { if (this.$chat) this.$chat.html(''); }, // highlight getHighlight: function(message) { var highlights = Tools.prefs('highlights') || []; if (!app.highlightRegExp) { try { app.highlightRegExp = new RegExp('\\b('+highlights.join('|')+')\\b', 'i'); } catch (e) { // If the expression above is not a regexp, we'll get here. // Don't throw an exception because that would prevent the chat // message from showing up, or, when the lobby is initialising, // it will prevent the initialisation from completing. return false; } } return ((highlights.length > 0) && app.highlightRegExp.test(message)); }, // chat history chatHistory: null, initializeChatHistory: function() { var chatHistory = { lines: [], index: 0, push: function(line) { if (chatHistory.lines.length > 100) { chatHistory.lines.splice(0, 20); } chatHistory.lines.push(line); chatHistory.index = chatHistory.lines.length; } }; this.chatHistory = chatHistory; }, chatHistoryUp: function($textbox, e) { var idx = +$textbox.prop('selectionStart'); var line = $textbox.val(); if (e && !e.ctrlKey && idx !== 0 && idx !== line.length) return false; if (this.chatHistory.index > 0) { if (this.chatHistory.index === this.chatHistory.lines.length) { if (line !== '') { this.chatHistory.push(line); --this.chatHistory.index; } } else { this.chatHistory.lines[this.chatHistory.index] = line; } $textbox.val(this.chatHistory.lines[--this.chatHistory.index]); return true; } return false; }, chatHistoryDown: function($textbox, e) { var idx = +$textbox.prop('selectionStart'); var line = $textbox.val(); if (e && !e.ctrlKey && idx !== 0 && idx !== line.length) return false; if (this.chatHistory.index === this.chatHistory.lines.length) { if (line !== '') { this.chatHistory.push(line); $textbox.val(''); } } else if (this.chatHistory.index === this.chatHistory.lines.length - 1) { this.chatHistory.lines[this.chatHistory.index] = $textbox.val(); $textbox.val(''); ++this.chatHistory.index; } else { this.chatHistory.lines[this.chatHistory.index] = $textbox.val(); line = this.chatHistory.lines[++this.chatHistory.index]; $textbox.val(line); } return true; }, // tab completion initializeTabComplete: function() { this.tabComplete = { candidates: null, index: 0, prefix: null, cursor: -1, reset: function() { this.cursor = -1; } }; this.userActivity = []; }, markUserActive: function(userid) { var idx = this.userActivity.indexOf(userid); if (idx !== -1) { this.userActivity.splice(idx, 1); } this.userActivity.push(userid); if (this.userActivity.length > 100) { // Prune the list. this.userActivity.splice(0, 20); } }, tabComplete: null, userActivity: null, handleTabComplete: function($textbox) { // Don't tab complete at the start of the text box. var idx = $textbox.prop('selectionStart'); if (idx === 0) return false; var users = this.users || (app.rooms['lobby']?app.rooms['lobby'].users:{}); var text = $textbox.val(); if (idx === this.tabComplete.cursor) { // The user is cycling through the candidate names. if (++this.tabComplete.index >= this.tabComplete.candidates.length) { this.tabComplete.index = 0; } } else { // This is a new tab completion. // There needs to be non-whitespace to the left of the cursor. var m = /^(.*?)([^ ]*)$/.exec(text.substr(0, idx)); if (!m) return true; this.tabComplete.prefix = m[1]; var idprefix = toId(m[2]); var candidates = []; for (var i in users) { if (i.substr(0, idprefix.length) === idprefix) { candidates.push(i); } } // Sort by most recent to speak in the chat, or, in the case of a tie, // in alphabetical order. var self = this; candidates.sort(function(a, b) { var aidx = self.userActivity.indexOf(a); var bidx = self.userActivity.indexOf(b); if (aidx !== -1) { if (bidx !== -1) { return bidx - aidx; } return -1; // a comes first } else if (bidx != -1) { return 1; // b comes first } return (a < b) ? -1 : 1; // alphabetical order }); this.tabComplete.candidates = candidates; this.tabComplete.index = 0; } // Substitute in the tab-completed name. var substituteUserId = this.tabComplete.candidates[this.tabComplete.index]; if (!users[substituteUserId]) return true; var name = users[substituteUserId].substr(1); $textbox.val(this.tabComplete.prefix + name + text.substr(idx)); var pos = this.tabComplete.prefix.length + name.length; $textbox[0].setSelectionRange(pos, pos); this.tabComplete.cursor = pos; return true; }, // command parsing parseCommand: function(text) { var cmd = ''; var target = ''; if (text.substr(0,2) !== '//' && text.substr(0,1) === '/') { var spaceIndex = text.indexOf(' '); if (spaceIndex > 0) { cmd = text.substr(1, spaceIndex-1); target = text.substr(spaceIndex+1); } else { cmd = text.substr(1); target = ''; } } switch (cmd.toLowerCase()) { case 'challenge': case 'user': case 'open': if (!target) target = prompt('Who?'); if (target) app.addPopup(UserPopup, {name: target}); return false; case 'ignore': if (app.ignore[toUserid(target)]) { this.add('User ' + target + ' is already on your ignore list. (Moderator messages will not be ignored.)'); } else { app.ignore[toUserid(target)] = 1; this.add('User ' + target + ' ignored. (Moderator messages will not be ignored.)'); } return false; case 'unignore': if (!app.ignore[toUserid(target)]) { this.add('User ' + target + ' isn\'t on your ignore list.'); } else { delete app.ignore[toUserid(target)]; this.add('User ' + target + ' no longer ignored.'); } return false; case 'clear': if (this.clear) { this.clear(); } else { this.add('||This room can\'t be cleared'); } return false; case 'nick': if (target) { app.user.rename(target); } else { app.addPopup(LoginPopup); } return false; case 'showjoins': this.add('Join/leave messages: ON'); Tools.prefs('showjoins', true); return false; case 'hidejoins': this.add('Join/leave messages: HIDDEN'); Tools.prefs('showjoins', false); return false; case 'showbattles': this.add('Battle messages: ON'); Tools.prefs('showbattles', true); return false; case 'hidebattles': this.add('Battle messages: HIDDEN'); Tools.prefs('showbattles', false); return false; case 'timestamps': var targets = target.split(','); if ((['all', 'lobby', 'pms'].indexOf(targets[0]) === -1) || (targets.length < 2) || (['off', 'minutes', 'seconds'].indexOf( targets[1] = targets[1].trim()) === -1)) { this.add('Error: Invalid /timestamps command'); return '/help timestamps'; // show help } var timestamps = Tools.prefs('timestamps') || {}; if (typeof timestamps === 'string') { // The previous has a timestamps preference from the previous // regime. We can't set properties of a string, so set it to // an empty object. timestamps = {}; } switch (targets[0]) { case 'all': timestamps.lobby = targets[1]; timestamps.pms = targets[1]; break; case 'lobby': timestamps.lobby = targets[1]; break; case 'pms': timestamps.pms = targets[1]; break; } this.add('Timestamps preference set to: `' + targets[1] + '` for `' + targets[0] + '`.'); Tools.prefs('timestamps', timestamps); return false; case 'highlight': var highlights = Tools.prefs('highlights') || []; if (target.indexOf(',') > -1) { var targets = target.split(','); // trim the targets to be safe for (var i=0, len=targets.length; i| User: '+target+' | ||||||
| This user has not played any ladder games yet. | ||||||
| Format | ACRE | GXE | Glicko2 | W | L | T | '+row.formatid+' | '+Math.round(row.acre)+' | '+Math.round(row.gxe,1)+' | '; if (row.rprd > 100) { buffer += ''+Math.round(row.rpr)+' ± '+Math.round(row.rprd)+' (provisional)'; } else { buffer += ''+Math.round(row.rpr)+' ± '+Math.round(row.rprd)+''; } buffer += ' | '+row.w+' | '+row.l+' | '+row.t+' | '; } } buffer += '
|---|---|---|---|---|---|---|
|' + Tools.escapeHTML(row.join('|')) + '