diff --git a/README.md b/README.md
index a171b592..cb2acd46 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,3 @@
-*NOTE: this is a work in progress and not yet finished. *
-
ingress.com/intel total conversion
==================================
@@ -8,6 +6,31 @@ It’s annoying to extend the intel page with new features because the minified
So instead, here’s 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 there’s *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 wouldn’t want to *quit*, would you?), privacy link, etc.
+- redeem pretty display
+
Install
-------
diff --git a/code/chat.js b/code/chat.js
index 10ea586a..7a12b3f4 100644
--- a/code/chat.js
+++ b/code/chat.js
@@ -1,5 +1,9 @@
window.chat = function() {};
+//
+// timestamp and clear management
+//
+
window.chat._oldFactionTimestamp = -1;
window.chat._newFactionTimestamp = -1;
window.chat._oldPublicTimestamp = -1;
@@ -13,8 +17,27 @@ window.chat.getNewestTimestamp = function(public) {
return chat['_new'+(public ? 'Public' : 'Faction')+'Timestamp'];
}
-
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.genPostData = function(public, getOlderMsgs) {
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 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+' )');
chat._oldBBox = bbs;
var ne = b.getNorthEast();
var sw = b.getSouthWest();
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),
minLngE6: Math.round(sw.lng*1E6),
maxLatE6: Math.round(ne.lat*1E6),
@@ -66,6 +89,8 @@ window.chat.genPostData = function(public, getOlderMsgs) {
return data;
}
+
+
//
// requesting faction
//
@@ -108,6 +133,7 @@ window.chat.requestNewFaction = function(isRetry) {
requests.add(r);
}
+
//
// handle faction
//
@@ -122,6 +148,8 @@ window.chat.handleNewFaction = function(data, textStatus, jqXHR) {
chat.handleFaction(data, textStatus, jqXHR, false);
}
+
+
window.chat._displayedFactionGuids = [];
window.chat.handleFaction = function(data, textStatus, jqXHR, isOldMsgs) {
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.');
}
+ chat.clearIfRequired();
+
+ if(data.result.length === 0) return;
+
chat._newFactionTimestamp = data.result[0][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 scrollBefore = scrollBottom(c);
- if(isOldMsgs)
- c.prepend(msgs);
- else
- c.append(msgs);
-
+ chat.renderPlayerMsgsTo(true, data, isOldMsgs, chat._displayedFactionGuids);
chat.keepScrollPosition(c, scrollBefore, isOldMsgs);
- chat.needMoreMessages();
+
+ if(data.result.length >= CHAT_FACTION_ITEMS) chat.needMoreMessages();
}
+
+
//
// 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.');
}
+ chat.clearIfRequired();
+
+ if(data.result.length === 0) return;
+
chat._newPublicTimestamp = data.result[0][1];
chat._oldPublicTimestamp = data.result[data.result.length-1][1];
- chat.clearIfRequired();
-
- var c = $('#chat > div:visible');
+ var c = $('#chatautomated');
var scrollBefore = scrollBottom(c);
-
chat.handlePublicAutomated(data);
- //chat.handlePublicPlayer(data, 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) {
$.each(data.result, function(ind, json) { // newest first!
var time = json[1];
@@ -310,14 +310,10 @@ window.chat.handlePublicAutomated = function(data) {
});
if(chat.getActive() === 'automated')
- window.chat.renderAutomatedMsgsToBox();
+ window.chat.renderAutomatedMsgsTo();
}
-window.chat.getActive = function() {
- return $('#chatcontrols .active').text();
-}
-
-window.chat.renderAutomatedMsgsToBox = function() {
+window.chat.renderAutomatedMsgsTo = function() {
var x = window.chat._displayedPlayerActionTime;
// we don’t care about the GUIDs anymore
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');
- 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('');
+//
+// common
+//
+
+
+window.chat.renderPlayerMsgsTo = function(isFaction, data, isOldMsgs, dupCheckArr) {
+ 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
+ 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;
- chat.clear();
- chat._needsClearing = false;
+
+window.chat.renderDivider = function(text) {
+ return '─ '+text+' ────────────────────────────────────────────────────────────────────────────';
}
+
+window.chat.renderMsg = function(msg, nick, time, team) {
+ var ta = unixTimeToHHmm(time);
+ var tb = unixTimeToString(time, true);
+ var t = '';
+ var s = 'style="color:'+COLORS[team]+'"';
+ var title = nick.length >= 8 ? 'title="'+nick+'"' : '';
+ return '
'+t+''+nick+''+msg+'
';
+}
+
+
+
+window.chat.getActive = function() {
+ return $('#chatcontrols .active').text();
+}
+
+
window.chat.toggle = function() {
var c = $('#chat, #chatcontrols');
if(c.hasClass('expand')) {
@@ -375,12 +436,14 @@ window.chat.toggle = function() {
}
}
+
window.chat.request = function() {
console.log('refreshing chat');
chat.requestNewFaction();
chat.requestNewPublic();
}
+
// checks if there are enough messages in the selected chat tab and
// loads more if not.
window.chat.needMoreMessages = function() {
@@ -393,19 +456,62 @@ window.chat.needMoreMessages = function() {
chat.requestOldPublic();
}
-window.chat.setupTime = function() {
- var inputTime = $('#chatinput time');
- var updateTime = function() {
- if(window.isIdle()) return;
- var d = new Date();
- inputTime.text(d.toLocaleTimeString().slice(0, 5));
- // update ON the minute (1ms after)
- setTimeout(updateTime, (60 - d.getSeconds()) * 1000 + 1);
- };
- updateTime();
- window.addResumeFunction(updateTime);
+
+window.chat.chooser = function(event) {
+ var t = $(event.target);
+ var tt = t.text();
+ var span = $('#chatinput span');
+
+ $('#chatcontrols .active').removeClass('active');
+ t.addClass('active');
+
+ $('#chat > div').hide();
+
+ 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 don’t
+ // 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._localRangeCircle = L.circle(map.getCenter(), CHAT_MIN_RANGE*1000);
@@ -420,6 +526,7 @@ window.chat.setup = function() {
});
window.chat.setupTime();
+ window.chat.setupPosting();
$('#chatfaction').scroll(function() {
var t = $(this);
@@ -444,61 +551,61 @@ window.chat.setup = function() {
}
-window.chat.renderMsg = function(msg, nick, time, team) {
- var ta = unixTimeToHHmm(time);
- var tb = unixTimeToString(time, true);
- var t = '';
- var s = 'style="color:'+COLORS[team]+'"';
- var title = nick.length >= 8 ? 'title="'+nick+'"' : '';
- return ''+t+''+nick+''+msg+'
';
-}
-
-window.chat.renderDivider = function(text) {
- return '─ '+text+' ────────────────────────────────────────────────────────────────────────────';
-}
-
-window.chat.chooser = function(event) {
- var t = $(event.target);
- var tt = t.text();
- var span = $('#chatinput span');
-
- $('#chatcontrols .active').removeClass('active');
- t.addClass('active');
-
- $('#chat > div').hide();
-
- switch(tt) {
- case 'faction':
- span.css('color', '');
- span.text('tell faction:');
- $('#chatfaction').show();
- break;
-
- case 'public':
- span.css('cssText', 'color: red !important');
- span.text('spam public:');
- $('#chatpublic').show();
- break;
-
- case 'automated':
- span.css('cssText', 'color: #bbb !important');
- span.text('tell Jarvis:');
- chat.renderAutomatedMsgsToBox();
- $('#chatautomated').show();
- break;
- }
+window.chat.setupTime = function() {
+ var inputTime = $('#chatinput time');
+ var updateTime = function() {
+ if(window.isIdle()) return;
+ var d = new Date();
+ inputTime.text(d.toLocaleTimeString().slice(0, 5));
+ // update ON the minute (1ms after)
+ setTimeout(updateTime, (60 - d.getSeconds()) * 1000 + 1);
+ };
+ updateTime();
+ window.addResumeFunction(updateTime);
}
-// 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 don’t
- // 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));
- }
+//
+// 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.postMsg = function() {
+ 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?');
+
+ var msg = $.trim($('#chatinput input').val());
+ if(!msg || msg === '') return;
+
+ var public = c === 'public';
+ var latlng = map.getCenter();
+
+ var data = {message: msg,
+ latE6: Math.round(latlng.lat*1E6),
+ lngE6: Math.round(latlng.lng*1E6),
+ factionOnly: !public};
+
+ window.postAjax('sendPlext', data,
+ function() { if(public) chat.requestNewPublic(); else chat.requestNewFaction(); },
+ function() {
+ alert('Your message could not be delivered. You can copy&' +
+ 'paste it here and try again if you want:\n\n'+msg);
+ }
+ );
+
+ $('#chatinput input').val('');
}
diff --git a/code/idle.js b/code/idle.js
index 097b0c21..39a4ab83 100644
--- a/code/idle.js
+++ b/code/idle.js
@@ -3,7 +3,7 @@
window.idleTime = 0; // in minutes
setInterval('window.idleTime += 1', 60*1000);
-var idleReset = function (e) {
+var idleReset = function () {
// update immediately when the user comes back
if(isIdle()) {
window.idleTime = 0;
diff --git a/code/map_data.js b/code/map_data.js
index 3d97639e..94bb7d50 100644
--- a/code/map_data.js
+++ b/code/map_data.js
@@ -111,8 +111,12 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
window.cleanUp = function() {
var cnt = [0,0,0];
var b = getPaddedBounds();
+ var minlvl = getMinPortalLevel();
portalsLayer.eachLayer(function(portal) {
- if(b.contains(portal.getLatLng())) return;
+ // portal must be in bounds and have a high enough level. Also don’t
+ // remove if it is selected.
+ if(portal.options.guid == window.selectedPortal ||
+ (b.contains(portal.getLatLng()) && portal.options.level >= minlvl)) return;
cnt[0]++;
portalsLayer.removeLayer(portal);
});
@@ -154,7 +158,7 @@ window.removeByGuid = function(guid) {
break;
default:
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
window.renderPortal = function(ent) {
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];
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
if(map.getZoom() >= PRECACHE_PLAYER_NAMES_ZOOM) {
if(ent[2].captured && ent[2].captured.capturingPlayerId)
@@ -186,6 +198,7 @@ window.renderPortal = function(ent) {
fillColor: COLORS[team],
fillOpacity: 0.5,
clickable: true,
+ level: portalLevel,
guid: ent[0]});
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
window.renderLink = function(ent) {
removeByGuid(ent[0]);
+ if(Object.keys(links).length >= MAX_DRAWN_LINKS) return;
+
var team = getTeam(ent[2]);
var edge = ent[2].edge;
var latlngs = [
@@ -209,10 +224,11 @@ window.renderLink = function(ent) {
];
var poly = L.polyline(latlngs, {
color: COLORS[team],
- opacity: 0.5,
+ opacity: 1,
weight:2,
clickable: false,
- guid: ent[0]
+ guid: ent[0],
+ smoothFactor: 10
});
if(!getPaddedBounds().intersects(poly.getBounds())) return;
@@ -225,6 +241,8 @@ window.renderLink = function(ent) {
// renders a field on the map from a given entity
window.renderField = function(ent) {
window.removeByGuid(ent[0]);
+ if(Object.keys(fields).length >= MAX_DRAWN_FIELDS) return;
+
var team = getTeam(ent[2]);
var reg = ent[2].capturedRegion;
var latlngs = [
@@ -237,6 +255,7 @@ window.renderField = function(ent) {
fillOpacity: 0.25,
stroke: false,
clickable: false,
+ smoothFactor: 10,
guid: ent[0]});
if(!getPaddedBounds().intersects(poly.getBounds())) return;
diff --git a/code/portal_detail_display.js b/code/portal_detail_display.js
index 09d9fbfe..5427cce0 100644
--- a/code/portal_detail_display.js
+++ b/code/portal_detail_display.js
@@ -30,11 +30,11 @@ window.renderPortalDetails = function(guid) {
// collect and html-ify random data
var randDetails = [playerText, sinceText, getRangeText(d), getEnergyText(d), linksText, getAvgResoDistText(d)];
- randDetails = randDetails.map(function(e) {
- if(!e) return '';
- e = e.split(':');
- e = '';
- return e;
+ randDetails = randDetails.map(function(detail) {
+ if(!detail) return '';
+ detail = detail.split(':');
+ detail = '';
+ return detail;
}).join('\n');
// replacing causes flicker, so if the selected portal does not
diff --git a/code/request_handling.js b/code/request_handling.js
index bef601c1..0415a7b9 100644
--- a/code/request_handling.js
+++ b/code/request_handling.js
@@ -46,16 +46,18 @@ window.renderUpdateStatus = function() {
else
t += 'Up to date.';
+ if(renderLimitReached())
+ t += ' RENDER LIMIT '
+
if(window.failedRequestCount > 0)
t += ' ' + window.failedRequestCount + ' requests failed.'
- t += '
(';
- var conv = ['impossible', 8,8,7,7,6,6,5,5,4,4,3,3,2,2,1];
- var z = map.getZoom();
- if(z >= 16)
- t += 'requesting all portals';
+ t += '
(';
+ var minlvl = getMinPortalLevel();
+ if(minlvl === 0)
+ t += 'showing all portals';
else
- t+= 'only requesting portals with level '+conv[z]+' and up';
+ t+= 'only showing portals with level '+minlvl+' and up';
t += ')';
$('#updatestatus').html(t);
diff --git a/code/utils_misc.js b/code/utils_misc.js
index 8d6c7d71..7eb9084c 100644
--- a/code/utils_misc.js
+++ b/code/utils_misc.js
@@ -107,11 +107,26 @@ window.getPaddedBounds = function() {
});
}
if(window._storedPaddedBounds) return window._storedPaddedBounds;
+
var p = window.map.getBounds().pad(VIEWPORT_PAD_RATIO);
window._storedPaddedBounds = 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
// bottom. Works similar to the native scrollTop function.
diff --git a/main.js b/main.js
index ada99d7e..de13ca94 100644
--- a/main.js
+++ b/main.js
@@ -1,7 +1,7 @@
// ==UserScript==
// @id ingress-intel-total-conversion@breunigs
// @name intel map total conversion
-// @version 0.1-@@BUILDDATE@@
+// @version 0.2-@@BUILDDATE@@
// @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
// @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.
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. It’s 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 COLORS = ['#FFCE00', '#0088FF', '#03FE03']; // none, res, enl
diff --git a/total-conversion-build.user.js b/total-conversion-build.user.js
index 3b97915e..b0fe56e2 100644
--- a/total-conversion-build.user.js
+++ b/total-conversion-build.user.js
@@ -1,7 +1,7 @@
// ==UserScript==
// @id ingress-intel-total-conversion@breunigs
// @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
// @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
@@ -94,6 +94,16 @@ var CHAT_MIN_RANGE = 6;
// high causes too many items to be drawn, making drag&drop sluggish.
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. It’s 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 COLORS = ['#FFCE00', '#0088FF', '#03FE03']; // none, res, enl
@@ -261,8 +271,12 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
window.cleanUp = function() {
var cnt = [0,0,0];
var b = getPaddedBounds();
+ var minlvl = getMinPortalLevel();
portalsLayer.eachLayer(function(portal) {
- if(b.contains(portal.getLatLng())) return;
+ // portal must be in bounds and have a high enough level. Also don’t
+ // remove if it is selected.
+ if(portal.options.guid == window.selectedPortal ||
+ (b.contains(portal.getLatLng()) && portal.options.level >= minlvl)) return;
cnt[0]++;
portalsLayer.removeLayer(portal);
});
@@ -304,7 +318,7 @@ window.removeByGuid = function(guid) {
break;
default:
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
window.renderPortal = function(ent) {
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];
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
if(map.getZoom() >= PRECACHE_PLAYER_NAMES_ZOOM) {
if(ent[2].captured && ent[2].captured.capturingPlayerId)
@@ -336,6 +358,7 @@ window.renderPortal = function(ent) {
fillColor: COLORS[team],
fillOpacity: 0.5,
clickable: true,
+ level: portalLevel,
guid: ent[0]});
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
window.renderLink = function(ent) {
removeByGuid(ent[0]);
+ if(Object.keys(links).length >= MAX_DRAWN_LINKS) return;
+
var team = getTeam(ent[2]);
var edge = ent[2].edge;
var latlngs = [
@@ -359,10 +384,11 @@ window.renderLink = function(ent) {
];
var poly = L.polyline(latlngs, {
color: COLORS[team],
- opacity: 0.5,
+ opacity: 1,
weight:2,
clickable: false,
- guid: ent[0]
+ guid: ent[0],
+ smoothFactor: 10
});
if(!getPaddedBounds().intersects(poly.getBounds())) return;
@@ -375,6 +401,8 @@ window.renderLink = function(ent) {
// renders a field on the map from a given entity
window.renderField = function(ent) {
window.removeByGuid(ent[0]);
+ if(Object.keys(fields).length >= MAX_DRAWN_FIELDS) return;
+
var team = getTeam(ent[2]);
var reg = ent[2].capturedRegion;
var latlngs = [
@@ -387,6 +415,7 @@ window.renderField = function(ent) {
fillOpacity: 0.25,
stroke: false,
clickable: false,
+ smoothFactor: 10,
guid: ent[0]});
if(!getPaddedBounds().intersects(poly.getBounds())) return;
@@ -445,16 +474,18 @@ window.renderUpdateStatus = function() {
else
t += 'Up to date.';
+ if(renderLimitReached())
+ t += ' RENDER LIMIT '
+
if(window.failedRequestCount > 0)
t += ' ' + window.failedRequestCount + ' requests failed.'
- t += '
(';
- var conv = ['impossible', 8,8,7,7,6,6,5,5,4,4,3,3,2,2,1];
- var z = map.getZoom();
- if(z >= 16)
- t += 'requesting all portals';
+ t += '
(';
+ var minlvl = getMinPortalLevel();
+ if(minlvl === 0)
+ t += 'showing all portals';
else
- t+= 'only requesting portals with level '+conv[z]+' and up';
+ t+= 'only showing portals with level '+minlvl+' and up';
t += ')';
$('#updatestatus').html(t);
@@ -616,11 +647,26 @@ window.getPaddedBounds = function() {
});
}
if(window._storedPaddedBounds) return window._storedPaddedBounds;
+
var p = window.map.getBounds().pad(VIEWPORT_PAD_RATIO);
window._storedPaddedBounds = 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
// bottom. Works similar to the native scrollTop function.
@@ -815,6 +861,10 @@ load(JQUERY, LEAFLET).then(LLGMAPS).thenRun(boot);
window.chat = function() {};
+//
+// timestamp and clear management
+//
+
window.chat._oldFactionTimestamp = -1;
window.chat._newFactionTimestamp = -1;
window.chat._oldPublicTimestamp = -1;
@@ -828,8 +878,27 @@ window.chat.getNewestTimestamp = function(public) {
return chat['_new'+(public ? 'Public' : 'Faction')+'Timestamp'];
}
-
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.genPostData = function(public, getOlderMsgs) {
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 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+' )');
chat._oldBBox = bbs;
var ne = b.getNorthEast();
var sw = b.getSouthWest();
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),
minLngE6: Math.round(sw.lng*1E6),
maxLatE6: Math.round(ne.lat*1E6),
@@ -881,6 +950,8 @@ window.chat.genPostData = function(public, getOlderMsgs) {
return data;
}
+
+
//
// requesting faction
//
@@ -923,6 +994,7 @@ window.chat.requestNewFaction = function(isRetry) {
requests.add(r);
}
+
//
// handle faction
//
@@ -937,6 +1009,8 @@ window.chat.handleNewFaction = function(data, textStatus, jqXHR) {
chat.handleFaction(data, textStatus, jqXHR, false);
}
+
+
window.chat._displayedFactionGuids = [];
window.chat.handleFaction = function(data, textStatus, jqXHR, isOldMsgs) {
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.');
}
+ chat.clearIfRequired();
+
+ if(data.result.length === 0) return;
+
chat._newFactionTimestamp = data.result[0][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 scrollBefore = scrollBottom(c);
- if(isOldMsgs)
- c.prepend(msgs);
- else
- c.append(msgs);
-
+ chat.renderPlayerMsgsTo(true, data, isOldMsgs, chat._displayedFactionGuids);
chat.keepScrollPosition(c, scrollBefore, isOldMsgs);
- chat.needMoreMessages();
+
+ if(data.result.length >= CHAT_FACTION_ITEMS) chat.needMoreMessages();
}
+
+
//
// 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.');
}
+ chat.clearIfRequired();
+
+ if(data.result.length === 0) return;
+
chat._newPublicTimestamp = data.result[0][1];
chat._oldPublicTimestamp = data.result[data.result.length-1][1];
- chat.clearIfRequired();
-
- var c = $('#chat > div:visible');
+ var c = $('#chatautomated');
var scrollBefore = scrollBottom(c);
-
chat.handlePublicAutomated(data);
- //chat.handlePublicPlayer(data, 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) {
$.each(data.result, function(ind, json) { // newest first!
var time = json[1];
@@ -1125,14 +1171,10 @@ window.chat.handlePublicAutomated = function(data) {
});
if(chat.getActive() === 'automated')
- window.chat.renderAutomatedMsgsToBox();
+ window.chat.renderAutomatedMsgsTo();
}
-window.chat.getActive = function() {
- return $('#chatcontrols .active').text();
-}
-
-window.chat.renderAutomatedMsgsToBox = function() {
+window.chat.renderAutomatedMsgsTo = function() {
var x = window.chat._displayedPlayerActionTime;
// we don’t care about the GUIDs anymore
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');
- 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('');
+//
+// common
+//
+
+
+window.chat.renderPlayerMsgsTo = function(isFaction, data, isOldMsgs, dupCheckArr) {
+ 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
+ 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;
- chat.clear();
- chat._needsClearing = false;
+
+window.chat.renderDivider = function(text) {
+ return '─ '+text+' ────────────────────────────────────────────────────────────────────────────';
}
+
+window.chat.renderMsg = function(msg, nick, time, team) {
+ var ta = unixTimeToHHmm(time);
+ var tb = unixTimeToString(time, true);
+ var t = '';
+ var s = 'style="color:'+COLORS[team]+'"';
+ var title = nick.length >= 8 ? 'title="'+nick+'"' : '';
+ return ''+t+''+nick+''+msg+'
';
+}
+
+
+
+window.chat.getActive = function() {
+ return $('#chatcontrols .active').text();
+}
+
+
window.chat.toggle = function() {
var c = $('#chat, #chatcontrols');
if(c.hasClass('expand')) {
@@ -1190,12 +1297,14 @@ window.chat.toggle = function() {
}
}
+
window.chat.request = function() {
console.log('refreshing chat');
chat.requestNewFaction();
chat.requestNewPublic();
}
+
// checks if there are enough messages in the selected chat tab and
// loads more if not.
window.chat.needMoreMessages = function() {
@@ -1208,19 +1317,62 @@ window.chat.needMoreMessages = function() {
chat.requestOldPublic();
}
-window.chat.setupTime = function() {
- var inputTime = $('#chatinput time');
- var updateTime = function() {
- if(window.isIdle()) return;
- var d = new Date();
- inputTime.text(d.toLocaleTimeString().slice(0, 5));
- // update ON the minute (1ms after)
- setTimeout(updateTime, (60 - d.getSeconds()) * 1000 + 1);
- };
- updateTime();
- window.addResumeFunction(updateTime);
+
+window.chat.chooser = function(event) {
+ var t = $(event.target);
+ var tt = t.text();
+ var span = $('#chatinput span');
+
+ $('#chatcontrols .active').removeClass('active');
+ t.addClass('active');
+
+ $('#chat > div').hide();
+
+ 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 don’t
+ // 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._localRangeCircle = L.circle(map.getCenter(), CHAT_MIN_RANGE*1000);
@@ -1235,6 +1387,7 @@ window.chat.setup = function() {
});
window.chat.setupTime();
+ window.chat.setupPosting();
$('#chatfaction').scroll(function() {
var t = $(this);
@@ -1259,63 +1412,63 @@ window.chat.setup = function() {
}
-window.chat.renderMsg = function(msg, nick, time, team) {
- var ta = unixTimeToHHmm(time);
- var tb = unixTimeToString(time, true);
- var t = '';
- var s = 'style="color:'+COLORS[team]+'"';
- var title = nick.length >= 8 ? 'title="'+nick+'"' : '';
- return ''+t+''+nick+''+msg+'
';
-}
-
-window.chat.renderDivider = function(text) {
- return '─ '+text+' ────────────────────────────────────────────────────────────────────────────';
-}
-
-window.chat.chooser = function(event) {
- var t = $(event.target);
- var tt = t.text();
- var span = $('#chatinput span');
-
- $('#chatcontrols .active').removeClass('active');
- t.addClass('active');
-
- $('#chat > div').hide();
-
- switch(tt) {
- case 'faction':
- span.css('color', '');
- span.text('tell faction:');
- $('#chatfaction').show();
- break;
-
- case 'public':
- span.css('cssText', 'color: red !important');
- span.text('spam public:');
- $('#chatpublic').show();
- break;
-
- case 'automated':
- span.css('cssText', 'color: #bbb !important');
- span.text('tell Jarvis:');
- chat.renderAutomatedMsgsToBox();
- $('#chatautomated').show();
- break;
- }
+window.chat.setupTime = function() {
+ var inputTime = $('#chatinput time');
+ var updateTime = function() {
+ if(window.isIdle()) return;
+ var d = new Date();
+ inputTime.text(d.toLocaleTimeString().slice(0, 5));
+ // update ON the minute (1ms after)
+ setTimeout(updateTime, (60 - d.getSeconds()) * 1000 + 1);
+ };
+ updateTime();
+ window.addResumeFunction(updateTime);
}
-// 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 don’t
- // 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));
- }
+//
+// 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.postMsg = function() {
+ 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?');
+
+ var msg = $.trim($('#chatinput input').val());
+ if(!msg || msg === '') return;
+
+ var public = c === 'public';
+ var latlng = map.getCenter();
+
+ var data = {message: msg,
+ latE6: Math.round(latlng.lat*1E6),
+ lngE6: Math.round(latlng.lng*1E6),
+ factionOnly: !public};
+
+ window.postAjax('sendPlext', data,
+ function() { if(public) chat.requestNewPublic(); else chat.requestNewFaction(); },
+ function() {
+ alert('Your message could not be delivered. You can copy&' +
+ 'paste it here and try again if you want:\n\n'+msg);
+ }
+ );
+
+ $('#chatinput input').val('');
}
@@ -1563,7 +1716,7 @@ window.getTeam = function(details) {
window.idleTime = 0; // in minutes
setInterval('window.idleTime += 1', 60*1000);
-var idleReset = function (e) {
+var idleReset = function () {
// update immediately when the user comes back
if(isIdle()) {
window.idleTime = 0;
@@ -1659,11 +1812,11 @@ window.renderPortalDetails = function(guid) {
// collect and html-ify random data
var randDetails = [playerText, sinceText, getRangeText(d), getEnergyText(d), linksText, getAvgResoDistText(d)];
- randDetails = randDetails.map(function(e) {
- if(!e) return '';
- e = e.split(':');
- e = '';
- return e;
+ randDetails = randDetails.map(function(detail) {
+ if(!detail) return '';
+ detail = detail.split(':');
+ detail = '';
+ return detail;
}).join('\n');
// replacing causes flicker, so if the selected portal does not