merge main
This commit is contained in:
124
code/boot.js
124
code/boot.js
@ -5,6 +5,31 @@
|
||||
// created a basic framework. All of these functions should only ever
|
||||
// be run once.
|
||||
|
||||
|
||||
window.setupBackButton = function() {
|
||||
var c = window.isSmartphone()
|
||||
? window.smartphone.mapButton
|
||||
: $('#chatcontrols a.active');
|
||||
|
||||
window.setupBackButton._actions = [c.get(0)];
|
||||
$('#chatcontrols a').click(function() {
|
||||
// ignore shrink button
|
||||
if($(this).hasClass('toggle')) return;
|
||||
window.setupBackButton._actions.push(this);
|
||||
window.setupBackButton._actions = window.setupBackButton._actions.slice(-2);
|
||||
});
|
||||
|
||||
window.goBack = function() {
|
||||
var a = window.setupBackButton._actions[0];
|
||||
if(!a) return;
|
||||
$(a).click();
|
||||
window.setupBackButton._actions = [a];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
window.setupLargeImagePreview = function() {
|
||||
$('#portaldetails').on('click', '.imgpreview', function() {
|
||||
var ex = $('#largepreview');
|
||||
@ -23,6 +48,26 @@ window.setupLargeImagePreview = function() {
|
||||
});
|
||||
}
|
||||
|
||||
// adds listeners to the layer chooser such that a long press hides
|
||||
// all custom layers except the long pressed one.
|
||||
window.setupLayerChooserSelectOne = function() {
|
||||
$('.leaflet-control-layers-overlays').on('click taphold', 'label', function(e) {
|
||||
if(!e) return;
|
||||
if(!(e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.type === 'taphold')) return;
|
||||
|
||||
var isChecked = $(this).find('input').is(':checked');
|
||||
var checkSize = $('.leaflet-control-layers-overlays input:checked').length;
|
||||
if((isChecked && checkSize === 1) || checkSize === 0) {
|
||||
// if nothing is selected or the users long-clicks the only
|
||||
// selected element, assume all boxes should be checked again
|
||||
$('.leaflet-control-layers-overlays input:not(:checked)').click();
|
||||
} else {
|
||||
// uncheck all
|
||||
$('.leaflet-control-layers-overlays input:checked').click();
|
||||
$(this).find('input').click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.setupStyles = function() {
|
||||
$('head').append('<style>' +
|
||||
@ -58,10 +103,6 @@ window.setupMap = function() {
|
||||
{zoomControl: !(localStorage['iitc.zoom.buttons'] === 'false')}
|
||||
));
|
||||
|
||||
try {
|
||||
map.addLayer(views[readCookie('ingress.intelmap.type')]);
|
||||
} catch(e) { map.addLayer(views[0]); }
|
||||
|
||||
var addLayers = {};
|
||||
|
||||
portalsLayers = [];
|
||||
@ -81,16 +122,24 @@ window.setupMap = function() {
|
||||
addLayers['Links'] = linksLayer;
|
||||
|
||||
window.layerChooser = new L.Control.Layers({
|
||||
'OSM Cloudmade Midnight': views[0],
|
||||
'OSM Cloudmade Minimal': views[1],
|
||||
'OSM Midnight': views[0],
|
||||
'OSM Minimal': views[1],
|
||||
'OSM Mapnik': views[2],
|
||||
'Google Roads Ingress Style': views[3],
|
||||
'Default Ingress Map': views[3],
|
||||
'Google Roads': views[4],
|
||||
'Google Satellite': views[5],
|
||||
'Google Hybrid': views[6]
|
||||
}, addLayers);
|
||||
|
||||
map.addControl(window.layerChooser);
|
||||
|
||||
// set the map AFTER adding the layer chooser, or Chrome reorders the
|
||||
// layers. This likely leads to broken layer selection because the
|
||||
// views/cookie order does not match the layer chooser order.
|
||||
try {
|
||||
map.addLayer(views[readCookie('ingress.intelmap.type')]);
|
||||
} catch(e) { map.addLayer(views[0]); }
|
||||
|
||||
map.attributionControl.setPrefix('');
|
||||
// listen for changes and store them in cookies
|
||||
map.on('moveend', window.storeMapPosition);
|
||||
@ -136,11 +185,13 @@ window.setupMap = function() {
|
||||
// included as inline script in the original site, the data is static
|
||||
// and cannot be updated.
|
||||
window.setupPlayerStat = function() {
|
||||
PLAYER.guid = playerNameToGuid(PLAYER.nickname);
|
||||
var level;
|
||||
var ap = parseInt(PLAYER.ap);
|
||||
for(level = 0; level < MIN_AP_FOR_LEVEL.length; level++) {
|
||||
if(ap < MIN_AP_FOR_LEVEL[level]) break;
|
||||
}
|
||||
PLAYER.level = level;
|
||||
|
||||
var thisLvlAp = MIN_AP_FOR_LEVEL[level-1];
|
||||
var nextLvlAp = MIN_AP_FOR_LEVEL[level] || ap;
|
||||
@ -163,13 +214,22 @@ window.setupPlayerStat = function() {
|
||||
|
||||
$('#playerstat').html(''
|
||||
+ '<h2 title="'+t+'">'+level+' '
|
||||
+ '<div id="name">'
|
||||
+ '<span class="'+cls+'">'+PLAYER.nickname+'</span>'
|
||||
+ '<div>'
|
||||
+ '<a href="https://www.ingress.com/_ah/logout?continue=https://www.google.com/accounts/Logout%3Fcontinue%3Dhttps://appengine.google.com/_ah/logout%253Fcontinue%253Dhttps://www.ingress.com/intel%26service%3Dah" id="signout">sign out</a>'
|
||||
+ '</div>'
|
||||
+ '<div id="stats">'
|
||||
+ '<sup>XM: '+xmRatio+'%</sup>'
|
||||
+ '<sub>' + (level < 8 ? 'level: '+lvlApProg+'%' : 'max level') + '</sub>'
|
||||
+ '</div>'
|
||||
+ '</h2>'
|
||||
);
|
||||
|
||||
$('#name').mouseenter(function() {
|
||||
$('#signout').show();
|
||||
}).mouseleave(function() {
|
||||
$('#signout').hide();
|
||||
});
|
||||
}
|
||||
|
||||
window.setupSidebarToggle = function() {
|
||||
@ -226,6 +286,14 @@ window.setupDialogs = function() {
|
||||
}
|
||||
}
|
||||
|
||||
window.setupTaphold = function() {
|
||||
@@INCLUDERAW:external/taphold.js@@
|
||||
}
|
||||
|
||||
|
||||
window.setupQRLoadLib = function() {
|
||||
@@INCLUDERAW:external/jquery.qrcode.min.js@@
|
||||
}
|
||||
|
||||
|
||||
// BOOTING ///////////////////////////////////////////////////////////
|
||||
@ -233,17 +301,18 @@ window.setupDialogs = function() {
|
||||
function boot() {
|
||||
window.debug.console.overwriteNativeIfRequired();
|
||||
|
||||
console.log('loading done, booting. Built: ' + window.iitcBuildDate);
|
||||
console.log('loading done, booting. Built: @@BUILDDATE@@');
|
||||
if(window.deviceID) console.log('Your device ID: ' + window.deviceID);
|
||||
window.runOnSmartphonesBeforeBoot();
|
||||
|
||||
// overwrite default Leaflet Marker icon to be a neutral color
|
||||
var base = 'http://breunigs.github.com/ingress-intel-total-conversion/dist/images/';
|
||||
var base = 'https://iitcserv.appspot.com/dist/images';
|
||||
L.Icon.Default.imagePath = base;
|
||||
|
||||
window.iconEnl = L.Icon.Default.extend({options: { iconUrl: base + 'marker-green.png' } });
|
||||
window.iconRes = L.Icon.Default.extend({options: { iconUrl: base + 'marker-blue.png' } });
|
||||
window.iconEnl = L.Icon.Default.extend({options: { iconUrl: base + '/marker-green.png' } });
|
||||
window.iconRes = L.Icon.Default.extend({options: { iconUrl: base + '/marker-blue.png' } });
|
||||
|
||||
window.setupTaphold();
|
||||
window.setupStyles();
|
||||
window.setupDialogs();
|
||||
window.setupMap();
|
||||
@ -255,6 +324,9 @@ function boot() {
|
||||
window.setupPlayerStat();
|
||||
window.setupTooltips();
|
||||
window.chat.setup();
|
||||
window.setupQRLoadLib();
|
||||
window.setupLayerChooserSelectOne();
|
||||
window.setupBackButton();
|
||||
// read here ONCE, so the URL is only evaluated one time after the
|
||||
// necessary data has been loaded.
|
||||
urlPortal = getURLParam('pguid');
|
||||
@ -287,26 +359,18 @@ function boot() {
|
||||
// Copyright (c) 2010 Chris O'Hara <cohara87@gmail.com>. MIT Licensed
|
||||
function asyncLoadScript(a){return function(b,c){var d=document.createElement("script");d.type="text/javascript",d.src=a,d.onload=b,d.onerror=c,d.onreadystatechange=function(){var a=this.readyState;if(a==="loaded"||a==="complete")d.onreadystatechange=null,b()},head.insertBefore(d,head.firstChild)}}(function(a){a=a||{};var b={},c,d;c=function(a,d,e){var f=a.halt=!1;a.error=function(a){throw a},a.next=function(c){c&&(f=!1);if(!a.halt&&d&&d.length){var e=d.shift(),g=e.shift();f=!0;try{b[g].apply(a,[e,e.length,g])}catch(h){a.error(h)}}return a};for(var g in b){if(typeof a[g]=="function")continue;(function(e){a[e]=function(){var g=Array.prototype.slice.call(arguments);if(e==="onError"){if(d)return b.onError.apply(a,[g,g.length]),a;var h={};return b.onError.apply(h,[g,g.length]),c(h,null,"onError")}return g.unshift(e),d?(a.then=a[e],d.push(g),f?a:a.next()):c({},[g],e)}})(g)}return e&&(a.then=a[e]),a.call=function(b,c){c.unshift(b),d.unshift(c),a.next(!0)},a.next()},d=a.addMethod=function(d){var e=Array.prototype.slice.call(arguments),f=e.pop();for(var g=0,h=e.length;g<h;g++)typeof e[g]=="string"&&(b[e[g]]=f);--h||(b["then"+d.substr(0,1).toUpperCase()+d.substr(1)]=f),c(a)},d("chain",function(a){var b=this,c=function(){if(!b.halt){if(!a.length)return b.next(!0);try{null!=a.shift().call(b,c,b.error)&&c()}catch(d){b.error(d)}}};c()}),d("run",function(a,b){var c=this,d=function(){c.halt||--b||c.next(!0)},e=function(a){c.error(a)};for(var f=0,g=b;!c.halt&&f<g;f++)null!=a[f].call(c,d,e)&&d()}),d("defer",function(a){var b=this;setTimeout(function(){b.next(!0)},a.shift())}),d("onError",function(a,b){var c=this;this.error=function(d){c.halt=!0;for(var e=0;e<b;e++)a[e].call(c,d)}})})(this);var head=document.getElementsByTagName("head")[0]||document.documentElement;addMethod("load",function(a,b){for(var c=[],d=0;d<b;d++)(function(b){c.push(asyncLoadScript(a[b]))})(d);this.call("run",c)})
|
||||
|
||||
|
||||
try { console.log('Loading included JS now'); } catch(e) {}
|
||||
@@INCLUDERAW:external/leaflet.js@@
|
||||
// modified version of https://github.com/shramov/leaflet-plugins. Also
|
||||
// contains the default Ingress map style.
|
||||
var LEAFLETGOOGLE = 'http://breunigs.github.com/ingress-intel-total-conversion/dist/leaflet_google.js';
|
||||
@@INCLUDERAW:external/leaflet_google.js@@
|
||||
@@INCLUDERAW:external/autolink.js@@
|
||||
@@INCLUDERAW:external/oms.min.js@@
|
||||
|
||||
try { console.log('done loading included JS'); } catch(e) {}
|
||||
|
||||
var JQUERY = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';
|
||||
var JQUERYUI = 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js';
|
||||
var LEAFLET = 'http://cdn.leafletjs.com/leaflet-0.5/leaflet.js';
|
||||
var AUTOLINK = 'http://breunigs.github.com/ingress-intel-total-conversion/dist/autolink.js';
|
||||
var EMPTY = 'data:text/javascript;base64,';
|
||||
|
||||
// don’t download resources which have been injected already
|
||||
var ir = window && window.internalResources ? window.internalResources : [];
|
||||
if(ir.indexOf('jquery') !== -1) JQUERY = EMPTY;
|
||||
if(ir.indexOf('jqueryui') !== -1) JQUERYUI = EMPTY;
|
||||
if(ir.indexOf('leaflet') !== -1) LEAFLET = EMPTY;
|
||||
if(ir.indexOf('autolink') !== -1) AUTOLINK = EMPTY;
|
||||
if(ir.indexOf('leafletgoogle') !== -1) LEAFLETGOOGLE = EMPTY;
|
||||
|
||||
var JQUERYUI = 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js';
|
||||
|
||||
// after all scripts have loaded, boot the actual app
|
||||
load(JQUERY, LEAFLET, AUTOLINK).then(LEAFLETGOOGLE, JQUERYUI).onError(function (err) {
|
||||
alert('Could not all resources, the script likely won’t work.\n\nIf this happend the first time for you, it’s probably a temporary issue. Just wait a bit and try again.\n\nIf you installed the script for the first time and this happens:\n– try disabling NoScript if you have it installed\n– press CTRL+SHIFT+K in Firefox or CTRL+SHIFT+I in Chrome/Opera and reload the page. Additional info may be available in the console.\n– Open an issue at https://github.com/breunigs/ingress-intel-total-conversion/issues');
|
||||
}).thenRun(boot);
|
||||
load(JQUERY).then(JQUERYUI).thenRun(boot);
|
||||
|
33
code/chat.js
33
code/chat.js
@ -279,8 +279,14 @@ window.chat.writeDataToHash = function(newData, storageHash, skipSecureMsgs) {
|
||||
|
||||
case 'PORTAL':
|
||||
var latlng = [markup[1].latE6/1E6, markup[1].lngE6/1E6];
|
||||
var js = 'window.zoomToAndShowPortal(\''+markup[1].guid+'\', ['+latlng[0]+', '+latlng[1]+'])';
|
||||
msg += '<a onclick="'+js+'" title="'+markup[1].address+'" class="help">'+markup[1].name+'</a>';
|
||||
var perma = 'https://ingress.com/intel?latE6='+markup[1].latE6+'&lngE6='+markup[1].lngE6+'&z=17&pguid='+markup[1].guid;
|
||||
var js = 'window.zoomToAndShowPortal(\''+markup[1].guid+'\', ['+latlng[0]+', '+latlng[1]+']);return false';
|
||||
|
||||
msg += '<a onclick="'+js+'"'
|
||||
+ ' title="'+markup[1].address+'"'
|
||||
+ ' href="'+perma+'" class="help">'
|
||||
+ window.chat.getChatPortalName(markup[1])
|
||||
+ '</a>';
|
||||
break;
|
||||
|
||||
case 'SECURE':
|
||||
@ -299,6 +305,16 @@ window.chat.writeDataToHash = function(newData, storageHash, skipSecureMsgs) {
|
||||
});
|
||||
}
|
||||
|
||||
// Override portal names that are used over and over, such as 'US Post Office'
|
||||
window.chat.getChatPortalName = function(markup) {
|
||||
var name = markup.name;
|
||||
if(name === 'US Post Office') {
|
||||
var address = markup.address.split(',');
|
||||
name = 'USPS: ' + address[0];
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
// renders data from the data-hash to the element defined by the given
|
||||
// ID. Set 3rd argument to true if it is likely that old data has been
|
||||
// added. Latter is only required for scrolling.
|
||||
@ -341,7 +357,7 @@ window.chat.renderMsg = function(msg, nick, time, team) {
|
||||
var s = 'style="color:'+COLORS[team]+'"';
|
||||
var title = nick.length >= 8 ? 'title="'+nick+'" class="help"' : '';
|
||||
var i = ['<span class="invisep"><</span>', '<span class="invisep">></span>'];
|
||||
return '<tr><td>'+t+'</td><td>'+i[0]+'<mark '+s+'>'+nick+'</mark>'+i[1]+'</td><td>'+msg+'</td></tr>';
|
||||
return '<tr><td>'+t+'</td><td>'+i[0]+'<mark class="nickname" '+s+'>'+nick+'</mark>'+i[1]+'</td><td>'+msg+'</td></tr>';
|
||||
}
|
||||
|
||||
|
||||
@ -383,6 +399,7 @@ window.chat.needMoreMessages = function() {
|
||||
if(activeTab === 'debug') return;
|
||||
|
||||
var activeChat = $('#chat > :visible');
|
||||
if(activeChat.length === 0) return;
|
||||
|
||||
var hasScrollbar = scrollBottom(activeChat) !== 0 || activeChat.scrollTop() !== 0;
|
||||
var nearTop = activeChat.scrollTop() <= CHAT_REQUEST_SCROLL_TOP;
|
||||
@ -402,6 +419,7 @@ window.chat.chooser = function(event) {
|
||||
var tt = t.text();
|
||||
|
||||
var mark = $('#chatinput mark');
|
||||
var input = $('#chatinput input');
|
||||
|
||||
$('#chatcontrols .active').removeClass('active');
|
||||
t.addClass('active');
|
||||
@ -412,11 +430,13 @@ window.chat.chooser = function(event) {
|
||||
|
||||
switch(tt) {
|
||||
case 'faction':
|
||||
input.css('color', '');
|
||||
mark.css('color', '');
|
||||
mark.text('tell faction:');
|
||||
break;
|
||||
|
||||
case 'public':
|
||||
input.css('cssText', 'color: red !important');
|
||||
mark.css('cssText', 'color: red !important');
|
||||
mark.text('broadcast:');
|
||||
break;
|
||||
@ -424,6 +444,7 @@ window.chat.chooser = function(event) {
|
||||
case 'compact':
|
||||
case 'full':
|
||||
mark.css('cssText', 'color: #bbb !important');
|
||||
input.css('cssText', 'color: #bbb !important');
|
||||
mark.text('tell Jarvis:');
|
||||
break;
|
||||
|
||||
@ -567,13 +588,13 @@ window.chat.postMsg = function() {
|
||||
|
||||
if(c === 'debug') return new Function (msg)();
|
||||
|
||||
var public = c === 'public';
|
||||
var publik = c === 'public';
|
||||
var latlng = map.getCenter();
|
||||
|
||||
var data = {message: msg,
|
||||
latE6: Math.round(latlng.lat*1E6),
|
||||
lngE6: Math.round(latlng.lng*1E6),
|
||||
factionOnly: !public};
|
||||
factionOnly: !publik};
|
||||
|
||||
var errMsg = 'Your message could not be delivered. You can copy&' +
|
||||
'paste it here and try again if you want:\n\n' + msg;
|
||||
@ -581,7 +602,7 @@ window.chat.postMsg = function() {
|
||||
window.postAjax('sendPlext', data,
|
||||
function(response) {
|
||||
if(response.error) alert(errMsg);
|
||||
if(public) chat.requestPublic(false); else chat.requestFaction(false); },
|
||||
if(publik) chat.requestPublic(false); else chat.requestFaction(false); },
|
||||
function() {
|
||||
alert(errMsg);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ window.updateGameScore = function(data) {
|
||||
var es = '<span class="enl" style="width:'+ep+'%;"> '+Math.round(ep)+'%</span>';
|
||||
$('#gamestat').html(rs+es).one('click', function() { window.updateGameScore() });
|
||||
// help cursor via “#gamestat span”
|
||||
$('#gamestat').attr('title', 'Resistance:\t'+r+' MindUnits\nEnlightenment:\t'+e+' MindUnits');
|
||||
$('#gamestat').attr('title', 'Resistance:\t'+r+' MindUnits\nEnlightened:\t'+e+' MindUnits');
|
||||
|
||||
window.setTimeout('window.updateGameScore', REFRESH_GAME_SCORE*1000);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ window.setupGeosearch = function() {
|
||||
northEast = new L.LatLng(b[1], b[3]),
|
||||
bounds = new L.LatLngBounds(southWest, northEast);
|
||||
window.map.fitBounds(bounds);
|
||||
if(window.isSmartphone()) window.smartphone.mapButton.click();
|
||||
});
|
||||
e.preventDefault();
|
||||
});
|
||||
|
@ -43,13 +43,18 @@
|
||||
// redrawn. It is called early on in the
|
||||
// code/map_data.js#renderPortal as long as there was an
|
||||
// old portal for the guid.
|
||||
|
||||
// checkRenderLimit: callback is passed the argument of
|
||||
// {reached : false} to indicate that the renderlimit is reached
|
||||
// set reached to true.
|
||||
// requestFinished: called after each request finished. Argument is
|
||||
// {success: boolean} indicated the request success or fail.
|
||||
|
||||
|
||||
|
||||
window._hooks = {}
|
||||
window.VALID_HOOKS = ['portalAdded', 'portalDetailsUpdated',
|
||||
'publicChatDataAvailable', 'portalDataLoaded', 'beforePortalReRender'];
|
||||
'publicChatDataAvailable', 'portalDataLoaded', 'beforePortalReRender',
|
||||
'checkRenderLimit', 'requestFinished'];
|
||||
|
||||
window.runHooks = function(event, data) {
|
||||
if(VALID_HOOKS.indexOf(event) === -1) throw('Unknown event type: ' + event);
|
||||
|
169
code/map_data.js
169
code/map_data.js
@ -43,25 +43,35 @@ window.requestData = function() {
|
||||
}
|
||||
}
|
||||
|
||||
// Reset previous result of Portal Render Limit handler
|
||||
portalRenderLimit.init();
|
||||
// finally send ajax requests
|
||||
$.each(tiles, function(ind, tls) {
|
||||
data = { minLevelOfDetail: -1 };
|
||||
data.boundsParamsList = tls;
|
||||
window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse));
|
||||
window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse, window.handleFailedRequest));
|
||||
});
|
||||
}
|
||||
|
||||
// Handle failed map data request
|
||||
window.handleFailedRequest = function() {
|
||||
if(requests.isLastRequest('getThinnedEntitiesV2')) {
|
||||
var leftOverPortals = portalRenderLimit.mergeLowLevelPortals(null);
|
||||
handlePortalsRender(leftOverPortals);
|
||||
}
|
||||
runHooks('requestFinished', {success: false});
|
||||
}
|
||||
|
||||
// works on map data response and ensures entities are drawn/updated.
|
||||
window.handleDataResponse = function(data, textStatus, jqXHR) {
|
||||
// remove from active ajax queries list
|
||||
if(!data || !data.result) {
|
||||
window.failedRequestCount++;
|
||||
console.warn(data);
|
||||
handleFailedRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
var portalUpdateAvailable = false;
|
||||
var portalInUrlAvailable = false;
|
||||
var m = data.result.map;
|
||||
// defer rendering of portals because there is no z-index in SVG.
|
||||
// this means that what’s rendered last ends up on top. While the
|
||||
@ -71,7 +81,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
|
||||
var ppp = [];
|
||||
var p2f = {};
|
||||
$.each(m, function(qk, val) {
|
||||
$.each(val.deletedGameEntityGuids, function(ind, guid) {
|
||||
$.each(val.deletedGameEntityGuids || [], function(ind, guid) {
|
||||
if(getTypeByGuid(guid) === TYPE_FIELD && window.fields[guid] !== undefined) {
|
||||
$.each(window.fields[guid].options.vertices, function(ind, vertex) {
|
||||
if(window.portals[vertex.guid] === undefined) return true;
|
||||
@ -82,14 +92,12 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
|
||||
window.removeByGuid(guid);
|
||||
});
|
||||
|
||||
$.each(val.gameEntities, function(ind, ent) {
|
||||
$.each(val.gameEntities || [], function(ind, ent) {
|
||||
// ent = [GUID, id(?), details]
|
||||
// format for links: { controllingTeam, creator, edge }
|
||||
// format for portals: { controllingTeam, turret }
|
||||
|
||||
if(ent[2].turret !== undefined) {
|
||||
if(selectedPortal === ent[0]) portalUpdateAvailable = true;
|
||||
if(urlPortal && ent[0] == urlPortal) portalInUrlAvailable = true;
|
||||
|
||||
var latlng = [ent[2].locationE6.latE6/1E6, ent[2].locationE6.lngE6/1E6];
|
||||
if(!window.getPaddedBounds().contains(latlng)
|
||||
@ -125,18 +133,37 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
|
||||
}
|
||||
});
|
||||
|
||||
// Preserve and restore "selectedPortal" between portal re-render
|
||||
if(portalUpdateAvailable) var oldSelectedPortal = selectedPortal;
|
||||
// Process the portals with portal render limit handler first
|
||||
// Low level portal will hold until last request
|
||||
var newPpp = portalRenderLimit.splitOrMergeLowLevelPortals(ppp);
|
||||
handlePortalsRender(newPpp);
|
||||
|
||||
runHooks('portalDataLoaded', {portals : ppp});
|
||||
$.each(ppp, function(ind, portal) { renderPortal(portal); });
|
||||
resolvePlayerNames();
|
||||
renderUpdateStatus();
|
||||
runHooks('requestFinished', {success: true});
|
||||
}
|
||||
|
||||
var selectedPortalLayer = portals[oldSelectedPortal];
|
||||
if(portalUpdateAvailable && selectedPortalLayer) selectedPortal = oldSelectedPortal;
|
||||
window.handlePortalsRender = function(portals) {
|
||||
var portalInUrlAvailable = false;
|
||||
|
||||
if(selectedPortalLayer) {
|
||||
// Preserve selectedPortal because it will get lost on re-rendering
|
||||
// the portal
|
||||
var oldSelectedPortal = selectedPortal;
|
||||
|
||||
runHooks('portalDataLoaded', {portals : portals});
|
||||
$.each(portals, function(ind, portal) {
|
||||
//~ if(selectedPortal === portal[0]) portalUpdateAvailable = true;
|
||||
if(urlPortal && portal[0] === urlPortal) portalInUrlAvailable = true;
|
||||
renderPortal(portal);
|
||||
});
|
||||
|
||||
// restore selected portal if still available
|
||||
var selectedPortalGroup = portals[oldSelectedPortal];
|
||||
if(selectedPortalGroup) {
|
||||
selectedPortal = oldSelectedPortal;
|
||||
renderPortalDetails(selectedPortal);
|
||||
try {
|
||||
selectedPortalLayer.bringToFront();
|
||||
selectedPortalGroup.bringToFront();
|
||||
} catch(e) { /* portal is now visible, catch Leaflet error */ }
|
||||
}
|
||||
|
||||
@ -144,9 +171,6 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
|
||||
renderPortalDetails(urlPortal);
|
||||
urlPortal = null; // select it only once
|
||||
}
|
||||
|
||||
if(portalUpdateAvailable) renderPortalDetails(selectedPortal);
|
||||
resolvePlayerNames();
|
||||
}
|
||||
|
||||
// removes entities that are still handled by Leaflet, although they
|
||||
@ -174,10 +198,13 @@ window.cleanUp = function() {
|
||||
cnt[1]++;
|
||||
linksLayer.removeLayer(link);
|
||||
});
|
||||
fieldsLayer.eachLayer(function(field) {
|
||||
if(b.intersects(field.getBounds())) return;
|
||||
cnt[2]++;
|
||||
fieldsLayer.removeLayer(field);
|
||||
fieldsLayer.eachLayer(function(fieldgroup) {
|
||||
fieldgroup.eachLayer(function(item) {
|
||||
if(!item.options.guid) return true; // Skip MU div container as this doesn't have the bounds we need
|
||||
if(b.intersects(item.getBounds())) return;
|
||||
cnt[2]++;
|
||||
fieldsLayer.removeLayer(fieldgroup);
|
||||
});
|
||||
});
|
||||
console.log('removed out-of-bounds: '+cnt[0]+' portals, '+cnt[1]+' links, '+cnt[2]+' fields');
|
||||
}
|
||||
@ -261,8 +288,11 @@ window.renderPortal = function(ent) {
|
||||
// pre-loads player names for high zoom levels
|
||||
loadPlayerNamesForPortal(ent[2]);
|
||||
|
||||
var lvWeight = Math.max(2, portalLevel / 1.5);
|
||||
var lvRadius = Math.max(portalLevel + 3, 5);
|
||||
var lvWeight = Math.max(2, Math.floor(portalLevel) / 1.5);
|
||||
var lvRadius = Math.floor(portalLevel) + 4;
|
||||
if(team === window.TEAM_NONE) {
|
||||
lvRadius = 7;
|
||||
}
|
||||
|
||||
var p = L.circleMarker(latlng, {
|
||||
radius: lvRadius + (L.Browser.mobile ? PORTAL_RADIUS_ENLARGE_MOBILE : 0),
|
||||
@ -422,6 +452,7 @@ window.isResonatorsShow = function() {
|
||||
|
||||
window.isSameResonator = function(oldRes, newRes) {
|
||||
if(!oldRes && !newRes) return true;
|
||||
if(!oldRes || !newRes) return false;
|
||||
if(typeof oldRes !== typeof newRes) return false;
|
||||
if(oldRes.level !== newRes.level) return false;
|
||||
if(oldRes.energyTotal !== newRes.energyTotal) return false;
|
||||
@ -481,8 +512,18 @@ window.renderLink = function(ent) {
|
||||
weight:2,
|
||||
clickable: false,
|
||||
guid: ent[0],
|
||||
smoothFactor: 10
|
||||
data: ent[2],
|
||||
smoothFactor: 0 // doesn’t work for two points anyway, so disable
|
||||
});
|
||||
// determine which links are very short and don’t render them at all.
|
||||
// in most cases this will go unnoticed, but improve rendering speed.
|
||||
poly._map = window.map;
|
||||
poly.projectLatlngs();
|
||||
var op = poly._originalPoints;
|
||||
var dist = Math.abs(op[0].x - op[1].x) + Math.abs(op[0].y - op[1].y);
|
||||
if(dist <= 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!getPaddedBounds().intersects(poly.getBounds())) return;
|
||||
|
||||
@ -501,17 +542,18 @@ window.renderField = function(ent) {
|
||||
if(Object.keys(fields).length >= MAX_DRAWN_FIELDS)
|
||||
return window.removeByGuid(ent[0]);
|
||||
|
||||
// assume that fields never change. If they do, they will have a
|
||||
// different ID.
|
||||
if(findEntityInLeaflet(fieldsLayer, fields, ent[0])) return;
|
||||
var old = findEntityInLeaflet(fieldsLayer, window.fields, ent[0]);
|
||||
// If this already exists and the zoom level has not changed, we don't need to do anything
|
||||
if(old && map.getZoom() === old.options.creationZoom) return;
|
||||
|
||||
var team = getTeam(ent[2]);
|
||||
var reg = ent[2].capturedRegion;
|
||||
var latlngs = [
|
||||
[reg.vertexA.location.latE6/1E6, reg.vertexA.location.lngE6/1E6],
|
||||
[reg.vertexB.location.latE6/1E6, reg.vertexB.location.lngE6/1E6],
|
||||
[reg.vertexC.location.latE6/1E6, reg.vertexC.location.lngE6/1E6]
|
||||
L.latLng(reg.vertexA.location.latE6/1E6, reg.vertexA.location.lngE6/1E6),
|
||||
L.latLng(reg.vertexB.location.latE6/1E6, reg.vertexB.location.lngE6/1E6),
|
||||
L.latLng(reg.vertexC.location.latE6/1E6, reg.vertexC.location.lngE6/1E6)
|
||||
];
|
||||
|
||||
var poly = L.polygon(latlngs, {
|
||||
fillColor: COLORS[team],
|
||||
fillOpacity: 0.25,
|
||||
@ -523,16 +565,77 @@ window.renderField = function(ent) {
|
||||
guid: ent[0],
|
||||
data: ent[2]});
|
||||
|
||||
// determine which fields are too small to be rendered and don’t
|
||||
// render them, so they don’t count towards the maximum fields limit.
|
||||
// This saves some DOM operations as well, but given the relatively
|
||||
// low amount of fields there isn’t much to gain.
|
||||
// The algorithm is the same as used by Leaflet.
|
||||
poly._map = window.map;
|
||||
poly.projectLatlngs();
|
||||
var count = L.LineUtil.simplify(poly._originalPoints, 6).length;
|
||||
if(count <= 2) return;
|
||||
|
||||
if(!getPaddedBounds().intersects(poly.getBounds())) return;
|
||||
|
||||
// Curve fit equation to normalize zoom window area
|
||||
var areaZoomRatio = calcTriArea(latlngs)/Math.exp(14.2714860198866-1.384987247*map.getZoom());
|
||||
var countForMUDisplay = L.LineUtil.simplify(poly._originalPoints, FIELD_MU_DISPLAY_POINT_TOLERANCE).length
|
||||
|
||||
// Do nothing if zoom did not change. We need to recheck the field if the
|
||||
// zoom level is different then when the field was rendered as it could
|
||||
// now be appropriate or not to show an MU count
|
||||
if(old) {
|
||||
var layerCount = 0;
|
||||
old.eachLayer(function(item) {
|
||||
layerCount++;
|
||||
});
|
||||
// Don't do anything since we already have an MU display and we still want to
|
||||
if(areaZoomRatio > FIELD_MU_DISPLAY_AREA_ZOOM_RATIO && countForMUDisplay > 2 && layerCount === 2) return;
|
||||
// Don't do anything since we don't have an MU display and don't want to
|
||||
if(areaZoomRatio <= FIELD_MU_DISPLAY_AREA_ZOOM_RATIO && countForMUDisplay <= 2 && layerCount === 1) return;
|
||||
removeByGuid(ent[0]);
|
||||
}
|
||||
|
||||
// put both in one group, so they can be handled by the same logic.
|
||||
if (areaZoomRatio > FIELD_MU_DISPLAY_AREA_ZOOM_RATIO && countForMUDisplay > 2) {
|
||||
// centroid of field for placing MU count at
|
||||
var centroid = [
|
||||
(latlngs[0].lat + latlngs[1].lat + latlngs[2].lat)/3,
|
||||
(latlngs[0].lng + latlngs[1].lng + latlngs[2].lng)/3
|
||||
];
|
||||
|
||||
var fieldMu = L.marker(centroid, {
|
||||
icon: L.divIcon({
|
||||
className: 'fieldmu',
|
||||
iconSize: [70,12],
|
||||
html: digits(ent[2].entityScore.entityScore)
|
||||
}),
|
||||
clickable: false
|
||||
});
|
||||
var f = L.layerGroup([poly, fieldMu]);
|
||||
} else {
|
||||
var f = L.layerGroup([poly]);
|
||||
}
|
||||
f.options = {
|
||||
vertices: reg,
|
||||
lastUpdate: ent[1],
|
||||
creationZoom: map.getZoom(),
|
||||
guid: ent[0],
|
||||
data: ent[2]
|
||||
};
|
||||
|
||||
// However, LayerGroups (and FeatureGroups) don’t fire add/remove
|
||||
// events, thus this listener will be attached to the field. It
|
||||
// doesn’t matter to which element these are bound since Leaflet
|
||||
// will add/remove all elements of the LayerGroup at once.
|
||||
poly.on('remove', function() { delete window.fields[this.options.guid]; });
|
||||
poly.on('add', function() {
|
||||
// enable for debugging
|
||||
if(window.fields[this.options.guid]) console.warn('duplicate field detected');
|
||||
window.fields[this.options.guid] = this;
|
||||
window.fields[this.options.guid] = f;
|
||||
this.bringToBack();
|
||||
});
|
||||
poly.addTo(fieldsLayer);
|
||||
f.addTo(fieldsLayer);
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,6 +17,17 @@ window.getPlayerName = function(guid) {
|
||||
return '{'+guid.slice(0, 12)+'}';
|
||||
}
|
||||
|
||||
window.playerNameToGuid = function(playerName){
|
||||
var guid = null;
|
||||
$.each(Object.keys(localStorage), function(ind,key) {
|
||||
if(playerName === localStorage[key]) {
|
||||
guid = key;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return guid;
|
||||
}
|
||||
|
||||
// resolves all player GUIDs that have been added to the list. Reruns
|
||||
// renderPortalDetails when finished, so that then-unresolved names
|
||||
// get replaced by their correct versions.
|
||||
|
@ -22,11 +22,14 @@ window.renderPortalDetails = function(guid) {
|
||||
var linksText = [linkExpl('links'), linkExpl(' ↳ ' + links.incoming+' • '+links.outgoing+' ↴')];
|
||||
|
||||
var player = d.captured && d.captured.capturingPlayerId
|
||||
? getPlayerName(d.captured.capturingPlayerId)
|
||||
? '<span class="nickname">' + getPlayerName(d.captured.capturingPlayerId) + '</span>'
|
||||
: null;
|
||||
var playerText = player ? ['owner', player] : null;
|
||||
|
||||
var time = d.captured ? unixTimeToString(d.captured.capturedTime) : null;
|
||||
var time = d.captured
|
||||
? '<span title="' + unixTimeToString(d.captured.capturedTime, true) + '">'
|
||||
+ unixTimeToString(d.captured.capturedTime) + '</span>'
|
||||
: null;
|
||||
var sinceText = time ? ['since', time] : null;
|
||||
|
||||
var linkedFields = ['fields', d.portalV2.linkedFields.length];
|
||||
@ -41,13 +44,15 @@ window.renderPortalDetails = function(guid) {
|
||||
var resoDetails = '<table id="resodetails">' + getResonatorDetails(d) + '</table>';
|
||||
|
||||
setPortalIndicators(d);
|
||||
var img = d.imageByUrl && d.imageByUrl.imageUrl ? d.imageByUrl.imageUrl : DEFAULT_PORTAL_IMG;
|
||||
var img = d.imageByUrl && d.imageByUrl.imageUrl
|
||||
? d.imageByUrl.imageUrl
|
||||
: DEFAULT_PORTAL_IMG;
|
||||
|
||||
var lat = d.locationE6.latE6;
|
||||
var lng = d.locationE6.lngE6;
|
||||
var perma = 'http://ingress.com/intel?latE6='+lat+'&lngE6='+lng+'&z=17&pguid='+guid;
|
||||
var perma = 'https://ingress.com/intel?latE6='+lat+'&lngE6='+lng+'&z=17&pguid='+guid;
|
||||
var imgTitle = 'title="'+getPortalDescriptionFromDetails(d)+'\n\nClick to show full image."';
|
||||
var gmaps = 'https://maps.google.com/?q='+lat/1E6+','+lng/1E6;
|
||||
var poslinks = 'window.showPortalPosLinks('+lat/1E6+','+lng/1E6+')';
|
||||
var postcard = 'Send in a postcard. Will put it online after receiving. Address:\\n\\nStefan Breunig\\nINF 305 – R045\\n69120 Heidelberg\\nGermany';
|
||||
|
||||
$('#portaldetails')
|
||||
@ -63,7 +68,7 @@ window.renderPortalDetails = function(guid) {
|
||||
+ randDetails
|
||||
+ resoDetails
|
||||
+ '<div class="linkdetails">'+ '<aside><a href="'+perma+'">portal link</a></aside>'
|
||||
+ '<aside><a href="'+gmaps+'" target="_blank">gmaps</a></aside>'
|
||||
+ '<aside><a onclick="'+poslinks+'">poslinks</a></aside>'
|
||||
+ '<aside><a onclick="alert(\''+postcard+'\');">donate</a></aside>'
|
||||
+ '<aside><a onclick="window.reportPortalIssue()">report issue</a></aside>'
|
||||
+ '</div>'
|
||||
|
@ -132,6 +132,7 @@ window.renderResonatorDetails = function(slot, level, nrg, dist, nick) {
|
||||
|
||||
var meter = '<span class="meter" title="'+inf+'">' + fill + lbar + '</span>';
|
||||
}
|
||||
nick = nick ? '<span class="nickname">'+nick+'</span>' : null;
|
||||
return [meter, nick || ''];
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ window.getAvgResoDist = function(d) {
|
||||
sum += parseInt(reso.distanceToPortal);
|
||||
resos++;
|
||||
});
|
||||
return sum/resos;
|
||||
return resos ? sum/resos : 0;
|
||||
}
|
||||
|
||||
window.getAttackApGain = function(d) {
|
||||
|
155
code/portal_render_limit.js
Normal file
155
code/portal_render_limit.js
Normal file
@ -0,0 +1,155 @@
|
||||
|
||||
// PORTAL RENDER LIMIT HANDLER ///////////////////////////////////////
|
||||
// Functions to handle hiding low level portal when portal render
|
||||
// limit is reached.
|
||||
//
|
||||
// On initialization, previous minLevel will preserve to previousMinLevel
|
||||
// with zoom level difference.
|
||||
//
|
||||
// After initialized and reset in window.requestData(), "processPortals"
|
||||
// intercept all portals data in "handleDataResponse". Put the count of
|
||||
// new portals to newPortalsPerLevel[portal level]. And split portals
|
||||
// into two parts base on previousMinLevel. Portals with level >=
|
||||
// previousMinLevel will return as result and continue to render.
|
||||
// Others will save to portalsPreviousMinLevel. If there is no more
|
||||
// active request of map data, portals will not split and
|
||||
// portalsPreviousMinLevel will add back to result and render base on
|
||||
// current minLevel.
|
||||
//
|
||||
// "handleFailRequest" is added to handle the case when the last request
|
||||
// failed and "processPortals" didn't get called. It will get
|
||||
// portalsPreviousMinLevel base on current minLevel and render them.
|
||||
//
|
||||
// "getMinLevel" will be called by "getMinPortalLevel" in utils_misc.js
|
||||
// to determine min portal level to draw on map.
|
||||
//
|
||||
// "getMinLevel" will return minLevel and call "setMinLevel" if
|
||||
// minLevel hasn't set yet.
|
||||
//
|
||||
// In "setMinLevel", it will loop through all portal level from
|
||||
// high to low, and sum total portal count (old + new) to check
|
||||
// minLevel.
|
||||
//
|
||||
// In each call of window.handleDataResponse(), it will call
|
||||
// "resetCounting" to reset previous response data. But minLevel
|
||||
// is preserved and only replaced when render limit reached in
|
||||
// higher level, until next window.requestData() called and reset.
|
||||
//
|
||||
|
||||
window.portalRenderLimit = function() {}
|
||||
|
||||
window.portalRenderLimit.initialized = false;
|
||||
window.portalRenderLimit.minLevelSet = false;
|
||||
window.portalRenderLimit.minLevel = -1;
|
||||
window.portalRenderLimit.previousMinLevel = -1;
|
||||
window.portalRenderLimit.previousZoomLevel;
|
||||
window.portalRenderLimit.newPortalsPerLevel = new Array(MAX_PORTAL_LEVEL + 1);
|
||||
window.portalRenderLimit.portalsPreviousMinLevel = new Array(MAX_PORTAL_LEVEL + 1);
|
||||
|
||||
window.portalRenderLimit.init = function () {
|
||||
var currentZoomLevel = map.getZoom();
|
||||
portalRenderLimit.previousZoomLevel = portalRenderLimit.previousZoomLevel || currentZoomLevel;
|
||||
|
||||
// If there is a minLevel set in previous run, calculate previousMinLevel with it.
|
||||
if(portalRenderLimit.minLevelSet) {
|
||||
var zoomDiff = currentZoomLevel - portalRenderLimit.previousZoomLevel;
|
||||
portalRenderLimit.previousMinLevel = Math.max(portalRenderLimit.minLevel - zoomDiff, -1);
|
||||
portalRenderLimit.previousMinLevel = Math.min(portalRenderLimit.previousMinLevel, MAX_PORTAL_LEVEL);
|
||||
}
|
||||
|
||||
portalRenderLimit.previousZoomLevel = currentZoomLevel;
|
||||
|
||||
portalRenderLimit.initialized = true;
|
||||
portalRenderLimit.minLevel = -1;
|
||||
portalRenderLimit.resetCounting();
|
||||
portalRenderLimit.resetPortalsPreviousMinLevel();
|
||||
}
|
||||
|
||||
window.portalRenderLimit.resetCounting = function() {
|
||||
portalRenderLimit.minLevelSet = false;
|
||||
for(var i = 0; i <= MAX_PORTAL_LEVEL; i++) {
|
||||
portalRenderLimit.newPortalsPerLevel[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
window.portalRenderLimit.resetPortalsPreviousMinLevel = function() {
|
||||
for(var i = 0; i <= MAX_PORTAL_LEVEL; i++) {
|
||||
portalRenderLimit.portalsPreviousMinLevel[i] = new Array();
|
||||
}
|
||||
}
|
||||
|
||||
window.portalRenderLimit.splitOrMergeLowLevelPortals = function(originPortals) {
|
||||
portalRenderLimit.resetCounting();
|
||||
portalRenderLimit.countingPortals(originPortals);
|
||||
|
||||
var resultPortals = requests.isLastRequest('getThinnedEntitiesV2')
|
||||
? portalRenderLimit.mergeLowLevelPortals(originPortals)
|
||||
: portalRenderLimit.splitLowLevelPortals(originPortals);
|
||||
|
||||
return resultPortals;
|
||||
}
|
||||
|
||||
window.portalRenderLimit.countingPortals = function(portals) {
|
||||
$.each(portals, function(ind, portal) {
|
||||
var portalGuid = portal[0];
|
||||
var portalLevel = parseInt(getPortalLevel(portal[2]));
|
||||
var layerGroup = portalsLayers[portalLevel];
|
||||
|
||||
if(findEntityInLeaflet(layerGroup, window.portals, portalGuid)) return true;
|
||||
|
||||
portalRenderLimit.newPortalsPerLevel[portalLevel]++;
|
||||
});
|
||||
}
|
||||
|
||||
window.portalRenderLimit.splitLowLevelPortals = function(portals) {
|
||||
var resultPortals = new Array();
|
||||
$.each(portals, function(ind, portal) {
|
||||
var portalLevel = parseInt(getPortalLevel(portal[2]));
|
||||
if(portalLevel < portalRenderLimit.previousMinLevel) {
|
||||
portalRenderLimit.portalsPreviousMinLevel[portalLevel].push(portal);
|
||||
}else{
|
||||
resultPortals.push(portal);
|
||||
}
|
||||
});
|
||||
return resultPortals;
|
||||
}
|
||||
|
||||
window.portalRenderLimit.mergeLowLevelPortals = function(appendTo) {
|
||||
var resultPortals = appendTo ? appendTo : new Array();
|
||||
for(var i = portalRenderLimit.getMinLevel();
|
||||
i < portalRenderLimit.previousMinLevel;
|
||||
i++) {
|
||||
$.merge(resultPortals, portalRenderLimit.portalsPreviousMinLevel[i]);
|
||||
}
|
||||
|
||||
// Reset portalsPreviousMinLevel, ensure they return only once
|
||||
portalRenderLimit.resetPortalsPreviousMinLevel();
|
||||
return resultPortals;
|
||||
}
|
||||
|
||||
window.portalRenderLimit.getMinLevel = function() {
|
||||
if(!portalRenderLimit.initialized) return -1;
|
||||
if(!portalRenderLimit.minLevelSet) portalRenderLimit.setMinLevel();
|
||||
return portalRenderLimit.minLevel;
|
||||
}
|
||||
|
||||
window.portalRenderLimit.setMinLevel = function() {
|
||||
var totalPortalsCount = 0;
|
||||
var newMinLevel = MAX_PORTAL_LEVEL + 1;
|
||||
|
||||
// Find the min portal level under render limit
|
||||
while(newMinLevel > 0) {
|
||||
var oldPortalCount = layerGroupLength(portalsLayers[newMinLevel - 1]);
|
||||
var newPortalCount = portalRenderLimit.newPortalsPerLevel[newMinLevel - 1];
|
||||
totalPortalsCount += oldPortalCount + newPortalCount;
|
||||
if(totalPortalsCount >= MAX_DRAWN_PORTALS)
|
||||
break;
|
||||
newMinLevel--;
|
||||
}
|
||||
|
||||
// If render limit reached at max portal level, still let portal at max level render
|
||||
newMinLevel = Math.min(newMinLevel, MAX_PORTAL_LEVEL);
|
||||
|
||||
portalRenderLimit.minLevel = Math.max(newMinLevel, portalRenderLimit.minLevel);
|
||||
portalRenderLimit.minLevelSet = true;
|
||||
}
|
@ -3,44 +3,69 @@
|
||||
// REDEEMING /////////////////////////////////////////////////////////
|
||||
|
||||
window.handleRedeemResponse = function(data, textStatus, jqXHR) {
|
||||
if (data.error) {
|
||||
if(data.error) {
|
||||
var error = '';
|
||||
if (data.error === 'ALREADY_REDEEMED') {
|
||||
if(data.error === 'ALREADY_REDEEMED') {
|
||||
error = 'The passcode has already been redeemed.';
|
||||
} else if (data.error === 'ALREADY_REDEEMED_BY_PLAYER') {
|
||||
} else if(data.error === 'ALREADY_REDEEMED_BY_PLAYER') {
|
||||
error = 'You have already redeemed this passcode.';
|
||||
} else if (data.error === 'INVALID_PASSCODE') {
|
||||
} else if(data.error === 'INVALID_PASSCODE') {
|
||||
error = 'This passcode is invalid.';
|
||||
} else {
|
||||
error = 'The passcode cannot be redeemed.';
|
||||
error = 'There was a problem redeeming the passcode. Try again?';
|
||||
}
|
||||
alert("Error: " + data.error + "\n" + error);
|
||||
} else if (data.result) {
|
||||
var res_level = 0, res_count = 0;
|
||||
var xmp_level = 0, xmp_count = 0;
|
||||
var shield_rarity = '', shield_count = 0;
|
||||
|
||||
// This assumes that each passcode gives only one type of resonator/XMP/shield.
|
||||
// This may break at some point, depending on changes to passcode functionality.
|
||||
for (var i in data.result.inventoryAward) {
|
||||
alert('<strong>' + data.error + '</strong>\n' + error);
|
||||
} else if(data.result) {
|
||||
var tblResult = $('<table class="redeem-result" />');
|
||||
tblResult.append($('<tr><th colspan="2">Passcode accepted!</th></tr>'));
|
||||
|
||||
if(data.result.apAward)
|
||||
tblResult.append($('<tr><td>+</td><td>' + data.result.apAward + 'AP</td></tr>'));
|
||||
if(data.result.xmAward)
|
||||
tblResult.append($('<tr><td>+</td><td>' + data.result.xmAward + 'XM</td></tr>'));
|
||||
|
||||
var resonators = {};
|
||||
var bursts = {};
|
||||
var shields = {};
|
||||
|
||||
for(var i in data.result.inventoryAward) {
|
||||
var acquired = data.result.inventoryAward[i][2];
|
||||
if (acquired.modResource) {
|
||||
if (acquired.modResource.resourceType === 'RES_SHIELD') {
|
||||
shield_rarity = acquired.modResource.rarity.split('_').map(function (i) {return i[0]}).join('');
|
||||
shield_count++;
|
||||
if(acquired.modResource) {
|
||||
if(acquired.modResource.resourceType === 'RES_SHIELD') {
|
||||
var rarity = acquired.modResource.rarity.split('_').map(function (i) {return i[0]}).join('');
|
||||
if(!shields[rarity]) shields[rarity] = 0;
|
||||
shields[rarity] += 1;
|
||||
}
|
||||
} else if (acquired.resourceWithLevels) {
|
||||
if (acquired.resourceWithLevels.resourceType === 'EMITTER_A') {
|
||||
res_level = acquired.resourceWithLevels.level;
|
||||
res_count++;
|
||||
} else if (acquired.resourceWithLevels.resourceType === 'EMP_BURSTER') {
|
||||
xmp_level = acquired.resourceWithLevels.level;
|
||||
xmp_count++;
|
||||
} else if(acquired.resourceWithLevels) {
|
||||
if(acquired.resourceWithLevels.resourceType === 'EMITTER_A') {
|
||||
var level = acquired.resourceWithLevels.level
|
||||
if(!resonators[level]) resonators[level] = 0;
|
||||
resonators[level] += 1;
|
||||
} else if(acquired.resourceWithLevels.resourceType === 'EMP_BURSTER') {
|
||||
var level = acquired.resourceWithLevels.level
|
||||
if(!bursts[level]) bursts[level] = 0;
|
||||
bursts[level] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$.each(resonators, function(lvl, count) {
|
||||
var text = 'Resonator';
|
||||
if(count >= 2) text += ' ('+count+')';
|
||||
tblResult.append($('<tr ><td style="color: ' +window.COLORS_LVL[lvl]+ ';">L' +lvl+ '</td><td>' + text + '</td></tr>'));
|
||||
});
|
||||
$.each(bursts, function(lvl, count) {
|
||||
var text = 'Xmp Burster';
|
||||
if(count >= 2) text += ' ('+count+')';
|
||||
tblResult.append($('<tr ><td style="color: ' +window.COLORS_LVL[lvl]+ ';">L' +lvl+ '</td><td>' + text + '</td></tr>'));
|
||||
});
|
||||
$.each(shields, function(lvl, count) {
|
||||
var text = 'Portal Shield';
|
||||
if(count >= 2) text += ' ('+count+')';
|
||||
tblResult.append($('<tr><td>'+lvl+'</td><td>'+text+'</td></tr>'));
|
||||
});
|
||||
|
||||
alert("Passcode redeemed!\n" + [data.result.apAward + 'AP', data.result.xmAward + 'XM', res_count + 'xL' + res_level + ' RES', xmp_count + 'xL' + xmp_level + ' XMP', shield_count + 'x' + shield_rarity + ' SHIELD'].join('/'));
|
||||
alert(tblResult, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,6 +74,19 @@ window.setupRedeem = function() {
|
||||
if((e.keyCode ? e.keyCode : e.which) != 13) return;
|
||||
var data = {passcode: $(this).val()};
|
||||
window.postAjax('redeemReward', data, window.handleRedeemResponse,
|
||||
function() { alert('The HTTP request failed. Either your code is invalid or their servers are down. No way to tell.'); });
|
||||
function(response) {
|
||||
var extra = '';
|
||||
if(response && response.status) {
|
||||
if(response.status === 429) {
|
||||
extra = 'You have been rate-limited by the server. Wait a bit and try again.';
|
||||
} else {
|
||||
extra = 'The server indicated an error.';
|
||||
}
|
||||
extra += '\nResponse: HTTP <a href="http://httpstatus.es/' + response.status + '" alt="HTTP ' + response.status + '">' + response.status + '</a>.';
|
||||
} else {
|
||||
extra = 'No status code was returned.';
|
||||
}
|
||||
alert('<strong>The HTTP request failed.</strong> ' + extra);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -111,3 +111,14 @@ window.requests._callOnRefreshFunctions = function() {
|
||||
window.requests.addRefreshFunction = function(f) {
|
||||
window.requests._onRefreshFunctions.push(f);
|
||||
}
|
||||
|
||||
window.requests.isLastRequest = function(action) {
|
||||
var result = true;
|
||||
$.each(window.activeRequests, function(ind, req) {
|
||||
if(req.action === action) {
|
||||
result = false;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
@ -49,13 +49,6 @@ window.runOnSmartphonesBeforeBoot = function() {
|
||||
|
||||
$('#chatcontrols').append(smartphone.mapButton).append(smartphone.sideButton);
|
||||
|
||||
// add event to portals that allows long press to switch to sidebar
|
||||
window.addHook('portalAdded', function(data) {
|
||||
data.portal.on('dblclick', function() {
|
||||
window.lastClickedPortal = this.options.guid;
|
||||
});
|
||||
});
|
||||
|
||||
window.addHook('portalDetailsUpdated', function(data) {
|
||||
var x = $('.imgpreview img').removeClass('hide');
|
||||
|
||||
@ -83,4 +76,23 @@ window.runOnSmartphonesAfterBoot = function() {
|
||||
$('#portaldetails').off('click', '**');
|
||||
|
||||
$('.leaflet-right').addClass('leaflet-left').removeClass('leaflet-right');
|
||||
|
||||
// make buttons in action bar flexible
|
||||
var l = $('#chatcontrols a:visible');
|
||||
l.css('width', 100/l.length + '%');
|
||||
|
||||
// add event to portals that allows long press to switch to sidebar
|
||||
window.addHook('portalAdded', function(data) {
|
||||
data.portal.on('add', function() {
|
||||
if(!this._container || this.options.addedTapHoldHandler) return;
|
||||
this.options.addedTapHoldHandler = true;
|
||||
var guid = this.options.guid;
|
||||
|
||||
// this is a hack, accessing Leaflet’s private _container is evil
|
||||
$(this._container).on('taphold', function() {
|
||||
window.renderPortalDetails(guid);
|
||||
window.smartphone.sideButton.click();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -2,6 +2,14 @@
|
||||
|
||||
// UTILS + MISC ///////////////////////////////////////////////////////
|
||||
|
||||
window.layerGroupLength = function(layerGroup) {
|
||||
var layersCount = 0;
|
||||
var layers = layerGroup._layers;
|
||||
if (layers)
|
||||
layersCount = Object.keys(layers).length;
|
||||
return layersCount;
|
||||
}
|
||||
|
||||
// retrieves parameter from the URL?query=string.
|
||||
window.getURLParam = function(param) {
|
||||
var v = document.URL;
|
||||
@ -50,11 +58,11 @@ window.postAjax = function(action, data, success, error) {
|
||||
data = JSON.stringify($.extend({method: 'dashboard.'+action}, data));
|
||||
var remove = function(data, textStatus, jqXHR) { window.requests.remove(jqXHR); };
|
||||
var errCnt = function(jqXHR) { window.failedRequestCount++; window.requests.remove(jqXHR); };
|
||||
return $.ajax({
|
||||
var result = $.ajax({
|
||||
// use full URL to avoid issues depending on how people set their
|
||||
// slash. See:
|
||||
// https://github.com/breunigs/ingress-intel-total-conversion/issues/56
|
||||
url: 'http://www.ingress.com/rpc/dashboard.'+action,
|
||||
url: 'https://www.ingress.com/rpc/dashboard.'+action,
|
||||
type: 'POST',
|
||||
data: data,
|
||||
dataType: 'json',
|
||||
@ -65,6 +73,8 @@ window.postAjax = function(action, data, success, error) {
|
||||
req.setRequestHeader('X-CSRFToken', readCookie('csrftoken'));
|
||||
}
|
||||
});
|
||||
result.action = action;
|
||||
return result;
|
||||
}
|
||||
|
||||
// converts unix timestamps to HH:mm:ss format if it was today;
|
||||
@ -96,8 +106,16 @@ window.rangeLinkClick = function() {
|
||||
window.smartphone.mapButton.click();
|
||||
}
|
||||
|
||||
window.showPortalPosLinks = function(lat, lng) {
|
||||
var qrcode = '<div id="qrcode"></div>';
|
||||
var script = '<script>$(\'#qrcode\').qrcode({text:\'GEO:'+lat+','+lng+'\'});</script>';
|
||||
var gmaps = '<a href="https://maps.google.com/?q='+lat+','+lng+'">gmaps</a>';
|
||||
var osm = '<a href="http://www.openstreetmap.org/?mlat='+lat+'&mlon='+lng+'&zoom=16">OSM</a>';
|
||||
alert('<div style="text-align: center;">' + qrcode + script + gmaps + ' ' + osm + '</div>');
|
||||
}
|
||||
|
||||
window.reportPortalIssue = function(info) {
|
||||
var t = 'Redirecting you to a Google Help Page. Once there, click on “Contact Us” in the upper right corner.\n\nThe text box contains all necessary information. Press CTRL+C to copy it.';
|
||||
var t = 'Redirecting you to a Google Help Page.\n\nThe text box contains all necessary information. Press CTRL+C to copy it.';
|
||||
var d = window.portals[window.selectedPortal].options.details;
|
||||
|
||||
var info = 'Your Nick: ' + PLAYER.nickname + ' '
|
||||
@ -107,7 +125,7 @@ window.reportPortalIssue = function(info) {
|
||||
|
||||
//codename, approx addr, portalname
|
||||
if(prompt(t, info) !== null)
|
||||
location.href = 'https://support.google.com/ingress?hl=en';
|
||||
location.href = 'https://support.google.com/ingress?hl=en&contact=1';
|
||||
}
|
||||
|
||||
window._storedPaddedBounds = undefined;
|
||||
@ -117,6 +135,7 @@ window.getPaddedBounds = function() {
|
||||
window._storedPaddedBounds = null;
|
||||
});
|
||||
}
|
||||
if(renderLimitReached(0.7)) return window.map.getBounds();
|
||||
if(window._storedPaddedBounds) return window._storedPaddedBounds;
|
||||
|
||||
var p = window.map.getBounds().pad(VIEWPORT_PAD_RATIO);
|
||||
@ -124,18 +143,30 @@ window.getPaddedBounds = function() {
|
||||
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;
|
||||
// returns true if the render limit has been reached. The default ratio
|
||||
// is 1, which means it will tell you if there are more items drawn than
|
||||
// acceptable. A value of 0.9 will tell you if 90% of the amount of
|
||||
// acceptable entities have been drawn. You can use this to heuristi-
|
||||
// cally detect if the render limit will be hit.
|
||||
window.renderLimitReached = function(ratio) {
|
||||
ratio = ratio || 1;
|
||||
if(Object.keys(portals).length*ratio >= MAX_DRAWN_PORTALS) return true;
|
||||
if(Object.keys(links).length*ratio >= MAX_DRAWN_LINKS) return true;
|
||||
if(Object.keys(fields).length*ratio >= MAX_DRAWN_FIELDS) return true;
|
||||
var param = { 'reached': false };
|
||||
window.runHooks('checkRenderLimit', param);
|
||||
return param.reached;
|
||||
}
|
||||
|
||||
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];
|
||||
var minLevelByRenderLimit = portalRenderLimit.getMinLevel();
|
||||
var result = minLevelByRenderLimit > conv[z]
|
||||
? minLevelByRenderLimit
|
||||
: conv[z];
|
||||
return result;
|
||||
}
|
||||
|
||||
// returns number of pixels left to scroll down before reaching the
|
||||
@ -213,7 +244,7 @@ window.setPermaLink = function(elm) {
|
||||
var lat = Math.round(c.lat*1E6);
|
||||
var lng = Math.round(c.lng*1E6);
|
||||
var qry = 'latE6='+lat+'&lngE6='+lng+'&z=' + (map.getZoom()-1);
|
||||
$(elm).attr('href', 'http://www.ingress.com/intel?' + qry);
|
||||
$(elm).attr('href', 'https://www.ingress.com/intel?' + qry);
|
||||
}
|
||||
|
||||
window.uniqueArray = function(arr) {
|
||||
@ -267,3 +298,8 @@ window.convertTextToTableMagic = function(text) {
|
||||
table += '</table>';
|
||||
return table;
|
||||
}
|
||||
|
||||
// Given 3 sets of points in an array[3]{lat, lng} returns the area of the triangle
|
||||
window.calcTriArea = function(p) {
|
||||
return Math.abs((p[0].lat*(p[1].lng-p[2].lng)+p[1].lat*(p[2].lng-p[0].lng)+p[2].lat*(p[0].lng-p[1].lng))/2);
|
||||
}
|
||||
|
Reference in New Issue
Block a user