rework chat handling completely

The old system was getting too complicated to add new features to.
The new one should be easier to understand and will be explained
below. This patch should fix #140 and fix #16.

There are several places where new data requests may come from:
- chat.needMoreMessages checks if we are scrolled too far up or
  there is no scrollbar. It then requests new messages.
- scrolling up
- switching the chat tab via chat.chooser
- auto refresh
- once on boot
The latter two always request both types of chat.

Faction and public are handled the same way. Public is later split
into categories. I will explain the faction chat here because it’s
easier.

It starts in chat.requestFaction. This will initialize the query to
the server for data. The exact query is determined by chat.
genPostData. There can only be one faction chat request at a time.
Clearing on map move is handled automatically in code/requests.js.

Let’s assume the data query is successful. It is now passed to
chat.handleFaction which runs some basic checks before the data is
processed and stored in chat._factionData. This is done by chat.
writeDataToHash. The hash keys are the message GUIDs to avoid
duplicates. The hash values are an array of timestamp, processed
message and other meta data.

There is only one way to render faction chat, so data is directly
handed to chat.renderFaction which immediately hands it to chat
.renderData. renderData discards the GUIDs and sorts the values
by their timestamp. It then iterates over the data to insert
date break lines and finally renders the data in the DOM. It also
does some magic to keep the correct scrolling position.

Chat data will be cleared on map move or zoom. However, the
display is not refreshed, so the old, invalid chat data is still
displayed. Only once the data query is finished the data is
rendered. The upside is that small map operations within your
local area appear to never lose their chat data. Downside is that
there’s invalid chat for some time when changing cities.
This commit is contained in:
Stefan Breunig 2013-02-13 02:52:27 +01:00
parent 4c07fb12ae
commit 360f6f8336
4 changed files with 183 additions and 297 deletions

View File

@ -1,22 +1,14 @@
window.chat = function() {}; window.chat = function() {};
window.chat._lastNicksForAutocomplete = [[], []];
window.chat.addNickForAutocomplete = function(nick, isFaction) {
var r = chat._lastNicksForAutocomplete[isFaction ? 0 : 1];
if(r.indexOf(nick) !== -1) return;
r.push(nick);
if(r.length >= 15)
r.shift();
}
window.chat.handleTabCompletion = function() { window.chat.handleTabCompletion = function() {
var el = $('#chatinput input'); var el = $('#chatinput input');
var curPos = el.get(0).selectionStart; var curPos = el.get(0).selectionStart;
var text = el.val(); var text = el.val();
var word = text.slice(0, curPos).replace(/.*\b([a-z0-9-_])/, '$1').toLowerCase(); var word = text.slice(0, curPos).replace(/.*\b([a-z0-9-_])/, '$1').toLowerCase();
var list = window.chat._lastNicksForAutocomplete; var list = $('#chat > div:visible mark');
list = list[1].concat(list[0]); list = list.map(function(ind, mark) { return $(mark).text(); } );
list = uniqueArray(list);
var nick = null; var nick = null;
for(var i = 0; i < list.length; i++) { for(var i = 0; i < list.length; i++) {
@ -43,27 +35,24 @@ window.chat.handleTabCompletion = function() {
// timestamp and clear management // timestamp and clear management
// //
window.chat._oldFactionTimestamp = -1; window.chat.getTimestamps = function(isFaction) {
window.chat._newFactionTimestamp = -1; var storage = isFaction ? chat._factionData : chat._publicData;
window.chat._oldPublicTimestamp = -1; return $.map(storage, function(v, k) { return [v[0]]; });
window.chat._newPublicTimestamp = -1;
window.chat.getOldestTimestamp = function(public) {
return chat['_old'+(public ? 'Public' : 'Faction')+'Timestamp'];
} }
window.chat.getNewestTimestamp = function(public) { window.chat.getOldestTimestamp = function(isFaction) {
return chat['_new'+(public ? 'Public' : 'Faction')+'Timestamp']; var t = Math.min.apply(null, chat.getTimestamps(isFaction));
return t === Infinity ? -1 : t;
} }
window.chat.clearIfRequired = function(elm) { window.chat.getNewestTimestamp = function(isFaction) {
if(!elm.data('needsClearing')) return; var t = Math.max.apply(null, chat.getTimestamps(isFaction));
elm.data('ignoreNextScroll', true).data('needsClearing', false).html(''); return t === -1*Infinity ? -1 : t;
} }
window.chat._oldBBox = null; window.chat._oldBBox = null;
window.chat.genPostData = function(public, getOlderMsgs) { window.chat.genPostData = function(isFaction, getOlderMsgs) {
if(typeof public !== 'boolean') throw('Need to know if public or faction chat.'); if(typeof isFaction !== 'boolean') throw('Need to know if public or faction chat.');
chat._localRangeCircle.setLatLng(map.getCenter()); chat._localRangeCircle.setLatLng(map.getCenter());
var b = map.getBounds().extend(chat._localRangeCircle.getBounds()); var b = map.getBounds().extend(chat._localRangeCircle.getBounds());
@ -78,35 +67,30 @@ window.chat.genPostData = function(public, getOlderMsgs) {
// need to reset these flags now because clearing will only occur // need to reset these flags now because clearing will only occur
// after the request is finished i.e. there would be one almost // after the request is finished i.e. there would be one almost
// useless request. // useless request.
chat._displayedFactionGuids = []; chat._factionData = {};
chat._displayedPublicGuids = []; chat._publicData = {};
chat._displayedPlayerActionTime = {};
chat._oldFactionTimestamp = -1;
chat._newFactionTimestamp = -1;
chat._oldPublicTimestamp = -1;
chat._newPublicTimestamp = -1;
} }
chat._oldBBox = bbs; chat._oldBBox = bbs;
var ne = b.getNorthEast(); var ne = b.getNorthEast();
var sw = b.getSouthWest(); var sw = b.getSouthWest();
var data = { var data = {
desiredNumItems: public ? CHAT_PUBLIC_ITEMS : CHAT_FACTION_ITEMS, desiredNumItems: isFaction ? CHAT_FACTION_ITEMS : CHAT_PUBLIC_ITEMS ,
minLatE6: Math.round(sw.lat*1E6), minLatE6: Math.round(sw.lat*1E6),
minLngE6: Math.round(sw.lng*1E6), minLngE6: Math.round(sw.lng*1E6),
maxLatE6: Math.round(ne.lat*1E6), maxLatE6: Math.round(ne.lat*1E6),
maxLngE6: Math.round(ne.lng*1E6), maxLngE6: Math.round(ne.lng*1E6),
minTimestampMs: -1, minTimestampMs: -1,
maxTimestampMs: -1, maxTimestampMs: -1,
factionOnly: !public factionOnly: isFaction
} }
if(getOlderMsgs) { if(getOlderMsgs) {
// ask for older chat when scrolling up // ask for older chat when scrolling up
data = $.extend(data, {maxTimestampMs: chat.getOldestTimestamp(public)}); data = $.extend(data, {maxTimestampMs: chat.getOldestTimestamp(isFaction)});
} else { } else {
// ask for newer chat // ask for newer chat
var min = chat.getNewestTimestamp(public); var min = chat.getNewestTimestamp(isFaction);
// the inital request will have both timestamp values set to -1, // the inital request will have both timestamp values set to -1,
// thus we receive the newest desiredNumItems. After that, we will // thus we receive the newest desiredNumItems. After that, we will
// only receive messages with a timestamp greater or equal to min // only receive messages with a timestamp greater or equal to min
@ -130,322 +114,217 @@ window.chat.genPostData = function(public, getOlderMsgs) {
// //
// requesting faction // faction
// //
window.chat._requestOldFactionRunning = false; window.chat._requestFactionRunning = false;
window.chat.requestOldFaction = function(isRetry) { window.chat.requestFaction = function(getOlderMsgs, isRetry) {
if(chat._requestOldFactionRunning) return; if(chat._requestFactionRunning && !isRetry) return;
if(isIdle()) return renderUpdateStatus(); if(isIdle()) return renderUpdateStatus();
chat._requestOldFactionRunning = true; chat._requestFactionRunning = true;
var d = chat.genPostData(false, true); var d = chat.genPostData(true, getOlderMsgs);
var r = window.postAjax( var r = window.postAjax(
'getPaginatedPlextsV2', 'getPaginatedPlextsV2',
d, d,
chat.handleOldFaction, chat.handleFaction,
isRetry isRetry
? function() { window.chat._requestOldFactionRunning = false; } ? function() { window.chat._requestFactionRunning = false; }
: function() { window.chat.requestOldFaction(true) } : function() { window.chat.requestFaction(getOlderMsgs, true) }
);
requests.add(r);
}
window.chat._requestNewFactionRunning = false;
window.chat.requestNewFaction = function(isRetry) {
if(chat._requestNewFactionRunning) return;
if(window.isIdle()) return renderUpdateStatus();
chat._requestNewFactionRunning = true;
var d = chat.genPostData(false, false);
var r = window.postAjax(
'getPaginatedPlextsV2',
d,
chat.handleNewFaction,
isRetry
? function() { window.chat._requestNewFactionRunning = false; }
: function() { window.chat.requestNewFaction(true) }
); );
requests.add(r); requests.add(r);
} }
// window.chat._factionData = {};
// handle faction window.chat.handleFaction = function(data, textStatus, jqXHR) {
// chat._requestFactionRunning = false;
window.chat.handleOldFaction = function(data, textStatus, jqXHR) {
chat._requestOldFactionRunning = false;
chat.handleFaction(data, textStatus, jqXHR, true);
}
window.chat.handleNewFaction = function(data, textStatus, jqXHR) {
chat._requestNewFactionRunning = false;
chat.handleFaction(data, textStatus, jqXHR, false);
}
window.chat._displayedFactionGuids = [];
window.chat.handleFaction = function(data, textStatus, jqXHR, isOldMsgs) {
if(!data || !data.result) { if(!data || !data.result) {
window.failedRequestCount++; window.failedRequestCount++;
return console.warn('faction chat error. Waiting for next auto-refresh.'); return console.warn('faction chat error. Waiting for next auto-refresh.');
} }
var c = $('#chatfaction');
chat.clearIfRequired(c);
if(data.result.length === 0) return; if(data.result.length === 0) return;
chat._newFactionTimestamp = data.result[0][1]; var old = chat.getOldestTimestamp(true);
chat._oldFactionTimestamp = data.result[data.result.length-1][1]; chat.writeDataToHash(data, chat._factionData, false);
var oldMsgsWereAdded = old !== chat.getOldestTimestamp(true);
var scrollBefore = scrollBottom(c); window.chat.renderFaction(oldMsgsWereAdded);
chat.renderPlayerMsgsTo(true, data, isOldMsgs, chat._displayedFactionGuids);
chat.keepScrollPosition(c, scrollBefore, isOldMsgs);
if(data.result.length >= CHAT_FACTION_ITEMS) chat.needMoreMessages(); if(data.result.length >= CHAT_FACTION_ITEMS) chat.needMoreMessages();
} }
window.chat.renderFaction = function(oldMsgsWereAdded) {
chat.renderData(chat._factionData, 'chatfaction', oldMsgsWereAdded);
}
// //
// requesting public // public
// //
window.chat._requestOldPublicRunning = false; window.chat._requestPublicRunning = false;
window.chat.requestOldPublic = function(isRetry) { window.chat.requestPublic = function(getOlderMsgs, isRetry) {
if(chat._requestOldPublicRunning) return; if(chat._requestPublicRunning && !isRetry) return;
if(isIdle()) return renderUpdateStatus(); if(isIdle()) return renderUpdateStatus();
chat._requestOldPublicRunning = true; chat._requestPublicRunning = true;
var d = chat.genPostData(true, true); var d = chat.genPostData(false, getOlderMsgs);
var r = window.postAjax( var r = window.postAjax(
'getPaginatedPlextsV2', 'getPaginatedPlextsV2',
d, d,
chat.handleOldPublic, chat.handlePublic,
isRetry isRetry
? function() { window.chat._requestOldPublicRunning = false; } ? function() { window.chat._requestPublicRunning = false; }
: function() { window.chat.requestOldPublic(true) } : function() { window.chat.requestPublic(getOlderMsgs, true) }
); );
requests.add(r); requests.add(r);
} }
window.chat._requestNewPublicRunning = false; window.chat._publicData = {};
window.chat.requestNewPublic = function(isRetry) { window.chat.handlePublic = function(data, textStatus, jqXHR) {
if(chat._requestNewPublicRunning) return; chat._requestPublicRunning = false;
if(window.isIdle()) return renderUpdateStatus();
chat._requestNewPublicRunning = true;
var d = chat.genPostData(true, false);
var r = window.postAjax(
'getPaginatedPlextsV2',
d,
chat.handleNewPublic,
isRetry
? function() { window.chat._requestNewPublicRunning = false; }
: function() { window.chat.requestNewPublic(true) }
);
requests.add(r);
}
//
// handle public
//
window.chat.handleOldPublic = function(data, textStatus, jqXHR) {
chat._requestOldPublicRunning = false;
chat.handlePublic(data, textStatus, jqXHR, true);
}
window.chat.handleNewPublic = function(data, textStatus, jqXHR) {
chat._requestNewPublicRunning = false;
chat.handlePublic(data, textStatus, jqXHR, false);
}
window.chat._displayedPublicGuids = [];
window.chat._displayedPlayerActionTime = {};
window.chat.handlePublic = function(data, textStatus, jqXHR, isOldMsgs) {
if(!data || !data.result) { if(!data || !data.result) {
window.failedRequestCount++; window.failedRequestCount++;
return console.warn('public chat error. Waiting for next auto-refresh.'); return console.warn('public chat error. Waiting for next auto-refresh.');
} }
var ca = $('#chatautomated');
var cp = $('#chatpublic');
chat.clearIfRequired(ca);
chat.clearIfRequired(cp);
if(data.result.length === 0) return; if(data.result.length === 0) return;
chat._newPublicTimestamp = data.result[0][1]; var old = chat.getOldestTimestamp(true);
chat._oldPublicTimestamp = data.result[data.result.length-1][1]; chat.writeDataToHash(data, chat._publicData, true);
var oldMsgsWereAdded = old !== chat.getOldestTimestamp(true);
switch(chat.getActive()) {
var scrollBefore = scrollBottom(ca); case 'public': window.chat.renderPublic(oldMsgsWereAdded); break;
chat.handlePublicAutomated(data); case 'compact': window.chat.renderCompact(oldMsgsWereAdded); break;
chat.keepScrollPosition(ca, scrollBefore, isOldMsgs); case 'full': window.chat.renderFull(oldMsgsWereAdded); break;
}
var scrollBefore = scrollBottom(cp);
chat.renderPlayerMsgsTo(false, data, isOldMsgs, chat._displayedPublicGuids);
chat.keepScrollPosition(cp, scrollBefore, isOldMsgs);
if(data.result.length >= CHAT_PUBLIC_ITEMS) chat.needMoreMessages(); if(data.result.length >= CHAT_PUBLIC_ITEMS) chat.needMoreMessages();
} }
window.chat.renderPublic = function(oldMsgsWereAdded) {
window.chat.handlePublicAutomated = function(data) { // only keep player data
$.each(data.result, function(ind, json) { // newest first! var data = $.map(chat._publicData, function(entry) {
var time = json[1]; if(!entry[1]) return [entry];
// ignore player messages
var t = json[2].plext.plextType;
if(t !== 'SYSTEM_BROADCAST' && t !== 'SYSTEM_NARROWCAST') return true;
var tmpmsg = '', nick = null, pguid, team;
// each automated message is composed of many text chunks. loop
// over them to gather all necessary data.
$.each(json[2].plext.markup, function(ind, part) {
switch(part[0]) {
case 'PLAYER':
pguid = part[1].guid;
var lastAction = window.chat._displayedPlayerActionTime[pguid];
// ignore older messages about player
if(lastAction && lastAction[0] > time) return false;
nick = part[1].plain;
team = part[1].team === 'ALIENS' ? TEAM_ENL : TEAM_RES;
window.setPlayerName(pguid, nick); // free nick name resolves
if(ind > 0) tmpmsg += nick; // dont repeat nick directly
break;
case 'TEXT':
tmpmsg += part[1].plain;
break;
case 'PORTAL':
var latlng = [part[1].latE6/1E6, part[1].lngE6/1E6];
var js = 'window.zoomToAndShowPortal(\''+part[1].guid+'\', ['+latlng[0]+', '+latlng[1]+'])';
tmpmsg += '<a onclick="'+js+'" title="'+part[1].address+'" class="help">'+part[1].name+'</a>';
break;
}
}); });
chat.renderData(data, 'chatpublic', oldMsgsWereAdded);
}
// nick will only be set if we dont have any info about that window.chat.renderCompact = function(oldMsgsWereAdded) {
// player yet. var data = {};
if(nick) { $.each(chat._publicData, function(guid, entry) {
tmpmsg = chat.renderMsg(tmpmsg, nick, time, team); // skip player msgs
window.chat._displayedPlayerActionTime[pguid] = [time, tmpmsg]; if(!entry[1]) return true;
}; var pguid = entry[3];
// ignore if player has newer data
if(data[pguid] && data[pguid][0] > entry[0]) return true;
data[pguid] = entry;
}); });
// data keys are now player guids instead of message guids. However,
if(chat.getActive() === 'automated') // it is all the same to renderData.
window.chat.renderAutomatedMsgsTo(); chat.renderData(data, 'chatcompact', oldMsgsWereAdded);
} }
window.chat.renderAutomatedMsgsTo = function() { window.chat.renderFull = function(oldMsgsWereAdded) {
var x = window.chat._displayedPlayerActionTime; // only keep automatically generated data
// we dont care about the GUIDs anymore var data = $.map(chat._publicData, function(entry) {
var vals = $.map(x, function(v, k) { return [v]; }); if(entry[1]) return [entry];
// sort them old to new });
vals = vals.sort(function(a, b) { return a[0]-b[0]; }); chat.renderData(data, 'chatfull', oldMsgsWereAdded);
var prevTime = null;
var msgs = $.map(vals, function(v) {
var nowTime = new Date(v[0]).toLocaleDateString();
if(prevTime && prevTime !== nowTime)
var val = chat.renderDivider(nowTime) + v[1];
else
var val = v[1];
prevTime = nowTime;
return val;
}).join('\n');
$('#chatautomated').html(msgs);
} }
// //
// common // common
// //
window.chat.writeDataToHash = function(newData, storageHash, skipSecureMsgs) {
window.chat.renderPlayerMsgsTo = function(isFaction, data, isOldMsgs, dupCheckArr) { $.each(newData.result, function(ind, json) {
var msgs = '';
var prevTime = null;
$.each(data.result.reverse(), function(ind, json) { // oldest first!
if(json[2].plext.plextType !== 'PLAYER_GENERATED') return true;
// avoid duplicates // avoid duplicates
if(dupCheckArr.indexOf(json[0]) !== -1) return true; if(json[0] in storageHash) return true;
dupCheckArr.push(json[0]);
var time = json[1]; var time = json[1];
var team = json[2].plext.team === 'ALIENS' ? TEAM_ENL : TEAM_RES; var team = json[2].plext.team === 'ALIENS' ? TEAM_ENL : TEAM_RES;
var msg, nick, pguid; var auto = json[2].plext.plextType !== 'PLAYER_GENERATED';
var msg = '', nick, pguid;
$.each(json[2].plext.markup, function(ind, markup) { $.each(json[2].plext.markup, function(ind, markup) {
if(markup[0] === 'SENDER') { switch(markup[0]) {
case 'SENDER': // user generated messages
nick = markup[1].plain.slice(0, -2); // cut “: ” at end nick = markup[1].plain.slice(0, -2); // cut “: ” at end
pguid = markup[1].guid; pguid = markup[1].guid;
window.setPlayerName(pguid, nick); // free nick name resolves break;
if(!isOldMsgs) window.chat.addNickForAutocomplete(nick, isFaction);
}
if(markup[0] === 'TEXT') { case 'PLAYER': // automatically generated messages
msg = markup[1].plain.autoLink(); pguid = markup[1].guid;
msg = msg.replace(window.PLAYER['nickMatcher'], '<em>$1</em>'); nick = markup[1].plain;
} team = markup[1].team === 'ALIENS' ? TEAM_ENL : TEAM_RES;
if(ind > 0) msg += nick; // dont repeat nick directly
break;
if(!isFaction && markup[0] === 'SECURE') { case 'TEXT':
var tmp = markup[1].plain.autoLink();
msg += tmp.replace(window.PLAYER['nickMatcher'], '<em>$1</em>');
break;
case 'PORTAL':
var latlng = [markup[1].latE6/1E6, markup[1].lngE6/1E6];
var js = 'window.zoomToAndShowPortal(\''+markup[1].guid+'\', ['+latlng[0]+', '+latlng[1]+'])';
msg += '<a onclick="'+js+'" title="'+markup[1].address+'" class="help">'+markup[1].name+'</a>';
break;
case 'SECURE':
if(skipSecureMsgs) {
nick = null; nick = null;
return false; // aka break return false; // breaks $.each
}
} }
}); });
if(!nick) return true; // aka next if(!nick) return true; // aka next
var nowTime = new Date(time).toLocaleDateString(); // format: timestamp, autogenerated, HTML message, player guid
if(prevTime && prevTime !== nowTime) storageHash[json[0]] = [json[1], auto, chat.renderMsg(msg, nick, time, team), pguid];
msgs += chat.renderDivider(nowTime);
msgs += chat.renderMsg(msg, nick, time, team); window.setPlayerName(pguid, nick); // free nick name resolves
prevTime = nowTime;
}); });
var addTo = isFaction ? $('#chatfaction') : $('#chatpublic');
// if there is a change of day between two requests, handle the
// divider insertion here.
if(isOldMsgs) {
var ts = addTo.find('time:first').data('timestamp');
var nextTime = new Date(ts).toLocaleDateString();
if(prevTime && prevTime !== nextTime && ts)
msgs += chat.renderDivider(nextTime);
} }
if(isOldMsgs) // renders data from the data-hash to the element defined by the given
addTo.prepend(msgs); // ID. Set 3rd argument to true if it is likely that old data has been
else // added. Latter is only required for scrolling.
addTo.append(msgs); window.chat.renderData = function(data, element, likelyWereOldMsgs) {
var elm = $('#'+element);
if(elm.is(':hidden')) return;
// discard guids and sort old to new
var vals = $.map(data, function(v, k) { return [v]; });
vals = vals.sort(function(a, b) { return a[0]-b[0]; });
// render to string with date separators inserted
var msgs = '';
var prevTime = null;
$.each(vals, function(ind, msg) {
var nextTime = new Date(msg[0]).toLocaleDateString();
if(prevTime && prevTime !== nextTime)
msgs += chat.renderDivider(nextTime);
msgs += msg[2];
prevTime = nextTime;
});
var scrollBefore = scrollBottom(elm);
elm.html(msgs);
chat.keepScrollPosition(elm, scrollBefore, likelyWereOldMsgs);
} }
window.chat.renderDivider = function(text) { window.chat.renderDivider = function(text) {
return '<summary>─ '+text+' ────────────────────────────────────────────────────────────────────────────</summary>'; return '<summary>─ '+text+' ───────────────────────────────────────────────────────────</summary>';
} }
@ -486,25 +365,29 @@ window.chat.toggle = function() {
window.chat.request = function() { window.chat.request = function() {
console.log('refreshing chat'); console.log('refreshing chat');
chat.requestNewFaction(); chat.requestFaction(false);
chat.requestNewPublic(); chat.requestPublic(false);
} }
// checks if there are enough messages in the selected chat tab and // checks if there are enough messages in the selected chat tab and
// loads more if not. // loads more if not.
window.chat.needMoreMessages = function() { window.chat.needMoreMessages = function() {
var activeChat = $('#chat > :visible'); var activeTab = chat.getActive();
if(scrollBottom(activeChat) !== 0 || activeChat.scrollTop() !== 0) return;
var activeTab = $('#chatcontrols .active').text();
if(activeTab === 'debug') return; if(activeTab === 'debug') return;
console.log('no scrollbar in active chat, requesting more msgs'); var activeChat = $('#chat > :visible');
var hasScrollbar = scrollBottom(activeChat) !== 0 || activeChat.scrollTop() !== 0;
var nearTop = activeChat.scrollTop() <= CHAT_REQUEST_SCROLL_TOP;
if(hasScrollbar && !nearTop) return;
console.log('No scrollbar or near top in active chat. Requesting more data.');
if(activeTab === 'faction') if(activeTab === 'faction')
chat.requestOldFaction(); chat.requestFaction(true);
else else
chat.requestOldPublic(); chat.requestPublic(true);
} }
@ -525,26 +408,26 @@ window.chat.chooser = function(event) {
case 'faction': case 'faction':
span.css('color', ''); span.css('color', '');
span.text('tell faction:'); span.text('tell faction:');
elm = $('#chatfaction');
break; break;
case 'public': case 'public':
span.css('cssText', 'color: red !important'); span.css('cssText', 'color: red !important');
span.text('broadcast:'); span.text('broadcast:');
elm = $('#chatpublic');
break; break;
case 'automated': case 'compact':
case 'full':
span.css('cssText', 'color: #bbb !important'); span.css('cssText', 'color: #bbb !important');
span.text('tell Jarvis:'); span.text('tell Jarvis:');
chat.renderAutomatedMsgsTo();
elm = $('#chatautomated');
break; break;
default:
throw('chat.chooser was asked to handle unknown button: ' + tt);
} }
if(!elm) throw('chat button handled by chat.chooser, yet it is null'); var elm = $('#chat' + tt);
elm.show(); elm.show();
eval('chat.render' + tt.capitalize() + '(false);');
if(elm.data('needsScrollTop')) { if(elm.data('needsScrollTop')) {
elm.data('ignoreNextScroll', true); elm.data('ignoreNextScroll', true);
elm.scrollTop(elm.data('needsScrollTop')); elm.scrollTop(elm.data('needsScrollTop'));
@ -588,7 +471,7 @@ window.chat.setup = function() {
$('#chatcontrols a:first').click(window.chat.toggle); $('#chatcontrols a:first').click(window.chat.toggle);
$('#chatcontrols a').each(function(ind, elm) { $('#chatcontrols a').each(function(ind, elm) {
if($.inArray($(elm).text(), ['automated', 'public', 'faction']) !== -1) if($.inArray($(elm).text(), ['full', 'compact', 'public', 'faction']) !== -1)
$(elm).click(window.chat.chooser); $(elm).click(window.chat.chooser);
}); });
@ -603,15 +486,15 @@ window.chat.setup = function() {
$('#chatfaction').scroll(function() { $('#chatfaction').scroll(function() {
var t = $(this); var t = $(this);
if(t.data('ignoreNextScroll')) return t.data('ignoreNextScroll', false); if(t.data('ignoreNextScroll')) return t.data('ignoreNextScroll', false);
if(t.scrollTop() < 200) chat.requestOldFaction(); if(t.scrollTop() < CHAT_REQUEST_SCROLL_TOP) chat.requestFaction(true);
if(scrollBottom(t) === 0) chat.requestNewFaction(); if(scrollBottom(t) === 0) chat.requestFaction(false);
}); });
$('#chatpublic, #chatautomated').scroll(function() { $('#chatpublic, #chatfull, #chatcompact').scroll(function() {
var t = $(this); var t = $(this);
if(t.data('ignoreNextScroll')) return t.data('ignoreNextScroll', false); if(t.data('ignoreNextScroll')) return t.data('ignoreNextScroll', false);
if(t.scrollTop() < 200) chat.requestOldPublic(); if(t.scrollTop() < CHAT_REQUEST_SCROLL_TOP) chat.requestPublic(true);
if(scrollBottom(t) === 0) chat.requestNewPublic(); if(scrollBottom(t) === 0) chat.requestPublic(false);
}); });
chat.request(); chat.request();
@ -670,7 +553,8 @@ window.chat.setupPosting = function() {
window.chat.postMsg = function() { window.chat.postMsg = function() {
var c = chat.getActive(); var c = chat.getActive();
if(c === 'automated') return alert('Jarvis: A strange game. The only winning move is not to play. How about a nice game of chess?'); if(c === 'full' || c === 'compact')
return alert('Jarvis: A strange game. The only winning move is not to play. How about a nice game of chess?');
var msg = $.trim($('#chatinput input').val()); var msg = $.trim($('#chatinput input').val());
if(!msg || msg === '') return; if(!msg || msg === '') return;
@ -691,7 +575,7 @@ window.chat.postMsg = function() {
window.postAjax('sendPlext', data, window.postAjax('sendPlext', data,
function(response) { function(response) {
if(response.error) alert(errMsg); if(response.error) alert(errMsg);
if(public) chat.requestNewPublic(); else chat.requestNewFaction(); }, if(public) chat.requestPublic(false); else chat.requestFaction(false); },
function() { function() {
alert(errMsg); alert(errMsg);
} }

View File

@ -25,10 +25,8 @@ window.requests.abort = function() {
window.activeRequests = []; window.activeRequests = [];
window.failedRequestCount = 0; window.failedRequestCount = 0;
window.chat._requestOldPublicRunning = false; window.chat._requestPublicRunning = false;
window.chat._requestNewPublicRunning = false; window.chat._requestFactionRunning = false;
window.chat._requestOldFactionRunning = false;
window.chat._requestNewFactionRunning = false;
renderUpdateStatus(); renderUpdateStatus();
} }

12
main.js
View File

@ -62,12 +62,14 @@ document.getElementsByTagName('head')[0].innerHTML = ''
document.getElementsByTagName('body')[0].innerHTML = '' document.getElementsByTagName('body')[0].innerHTML = ''
+ '<div id="map">Loading, please wait</div>' + '<div id="map">Loading, please wait</div>'
+ '<div id="chatcontrols" style="display:none">' + '<div id="chatcontrols" style="display:none">'
+ ' <a><span class="toggle expand"></span></a><a>automated</a><a>public</a><a class="active">faction</a>' + ' <a><span class="toggle expand"></span></a>'
+ '<a>full</a><a>compact</a><a>public</a><a class="active">faction</a>'
+ '</div>' + '</div>'
+ '<div id="chat" style="display:none">' + '<div id="chat" style="display:none">'
+ ' <div id="chatfaction"></div>' + ' <div id="chatfaction"></div>'
+ ' <div id="chatpublic"></div>' + ' <div id="chatpublic"></div>'
+ ' <div id="chatautomated"></div>' + ' <div id="chatcompact"></div>'
+ ' <div id="chatfull"></div>'
+ '</div>' + '</div>'
+ '<form id="chatinput" style="display:none"><time></time><span>tell faction:</span><input type="text"/></form>' + '<form id="chatinput" style="display:none"><time></time><span>tell faction:</span><input type="text"/></form>'
+ '<a id="sidebartoggle"><span class="toggle close"></span></a>' + '<a id="sidebartoggle"><span class="toggle close"></span></a>'
@ -115,8 +117,10 @@ var CHAT_MIN_RANGE = 6;
var VIEWPORT_PAD_RATIO = 0.3; var VIEWPORT_PAD_RATIO = 0.3;
// how many items to request each query // how many items to request each query
var CHAT_PUBLIC_ITEMS = 200 var CHAT_PUBLIC_ITEMS = 200;
var CHAT_FACTION_ITEMS = 50 var CHAT_FACTION_ITEMS = 50;
// how many pixels to the top before requesting new data
var CHAT_REQUEST_SCROLL_TOP = 200;
// Leaflet will get very slow for MANY items. Its better to display // Leaflet will get very slow for MANY items. Its better to display
// only some instead of crashing the browser. // only some instead of crashing the browser.

View File

@ -191,7 +191,7 @@ em {
top: 25px; top: 25px;
} }
#chatpublic, #chatautomated { #chatpublic, #chatfull, #chatcompact, /* FIXME DEPRECATED: */#chatautomated {
display: none; display: none;
} }