finish chat feature; hide low level portal on zoom out; introduce render limit

This commit is contained in:
Stefan Breunig 2013-02-04 02:52:24 +01:00
parent ecfaca7f9b
commit f92c963a54
9 changed files with 639 additions and 310 deletions

View File

@ -1,5 +1,3 @@
*NOTE: this is a work in progress and not yet finished. *
ingress.com/intel total conversion ingress.com/intel total conversion
================================== ==================================
@ -8,6 +6,31 @@ Its annoying to extend the intel page with new features because the minified
So instead, heres a userscript that starts from scratch. So instead, heres a userscript that starts from scratch.
Features
--------
- feels faster. (Likely because [leaflet](http://leafletjs.com/) is faster, although there are some other tricks.)
full view of portal images
- better chat
- separated automated/public/faction
- only showing the last automated message for each user. Makes a great “where are they now” guide.
- automatic idle resume
- portal details actually update themselves
- links to portals made easy (the location/zoom part is supported by the normal intel map as well, so theres *some* backwards compability)
- info porn. Everything with the help cursor has more info hidden in a tooltip.
- may toggle portals/links/fields
- hack range (yellow circle) and link range (large red circle) for portals. You can click on the range link in the sidebar to zoom to link range.
- double clicking a portal zooms in and focuses it
Missing
-------
(and probably not going to implement it)
- logout link (but you wouldnt want to *quit*, would you?), privacy link, etc.
- redeem pretty display
Install Install
------- -------

View File

@ -1,5 +1,9 @@
window.chat = function() {}; window.chat = function() {};
//
// timestamp and clear management
//
window.chat._oldFactionTimestamp = -1; window.chat._oldFactionTimestamp = -1;
window.chat._newFactionTimestamp = -1; window.chat._newFactionTimestamp = -1;
window.chat._oldPublicTimestamp = -1; window.chat._oldPublicTimestamp = -1;
@ -13,8 +17,27 @@ window.chat.getNewestTimestamp = function(public) {
return chat['_new'+(public ? 'Public' : 'Faction')+'Timestamp']; return chat['_new'+(public ? 'Public' : 'Faction')+'Timestamp'];
} }
window.chat._needsClearing = false; window.chat._needsClearing = false;
window.chat.clear = function() {
console.log('clearing now');
window.chat._displayedFactionGuids = [];
window.chat._displayedPublicGuids = [];
window.chat._displayedPlayerActionTime = {};
window.chat._oldFactionTimestamp = -1;
window.chat._newFactionTimestamp = -1;
window.chat._oldPublicTimestamp = -1;
window.chat._newPublicTimestamp = -1;
$('#chatfaction, #chatpublic, #chatautomated').data('ignoreNextScroll', true).html('');
}
window.chat.clearIfRequired = function() {
if(!chat._needsClearing) return;
chat.clear();
chat._needsClearing = false;
}
window.chat._oldBBox = null; window.chat._oldBBox = null;
window.chat.genPostData = function(public, getOlderMsgs) { window.chat.genPostData = function(public, getOlderMsgs) {
if(typeof public !== 'boolean') throw('Need to know if public or faction chat.'); if(typeof public !== 'boolean') throw('Need to know if public or faction chat.');
@ -23,14 +46,14 @@ window.chat.genPostData = function(public, getOlderMsgs) {
var b = map.getBounds().extend(chat._localRangeCircle.getBounds()); var b = map.getBounds().extend(chat._localRangeCircle.getBounds());
var bbs = b.toBBoxString(); var bbs = b.toBBoxString();
chat._needsClearing = chat._oldBBox && chat._oldBBox !== bbs; chat._needsClearing = chat._needsClearing || chat._oldBBox && chat._oldBBox !== bbs;
if(chat._needsClearing) console.log('Bounding Box changed, chat will be cleared (old: '+chat._oldBBox+' ; new: '+bbs+' )'); if(chat._needsClearing) console.log('Bounding Box changed, chat will be cleared (old: '+chat._oldBBox+' ; new: '+bbs+' )');
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 ? 100 : 50, // public contains so much crap desiredNumItems: public ? CHAT_PUBLIC_ITEMS : CHAT_FACTION_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),
@ -66,6 +89,8 @@ window.chat.genPostData = function(public, getOlderMsgs) {
return data; return data;
} }
// //
// requesting faction // requesting faction
// //
@ -108,6 +133,7 @@ window.chat.requestNewFaction = function(isRetry) {
requests.add(r); requests.add(r);
} }
// //
// handle faction // handle faction
// //
@ -122,6 +148,8 @@ window.chat.handleNewFaction = function(data, textStatus, jqXHR) {
chat.handleFaction(data, textStatus, jqXHR, false); chat.handleFaction(data, textStatus, jqXHR, false);
} }
window.chat._displayedFactionGuids = []; window.chat._displayedFactionGuids = [];
window.chat.handleFaction = function(data, textStatus, jqXHR, isOldMsgs) { window.chat.handleFaction = function(data, textStatus, jqXHR, isOldMsgs) {
if(!data || !data.result) { if(!data || !data.result) {
@ -129,55 +157,25 @@ window.chat.handleFaction = function(data, textStatus, jqXHR, isOldMsgs) {
return console.warn('faction chat error. Waiting for next auto-refresh.'); return console.warn('faction chat error. Waiting for next auto-refresh.');
} }
chat.clearIfRequired();
if(data.result.length === 0) return;
chat._newFactionTimestamp = data.result[0][1]; chat._newFactionTimestamp = data.result[0][1];
chat._oldFactionTimestamp = data.result[data.result.length-1][1]; chat._oldFactionTimestamp = data.result[data.result.length-1][1];
chat.clearIfRequired();
var msgs = '';
var prevTime = null;
$.each(data.result.reverse(), function(ind, json) { // oldest first!
// avoid duplicates
if(window.chat._displayedFactionGuids.indexOf(json[0]) !== -1) return;
window.chat._displayedFactionGuids.push(json[0]);
var time = json[1];
var msg = json[2].plext.markup[2][1].plain;
var team = json[2].plext.team === 'ALIENS' ? TEAM_ENL : TEAM_RES;
var nick = json[2].plext.markup[1][1].plain.slice(0, -2); // cut “: ” at end
var pguid = json[2].plext.markup[1][1].guid;
window.setPlayerName(pguid, nick); // free nick name resolves
var nowTime = new Date(time).toLocaleDateString();
if(prevTime && prevTime !== nowTime)
msgs += chat.renderDivider(nowTime);
msgs += chat.renderMsg(msg, nick, time, team);
prevTime = nowTime;
});
// if there is a change of day between two requests, handle the
// divider insertion here.
if(isOldMsgs) {
var ts = $('#chatfaction time:first').data('timestamp');
var nextTime = new Date(ts).toLocaleDateString();
if(prevTime && prevTime !== nextTime && ts)
msgs += chat.renderDivider(nextTime);
}
var c = $('#chatfaction'); var c = $('#chatfaction');
var scrollBefore = scrollBottom(c); var scrollBefore = scrollBottom(c);
if(isOldMsgs) chat.renderPlayerMsgsTo(true, data, isOldMsgs, chat._displayedFactionGuids);
c.prepend(msgs);
else
c.append(msgs);
chat.keepScrollPosition(c, scrollBefore, isOldMsgs); chat.keepScrollPosition(c, scrollBefore, isOldMsgs);
chat.needMoreMessages();
if(data.result.length >= CHAT_FACTION_ITEMS) chat.needMoreMessages();
} }
// //
// requesting public // requesting public
// //
@ -244,25 +242,27 @@ window.chat.handlePublic = function(data, textStatus, jqXHR, isOldMsgs) {
return console.warn('public chat error. Waiting for next auto-refresh.'); return console.warn('public chat error. Waiting for next auto-refresh.');
} }
chat.clearIfRequired();
if(data.result.length === 0) return;
chat._newPublicTimestamp = data.result[0][1]; chat._newPublicTimestamp = data.result[0][1];
chat._oldPublicTimestamp = data.result[data.result.length-1][1]; chat._oldPublicTimestamp = data.result[data.result.length-1][1];
chat.clearIfRequired(); var c = $('#chatautomated');
var c = $('#chat > div:visible');
var scrollBefore = scrollBottom(c); var scrollBefore = scrollBottom(c);
chat.handlePublicAutomated(data); chat.handlePublicAutomated(data);
//chat.handlePublicPlayer(data, isOldMsgs);
chat.keepScrollPosition(c, scrollBefore, isOldMsgs); chat.keepScrollPosition(c, scrollBefore, isOldMsgs);
chat.needMoreMessages();
c = $('#chatpublic');
var scrollBefore = scrollBottom(c);
chat.renderPlayerMsgsTo(false, data, isOldMsgs, chat._displayedPublicGuids);
chat.keepScrollPosition(c, scrollBefore, isOldMsgs);
if(data.result.length >= CHAT_PUBLIC_ITEMS) chat.needMoreMessages();
} }
window.chat.handlePublicAutomated = function(data) { window.chat.handlePublicAutomated = function(data) {
$.each(data.result, function(ind, json) { // newest first! $.each(data.result, function(ind, json) { // newest first!
var time = json[1]; var time = json[1];
@ -310,14 +310,10 @@ window.chat.handlePublicAutomated = function(data) {
}); });
if(chat.getActive() === 'automated') if(chat.getActive() === 'automated')
window.chat.renderAutomatedMsgsToBox(); window.chat.renderAutomatedMsgsTo();
} }
window.chat.getActive = function() { window.chat.renderAutomatedMsgsTo = function() {
return $('#chatcontrols .active').text();
}
window.chat.renderAutomatedMsgsToBox = function() {
var x = window.chat._displayedPlayerActionTime; var x = window.chat._displayedPlayerActionTime;
// we dont care about the GUIDs anymore // we dont care about the GUIDs anymore
var vals = $.map(x, function(v, k) { return [v]; }); var vals = $.map(x, function(v, k) { return [v]; });
@ -342,24 +338,89 @@ window.chat.renderAutomatedMsgsToBox = function() {
window.chat.clear = function() { //
console.log('clearing now'); // common
window.chat._displayedFactionGuids = []; //
window.chat._displayedPublicGuids = [];
window.chat._displayedPlayerActionTime = {};
window.chat._oldFactionTimestamp = -1; window.chat.renderPlayerMsgsTo = function(isFaction, data, isOldMsgs, dupCheckArr) {
window.chat._newFactionTimestamp = -1; var msgs = '';
window.chat._oldPublicTimestamp = -1; var prevTime = null;
window.chat._newPublicTimestamp = -1;
$('#chatfaction, #chatpublic, #chatautomated').data('ignoreNextScroll', true).html(''); $.each(data.result.reverse(), function(ind, json) { // oldest first!
if(json[2].plext.plextType !== 'PLAYER_GENERATED') return true;
// avoid duplicates
if(dupCheckArr.indexOf(json[0]) !== -1) return true;
dupCheckArr.push(json[0]);
var time = json[1];
var team = json[2].plext.team === 'ALIENS' ? TEAM_ENL : TEAM_RES;
var msg, nick, pguid;
$.each(json[2].plext.markup, function(ind, markup) {
if(markup[0] === 'SENDER') {
nick = markup[1].plain.slice(0, -2); // cut “: ” at end
pguid = markup[1].guid;
window.setPlayerName(pguid, nick); // free nick name resolves
}
if(markup[0] === 'TEXT') msg = markup[1].plain;
if(!isFaction && markup[0] === 'SECURE') {
nick = null;
return false; // aka break
}
});
if(!nick) return true; // aka next
var nowTime = new Date(time).toLocaleDateString();
if(prevTime && prevTime !== nowTime)
msgs += chat.renderDivider(nowTime);
msgs += chat.renderMsg(msg, nick, time, team);
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)
addTo.prepend(msgs);
else
addTo.append(msgs);
} }
window.chat.clearIfRequired = function() {
if(!chat._needsClearing) return; window.chat.renderDivider = function(text) {
chat.clear(); return '<summary>─ '+text+' ────────────────────────────────────────────────────────────────────────────</summary>';
chat._needsClearing = false;
} }
window.chat.renderMsg = function(msg, nick, time, team) {
var ta = unixTimeToHHmm(time);
var tb = unixTimeToString(time, true);
var t = '<time title="'+tb+'" data-timestamp="'+time+'">'+ta+'</time>';
var s = 'style="color:'+COLORS[team]+'"';
var title = nick.length >= 8 ? 'title="'+nick+'"' : '';
return '<p>'+t+'<mark '+s+'>'+nick+'</mark><span>'+msg+'</span></p>';
}
window.chat.getActive = function() {
return $('#chatcontrols .active').text();
}
window.chat.toggle = function() { window.chat.toggle = function() {
var c = $('#chat, #chatcontrols'); var c = $('#chat, #chatcontrols');
if(c.hasClass('expand')) { if(c.hasClass('expand')) {
@ -375,12 +436,14 @@ window.chat.toggle = function() {
} }
} }
window.chat.request = function() { window.chat.request = function() {
console.log('refreshing chat'); console.log('refreshing chat');
chat.requestNewFaction(); chat.requestNewFaction();
chat.requestNewPublic(); chat.requestNewPublic();
} }
// 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() {
@ -393,19 +456,62 @@ window.chat.needMoreMessages = function() {
chat.requestOldPublic(); chat.requestOldPublic();
} }
window.chat.setupTime = function() {
var inputTime = $('#chatinput time'); window.chat.chooser = function(event) {
var updateTime = function() { var t = $(event.target);
if(window.isIdle()) return; var tt = t.text();
var d = new Date(); var span = $('#chatinput span');
inputTime.text(d.toLocaleTimeString().slice(0, 5));
// update ON the minute (1ms after) $('#chatcontrols .active').removeClass('active');
setTimeout(updateTime, (60 - d.getSeconds()) * 1000 + 1); t.addClass('active');
};
updateTime(); $('#chat > div').hide();
window.addResumeFunction(updateTime);
switch(tt) {
case 'faction':
span.css('color', '');
span.text('tell faction:');
$('#chatfaction').show();
break;
case 'public':
span.css('cssText', 'color: red !important');
span.text('tell public:');
$('#chatpublic').show();
break;
case 'automated':
span.css('cssText', 'color: #bbb !important');
span.text('tell Jarvis:');
chat.renderAutomatedMsgsTo();
$('#chatautomated').show();
break;
}
chat.needMoreMessages();
} }
// contains the logic to keep the correct scroll position.
window.chat.keepScrollPosition = function(box, scrollBefore, isOldMsgs) {
// If scrolled down completely, keep it that way so new messages can
// be seen easily. If scrolled up, only need to fix scroll position
// when old messages are added. New messages added at the bottom dont
// change the view and enabling this would make the chat scroll down
// for every added message, even if the user wants to read old stuff.
if(scrollBefore === 0 || isOldMsgs) {
box.data('ignoreNextScroll', true);
box.scrollTop(box.scrollTop() + (scrollBottom(box)-scrollBefore));
}
}
//
// setup
//
window.chat.setup = function() { window.chat.setup = function() {
window.chat._localRangeCircle = L.circle(map.getCenter(), CHAT_MIN_RANGE*1000); window.chat._localRangeCircle = L.circle(map.getCenter(), CHAT_MIN_RANGE*1000);
@ -420,6 +526,7 @@ window.chat.setup = function() {
}); });
window.chat.setupTime(); window.chat.setupTime();
window.chat.setupPosting();
$('#chatfaction').scroll(function() { $('#chatfaction').scroll(function() {
var t = $(this); var t = $(this);
@ -444,61 +551,61 @@ window.chat.setup = function() {
} }
window.chat.renderMsg = function(msg, nick, time, team) { window.chat.setupTime = function() {
var ta = unixTimeToHHmm(time); var inputTime = $('#chatinput time');
var tb = unixTimeToString(time, true); var updateTime = function() {
var t = '<time title="'+tb+'" data-timestamp="'+time+'">'+ta+'</time>'; if(window.isIdle()) return;
var s = 'style="color:'+COLORS[team]+'"'; var d = new Date();
var title = nick.length >= 8 ? 'title="'+nick+'"' : ''; inputTime.text(d.toLocaleTimeString().slice(0, 5));
return '<p>'+t+'<mark '+s+'>'+nick+'</mark><span>'+msg+'</span></p>'; // update ON the minute (1ms after)
setTimeout(updateTime, (60 - d.getSeconds()) * 1000 + 1);
};
updateTime();
window.addResumeFunction(updateTime);
} }
window.chat.renderDivider = function(text) {
return '<summary>─ '+text+' ────────────────────────────────────────────────────────────────────────────</summary>'; //
// posting
//
window.chat.setupPosting = function() {
$('#chatinput input').keypress(function(e) {
if((e.keyCode ? e.keyCode : e.which) != 13) return;
chat.postMsg();
e.preventDefault();
});
$('#chatinput').submit(function(e) {
chat.postMsg();
e.preventDefault();
});
} }
window.chat.chooser = function(event) {
var t = $(event.target);
var tt = t.text();
var span = $('#chatinput span');
$('#chatcontrols .active').removeClass('active'); window.chat.postMsg = function() {
t.addClass('active'); 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?');
$('#chat > div').hide(); var msg = $.trim($('#chatinput input').val());
if(!msg || msg === '') return;
switch(tt) { var public = c === 'public';
case 'faction': var latlng = map.getCenter();
span.css('color', '');
span.text('tell faction:');
$('#chatfaction').show();
break;
case 'public': var data = {message: msg,
span.css('cssText', 'color: red !important'); latE6: Math.round(latlng.lat*1E6),
span.text('spam public:'); lngE6: Math.round(latlng.lng*1E6),
$('#chatpublic').show(); factionOnly: !public};
break;
case 'automated': window.postAjax('sendPlext', data,
span.css('cssText', 'color: #bbb !important'); function() { if(public) chat.requestNewPublic(); else chat.requestNewFaction(); },
span.text('tell Jarvis:'); function() {
chat.renderAutomatedMsgsToBox(); alert('Your message could not be delivered. You can copy&' +
$('#chatautomated').show(); 'paste it here and try again if you want:\n\n'+msg);
break;
} }
} );
$('#chatinput input').val('');
// contains the logic to keep the correct scroll position.
window.chat.keepScrollPosition = function(box, scrollBefore, isOldMsgs) {
// If scrolled down completely, keep it that way so new messages can
// be seen easily. If scrolled up, only need to fix scroll position
// when old messages are added. New messages added at the bottom dont
// change the view and enabling this would make the chat scroll down
// for every added message, even if the user wants to read old stuff.
if(scrollBefore === 0 || isOldMsgs) {
box.data('ignoreNextScroll', true);
box.scrollTop(box.scrollTop() + (scrollBottom(box)-scrollBefore));
}
} }

View File

@ -3,7 +3,7 @@
window.idleTime = 0; // in minutes window.idleTime = 0; // in minutes
setInterval('window.idleTime += 1', 60*1000); setInterval('window.idleTime += 1', 60*1000);
var idleReset = function (e) { var idleReset = function () {
// update immediately when the user comes back // update immediately when the user comes back
if(isIdle()) { if(isIdle()) {
window.idleTime = 0; window.idleTime = 0;

View File

@ -111,8 +111,12 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
window.cleanUp = function() { window.cleanUp = function() {
var cnt = [0,0,0]; var cnt = [0,0,0];
var b = getPaddedBounds(); var b = getPaddedBounds();
var minlvl = getMinPortalLevel();
portalsLayer.eachLayer(function(portal) { portalsLayer.eachLayer(function(portal) {
if(b.contains(portal.getLatLng())) return; // portal must be in bounds and have a high enough level. Also dont
// remove if it is selected.
if(portal.options.guid == window.selectedPortal ||
(b.contains(portal.getLatLng()) && portal.options.level >= minlvl)) return;
cnt[0]++; cnt[0]++;
portalsLayer.removeLayer(portal); portalsLayer.removeLayer(portal);
}); });
@ -154,7 +158,7 @@ window.removeByGuid = function(guid) {
break; break;
default: default:
console.warn('unknown GUID type: ' + guid); console.warn('unknown GUID type: ' + guid);
window.debug.printStackTrace(); //window.debug.printStackTrace();
} }
} }
@ -163,9 +167,17 @@ window.removeByGuid = function(guid) {
// renders a portal on the map from the given entity // renders a portal on the map from the given entity
window.renderPortal = function(ent) { window.renderPortal = function(ent) {
removeByGuid(ent[0]); removeByGuid(ent[0]);
if(Object.keys(portals).length >= MAX_DRAWN_PORTALS && ent[0] != selectedPortal)
return;
var latlng = [ent[2].locationE6.latE6/1E6, ent[2].locationE6.lngE6/1E6]; var latlng = [ent[2].locationE6.latE6/1E6, ent[2].locationE6.lngE6/1E6];
if(!getPaddedBounds().contains(latlng)) return; if(!getPaddedBounds().contains(latlng)) return;
// hide low level portals on low zooms
var portalLevel = getPortalLevel(ent[2]);
if(portalLevel < getMinPortalLevel() && ent[0] != selectedPortal) return;
// pre-load player names for high zoom levels // pre-load player names for high zoom levels
if(map.getZoom() >= PRECACHE_PLAYER_NAMES_ZOOM) { if(map.getZoom() >= PRECACHE_PLAYER_NAMES_ZOOM) {
if(ent[2].captured && ent[2].captured.capturingPlayerId) if(ent[2].captured && ent[2].captured.capturingPlayerId)
@ -186,6 +198,7 @@ window.renderPortal = function(ent) {
fillColor: COLORS[team], fillColor: COLORS[team],
fillOpacity: 0.5, fillOpacity: 0.5,
clickable: true, clickable: true,
level: portalLevel,
guid: ent[0]}); guid: ent[0]});
p.on('remove', function() { delete window.portals[this.options.guid]; }); p.on('remove', function() { delete window.portals[this.options.guid]; });
@ -201,6 +214,8 @@ window.renderPortal = function(ent) {
// renders a link on the map from the given entity // renders a link on the map from the given entity
window.renderLink = function(ent) { window.renderLink = function(ent) {
removeByGuid(ent[0]); removeByGuid(ent[0]);
if(Object.keys(links).length >= MAX_DRAWN_LINKS) return;
var team = getTeam(ent[2]); var team = getTeam(ent[2]);
var edge = ent[2].edge; var edge = ent[2].edge;
var latlngs = [ var latlngs = [
@ -209,10 +224,11 @@ window.renderLink = function(ent) {
]; ];
var poly = L.polyline(latlngs, { var poly = L.polyline(latlngs, {
color: COLORS[team], color: COLORS[team],
opacity: 0.5, opacity: 1,
weight:2, weight:2,
clickable: false, clickable: false,
guid: ent[0] guid: ent[0],
smoothFactor: 10
}); });
if(!getPaddedBounds().intersects(poly.getBounds())) return; if(!getPaddedBounds().intersects(poly.getBounds())) return;
@ -225,6 +241,8 @@ window.renderLink = function(ent) {
// renders a field on the map from a given entity // renders a field on the map from a given entity
window.renderField = function(ent) { window.renderField = function(ent) {
window.removeByGuid(ent[0]); window.removeByGuid(ent[0]);
if(Object.keys(fields).length >= MAX_DRAWN_FIELDS) return;
var team = getTeam(ent[2]); var team = getTeam(ent[2]);
var reg = ent[2].capturedRegion; var reg = ent[2].capturedRegion;
var latlngs = [ var latlngs = [
@ -237,6 +255,7 @@ window.renderField = function(ent) {
fillOpacity: 0.25, fillOpacity: 0.25,
stroke: false, stroke: false,
clickable: false, clickable: false,
smoothFactor: 10,
guid: ent[0]}); guid: ent[0]});
if(!getPaddedBounds().intersects(poly.getBounds())) return; if(!getPaddedBounds().intersects(poly.getBounds())) return;

View File

@ -30,11 +30,11 @@ window.renderPortalDetails = function(guid) {
// collect and html-ify random data // collect and html-ify random data
var randDetails = [playerText, sinceText, getRangeText(d), getEnergyText(d), linksText, getAvgResoDistText(d)]; var randDetails = [playerText, sinceText, getRangeText(d), getEnergyText(d), linksText, getAvgResoDistText(d)];
randDetails = randDetails.map(function(e) { randDetails = randDetails.map(function(detail) {
if(!e) return ''; if(!detail) return '';
e = e.split(':'); detail = detail.split(':');
e = '<aside>'+e.shift()+'<span>'+e.join(':')+'</span></aside>'; detail = '<aside>'+detail.shift()+'<span>'+detail.join(':')+'</span></aside>';
return e; return detail;
}).join('\n'); }).join('\n');
// replacing causes flicker, so if the selected portal does not // replacing causes flicker, so if the selected portal does not

View File

@ -46,16 +46,18 @@ window.renderUpdateStatus = function() {
else else
t += 'Up to date.'; t += 'Up to date.';
if(renderLimitReached())
t += ' <span style="color:red" title="Can only render so much before it gets unbearably slow. Not all entities are shown. Zoom in or increase the limit (search for MAX_DRAWN_*).">RENDER LIMIT</span> '
if(window.failedRequestCount > 0) if(window.failedRequestCount > 0)
t += ' ' + window.failedRequestCount + ' requests failed.' t += ' ' + window.failedRequestCount + ' requests failed.'
t += '<br/><span title="not removing portals as long as you keep them in view, though">('; t += '<br/>(';
var conv = ['impossible', 8,8,7,7,6,6,5,5,4,4,3,3,2,2,1]; var minlvl = getMinPortalLevel();
var z = map.getZoom(); if(minlvl === 0)
if(z >= 16) t += 'showing all portals';
t += 'requesting all portals';
else else
t+= 'only requesting portals with level '+conv[z]+' and up'; t+= 'only showing portals with level '+minlvl+' and up';
t += ')</span>'; t += ')</span>';
$('#updatestatus').html(t); $('#updatestatus').html(t);

View File

@ -107,11 +107,26 @@ window.getPaddedBounds = function() {
}); });
} }
if(window._storedPaddedBounds) return window._storedPaddedBounds; if(window._storedPaddedBounds) return window._storedPaddedBounds;
var p = window.map.getBounds().pad(VIEWPORT_PAD_RATIO); var p = window.map.getBounds().pad(VIEWPORT_PAD_RATIO);
window._storedPaddedBounds = p; window._storedPaddedBounds = p;
return p; return p;
} }
window.renderLimitReached = function() {
if(Object.keys(portals).length >= MAX_DRAWN_PORTALS) return true;
if(Object.keys(links).length >= MAX_DRAWN_LINKS) return true;
if(Object.keys(fields).length >= MAX_DRAWN_FIELDS) return true;
return false;
}
window.getMinPortalLevel = function() {
var z = map.getZoom();
if(z >= 16) return 0;
var conv = ['impossible', 8,7,7,6,6,5,5,4,4,3,3,2,2,1,1];
return conv[z];
}
// returns number of pixels left to scroll down before reaching the // returns number of pixels left to scroll down before reaching the
// bottom. Works similar to the native scrollTop function. // bottom. Works similar to the native scrollTop function.

12
main.js
View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @id ingress-intel-total-conversion@breunigs // @id ingress-intel-total-conversion@breunigs
// @name intel map total conversion // @name intel map total conversion
// @version 0.1-@@BUILDDATE@@ // @version 0.2-@@BUILDDATE@@
// @namespace https://github.com/breunigs/ingress-intel-total-conversion // @namespace https://github.com/breunigs/ingress-intel-total-conversion
// @updateURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/total-conversion-build.user.js // @updateURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/total-conversion-build.user.js
// @downloadURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/total-conversion-build.user.js // @downloadURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/total-conversion-build.user.js
@ -94,6 +94,16 @@ var CHAT_MIN_RANGE = 6;
// high causes too many items to be drawn, making drag&drop sluggish. // high causes too many items to be drawn, making drag&drop sluggish.
var VIEWPORT_PAD_RATIO = 0.3; var VIEWPORT_PAD_RATIO = 0.3;
// how many items to request each query
var CHAT_PUBLIC_ITEMS = 200
var CHAT_FACTION_ITEMS = 50
// Leaflet will get very slow for MANY items. Its better to display
// only some instead of crashing the browser.
var MAX_DRAWN_PORTALS = 1000;
var MAX_DRAWN_LINKS = 400;
var MAX_DRAWN_FIELDS = 200;
var COLOR_SELECTED_PORTAL = '#f00'; var COLOR_SELECTED_PORTAL = '#f00';
var COLORS = ['#FFCE00', '#0088FF', '#03FE03']; // none, res, enl var COLORS = ['#FFCE00', '#0088FF', '#03FE03']; // none, res, enl

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @id ingress-intel-total-conversion@breunigs // @id ingress-intel-total-conversion@breunigs
// @name intel map total conversion // @name intel map total conversion
// @version 0.1-2013-02-03-194418 // @version 0.2-2013-02-04-025217
// @namespace https://github.com/breunigs/ingress-intel-total-conversion // @namespace https://github.com/breunigs/ingress-intel-total-conversion
// @updateURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/total-conversion-build.user.js // @updateURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/total-conversion-build.user.js
// @downloadURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/total-conversion-build.user.js // @downloadURL https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/total-conversion-build.user.js
@ -94,6 +94,16 @@ var CHAT_MIN_RANGE = 6;
// high causes too many items to be drawn, making drag&drop sluggish. // high causes too many items to be drawn, making drag&drop sluggish.
var VIEWPORT_PAD_RATIO = 0.3; var VIEWPORT_PAD_RATIO = 0.3;
// how many items to request each query
var CHAT_PUBLIC_ITEMS = 200
var CHAT_FACTION_ITEMS = 50
// Leaflet will get very slow for MANY items. Its better to display
// only some instead of crashing the browser.
var MAX_DRAWN_PORTALS = 1000;
var MAX_DRAWN_LINKS = 400;
var MAX_DRAWN_FIELDS = 200;
var COLOR_SELECTED_PORTAL = '#f00'; var COLOR_SELECTED_PORTAL = '#f00';
var COLORS = ['#FFCE00', '#0088FF', '#03FE03']; // none, res, enl var COLORS = ['#FFCE00', '#0088FF', '#03FE03']; // none, res, enl
@ -261,8 +271,12 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
window.cleanUp = function() { window.cleanUp = function() {
var cnt = [0,0,0]; var cnt = [0,0,0];
var b = getPaddedBounds(); var b = getPaddedBounds();
var minlvl = getMinPortalLevel();
portalsLayer.eachLayer(function(portal) { portalsLayer.eachLayer(function(portal) {
if(b.contains(portal.getLatLng())) return; // portal must be in bounds and have a high enough level. Also dont
// remove if it is selected.
if(portal.options.guid == window.selectedPortal ||
(b.contains(portal.getLatLng()) && portal.options.level >= minlvl)) return;
cnt[0]++; cnt[0]++;
portalsLayer.removeLayer(portal); portalsLayer.removeLayer(portal);
}); });
@ -304,7 +318,7 @@ window.removeByGuid = function(guid) {
break; break;
default: default:
console.warn('unknown GUID type: ' + guid); console.warn('unknown GUID type: ' + guid);
window.debug.printStackTrace(); //window.debug.printStackTrace();
} }
} }
@ -313,9 +327,17 @@ window.removeByGuid = function(guid) {
// renders a portal on the map from the given entity // renders a portal on the map from the given entity
window.renderPortal = function(ent) { window.renderPortal = function(ent) {
removeByGuid(ent[0]); removeByGuid(ent[0]);
if(Object.keys(portals).length >= MAX_DRAWN_PORTALS && ent[0] != selectedPortal)
return;
var latlng = [ent[2].locationE6.latE6/1E6, ent[2].locationE6.lngE6/1E6]; var latlng = [ent[2].locationE6.latE6/1E6, ent[2].locationE6.lngE6/1E6];
if(!getPaddedBounds().contains(latlng)) return; if(!getPaddedBounds().contains(latlng)) return;
// hide low level portals on low zooms
var portalLevel = getPortalLevel(ent[2]);
if(portalLevel < getMinPortalLevel() && ent[0] != selectedPortal) return;
// pre-load player names for high zoom levels // pre-load player names for high zoom levels
if(map.getZoom() >= PRECACHE_PLAYER_NAMES_ZOOM) { if(map.getZoom() >= PRECACHE_PLAYER_NAMES_ZOOM) {
if(ent[2].captured && ent[2].captured.capturingPlayerId) if(ent[2].captured && ent[2].captured.capturingPlayerId)
@ -336,6 +358,7 @@ window.renderPortal = function(ent) {
fillColor: COLORS[team], fillColor: COLORS[team],
fillOpacity: 0.5, fillOpacity: 0.5,
clickable: true, clickable: true,
level: portalLevel,
guid: ent[0]}); guid: ent[0]});
p.on('remove', function() { delete window.portals[this.options.guid]; }); p.on('remove', function() { delete window.portals[this.options.guid]; });
@ -351,6 +374,8 @@ window.renderPortal = function(ent) {
// renders a link on the map from the given entity // renders a link on the map from the given entity
window.renderLink = function(ent) { window.renderLink = function(ent) {
removeByGuid(ent[0]); removeByGuid(ent[0]);
if(Object.keys(links).length >= MAX_DRAWN_LINKS) return;
var team = getTeam(ent[2]); var team = getTeam(ent[2]);
var edge = ent[2].edge; var edge = ent[2].edge;
var latlngs = [ var latlngs = [
@ -359,10 +384,11 @@ window.renderLink = function(ent) {
]; ];
var poly = L.polyline(latlngs, { var poly = L.polyline(latlngs, {
color: COLORS[team], color: COLORS[team],
opacity: 0.5, opacity: 1,
weight:2, weight:2,
clickable: false, clickable: false,
guid: ent[0] guid: ent[0],
smoothFactor: 10
}); });
if(!getPaddedBounds().intersects(poly.getBounds())) return; if(!getPaddedBounds().intersects(poly.getBounds())) return;
@ -375,6 +401,8 @@ window.renderLink = function(ent) {
// renders a field on the map from a given entity // renders a field on the map from a given entity
window.renderField = function(ent) { window.renderField = function(ent) {
window.removeByGuid(ent[0]); window.removeByGuid(ent[0]);
if(Object.keys(fields).length >= MAX_DRAWN_FIELDS) return;
var team = getTeam(ent[2]); var team = getTeam(ent[2]);
var reg = ent[2].capturedRegion; var reg = ent[2].capturedRegion;
var latlngs = [ var latlngs = [
@ -387,6 +415,7 @@ window.renderField = function(ent) {
fillOpacity: 0.25, fillOpacity: 0.25,
stroke: false, stroke: false,
clickable: false, clickable: false,
smoothFactor: 10,
guid: ent[0]}); guid: ent[0]});
if(!getPaddedBounds().intersects(poly.getBounds())) return; if(!getPaddedBounds().intersects(poly.getBounds())) return;
@ -445,16 +474,18 @@ window.renderUpdateStatus = function() {
else else
t += 'Up to date.'; t += 'Up to date.';
if(renderLimitReached())
t += ' <span style="color:red" title="Can only render so much before it gets unbearably slow. Not all entities are shown. Zoom in or increase the limit (search for MAX_DRAWN_*).">RENDER LIMIT</span> '
if(window.failedRequestCount > 0) if(window.failedRequestCount > 0)
t += ' ' + window.failedRequestCount + ' requests failed.' t += ' ' + window.failedRequestCount + ' requests failed.'
t += '<br/><span title="not removing portals as long as you keep them in view, though">('; t += '<br/>(';
var conv = ['impossible', 8,8,7,7,6,6,5,5,4,4,3,3,2,2,1]; var minlvl = getMinPortalLevel();
var z = map.getZoom(); if(minlvl === 0)
if(z >= 16) t += 'showing all portals';
t += 'requesting all portals';
else else
t+= 'only requesting portals with level '+conv[z]+' and up'; t+= 'only showing portals with level '+minlvl+' and up';
t += ')</span>'; t += ')</span>';
$('#updatestatus').html(t); $('#updatestatus').html(t);
@ -616,11 +647,26 @@ window.getPaddedBounds = function() {
}); });
} }
if(window._storedPaddedBounds) return window._storedPaddedBounds; if(window._storedPaddedBounds) return window._storedPaddedBounds;
var p = window.map.getBounds().pad(VIEWPORT_PAD_RATIO); var p = window.map.getBounds().pad(VIEWPORT_PAD_RATIO);
window._storedPaddedBounds = p; window._storedPaddedBounds = p;
return p; return p;
} }
window.renderLimitReached = function() {
if(Object.keys(portals).length >= MAX_DRAWN_PORTALS) return true;
if(Object.keys(links).length >= MAX_DRAWN_LINKS) return true;
if(Object.keys(fields).length >= MAX_DRAWN_FIELDS) return true;
return false;
}
window.getMinPortalLevel = function() {
var z = map.getZoom();
if(z >= 16) return 0;
var conv = ['impossible', 8,7,7,6,6,5,5,4,4,3,3,2,2,1,1];
return conv[z];
}
// returns number of pixels left to scroll down before reaching the // returns number of pixels left to scroll down before reaching the
// bottom. Works similar to the native scrollTop function. // bottom. Works similar to the native scrollTop function.
@ -815,6 +861,10 @@ load(JQUERY, LEAFLET).then(LLGMAPS).thenRun(boot);
window.chat = function() {}; window.chat = function() {};
//
// timestamp and clear management
//
window.chat._oldFactionTimestamp = -1; window.chat._oldFactionTimestamp = -1;
window.chat._newFactionTimestamp = -1; window.chat._newFactionTimestamp = -1;
window.chat._oldPublicTimestamp = -1; window.chat._oldPublicTimestamp = -1;
@ -828,8 +878,27 @@ window.chat.getNewestTimestamp = function(public) {
return chat['_new'+(public ? 'Public' : 'Faction')+'Timestamp']; return chat['_new'+(public ? 'Public' : 'Faction')+'Timestamp'];
} }
window.chat._needsClearing = false; window.chat._needsClearing = false;
window.chat.clear = function() {
console.log('clearing now');
window.chat._displayedFactionGuids = [];
window.chat._displayedPublicGuids = [];
window.chat._displayedPlayerActionTime = {};
window.chat._oldFactionTimestamp = -1;
window.chat._newFactionTimestamp = -1;
window.chat._oldPublicTimestamp = -1;
window.chat._newPublicTimestamp = -1;
$('#chatfaction, #chatpublic, #chatautomated').data('ignoreNextScroll', true).html('');
}
window.chat.clearIfRequired = function() {
if(!chat._needsClearing) return;
chat.clear();
chat._needsClearing = false;
}
window.chat._oldBBox = null; window.chat._oldBBox = null;
window.chat.genPostData = function(public, getOlderMsgs) { window.chat.genPostData = function(public, getOlderMsgs) {
if(typeof public !== 'boolean') throw('Need to know if public or faction chat.'); if(typeof public !== 'boolean') throw('Need to know if public or faction chat.');
@ -838,14 +907,14 @@ window.chat.genPostData = function(public, getOlderMsgs) {
var b = map.getBounds().extend(chat._localRangeCircle.getBounds()); var b = map.getBounds().extend(chat._localRangeCircle.getBounds());
var bbs = b.toBBoxString(); var bbs = b.toBBoxString();
chat._needsClearing = chat._oldBBox && chat._oldBBox !== bbs; chat._needsClearing = chat._needsClearing || chat._oldBBox && chat._oldBBox !== bbs;
if(chat._needsClearing) console.log('Bounding Box changed, chat will be cleared (old: '+chat._oldBBox+' ; new: '+bbs+' )'); if(chat._needsClearing) console.log('Bounding Box changed, chat will be cleared (old: '+chat._oldBBox+' ; new: '+bbs+' )');
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 ? 100 : 50, // public contains so much crap desiredNumItems: public ? CHAT_PUBLIC_ITEMS : CHAT_FACTION_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),
@ -881,6 +950,8 @@ window.chat.genPostData = function(public, getOlderMsgs) {
return data; return data;
} }
// //
// requesting faction // requesting faction
// //
@ -923,6 +994,7 @@ window.chat.requestNewFaction = function(isRetry) {
requests.add(r); requests.add(r);
} }
// //
// handle faction // handle faction
// //
@ -937,6 +1009,8 @@ window.chat.handleNewFaction = function(data, textStatus, jqXHR) {
chat.handleFaction(data, textStatus, jqXHR, false); chat.handleFaction(data, textStatus, jqXHR, false);
} }
window.chat._displayedFactionGuids = []; window.chat._displayedFactionGuids = [];
window.chat.handleFaction = function(data, textStatus, jqXHR, isOldMsgs) { window.chat.handleFaction = function(data, textStatus, jqXHR, isOldMsgs) {
if(!data || !data.result) { if(!data || !data.result) {
@ -944,55 +1018,25 @@ window.chat.handleFaction = function(data, textStatus, jqXHR, isOldMsgs) {
return console.warn('faction chat error. Waiting for next auto-refresh.'); return console.warn('faction chat error. Waiting for next auto-refresh.');
} }
chat.clearIfRequired();
if(data.result.length === 0) return;
chat._newFactionTimestamp = data.result[0][1]; chat._newFactionTimestamp = data.result[0][1];
chat._oldFactionTimestamp = data.result[data.result.length-1][1]; chat._oldFactionTimestamp = data.result[data.result.length-1][1];
chat.clearIfRequired();
var msgs = '';
var prevTime = null;
$.each(data.result.reverse(), function(ind, json) { // oldest first!
// avoid duplicates
if(window.chat._displayedFactionGuids.indexOf(json[0]) !== -1) return;
window.chat._displayedFactionGuids.push(json[0]);
var time = json[1];
var msg = json[2].plext.markup[2][1].plain;
var team = json[2].plext.team === 'ALIENS' ? TEAM_ENL : TEAM_RES;
var nick = json[2].plext.markup[1][1].plain.slice(0, -2); // cut “: ” at end
var pguid = json[2].plext.markup[1][1].guid;
window.setPlayerName(pguid, nick); // free nick name resolves
var nowTime = new Date(time).toLocaleDateString();
if(prevTime && prevTime !== nowTime)
msgs += chat.renderDivider(nowTime);
msgs += chat.renderMsg(msg, nick, time, team);
prevTime = nowTime;
});
// if there is a change of day between two requests, handle the
// divider insertion here.
if(isOldMsgs) {
var ts = $('#chatfaction time:first').data('timestamp');
var nextTime = new Date(ts).toLocaleDateString();
if(prevTime && prevTime !== nextTime && ts)
msgs += chat.renderDivider(nextTime);
}
var c = $('#chatfaction'); var c = $('#chatfaction');
var scrollBefore = scrollBottom(c); var scrollBefore = scrollBottom(c);
if(isOldMsgs) chat.renderPlayerMsgsTo(true, data, isOldMsgs, chat._displayedFactionGuids);
c.prepend(msgs);
else
c.append(msgs);
chat.keepScrollPosition(c, scrollBefore, isOldMsgs); chat.keepScrollPosition(c, scrollBefore, isOldMsgs);
chat.needMoreMessages();
if(data.result.length >= CHAT_FACTION_ITEMS) chat.needMoreMessages();
} }
// //
// requesting public // requesting public
// //
@ -1059,25 +1103,27 @@ window.chat.handlePublic = function(data, textStatus, jqXHR, isOldMsgs) {
return console.warn('public chat error. Waiting for next auto-refresh.'); return console.warn('public chat error. Waiting for next auto-refresh.');
} }
chat.clearIfRequired();
if(data.result.length === 0) return;
chat._newPublicTimestamp = data.result[0][1]; chat._newPublicTimestamp = data.result[0][1];
chat._oldPublicTimestamp = data.result[data.result.length-1][1]; chat._oldPublicTimestamp = data.result[data.result.length-1][1];
chat.clearIfRequired(); var c = $('#chatautomated');
var c = $('#chat > div:visible');
var scrollBefore = scrollBottom(c); var scrollBefore = scrollBottom(c);
chat.handlePublicAutomated(data); chat.handlePublicAutomated(data);
//chat.handlePublicPlayer(data, isOldMsgs);
chat.keepScrollPosition(c, scrollBefore, isOldMsgs); chat.keepScrollPosition(c, scrollBefore, isOldMsgs);
chat.needMoreMessages();
c = $('#chatpublic');
var scrollBefore = scrollBottom(c);
chat.renderPlayerMsgsTo(false, data, isOldMsgs, chat._displayedPublicGuids);
chat.keepScrollPosition(c, scrollBefore, isOldMsgs);
if(data.result.length >= CHAT_PUBLIC_ITEMS) chat.needMoreMessages();
} }
window.chat.handlePublicAutomated = function(data) { window.chat.handlePublicAutomated = function(data) {
$.each(data.result, function(ind, json) { // newest first! $.each(data.result, function(ind, json) { // newest first!
var time = json[1]; var time = json[1];
@ -1125,14 +1171,10 @@ window.chat.handlePublicAutomated = function(data) {
}); });
if(chat.getActive() === 'automated') if(chat.getActive() === 'automated')
window.chat.renderAutomatedMsgsToBox(); window.chat.renderAutomatedMsgsTo();
} }
window.chat.getActive = function() { window.chat.renderAutomatedMsgsTo = function() {
return $('#chatcontrols .active').text();
}
window.chat.renderAutomatedMsgsToBox = function() {
var x = window.chat._displayedPlayerActionTime; var x = window.chat._displayedPlayerActionTime;
// we dont care about the GUIDs anymore // we dont care about the GUIDs anymore
var vals = $.map(x, function(v, k) { return [v]; }); var vals = $.map(x, function(v, k) { return [v]; });
@ -1157,24 +1199,89 @@ window.chat.renderAutomatedMsgsToBox = function() {
window.chat.clear = function() { //
console.log('clearing now'); // common
window.chat._displayedFactionGuids = []; //
window.chat._displayedPublicGuids = [];
window.chat._displayedPlayerActionTime = {};
window.chat._oldFactionTimestamp = -1; window.chat.renderPlayerMsgsTo = function(isFaction, data, isOldMsgs, dupCheckArr) {
window.chat._newFactionTimestamp = -1; var msgs = '';
window.chat._oldPublicTimestamp = -1; var prevTime = null;
window.chat._newPublicTimestamp = -1;
$('#chatfaction, #chatpublic, #chatautomated').data('ignoreNextScroll', true).html(''); $.each(data.result.reverse(), function(ind, json) { // oldest first!
if(json[2].plext.plextType !== 'PLAYER_GENERATED') return true;
// avoid duplicates
if(dupCheckArr.indexOf(json[0]) !== -1) return true;
dupCheckArr.push(json[0]);
var time = json[1];
var team = json[2].plext.team === 'ALIENS' ? TEAM_ENL : TEAM_RES;
var msg, nick, pguid;
$.each(json[2].plext.markup, function(ind, markup) {
if(markup[0] === 'SENDER') {
nick = markup[1].plain.slice(0, -2); // cut “: ” at end
pguid = markup[1].guid;
window.setPlayerName(pguid, nick); // free nick name resolves
}
if(markup[0] === 'TEXT') msg = markup[1].plain;
if(!isFaction && markup[0] === 'SECURE') {
nick = null;
return false; // aka break
}
});
if(!nick) return true; // aka next
var nowTime = new Date(time).toLocaleDateString();
if(prevTime && prevTime !== nowTime)
msgs += chat.renderDivider(nowTime);
msgs += chat.renderMsg(msg, nick, time, team);
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)
addTo.prepend(msgs);
else
addTo.append(msgs);
} }
window.chat.clearIfRequired = function() {
if(!chat._needsClearing) return; window.chat.renderDivider = function(text) {
chat.clear(); return '<summary>─ '+text+' ────────────────────────────────────────────────────────────────────────────</summary>';
chat._needsClearing = false;
} }
window.chat.renderMsg = function(msg, nick, time, team) {
var ta = unixTimeToHHmm(time);
var tb = unixTimeToString(time, true);
var t = '<time title="'+tb+'" data-timestamp="'+time+'">'+ta+'</time>';
var s = 'style="color:'+COLORS[team]+'"';
var title = nick.length >= 8 ? 'title="'+nick+'"' : '';
return '<p>'+t+'<mark '+s+'>'+nick+'</mark><span>'+msg+'</span></p>';
}
window.chat.getActive = function() {
return $('#chatcontrols .active').text();
}
window.chat.toggle = function() { window.chat.toggle = function() {
var c = $('#chat, #chatcontrols'); var c = $('#chat, #chatcontrols');
if(c.hasClass('expand')) { if(c.hasClass('expand')) {
@ -1190,12 +1297,14 @@ window.chat.toggle = function() {
} }
} }
window.chat.request = function() { window.chat.request = function() {
console.log('refreshing chat'); console.log('refreshing chat');
chat.requestNewFaction(); chat.requestNewFaction();
chat.requestNewPublic(); chat.requestNewPublic();
} }
// 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() {
@ -1208,19 +1317,62 @@ window.chat.needMoreMessages = function() {
chat.requestOldPublic(); chat.requestOldPublic();
} }
window.chat.setupTime = function() {
var inputTime = $('#chatinput time'); window.chat.chooser = function(event) {
var updateTime = function() { var t = $(event.target);
if(window.isIdle()) return; var tt = t.text();
var d = new Date(); var span = $('#chatinput span');
inputTime.text(d.toLocaleTimeString().slice(0, 5));
// update ON the minute (1ms after) $('#chatcontrols .active').removeClass('active');
setTimeout(updateTime, (60 - d.getSeconds()) * 1000 + 1); t.addClass('active');
};
updateTime(); $('#chat > div').hide();
window.addResumeFunction(updateTime);
switch(tt) {
case 'faction':
span.css('color', '');
span.text('tell faction:');
$('#chatfaction').show();
break;
case 'public':
span.css('cssText', 'color: red !important');
span.text('tell public:');
$('#chatpublic').show();
break;
case 'automated':
span.css('cssText', 'color: #bbb !important');
span.text('tell Jarvis:');
chat.renderAutomatedMsgsTo();
$('#chatautomated').show();
break;
}
chat.needMoreMessages();
} }
// contains the logic to keep the correct scroll position.
window.chat.keepScrollPosition = function(box, scrollBefore, isOldMsgs) {
// If scrolled down completely, keep it that way so new messages can
// be seen easily. If scrolled up, only need to fix scroll position
// when old messages are added. New messages added at the bottom dont
// change the view and enabling this would make the chat scroll down
// for every added message, even if the user wants to read old stuff.
if(scrollBefore === 0 || isOldMsgs) {
box.data('ignoreNextScroll', true);
box.scrollTop(box.scrollTop() + (scrollBottom(box)-scrollBefore));
}
}
//
// setup
//
window.chat.setup = function() { window.chat.setup = function() {
window.chat._localRangeCircle = L.circle(map.getCenter(), CHAT_MIN_RANGE*1000); window.chat._localRangeCircle = L.circle(map.getCenter(), CHAT_MIN_RANGE*1000);
@ -1235,6 +1387,7 @@ window.chat.setup = function() {
}); });
window.chat.setupTime(); window.chat.setupTime();
window.chat.setupPosting();
$('#chatfaction').scroll(function() { $('#chatfaction').scroll(function() {
var t = $(this); var t = $(this);
@ -1259,63 +1412,63 @@ window.chat.setup = function() {
} }
window.chat.renderMsg = function(msg, nick, time, team) { window.chat.setupTime = function() {
var ta = unixTimeToHHmm(time); var inputTime = $('#chatinput time');
var tb = unixTimeToString(time, true); var updateTime = function() {
var t = '<time title="'+tb+'" data-timestamp="'+time+'">'+ta+'</time>'; if(window.isIdle()) return;
var s = 'style="color:'+COLORS[team]+'"'; var d = new Date();
var title = nick.length >= 8 ? 'title="'+nick+'"' : ''; inputTime.text(d.toLocaleTimeString().slice(0, 5));
return '<p>'+t+'<mark '+s+'>'+nick+'</mark><span>'+msg+'</span></p>'; // update ON the minute (1ms after)
setTimeout(updateTime, (60 - d.getSeconds()) * 1000 + 1);
};
updateTime();
window.addResumeFunction(updateTime);
} }
window.chat.renderDivider = function(text) {
return '<summary>─ '+text+' ────────────────────────────────────────────────────────────────────────────</summary>'; //
// posting
//
window.chat.setupPosting = function() {
$('#chatinput input').keypress(function(e) {
if((e.keyCode ? e.keyCode : e.which) != 13) return;
chat.postMsg();
e.preventDefault();
});
$('#chatinput').submit(function(e) {
chat.postMsg();
e.preventDefault();
});
} }
window.chat.chooser = function(event) {
var t = $(event.target);
var tt = t.text();
var span = $('#chatinput span');
$('#chatcontrols .active').removeClass('active'); window.chat.postMsg = function() {
t.addClass('active'); 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?');
$('#chat > div').hide(); var msg = $.trim($('#chatinput input').val());
if(!msg || msg === '') return;
switch(tt) { var public = c === 'public';
case 'faction': var latlng = map.getCenter();
span.css('color', '');
span.text('tell faction:');
$('#chatfaction').show();
break;
case 'public': var data = {message: msg,
span.css('cssText', 'color: red !important'); latE6: Math.round(latlng.lat*1E6),
span.text('spam public:'); lngE6: Math.round(latlng.lng*1E6),
$('#chatpublic').show(); factionOnly: !public};
break;
case 'automated': window.postAjax('sendPlext', data,
span.css('cssText', 'color: #bbb !important'); function() { if(public) chat.requestNewPublic(); else chat.requestNewFaction(); },
span.text('tell Jarvis:'); function() {
chat.renderAutomatedMsgsToBox(); alert('Your message could not be delivered. You can copy&' +
$('#chatautomated').show(); 'paste it here and try again if you want:\n\n'+msg);
break;
} }
} );
$('#chatinput input').val('');
// contains the logic to keep the correct scroll position.
window.chat.keepScrollPosition = function(box, scrollBefore, isOldMsgs) {
// If scrolled down completely, keep it that way so new messages can
// be seen easily. If scrolled up, only need to fix scroll position
// when old messages are added. New messages added at the bottom dont
// change the view and enabling this would make the chat scroll down
// for every added message, even if the user wants to read old stuff.
if(scrollBefore === 0 || isOldMsgs) {
box.data('ignoreNextScroll', true);
box.scrollTop(box.scrollTop() + (scrollBottom(box)-scrollBefore));
}
} }
@ -1563,7 +1716,7 @@ window.getTeam = function(details) {
window.idleTime = 0; // in minutes window.idleTime = 0; // in minutes
setInterval('window.idleTime += 1', 60*1000); setInterval('window.idleTime += 1', 60*1000);
var idleReset = function (e) { var idleReset = function () {
// update immediately when the user comes back // update immediately when the user comes back
if(isIdle()) { if(isIdle()) {
window.idleTime = 0; window.idleTime = 0;
@ -1659,11 +1812,11 @@ window.renderPortalDetails = function(guid) {
// collect and html-ify random data // collect and html-ify random data
var randDetails = [playerText, sinceText, getRangeText(d), getEnergyText(d), linksText, getAvgResoDistText(d)]; var randDetails = [playerText, sinceText, getRangeText(d), getEnergyText(d), linksText, getAvgResoDistText(d)];
randDetails = randDetails.map(function(e) { randDetails = randDetails.map(function(detail) {
if(!e) return ''; if(!detail) return '';
e = e.split(':'); detail = detail.split(':');
e = '<aside>'+e.shift()+'<span>'+e.join(':')+'</span></aside>'; detail = '<aside>'+detail.shift()+'<span>'+detail.join(':')+'</span></aside>';
return e; return detail;
}).join('\n'); }).join('\n');
// replacing causes flicker, so if the selected portal does not // replacing causes flicker, so if the selected portal does not