This commit is contained in:
Jeremy Lindgren 2013-04-25 09:51:59 -05:00
commit 9908175bb2
29 changed files with 515 additions and 142 deletions

View File

@ -8,7 +8,14 @@ import base64
import sys import sys
import os import os
import shutil import shutil
import json
import shelve
import hashlib
try:
import urllib2
except ImportError:
import urllib.request as urllib2
# load settings file # load settings file
from buildsettings import buildSettings from buildsettings import buildSettings
@ -66,6 +73,33 @@ def loaderRaw(var):
fn = var.group(1) fn = var.group(1)
return readfile(fn) return readfile(fn)
def loaderMD(var):
fn = var.group(1)
# use different MD.dat's for python 2 vs 3 incase user switches versions, as they are not compatible
db = shelve.open('build/MDv' + str(sys.version_info.major) + '.dat')
if 'files' in db:
files = db['files']
else:
files = {}
file = readfile(fn)
filemd5 = hashlib.md5(file.encode('utf8')).hexdigest()
# check if file has already been parsed by the github api
if fn in files and filemd5 in files[fn]:
# use the stored copy if nothing has changed to avoid hiting the api more then the 60/hour when not signed in
db.close()
return files[fn][filemd5]
else:
url = 'https://api.github.com/markdown'
payload = {'text': file, 'mode': 'markdown'}
headers = {'Content-Type': 'application/json'}
req = urllib2.Request(url, json.dumps(payload).encode('utf8'), headers)
md = urllib2.urlopen(req).read().decode('utf8').replace('\n', '').replace('\'', '\\\'')
files[fn] = {}
files[fn][filemd5] = md
db['files'] = files
db.close()
return md
def loaderImage(var): def loaderImage(var):
fn = var.group(1) fn = var.group(1)
return 'data:image/png;base64,{0}'.format(base64.encodestring(open(fn, 'rb').read()).decode('utf8').replace('\n', '')) return 'data:image/png;base64,{0}'.format(base64.encodestring(open(fn, 'rb').read()).decode('utf8').replace('\n', ''))
@ -86,6 +120,7 @@ def doReplacements(script,updateUrl,downloadUrl):
script = re.sub('@@INCLUDERAW:([0-9a-zA-Z_./-]+)@@', loaderRaw, script) script = re.sub('@@INCLUDERAW:([0-9a-zA-Z_./-]+)@@', loaderRaw, script)
script = re.sub('@@INCLUDESTRING:([0-9a-zA-Z_./-]+)@@', loaderString, script) script = re.sub('@@INCLUDESTRING:([0-9a-zA-Z_./-]+)@@', loaderString, script)
script = re.sub('@@INCLUDEMD:([0-9a-zA-Z_./-]+)@@', loaderMD, script)
script = re.sub('@@INCLUDEIMAGE:([0-9a-zA-Z_./-]+)@@', loaderImage, script) script = re.sub('@@INCLUDEIMAGE:([0-9a-zA-Z_./-]+)@@', loaderImage, script)
script = script.replace('@@BUILDDATE@@', buildDate) script = script.replace('@@BUILDDATE@@', buildDate)
@ -156,6 +191,14 @@ for fn in glob.glob("plugins/*.user.js"):
metafn = fn.replace('.user.js', '.meta.js') metafn = fn.replace('.user.js', '.meta.js')
saveScriptAndMeta(script, os.path.join(outDir,fn), os.path.join(outDir,metafn)) saveScriptAndMeta(script, os.path.join(outDir,fn), os.path.join(outDir,metafn))
def copytree(src, dst, symlinks=False, ignore=None):
for item in os.listdir(src):
s = os.path.join(src, item)
d = os.path.join(dst, item)
if os.path.isdir(s):
shutil.copytree(s, d, symlinks, ignore)
else:
shutil.copy2(s, d)
# if we're building mobile too # if we're building mobile too
if buildMobile: if buildMobile:
@ -169,7 +212,12 @@ if buildMobile:
pass pass
shutil.copy(os.path.join(outDir,"total-conversion-build.user.js"), "mobile/assets/iitc.js") shutil.copy(os.path.join(outDir,"total-conversion-build.user.js"), "mobile/assets/iitc.js")
# TODO? also copy plugins - once the mobile app supports plugins, that is # also copy plugins
try:
os.makedirs("mobile/assets/plugins")
except:
pass
copytree(os.path.join(outDir,"plugins"), "mobile/assets/plugins")
# now launch 'ant' to build the mobile project # now launch 'ant' to build the mobile project

View File

@ -118,8 +118,9 @@ window.setupMap = function() {
//MapQuest offer tiles - http://developer.mapquest.com/web/products/open/map //MapQuest offer tiles - http://developer.mapquest.com/web/products/open/map
//their usage policy has no limits (except required notification above 4000 tiles/sec - we're perhaps at 50 tiles/sec based on CloudMade stats) //their usage policy has no limits (except required notification above 4000 tiles/sec - we're perhaps at 50 tiles/sec based on CloudMade stats)
var mqSubdomains = [ 'otile1','otile2', 'otile3', 'otile4' ]; var mqSubdomains = [ 'otile1','otile2', 'otile3', 'otile4' ];
var mqTileUrlPrefix = window.location.protocol !== 'https:' ? 'http://{s}.mqcdn.com' : 'https://{s}-s.mqcdn.com';
var mqMapOpt = {attribution: osmAttribution+', Tiles Courtesy of MapQuest', mazZoom: 18, detectRetena: true, subdomains: mqSubdomains}; var mqMapOpt = {attribution: osmAttribution+', Tiles Courtesy of MapQuest', mazZoom: 18, detectRetena: true, subdomains: mqSubdomains};
var mqMap = new L.TileLayer('http://{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg',mqMapOpt); var mqMap = new L.TileLayer(mqTileUrlPrefix+'/tiles/1.0.0/map/{z}/{x}/{y}.jpg',mqMapOpt);
//MapQuest satellite coverage outside of the US is rather limited - so not really worth having as we have google as an option //MapQuest satellite coverage outside of the US is rather limited - so not really worth having as we have google as an option
//var mqSatOpt = {attribution: 'Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency', mazZoom: 18, detectRetena: true, subdomains: mqSubdomains}; //var mqSatOpt = {attribution: 'Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency', mazZoom: 18, detectRetena: true, subdomains: mqSubdomains};
//var mqSat = new L.TileLayer('http://{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg',mqSatOpt); //var mqSat = new L.TileLayer('http://{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg',mqSatOpt);
@ -128,8 +129,8 @@ window.setupMap = function() {
/*0*/ mqMap, /*0*/ mqMap,
/*1*/ new L.Google('INGRESS'), /*1*/ new L.Google('INGRESS'),
/*2*/ new L.Google('ROADMAP'), /*2*/ new L.Google('ROADMAP'),
/*3*/ new L.Google('SATELLITE'), /*3*/ new L.Google('SATELLITE',{maxZoom:20}),
/*4*/ new L.Google('HYBRID') /*4*/ new L.Google('HYBRID',{maxZoom:20})
]; ];

View File

@ -410,12 +410,12 @@ window.chat.renderMsg = function(msg, nick, time, team, msgToPlayer, systemNarro
var s = 'style="cursor:pointer; color:'+color+'"'; var s = 'style="cursor:pointer; color:'+color+'"';
var title = nick.length >= 8 ? 'title="'+nick+'" class="help"' : ''; var title = nick.length >= 8 ? 'title="'+nick+'" class="help"' : '';
var i = ['<span class="invisep">&lt;</span>', '<span class="invisep">&gt;</span>']; var i = ['<span class="invisep">&lt;</span>', '<span class="invisep">&gt;</span>'];
return '<tr><td>'+t+'</td><td>'+i[0]+'<mark class="nickname" onclick="window.chat.nicknameClicked(event, \'' + nick + '\')" ' + 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>';
} }
window.chat.addNickname= function(nick){ window.chat.addNickname= function(nick){
var c = document.getElementById("chattext"); var c = document.getElementById("chattext");
c.value = [c.value, nick, " "].join(" ").trim() + " "; c.value = [c.value.trim(), nick].join(" ").trim() + " ";
c.focus() c.focus()
} }
@ -589,7 +589,11 @@ window.chat.setup = function() {
window.requests.addRefreshFunction(chat.request); window.requests.addRefreshFunction(chat.request);
var cls = PLAYER.team === 'ALIENS' ? 'enl' : 'res'; var cls = PLAYER.team === 'ALIENS' ? 'enl' : 'res';
$('#chatinput mark').addClass(cls) $('#chatinput mark').addClass(cls);
$(window).on('click', '.nickname', function(event) {
window.chat.nicknameClicked(event, $(this).text());
});
} }

View File

@ -12,34 +12,30 @@ window.requestData = function() {
requests.abort(); requests.abort();
cleanUp(); cleanUp();
var magic = convertCenterLat(map.getCenter().lat);
var R = calculateR(magic);
var bounds = map.getBounds(); var bounds = map.getBounds();
// convert to point values
topRight = convertLatLngToPoint(bounds.getNorthEast(), magic, R); var x1 = lngToTile(bounds.getNorthWest().lng, map.getZoom());
bottomLeft = convertLatLngToPoint(bounds.getSouthWest() , magic, R); var x2 = lngToTile(bounds.getNorthEast().lng, map.getZoom());
// how many quadrants intersect the current view? var y1 = latToTile(bounds.getNorthWest().lat, map.getZoom());
quadsX = Math.abs(bottomLeft.x - topRight.x); var y2 = latToTile(bounds.getSouthWest().lat, map.getZoom());
quadsY = Math.abs(bottomLeft.y - topRight.y);
// will group requests by second-last quad-key quadrant // will group requests by second-last quad-key quadrant
tiles = {}; tiles = {};
// walk in x-direction, starts right goes left // walk in x-direction, starts right goes left
for(var i = 0; i <= quadsX; i++) { for (var x = x1; x <= x2; x++) {
var x = Math.abs(topRight.x - i); for (var y = y1; y <= y2; y++) {
var qk = pointToQuadKey(x, topRight.y); var tile_id = pointToTileId(map.getZoom(), x, y);
var bnds = convertPointToLatLng(x, topRight.y, magic, R); var bucket = Math.floor(x / 2) + "" + Math.floor(y / 2);
if(!tiles[qk.slice(0, -1)]) tiles[qk.slice(0, -1)] = []; if (!tiles[bucket])
tiles[qk.slice(0, -1)].push(generateBoundsParams(qk, bnds)); tiles[bucket] = [];
tiles[bucket].push(generateBoundsParams(
// walk in y-direction, starts top, goes down tile_id,
for(var j = 1; j <= quadsY; j++) { tileToLat(y + 1, map.getZoom()),
var qk = pointToQuadKey(x, topRight.y + j); tileToLng(x, map.getZoom()),
var bnds = convertPointToLatLng(x, topRight.y + j, magic, R); tileToLat(y, map.getZoom()),
if(!tiles[qk.slice(0, -1)]) tiles[qk.slice(0, -1)] = []; tileToLng(x + 1, map.getZoom())
tiles[qk.slice(0, -1)].push(generateBoundsParams(qk, bnds)); ));
} }
} }
@ -47,7 +43,7 @@ window.requestData = function() {
portalRenderLimit.init(); portalRenderLimit.init();
// finally send ajax requests // finally send ajax requests
$.each(tiles, function(ind, tls) { $.each(tiles, function(ind, tls) {
data = { minLevelOfDetail: -1 }; data = { zoom: map.getZoom() };
data.boundsParamsList = tls; data.boundsParamsList = tls;
window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse, window.handleFailedRequest)); window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse, window.handleFailedRequest));
}); });
@ -78,7 +74,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
// portals can be brought to front, this costs extra time. They need // portals can be brought to front, this costs extra time. They need
// to be in the foreground, or they cannot be clicked. See // to be in the foreground, or they cannot be clicked. See
// https://github.com/Leaflet/Leaflet/issues/185 // https://github.com/Leaflet/Leaflet/issues/185
var ppp = []; var ppp = {};
var p2f = {}; var p2f = {};
$.each(m, function(qk, val) { $.each(m, function(qk, val) {
$.each(val.deletedGameEntityGuids || [], function(ind, guid) { $.each(val.deletedGameEntityGuids || [], function(ind, guid) {
@ -105,9 +101,17 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
&& urlPortal !== ent[0] && urlPortal !== ent[0]
) return; ) return;
if('imageByUrl' in ent[2] && 'imageUrl' in ent[2].imageByUrl) {
if(window.location.protocol === 'https:') {
ent[2].imageByUrl.imageUrl = ent[2].imageByUrl.imageUrl.indexOf('www.panoramio.com') !== -1
? ent[2].imageByUrl.imageUrl.replace(/^http:\/\/www/, 'https://ssl').replace('small', 'medium')
: ent[2].imageByUrl.imageUrl.replace(/^http:\/\//, '//');
}
} else {
ent[2].imageByUrl = {'imageUrl': DEFAULT_PORTAL_IMG};
}
ppp[ent[0]] = ent; // delay portal render
ppp.push(ent); // delay portal render
} else if(ent[2].edge !== undefined) { } else if(ent[2].edge !== undefined) {
renderLink(ent); renderLink(ent);
} else if(ent[2].capturedRegion !== undefined) { } else if(ent[2].capturedRegion !== undefined) {
@ -124,6 +128,25 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
}); });
$.each(ppp, function(ind, portal) { $.each(ppp, function(ind, portal) {
if ('portalV2' in portal[2] && 'linkedEdges' in portal[2].portalV2) {
$.each(portal[2].portalV2.linkedEdges, function (ind, edge) {
if (!ppp[edge.otherPortalGuid])
return;
renderLink([
edge.edgeGuid,
portal[1],
{
"controllingTeam": portal[2].controllingTeam,
"edge": {
"destinationPortalGuid": edge.isOrigin ? ppp[edge.otherPortalGuid][0] : portal[0],
"destinationPortalLocation": edge.isOrigin ? ppp[edge.otherPortalGuid][2].locationE6 : portal[2].locationE6,
"originPortalGuid": !edge.isOrigin ? ppp[edge.otherPortalGuid][0] : portal[0],
"originPortalLocation": !edge.isOrigin ? ppp[edge.otherPortalGuid][2].locationE6 : portal[2].locationE6
}
}
]);
});
}
if(portal[2].portalV2['linkedFields'] === undefined) { if(portal[2].portalV2['linkedFields'] === undefined) {
portal[2].portalV2['linkedFields'] = []; portal[2].portalV2['linkedFields'] = [];
} }

View File

@ -1,79 +1,45 @@
// MAP DATA REQUEST CALCULATORS ////////////////////////////////////// // MAP DATA REQUEST CALCULATORS //////////////////////////////////////
// Ingress Intel splits up requests for map data (portals, links, // Ingress Intel splits up requests for map data (portals, links,
// fields) into tiles. To get data for the current viewport (i.e. what // fields) into tiles. To get data for the current viewport (i.e. what
// is currently visible) it first calculates which tiles intersect. // is currently visible) it first calculates which tiles intersect.
// For all those tiles, it then calculates the lat/lng bounds of that // For all those tiles, it then calculates the lat/lng bounds of that
// tile and a quadkey. Both the bounds and the quadkey are “somewhat” // tile and a quadkey. Both the bounds and the quadkey are “somewhat”
// required to get complete data. No idea how the projection between // required to get complete data.
// lat/lng and tiles works. //
// What follows now are functions that allow conversion between tiles // Convertion functions courtesy of
// and lat/lng as well as calculating the quad key. The variable names // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
// may be misleading.
// The minified source for this code was in gen_dashboard.js after the
// “// input 89” line (alternatively: the class was called “Xe”).
window.convertCenterLat = function(centerLat) { window.lngToTile = function(lng, zoom) {
return Math.round(256 * 0.9999 * Math.abs(1 / Math.cos(centerLat * DEG2RAD))); return Math.floor((lng + 180) / 360 * Math.pow(2, zoom));
} }
window.calculateR = function(convCenterLat) { window.latToTile = function(lat, zoom) {
return 1 << window.map.getZoom() - (convCenterLat / 256 - 1); return Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) +
1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom));
} }
window.convertLatLngToPoint = function(latlng, magic, R) { window.tileToLng = function(x, zoom) {
var x = (magic/2 + latlng.lng * magic / 360)*R; return x / Math.pow(2, zoom) * 360 - 180;
var l = Math.sin(latlng.lat * DEG2RAD);
var y = (magic/2 + 0.5*Math.log((1+l)/(1-l)) * -(magic / (2*Math.PI)))*R;
return {x: Math.floor(x/magic), y: Math.floor(y/magic)};
} }
window.convertPointToLatLng = function(x, y, magic, R) { window.tileToLat = function(y, zoom) {
var e = {}; var n = Math.PI - 2 * Math.PI * y / Math.pow(2, zoom);
e.sw = { return 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
// orig function put together from all over the place
// lat: (2 * Math.atan(Math.exp((((y + 1) * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180),
// shortened version by your favorite algebra program.
lat: (360*Math.atan(Math.exp(Math.PI - 2*Math.PI*(y+1)/R)))/Math.PI - 90,
lng: 360*x/R-180
};
e.ne = {
//lat: (2 * Math.atan(Math.exp(((y * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180),
lat: (360*Math.atan(Math.exp(Math.PI - 2*Math.PI*y/R)))/Math.PI - 90,
lng: 360*(x+1)/R-180
};
return e;
} }
// calculates the quad key for a given point. The point is not(!) in window.pointToTileId = function(zoom, x, y) {
// lat/lng format. return zoom + "_" + x + "_" + y;
window.pointToQuadKey = function(x, y) {
var quadkey = [];
for(var c = window.map.getZoom(); c > 0; c--) {
// +-------+ quadrants are probably ordered like this
// | 0 | 1 |
// |---|---|
// | 2 | 3 |
// |---|---|
var quadrant = 0;
var e = 1 << c - 1;
(x & e) != 0 && quadrant++; // push right
(y & e) != 0 && (quadrant++, quadrant++); // push down
quadkey.push(quadrant);
}
return quadkey.join("");
} }
// given quadkey and bounds, returns the format as required by the // given tile id and bounds, returns the format as required by the
// Ingress API to request map data. // Ingress API to request map data.
window.generateBoundsParams = function(quadkey, bounds) { window.generateBoundsParams = function(tile_id, minLat, minLng, maxLat, maxLng) {
return { return {
id: quadkey, id: tile_id,
qk: quadkey, qk: tile_id,
minLatE6: Math.round(bounds.sw.lat * 1E6), minLatE6: Math.round(minLat * 1E6),
minLngE6: Math.round(bounds.sw.lng * 1E6), minLngE6: Math.round(minLng * 1E6),
maxLatE6: Math.round(bounds.ne.lat * 1E6), maxLatE6: Math.round(maxLat * 1E6),
maxLngE6: Math.round(bounds.ne.lng * 1E6) maxLngE6: Math.round(maxLng * 1E6)
}; };
} }

View File

@ -44,10 +44,7 @@ window.renderPortalDetails = function(guid) {
var resoDetails = '<table id="resodetails">' + getResonatorDetails(d) + '</table>'; var resoDetails = '<table id="resodetails">' + getResonatorDetails(d) + '</table>';
setPortalIndicators(d); setPortalIndicators(d);
var img = d.imageByUrl && d.imageByUrl.imageUrl var img = d.imageByUrl.imageUrl;
? d.imageByUrl.imageUrl
: DEFAULT_PORTAL_IMG;
var lat = d.locationE6.latE6; var lat = d.locationE6.latE6;
var lng = d.locationE6.lngE6; var lng = d.locationE6.lngE6;
var perma = '/intel?latE6='+lat+'&lngE6='+lng+'&z=17&pguid='+guid; var perma = '/intel?latE6='+lat+'&lngE6='+lng+'&z=17&pguid='+guid;

View File

@ -1,7 +1,8 @@
// UTILS + MISC /////////////////////////////////////////////////////// // UTILS + MISC ///////////////////////////////////////////////////////
window.aboutIITC = function(){ window.aboutIITC = function(){
var v = '@@BUILDNAME@@-@@BUILDDATE@@' var v = '@@BUILDNAME@@-@@BUILDDATE@@';
var attrib = '@@INCLUDEMD:ATTRIBUTION.md@@';
var a = '' var a = ''
+ ' <div><b>About IITC</b></div> ' + ' <div><b>About IITC</b></div> '
+ ' <div>Ingress Intel Total Conversion</div> ' + ' <div>Ingress Intel Total Conversion</div> '
@ -20,8 +21,11 @@ window.aboutIITC = function(){
+ ' MapQuest OSM tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">' + ' MapQuest OSM tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">'
+ ' </div>' + ' </div>'
+ ' <hr>' + ' <hr>'
+ ' <div>Version: ' + v + '</div>'; + ' <div>Version: ' + v + '</div>'
alert(a); + ' <hr>'
+ ' <div>' + attrib + '</div>';
alert(a, true, function() {$('.ui-dialog').removeClass('ui-dialog-aboutIITC');});
$('.ui-dialog').addClass('ui-dialog-aboutIITC');
} }
@ -197,8 +201,8 @@ window.renderLimitReached = function(ratio) {
window.getMinPortalLevel = function() { window.getMinPortalLevel = function() {
var z = map.getZoom(); var z = map.getZoom();
if(z >= 16) return 0; if(z >= 17) return 0;
var conv = ['impossible', 8,7,7,6,6,5,5,4,4,3,3,2,2,1,1]; var conv = ['impossible', 8,8,8,7,7,6,6,5,4,4,3,3,2,2,1,1];
var minLevelByRenderLimit = portalRenderLimit.getMinLevel(); var minLevelByRenderLimit = portalRenderLimit.getMinLevel();
var result = minLevelByRenderLimit > conv[z] var result = minLevelByRenderLimit > conv[z]
? minLevelByRenderLimit ? minLevelByRenderLimit

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @id ingress-intel-total-conversion@jonatkins // @id ingress-intel-total-conversion@jonatkins
// @name IITC: Ingress intel map total conversion // @name IITC: Ingress intel map total conversion
// @version 0.10.5.@@DATETIMEVERSION@@ // @version 0.11.2.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@ // @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@ // @downloadURL @@DOWNLOADURL@@
@ -87,7 +87,7 @@ document.getElementsByTagName('body')[0].innerHTML = ''
+ ' <div id="gamestat">&nbsp;loading global control stats</div>' + ' <div id="gamestat">&nbsp;loading global control stats</div>'
+ ' <div id="geosearchwrapper">' + ' <div id="geosearchwrapper">'
+ ' <input id="geosearch" placeholder="Search location…" type="text"/>' + ' <input id="geosearch" placeholder="Search location…" type="text"/>'
+ ' <img src="@@INCLUDEIMAGE:images/current-location.png@@"/>' + ' <img src="@@INCLUDEIMAGE:images/current-location.png@@"/ title="Current Location">'
+ ' </div>' + ' </div>'
+ ' <div id="portaldetails"></div>' + ' <div id="portaldetails"></div>'
+ ' <input id="redeem" placeholder="Redeem code…" type="text"/>' + ' <input id="redeem" placeholder="Redeem code…" type="text"/>'

1
mobile/.gitignore vendored
View File

@ -7,3 +7,4 @@ libs/
proguard-project.txt proguard-project.txt
local.properties local.properties
assets/iitc.js assets/iitc.js
assets/plugins/

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cradle.iitc_mobile" package="com.cradle.iitc_mobile"
android:versionCode="9" android:versionCode="11"
android:versionName="0.2.8" > android:versionName="0.3" >
<uses-sdk <uses-sdk
android:minSdkVersion="14" android:minSdkVersion="14"

View File

@ -1,7 +1,11 @@
How does this basically work? How does this basically work?
----------------------------- -----------------------------
At the moment, the Android App is nothing more then a WebView which renders the normal web page. The IITC script is injected on page load and after this, it works the same way as on desktop browser. More functionality will be added soon... At the moment, the Android App is a WebView which renders the normal web page. The IITC script is injected by calling ```iitc_view.loadIITC_JS(Context)```. The app uses a local version of the script, which is located in the assets folder, if no external source is given (see "pref\_iitc\_source").
Communication from app to script is handled by loading Javascript function calls. For example: ```iitc_view.loadUrl("javascript: window.goBack();");```
Communication from script to app is handled by the JavascriptInterface (see /mobile/src/com/cradle/iitc\_mobile/IITC_JSInterface.java). If a method ```foo(String)``` is defined in JSInterface, it can be called by ```android.foo("Hello World")``` in the IITC script.
Debugging Debugging
--------- ---------
@ -16,13 +20,8 @@ Debugging IITC(M) **before** it has booted requires the Android Developer Tools.
Building the APK Building the APK
---------------- ----------------
- **Eclipse:** Just import this project and klick the build button.
- **ant:** - **ant:**
Set the ANDROID_HOME environment variable: Set the ANDROID_HOME environment variable:
```export ANDROID_HOME=/path/to/android_sdk``` ```export ANDROID_HOME=/path/to/android_sdk```
and build the project with ant: Then build the app via the build.py script ```./build.py mobile```
`ant debug` - **Eclipse:** Just import this project and klick the build button. Ensure that you have iitc.js in your assets folder. This is automatically created, when executing ```./build.py mobile```. Otherwise, just copy the IITC script to the assets folder and rename it to iitc.js
- You can use `build_mobile.js`, too, which builds IITC, compresses
it and uses ant to build a release APK of IITCM. It requires that
you have Python and uglifyjs installed. You need to set the
`ANDROID_HOME`, like explained above.

View File

@ -1,6 +1,22 @@
ingress intel total conversion (IITC) ingress intel total conversion mobile (IITCM)
===================================== =====================================
# [User documentation moved to the wiki. Please see there!](https://github.com/breunigs/ingress-intel-total-conversion/wiki/IITC-Mobile) The Android App behaves like the desktop version, but uses the mobile view, which is optimized for mobile devices, as default. Furthermore, there are some nice additions:
### [For developer docs, please see HACKING.md](https://github.com/breunigs/ingress-intel-total-conversion/blob/gh-pages/mobile/HACKING.md) - it should be much faster than the standard mobile ingress intel map
- a gmaps intent is sent, when a portals Map link is clicked (lets you navigate to portals)
- a geolocate button (you have to enable GPS satellites + location access to use this feature)
- toggle between desktop and mobile view (nice for tablets)
- possibility to use a custom IITC script source
- a click on Portal link copies it to clipboard
- more features will be added soon...
**The App only works with Android 4.0+**
### [For developer docs, please see HACKING.md](https://github.com/jonatkins/ingress-intel-total-conversion/blob/master/mobile/HACKING.md)

View File

@ -32,6 +32,8 @@
</string> </string>
<string name="pref_ui_cat">UI</string> <string name="pref_ui_cat">UI</string>
<string name="pref_plugins">Plugins</string>
<string name="pref_plugins_title">Available plugins</string>
<string name="pref_force_desktop">Force desktop mode</string> <string name="pref_force_desktop">Force desktop mode</string>
<string name="pref_force_desktop_sum">Nice for tablets, looks awful on smartphones</string> <string name="pref_force_desktop_sum">Nice for tablets, looks awful on smartphones</string>
<string name="pref_developer_options">Developer options</string> <string name="pref_developer_options">Developer options</string>

View File

@ -17,6 +17,10 @@
android:title="@string/pref_force_desktop" android:title="@string/pref_force_desktop"
android:summary="@string/pref_force_desktop_sum" android:summary="@string/pref_force_desktop_sum"
android:defaultValue="false" /> android:defaultValue="false" />
<MultiSelectListPreference
android:key="pref_plugins"
android:title="@string/pref_plugins"
android:dialogTitle="@string/pref_plugins_title"/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory

View File

@ -19,6 +19,14 @@ body {
} }
#geosearch {
width: 100%;
}
#geosearchwrapper img {
display: none;
}
#chatcontrols { #chatcontrols {
height: 38px; height: 38px;
width: 100%; width: 100%;

View File

@ -56,7 +56,7 @@ public class IITC_Mobile extends Activity {
if (Intent.ACTION_VIEW.equals(action)) { if (Intent.ACTION_VIEW.equals(action)) {
Uri uri = intent.getData(); Uri uri = intent.getData();
String url = uri.toString(); String url = uri.toString();
if (intent.getScheme().equals("http://")) if (intent.getScheme().equals("http"))
url = url.replace("http://", "https://"); url = url.replace("http://", "https://");
Log.d("iitcm", "intent received url: " + url); Log.d("iitcm", "intent received url: " + url);
if (url.contains("ingress.com")) { if (url.contains("ingress.com")) {

View File

@ -1,6 +1,11 @@
package com.cradle.iitc_mobile; package com.cradle.iitc_mobile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import android.app.Activity; import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle; import android.os.Bundle;
public class IITC_Settings extends Activity { public class IITC_Settings extends Activity {
@ -10,7 +15,52 @@ public class IITC_Settings extends Activity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
IITC_SettingsFragment settings = new IITC_SettingsFragment(); IITC_SettingsFragment settings = new IITC_SettingsFragment();
settings.setArguments(getIntent().getExtras());
AssetManager am = this.getAssets();
String[] asset_array = null;
try {
asset_array = am.list("plugins");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ArrayList<String> asset_list = new ArrayList<String>();
ArrayList<String> asset_values = new ArrayList<String>();
for (int i = 0; i < asset_array.length ; i++) {
if (asset_array[i].endsWith("user.js")) {
// find user plugin name for user readable entries
Scanner s = null;
String src = "";
try {
s = new Scanner(am.open("plugins/" + asset_array[i])).useDelimiter("\\A");
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
if (s != null) src = s.hasNext() ? s.next() : "";
String header = src.substring(src.indexOf("==UserScript=="), src.indexOf("==/UserScript=="));
// remove new line comments and replace with space
// this way we get double spaces instead of newline + double slash
header = header.replace("\n//", " ");
// get a list of key-value...split on multiple spaces
String[] attributes = header.split(" +");
String plugin_name = "not found";
for (int j = 0; j < attributes.length; j++) {
// search for name and use the value
if (attributes[j].equals("@name")) plugin_name = attributes[j+1];
}
asset_list.add(plugin_name);
// real value
asset_values.add(asset_array[i]);
}
}
Bundle bundle = getIntent().getExtras();
bundle.putStringArray("ASSETS", (String[]) asset_list.toArray(new String[0]));
bundle.putStringArray("ASSETS_VAL", (String[]) asset_values.toArray(new String[0]));
settings.setArguments(bundle);
// Display the fragment as the main content. // Display the fragment as the main content.
getFragmentManager().beginTransaction() getFragmentManager().beginTransaction()

View File

@ -6,6 +6,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle; import android.os.Bundle;
import android.preference.EditTextPreference; import android.preference.EditTextPreference;
import android.preference.ListPreference; import android.preference.ListPreference;
import android.preference.MultiSelectListPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
@ -21,7 +22,12 @@ public class IITC_SettingsFragment extends PreferenceFragment {
iitc_version = getArguments().getString("iitc_version"); iitc_version = getArguments().getString("iitc_version");
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
//plugins
MultiSelectListPreference pref_plugins = (MultiSelectListPreference) findPreference("pref_plugins");
pref_plugins.setEntries(getArguments().getStringArray("ASSETS"));
pref_plugins.setEntryValues(getArguments().getStringArray("ASSETS_VAL"));
// set build version // set build version
ListPreference pref_build_version = (ListPreference) findPreference("pref_build_version"); ListPreference pref_build_version = (ListPreference) findPreference("pref_build_version");
PackageManager pm = getActivity().getPackageManager(); PackageManager pm = getActivity().getPackageManager();

View File

@ -3,6 +3,7 @@ package com.cradle.iitc_mobile;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.net.Uri; import android.net.Uri;
import android.net.http.SslError; import android.net.http.SslError;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
@ -17,6 +18,7 @@ import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.Scanner; import java.util.Scanner;
import java.util.Set;
public class IITC_WebViewClient extends WebViewClient { public class IITC_WebViewClient extends WebViewClient {
private static final ByteArrayInputStream style = new ByteArrayInputStream( private static final ByteArrayInputStream style = new ByteArrayInputStream(
@ -44,7 +46,7 @@ public class IITC_WebViewClient extends WebViewClient {
String[] attributes = header.split(" +"); String[] attributes = header.split(" +");
String iitc_version = "not found"; String iitc_version = "not found";
for (int i = 0; i < attributes.length; i++) { for (int i = 0; i < attributes.length; i++) {
// search vor version and use the value // search for version and use the value
if (attributes[i].equals("@version")) iitc_version = attributes[i+1]; if (attributes[i].equals("@version")) iitc_version = attributes[i+1];
} }
return iitc_version; return iitc_version;
@ -91,6 +93,39 @@ public class IITC_WebViewClient extends WebViewClient {
handler.proceed() ; handler.proceed() ;
}; };
// plugins should be loaded after the main script is injected
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// get the plugin preferences
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
Set<String> plugin_list = sharedPref.getStringSet("pref_plugins", null);
// iterate through all enabled plugins and load them
if (plugin_list != null) {
AssetManager am = context.getAssets();
String[] plugin_array = plugin_list.toArray(new String[0]);
for(int i = 0; i < plugin_list.size(); i++) {
if (plugin_array[i].endsWith("user.js"));
{
Log.d("iitcm", "adding plugin " + plugin_array[i]);
Scanner s = null;
String src = "";
try {
s = new Scanner(am.open("plugins/" + plugin_array[i])).useDelimiter("\\A");
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
if (s != null) src = s.hasNext() ? s.next() : "";
view.loadUrl("javascript:" + src);
}
}
}
}
// Check every external resource if its okay to load it and maybe replace it // Check every external resource if its okay to load it and maybe replace it
// with our own content. This is used to block loading Niantic resources // with our own content. This is used to block loading Niantic resources
// which arent required and to inject IITC early into the site. // which arent required and to inject IITC early into the site.
@ -119,6 +154,11 @@ public class IITC_WebViewClient extends WebViewClient {
@Override @Override
public boolean shouldOverrideUrlLoading(WebView view, String url) { public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("ingress.com")) { if (url.contains("ingress.com")) {
// reload iitc if a poslink is clicked inside the app
if (url.contains("intel?ll=") || (url.contains("latE6") && url.contains("lngE6"))) {
Log.d("iitcm", "should be an internal clicked position link...reload script for: " + url);
((IITC_Mobile) context).loadUrl(url);
}
return false; return false;
} else { } else {
Log.d("iitcm", "no ingress intel link, start external app to load url: " + url); Log.d("iitcm", "no ingress intel link, start external app to load url: " + url);

View File

@ -1,11 +1,11 @@
// ==UserScript== // ==UserScript==
// @id iitc-plugin-ap-list@xelio // @id iitc-plugin-ap-list@xelio
// @name IITC plugin: AP List // @name IITC plugin: AP List
// @version 0.5.1.@@DATETIMEVERSION@@ // @version 0.5.2.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@ // @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@ // @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] List top 10 portals by AP of either faction. Other functions and controls please refer to the Userguide. // @description [@@BUILDNAME@@-@@BUILDDATE@@] List portals by AP of either faction or by effective level. Other functions and controls please refer to the Userguide.
// @include https://www.ingress.com/intel* // @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel* // @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel* // @match https://www.ingress.com/intel*

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @id iitc-plugin-ipas-link@graphracer // @id iitc-plugin-ipas-link@graphracer
// @name IITC Plugin: simulate an attack on portal // @name IITC Plugin: simulate an attack on portal
// @version 0.1.1.@@DATETIMEVERSION@@ // @version 0.2.0.@@DATETIMEVERSION@@
// @namespace https://github.com/xosofox/IPAS // @namespace https://github.com/xosofox/IPAS
// @updateURL @@UPDATEURL@@ // @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@ // @downloadURL @@DOWNLOADURL@@
@ -30,16 +30,34 @@ window.plugin.ipasLink.addLink = function(d) {
$('.linkdetails').append('<aside><a href="http://ipas.graphracer.com/index.html#' + window.plugin.ipasLink.getHash(d.portalDetails) + '" target="ipaswindow" title="Use IAPS to simulate an attack on this portal">Simulate attack</a></aside>'); $('.linkdetails').append('<aside><a href="http://ipas.graphracer.com/index.html#' + window.plugin.ipasLink.getHash(d.portalDetails) + '" target="ipaswindow" title="Use IAPS to simulate an attack on this portal">Simulate attack</a></aside>');
} }
window.plugin.ipasLink.getHash = function(d) { window.plugin.ipasLink.getHash = function (d) {
var hashParts=[]; var hashParts = [];
$.each(d.resonatorArray.resonators, function(ind, reso) { $.each(d.resonatorArray.resonators, function (ind, reso) {
if (reso) { if (reso) {
hashParts.push(reso.level + "," + reso.distanceToPortal + "," + reso.energyTotal); hashParts.push(reso.level + "," + reso.distanceToPortal + "," + reso.energyTotal);
} else { } else {
hashParts.push(1 + "," + 35 + "," + 0); // Dummy values, the only important one is energy=0 hashParts.push("1,20,0");
} }
}); });
return hashParts.join(";")+"|" + "0,0,0,0"; //shields not implemented yet var resos = hashParts.join(";");
hashParts = [];
$.each(d.portalV2.linkedModArray, function (ind, mod) {
//shields only, so far...
var s = "0";
if (mod) {
if (mod.type === "RES_SHIELD") {
s = mod.rarity.charAt(0).toLowerCase();
}
}
hashParts.push(s);
});
var shields = hashParts.join(",");
return resos + "|" + shields;
}
var setup = function () {
window.plugin.ipasLink.setupCallback();
} }
var setup = function() { var setup = function() {

View File

@ -266,12 +266,13 @@ window.plugin.playerTracker.drawData = function() {
if(window.plugin.guessPlayerLevels !== undefined && if(window.plugin.guessPlayerLevels !== undefined &&
window.plugin.guessPlayerLevels.fetchLevelByPlayer !== undefined) { window.plugin.guessPlayerLevels.fetchLevelByPlayer !== undefined) {
var playerLevel = window.plugin.guessPlayerLevels.fetchLevelByPlayer(pguid); var playerLevel = window.plugin.guessPlayerLevels.fetchLevelByPlayer(pguid);
if (playerLevel === undefined) playerLevel = 1; //if player level unknown, assume level 1
if(playerLevel !== undefined) { if(playerLevel !== undefined) {
title += '<span style="font-weight:bold;margin-left:10px;">Level ' title += '<span style="font-weight:bold;margin-left:10px;">Level '
+ playerLevel + playerLevel
+ (playerLevel < (window.MAX_XM_PER_LEVEL.length - 1) ? ' (guessed)' : '') + (playerLevel < (window.MAX_XM_PER_LEVEL.length - 1) ? ' (guessed)' : '')
+ '</span>'; + '</span>';
} else {
title += '<span style="font-weight:bold;margin-left:10px;">Level unknown</span>'
} }
} }

View File

@ -0,0 +1,51 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-level-color@vita10gy
// @name IITC plugin: highlight portals by level color
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals level color.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherPortalsLevelColor = function() {};
window.plugin.portalHighligherPortalsLevelColor.colorLevel = function(data) {
var d = data.portal.options.details;
var portal_level = Math.floor(getPortalLevel(d));
var opacity = .6;
data.portal.setStyle({fillColor: COLORS_LVL[portal_level], fillOpacity: opacity});
window.COLOR_SELECTED_PORTAL = '#f0f';
}
var setup = function() {
window.addPortalHighlighter('Level Color', window.plugin.portalHighligherPortalsLevelColor.colorLevel);
}
// PLUGIN END //////////////////////////////////////////////////////////
if(window.iitcLoaded && typeof setup === 'function') {
setup();
} else {
if(window.bootPlugins)
window.bootPlugins.push(setup);
else
window.bootPlugins = [setup];
}
} // wrapper end
// inject code into site context
var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ wrapper +')();'));
(document.body || document.head || document.documentElement).appendChild(script);

View File

@ -0,0 +1,118 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-by-ap-by-energy-relative@vita10gy
// @name IITC plugin: highlight portals by ap/energy (relative)
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote AP/Energy value relative to what's currently on the screen. Brighter is better. Orange means your standard 8 down 8 up swap.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherPortalAPPerEnergyRelative = function() {};
window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP = null;
window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP = null;
//This is the AP for a run of the mill takedown/putback
window.plugin.portalHighligherPortalAPPerEnergyRelative.baseSwapAP = 2350;
window.plugin.portalHighligherPortalAPPerEnergyRelative.highlight = function(data) {
var d = data.portal.options.details;
var color = 'red';
if(window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP == null ||
window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP == null) {
window.plugin.portalHighligherPortalAPPerEnergyRelative.calculateAPLevels();
}
var minApE = window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP;
var maxApE = window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP;
if(PLAYER.team !== d.controllingTeam.team) {
var ap = getAttackApGain(d);
var energy = getCurrentPortalEnergy(d);
if(energy < 1) {
energy = 1;
}
portal_ap = ap.enemyAp;
var opacity = 1;
if(minApE !== maxApE) {
opacity = ((ap.enemyAp / energy) - minApE) / (maxApE - minApE);
}
if(opacity < 0) {
opacity = 0;
}
if(opacity > 1) {
opacity = 1;
}
data.portal.setStyle({fillColor: color, fillOpacity: opacity});
window.COLOR_SELECTED_PORTAL = '#f0f';
}
}
window.plugin.portalHighligherPortalAPPerEnergyRelative.resetAPLevels = function() {
window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP = null;
window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP = null;
}
window.plugin.portalHighligherPortalAPPerEnergyRelative.calculateAPLevels = function() {
var displayBounds = map.getBounds();
$.each(window.portals, function(qk, portal) {
if(displayBounds.contains(portal.getLatLng())) {
if(PLAYER.team !== portal.options.details.controllingTeam.team) {
var ap = getAttackApGain(portal.options.details);
var energy = getCurrentPortalEnergy(portal.options.details);
if(energy < 1) {
energy = 1;
}
var portal_ap = ap.enemyAp / energy;
if(window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP === null ||
portal_ap < window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP) {
window.plugin.portalHighligherPortalAPPerEnergyRelative.minAP = portal_ap;
}
if(window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP === null ||
portal_ap > window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP) {
window.plugin.portalHighligherPortalAPPerEnergyRelative.maxAP = portal_ap;
}
}
}
});
}
var setup = function() {
window.addPortalHighlighter('AP/Energy (Relative)', window.plugin.portalHighligherPortalAPPerEnergyRelative.highlight);
window.addHook('requestFinished', window.plugin.portalHighligherPortalAPPerEnergyRelative.resetAPLevels);
}
// PLUGIN END //////////////////////////////////////////////////////////
if(window.iitcLoaded && typeof setup === 'function') {
setup();
} else {
if(window.bootPlugins)
window.bootPlugins.push(setup);
else
window.bootPlugins = [setup];
}
} // wrapper end
// inject code into site context
var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ wrapper +')();'));
(document.body || document.head || document.documentElement).appendChild(script);

View File

@ -90,10 +90,8 @@ window.plugin.portalHighligherPortalAPRelative.calculateAPLevels = function() {
}); });
} }
var setup = function() { var setup = function() {
window.addPortalHighlighter('Portal AP (Relative)', window.plugin.portalHighligherPortalAPRelative.highlight); window.addPortalHighlighter('AP (Relative)', window.plugin.portalHighligherPortalAPRelative.highlight);
window.addHook('requestFinished', window.plugin.portalHighligherPortalAPRelative.resetAPLevels); window.addHook('requestFinished', window.plugin.portalHighligherPortalAPRelative.resetAPLevels);
} }

View File

@ -54,7 +54,7 @@ window.plugin.portalHighligherPortalAP.highlight = function(data) {
} }
var setup = function() { var setup = function() {
window.addPortalHighlighter('Portal AP', window.plugin.portalHighligherPortalAP.highlight); window.addPortalHighlighter('AP (Static)', window.plugin.portalHighligherPortalAP.highlight);
} }
// PLUGIN END ////////////////////////////////////////////////////////// // PLUGIN END //////////////////////////////////////////////////////////

View File

@ -28,7 +28,7 @@ window.plugin.scaleBar.setup = function() {
// Before you ask: yes, I explicitely turned off imperial units. Imperial units // Before you ask: yes, I explicitely turned off imperial units. Imperial units
// are worse than Internet Explorer 6 whirring fans combined. Upgrade to the metric // are worse than Internet Explorer 6 whirring fans combined. Upgrade to the metric
// system already. // system already.
window.map.addControl(new L.Control.Scale({position: 'topleft', imperial: false})); window.map.addControl(new L.Control.Scale({position: 'topleft', imperial: false, maxWidth: 200}));
}; };
var setup = window.plugin.scaleBar.setup; var setup = window.plugin.scaleBar.setup;

View File

@ -71,9 +71,18 @@ window.plugin.showLinkedPortal.getPortalByGuid = function (guid) {
var portalDetails = window.portals[guid].options.details; var portalDetails = window.portals[guid].options.details;
portalInfoString = ''; portalInfoString = '';
var portalNameAdressAlt = "'" + portalDetails.portalV2.descriptiveText.TITLE + "' (" + portalDetails.portalV2.descriptiveText.ADDRESS + ")"; var portalNameAdressAlt = "'" + portalDetails.portalV2.descriptiveText.TITLE + "' (" + portalDetails.portalV2.descriptiveText.ADDRESS + ")";
var portalNameAdressTitle = "'<strong>" + portalDetails.portalV2.descriptiveText.TITLE + "</strong>'<br/> <em>(" + portalDetails.portalV2.descriptiveText.ADDRESS + ")</em>"; var portalNameAdressTitle = $('<div/>').append('\'')
.append($('<strong/>').text(portalDetails.portalV2.descriptiveText.TITLE))
.append('\'')
.append($('<br/>'))
.append($('<em/>').text('(' + portalDetails.portalV2.descriptiveText.ADDRESS + ')'))
.html();
var imageUrl = (portalDetails.imageByUrl ? portalDetails.imageByUrl.imageUrl : window.DEFAULT_PORTAL_IMG); var imageUrl = (portalDetails.imageByUrl ? portalDetails.imageByUrl.imageUrl : window.DEFAULT_PORTAL_IMG);
portalInfoString = '<img src="' + imageUrl + '" class="minImg" alt="' + portalNameAdressAlt + '" title="' + portalNameAdressTitle + '"/>'; portalInfoString = $('<div/>').html($('<img/>').attr('src', imageUrl)
.attr('class', 'minImg')
.attr('alt', portalNameAdressAlt)
.attr('title', portalNameAdressTitle))
.html();
} }
return portalInfoString; return portalInfoString;
}; };

View File

@ -68,6 +68,10 @@ body {
color: #fff; color: #fff;
} }
.nickname {
cursor: pointer !important;
}
a { a {
color: #ffce00; color: #ffce00;
cursor: pointer; cursor: pointer;
@ -434,6 +438,7 @@ input {
#geosearchwrapper img{ #geosearchwrapper img{
vertical-align: bottom; vertical-align: bottom;
margin-bottom: 2px; margin-bottom: 2px;
cursor: pointer;
} }
::-webkit-input-placeholder { ::-webkit-input-placeholder {
font-style: italic; font-style: italic;
@ -691,9 +696,8 @@ h3 {
} }
#largepreview img { #largepreview img {
box-shadow: 0 0 40px #000; box-shadow: 0 0 40px #000;
}
#largepreview img {
border: 2px solid #f8ff5e; border: 2px solid #f8ff5e;
background-color: rgba(8, 48, 78, 0.9); /* as some images - eg ZipCar - have transparency */
} }
/* tooltips, dialogs */ /* tooltips, dialogs */
@ -762,6 +766,11 @@ h3 {
text-decoration: underline; text-decoration: underline;
} }
.ui-dialog-aboutIITC {
max-width: 600px !important;
width: 600px !important;
}
td { td {
padding: 0; padding: 0;
vertical-align: top; vertical-align: top;