Add macro code

This commit is contained in:
Peter Dietrich
2013-07-11 00:15:20 +02:00
95 changed files with 3089 additions and 2026 deletions

View File

@ -61,6 +61,33 @@ distUrlBase = settings.get('distUrlBase')
buildMobile = settings.get('buildMobile')
# plugin wrapper code snippets. handled as macros, to ensure that
# 1. indentation caused by the "function wrapper()" doesn't apply to the plugin code body
# 2. the wrapper is formatted correctly for removal by the IITC Mobile android app
pluginWrapperStart = """
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
"""
pluginWrapperEnd = """
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);
"""
def readfile(fn):
with io.open(fn, 'Ur', encoding='utf8') as f:
return f.read()
@ -137,6 +164,9 @@ def doReplacements(script,updateUrl,downloadUrl):
script = script.replace('@@UPDATEURL@@', updateUrl)
script = script.replace('@@DOWNLOADURL@@', downloadUrl)
script = script.replace('@@PLUGINSTART@@', pluginWrapperStart)
script = script.replace('@@PLUGINEND@@', pluginWrapperEnd)
return script
@ -203,7 +233,7 @@ if buildMobile:
# compile the user location script
fn = "user-location.user.js"
script = readfile("mobile/" + fn)
script = readfile("mobile/plugins/" + fn)
downloadUrl = distUrlBase and distUrlBase + '/' + fn.replace("\\","/") or 'none'
updateUrl = distUrlBase and downloadUrl.replace('.user.js', '.meta.js') or 'none'
script = doReplacements(script, downloadUrl=downloadUrl, updateUrl=updateUrl)
@ -221,11 +251,14 @@ if buildMobile:
shutil.copy(os.path.join(outDir,"user-location.user.js"), "mobile/assets/user-location.user.js")
# also copy plugins
try:
os.makedirs("mobile/assets/plugins")
shutil.rmtree("mobile/assets/plugins")
except:
pass
shutil.rmtree("mobile/assets/plugins")
shutil.copytree(os.path.join(outDir,"plugins"), "mobile/assets/plugins", ignore=shutil.ignore_patterns('*.meta.js', 'force-https*', 'privacy-view*', 'speech-search*', 'basemap-cloudmade*'))
shutil.copytree(os.path.join(outDir,"plugins"), "mobile/assets/plugins",
# do not include desktop-only plugins to mobile assets
ignore=shutil.ignore_patterns('*.meta.js',
'force-https*', 'privacy-view*', 'speech-search*',
'basemap-cloudmade*', 'scroll-wheel-zoom-disable*'))
if buildMobile != 'copyonly':

View File

@ -10,15 +10,23 @@ window.showLayerChooser = true;
window.setupLargeImagePreview = function() {
$('#portaldetails').on('click', '.imgpreview', function() {
var img = $(this).find('img')[0];
var details = $(this).find('div.portalDetails')[0];
//dialogs have 12px padding around the content
var dlgWidth = Math.max(img.naturalWidth+24,400);
dialog({
html: '<div style="text-align: center">' + img.outerHTML + '</div>',
title: $(this).parent().find('h3.title').text(),
width: dlgWidth,
});
});
var dlgWidth = Math.max(img.naturalWidth+24,500);
if (details) {
dialog({
html: '<div style="text-align: center">' + img.outerHTML + '</div>' + details.outerHTML,
title: $(this).parent().find('h3.title').text(),
width: dlgWidth,
});
} else {
dialog({
html: '<div style="text-align: center">' + img.outerHTML + '</div>',
title: $(this).parent().find('h3.title').text(),
width: dlgWidth,
});
}
});
}
// adds listeners to the layer chooser such that a long press hides
@ -100,12 +108,6 @@ window.setupMap = function() {
//OpenStreetMap attribution - required by several of the layers
osmAttribution = 'Map data © OpenStreetMap contributors';
//CloudMade layers - only 500,000 tiles/month in their free plan. nowhere near enough for IITC
//var cmOpt = {attribution: osmAttribution+', Imagery © CloudMade', maxZoom: 18, detectRetina: true};
//var cmMin = new L.TileLayer('http://{s}.tile.cloudmade.com/{your api key here}/22677/256/{z}/{x}/{y}.png', cmOpt);
//var cmMid = new L.TileLayer('http://{s}.tile.cloudmade.com/{your api key here}/999/256/{z}/{x}/{y}.png', cmOpt);
//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)
var mqSubdomains = [ 'otile1','otile2', 'otile3', 'otile4' ];
@ -130,6 +132,13 @@ window.setupMap = function() {
{zoomControl: window.showZoom}
));
// add empty div to leaflet control areas - to force other leaflet controls to move around IITC UI elements
// TODO? move the actual IITC DOM into the leaflet control areas, so dummy <div>s aren't needed
if(!isSmartphone()) {
// chat window area
$(window.map._controlCorners['bottomleft']).append($('<div>').width(708).height(108).addClass('leaflet-control').css('margin','0'));
}
var addLayers = {};
var hiddenLayer = [];
@ -197,7 +206,7 @@ window.setupMap = function() {
map.on('movestart zoomstart', function() { window.mapRunsUserAction = true; window.requests.abort(); window.startRefreshTimeout(-1); });
map.on('moveend zoomend', function() { window.mapRunsUserAction = false; window.startRefreshTimeout(ON_MOVE_REFRESH*1000); });
window.addResumeFunction(window.requestData);
window.addResumeFunction(function() { window.startRefreshTimeout(ON_MOVE_REFRESH*1000); });
window.requests.addRefreshFunction(window.requestData);
// start the refresh process with a small timeout, so the first data request happens quickly

View File

@ -41,16 +41,22 @@ window.chat._oldBBox = null;
window.chat.genPostData = function(isFaction, storageHash, getOlderMsgs) {
if(typeof isFaction !== 'boolean') throw('Need to know if public or faction chat.');
// get window bounds, and extend to the minimum chat radius
chat._localRangeCircle.setLatLng(map.getCenter());
var b = map.getBounds().extend(chat._localRangeCircle.getBounds());
var ne = b.getNorthEast();
var sw = b.getSouthWest();
// round bounds in order to ignore rounding errors
var bbs = $.map([ne.lat, ne.lng, sw.lat, sw.lng], function(x) { return Math.round(x*1E4) }).join();
if(chat._oldBBox && chat._oldBBox !== bbs) {
// set a current bounding box if none set so far
if (!chat._oldBBox) chat._oldBBox = b;
// to avoid unnecessary chat refreshes, a small difference compared to the previous bounding box
// is not considered different
var CHAT_BOUNDINGBOX_SAME_FACTOR = 0.1;
// if the old and new box contain each other, after expanding by the factor, don't reset chat
if (!(b.pad(CHAT_BOUNDINGBOX_SAME_FACTOR).contains(chat._oldBBox) && chat._oldBBox.pad(CHAT_BOUNDINGBOX_SAME_FACTOR).contains(b))) {
console.log('Bounding Box changed, chat will be cleared (old: '+chat._oldBBox.toBBoxString()+'; new: '+b.toBBoxString()+')');
$('#chat > div').data('needsClearing', true);
console.log('Bounding Box changed, chat will be cleared (old: '+chat._oldBBox+' ; new: '+bbs+' )');
// need to reset these flags now because clearing will only occur
// after the request is finished i.e. there would be one almost
// useless request.
@ -61,8 +67,9 @@ window.chat.genPostData = function(isFaction, storageHash, getOlderMsgs) {
chat._public.data = {};
chat._public.oldestTimestamp = -1;
chat._public.newestTimestamp = -1;
chat._oldBBox = b;
}
chat._oldBBox = bbs;
var ne = b.getNorthEast();
var sw = b.getSouthWest();
@ -119,7 +126,7 @@ window.chat.requestFaction = function(getOlderMsgs, isRetry) {
var r = window.postAjax(
'getPaginatedPlextsV2',
d,
chat.handleFaction,
function(data, textStatus, jqXHR) { chat.handleFaction(data, getOlderMsgs); },
isRetry
? function() { window.chat._requestFactionRunning = false; }
: function() { window.chat.requestFaction(getOlderMsgs, true) }
@ -130,7 +137,7 @@ window.chat.requestFaction = function(getOlderMsgs, isRetry) {
window.chat._faction = {data:{}, oldestTimestamp:-1, newestTimestamp:-1};
window.chat.handleFaction = function(data, textStatus, jqXHR) {
window.chat.handleFaction = function(data, olderMsgs) {
chat._requestFactionRunning = false;
if(!data || !data.result) {
@ -141,7 +148,7 @@ window.chat.handleFaction = function(data, textStatus, jqXHR) {
if(data.result.length === 0) return;
var old = chat._faction.oldestTimestamp;
chat.writeDataToHash(data, chat._faction, false);
chat.writeDataToHash(data, chat._faction, false, olderMsgs);
var oldMsgsWereAdded = old !== chat._faction.oldestTimestamp;
runHooks('factionChatDataAvailable', {raw: data, processed: chat._faction.data});
@ -170,7 +177,7 @@ window.chat.requestPublic = function(getOlderMsgs, isRetry) {
var r = window.postAjax(
'getPaginatedPlextsV2',
d,
chat.handlePublic,
function(data, textStatus, jqXHR) { chat.handlePublic(data, getOlderMsgs); },
isRetry
? function() { window.chat._requestPublicRunning = false; }
: function() { window.chat.requestPublic(getOlderMsgs, true) }
@ -180,7 +187,7 @@ window.chat.requestPublic = function(getOlderMsgs, isRetry) {
}
window.chat._public = {data:{}, oldestTimestamp:-1, newestTimestamp:-1};
window.chat.handlePublic = function(data, textStatus, jqXHR) {
window.chat.handlePublic = function(data, olderMsgs) {
chat._requestPublicRunning = false;
if(!data || !data.result) {
@ -191,7 +198,7 @@ window.chat.handlePublic = function(data, textStatus, jqXHR) {
if(data.result.length === 0) return;
var old = chat._public.oldestTimestamp;
chat.writeDataToHash(data, chat._public, true);
chat.writeDataToHash(data, chat._public, true, olderMsgs);
var oldMsgsWereAdded = old !== chat._public.oldestTimestamp;
runHooks('publicChatDataAvailable', {raw: data, processed: chat._public.data});
@ -249,7 +256,7 @@ window.chat.nicknameClicked = function(event, nickname) {
}
}
window.chat.writeDataToHash = function(newData, storageHash, isPublicChannel) {
window.chat.writeDataToHash = function(newData, storageHash, isPublicChannel, isOlderMsgs) {
$.each(newData.result, function(ind, json) {
// avoid duplicates
if(json[0] in storageHash.data) return true;
@ -344,7 +351,10 @@ window.chat.writeDataToHash = function(newData, storageHash, isPublicChannel) {
// format: timestamp, autogenerated, HTML message, player guid
storageHash.data[json[0]] = [json[1], auto, chat.renderMsg(msg, nick, time, team, msgToPlayer, systemNarrowcast), pguid];
window.setPlayerName(pguid, nick); // free nick name resolves
// if we're processing older messages, we could be looking at pre-name change mentions or similar
// so in that case, flag it so we don't overwrite existing name cache entries.
// (it's not perfect - the initial request has the wrong value here)
window.setPlayerName(pguid, nick, isOlderMsgs); // free nick name resolves.
});
}
@ -598,8 +608,6 @@ window.chat.setup = function() {
if(scrollBottom(t) === 0) chat.requestPublic(false);
});
chat.request();
window.addResumeFunction(chat.request);
window.requests.addRefreshFunction(chat.request);
var cls = PLAYER.team === 'ALIENS' ? 'enl' : 'res';

View File

@ -19,6 +19,11 @@ window.DIALOG_COUNT = 0;
*/
window.DIALOG_FOCUS = null;
/* Controls how quickly the slide toggle animation
* should play for dialog collapsing and expanding.
*/
window.DIALOG_SLIDE_DURATION = 100;
/* Creates a dialog and puts it onscreen. Takes one argument: options, a JS object.
* == Common options
* (text|html): The text or HTML to display in the dialog. Text is auto-converted to HTML.
@ -48,6 +53,7 @@ window.dialog = function(options) {
options = options || {};
if(isSmartphone()) {
options.modal = true;
options.width = 'auto';
}
// Build an identifier for this dialog
@ -55,6 +61,11 @@ window.dialog = function(options) {
var jqID = '#' + id;
var html = '';
// hint for iitc mobile that a dialog was opened
if (typeof android !== 'undefined' && android && android.dialogOpened) {
android.dialogOpened(id, true);
}
// Convert text to HTML if necessary
if(options.text) {
html = window.convertTextToTableMagic(options.text);
@ -127,12 +138,14 @@ window.dialog = function(options) {
var dialog = $(this).closest('.ui-dialog');
var selector = dialog.find('.ui-dialog-content,.ui-dialog-buttonpane');
var button = dialog.find('.ui-dialog-titlebar-button-collapse');
// Slide toggle
$(selector).slideToggle({duration: window.DIALOG_SLIDE_DURATION});
if(collapsed) {
$(selector).removeClass('ui-dialog-content-hidden');
$(button).removeClass('ui-dialog-titlebar-button-collapse-collapsed');
$(button).addClass('ui-dialog-titlebar-button-collapse-expanded');
} else {
$(selector).addClass('ui-dialog-content-hidden');
$(button).removeClass('ui-dialog-titlebar-button-collapse-expanded');
$(button).addClass('ui-dialog-titlebar-button-collapse-collapsed');
}
@ -167,6 +180,10 @@ window.dialog = function(options) {
window.DIALOG_COUNT--;
console.log('window.dialog: ' + $(this).data('id') + ' (' + $(this).dialog('option', 'title') + ') closed. ' + window.DIALOG_COUNT + ' remain.');
// hint for iitc mobile that a dialog was closed
if (typeof android !== 'undefined' && android && android.dialogOpened) {
android.dialogOpened(id, false);
}
// remove from DOM and destroy
$(this).dialog('destroy').remove();
@ -189,6 +206,10 @@ window.dialog = function(options) {
// This dialog is now in focus
window.DIALOG_FOCUS = this;
// hint for iitc mobile that a dialog was focused
if (typeof android !== 'undefined' && android && android.dialogFocused) {
android.dialogFocused($(window.DIALOG_FOCUS).data('id'));
}
$(this).closest('.ui-dialog').find('.ui-dialog-title').removeClass('ui-dialog-title-inactive').addClass('ui-dialog-title-active');
}
}, options));

View File

@ -1,8 +1,22 @@
// IDLE HANDLING /////////////////////////////////////////////////////
window.idleTime = 0; // in minutes
window.idleTime = 0; // in seconds
window._idleTimeLimit = MAX_IDLE_TIME;
var IDLE_POLL_TIME = 10;
var idlePoll = function() {
window.idleTime += IDLE_POLL_TIME;
var hidden = (document.hidden || document.webkitHidden || document.mozHidden || document.msHidden || false);
if (hidden) {
// window hidden - use the refresh time as the idle limit, rather than the max time
window._idleTimeLimit = window.REFRESH;
}
}
setInterval(idlePoll, IDLE_POLL_TIME*1000);
setInterval('window.idleTime += 1', 60*1000);
var idleReset = function () {
// update immediately when the user comes back
if(isIdle()) {
@ -12,11 +26,29 @@ var idleReset = function () {
});
}
window.idleTime = 0;
window._idleTimeLimit = MAX_IDLE_TIME;
};
$('body').mousemove(idleReset).keypress(idleReset);
// only reset idle on mouse move where the coordinates are actually different.
// some browsers send the event when not moving!
var _lastMouseX=-1, _lastMouseY=-1;
var idleMouseMove = function(e) {
var dX = _lastMouseX-e.clientX;
var dY = _lastMouseY-e.clientY;
var deltaSquared = dX*dX + dY*dY;
// only treat movements over 3 pixels as enough to reset us
if (deltaSquared > 3*3) {
_lastMouseX = e.clientX;
_lastMouseY = e.clientY;
idleReset();
}
}
$('body').keypress(idleReset);
$('body').mousemove(idleMouseMove);
window.isIdle = function() {
return window.idleTime >= MAX_IDLE_TIME;
return window.idleTime >= window._idleTimeLimit;
}
window._onResumeFunctions = [];

View File

@ -1,9 +1,100 @@
// MAP DATA //////////////////////////////////////////////////////////
// these functions handle how and which entities are displayed on the
// map. They also keep them up to date, unless interrupted by user
// action.
// debug - display a set of rectangles on the map representing each data tile. the colour will represent it's state
window._debugDataTileStateLayer = undefined;
window.debugDataTileReset = function() {
if (!window._debugDataTileStateLayer) {
window._debugDataTileStateLayer = L.layerGroup();
window.addLayerGroup("DEBUG Data Tiles", window._debugDataTileStateLayer, false);
}
window._debugDataTileIdToRectangle = {};
window._debugDataTileStateLayer.clearLayers();
}
window.debugCreateTile = function(qk,bounds) {
var s = {color: '#888', weight: 3, opacity: 0.7, fillColor: '#888', fillOpacity: 0.4, clickable: false};
bounds = new L.LatLngBounds(bounds);
bounds = bounds.pad(-0.02);
var l = L.rectangle(bounds,s);
window._debugDataTileIdToRectangle[qk] = l;
window._debugDataTileStateLayer.addLayer(l);
}
window.debugSetTileColour = function(qk,bordercol,fillcol) {
var l = window._debugDataTileIdToRectangle[qk];
if (l) {
var s = {color: bordercol, weight: 3, opacity: 0.3, fillColor: fillcol, fillOpacity: 0.1, clickable: false};
l.setStyle(s);
}
}
// cache for data tiles. indexed by the query key (qk)
window._requestCache = {}
// cache entries older than the fresh age, and younger than the max age, are stale. they're used in the case of an error from the server
window.REQUEST_CACHE_FRESH_AGE = 60; // if younger than this, use data in the cache rather than fetching from the server
window.REQUEST_CACHE_MAX_AGE = 60*60; // maximum cache age. entries are deleted from the cache after this time
window.REQUEST_CACHE_MIN_SIZE = 200; // if fewer than this many entries, don't expire any
window.REQUEST_CACHE_MAX_SIZE = 2000; // if more than this many entries, expire early
window.storeDataCache = function(qk,data) {
// fixme? common behaviour for objects is that properties are kept in the order they're added
// this is handy, as it allows easy retrieval of the oldest entries for expiring
// however, this is not guaranteed by the standards, but all our supported browsers work this way
delete window._requestCache[qk];
var d = new Date();
window._requestCache[qk] = { time: d.getTime(), data: data };
}
window.getDataCache = function(qk) {
if (qk in window._requestCache) {
return window._requestCache[qk].data;
}
return undefined;
}
window.isDataCacheFresh = function(qk) {
if (qk in window._requestCache) {
var d = new Date();
var t = d.getTime()-REQUEST_CACHE_FRESH_AGE*1000;
if (window._requestCache[qk].time > t) {
return true;
}
}
return false;
}
window.expireDataCache = function() {
var d = new Date();
var t = d.getTime()-window.REQUEST_CACHE_MAX_AGE*1000;
var cacheSize = Object.keys(window._requestCache).length;
for(var qk in window._requestCache) {
// stop processing once we hit the minimum size
if (cacheSize < window.REQUEST_CACHE_MIN_SIZE) break;
// fixme? our MAX_SIZE test here assumes we're processing the oldest first. this relies
// on looping over object properties in the order they were added. this is true in most browsers,
// but is not a requirement of the standards
if (cacheSize > window.REQUEST_CACHE_MAX_SIZE || window._requestCache[qk].time < t) {
delete window._requestCache[qk];
cacheSize--;
}
}
}
// requests map data for current viewport. For details on how this
// works, refer to the description in “MAP DATA REQUEST CALCULATORS”
@ -11,14 +102,27 @@ window.requestData = function() {
console.log('refreshing data');
requests.abort();
cleanUp();
window.statusTotalMapTiles = 0;
window.statusCachedMapTiles = 0;
window.statusSuccessMapTiles = 0;
window.statusStaleMapTiles = 0;
window.statusErrorMapTiles = 0;
debugDataTileReset();
expireDataCache();
//a limit on the number of map tiles to be pulled in a single request
var MAX_TILES_PER_BUCKET = 20;
var MAX_TILES_PER_BUCKET = 11;
// the number of separate buckets. more can be created if the size exceeds MAX_TILES_PER_BUCKET
var BUCKET_COUNT = 4;
var bounds = clampLatLngBounds(map.getBounds());
//we query the server as if the zoom level was this. it may not match the actual map zoom level
var z = getPortalDataZoom();
console.log('requesting data tiles at zoom '+z+' (L'+getMinPortalLevelForZoom(z)+'+ portals), map zoom is '+map.getZoom());
var x1 = lngToTile(bounds.getWest(), z);
var x2 = lngToTile(bounds.getEast(), z);
@ -29,45 +133,114 @@ window.requestData = function() {
tiles = {};
fullBucketCount = 0;
var cachedData = { result: { map: {} } };
var requestTileCount = 0;
// walk in x-direction, starts right goes left
for (var x = x1; x <= x2; x++) {
for (var y = y1; y <= y2; y++) {
var tile_id = pointToTileId(z, x, y);
var bucket = (x % 2) + ":" + (y % 2);
if (!tiles[bucket]) {
//create empty bucket
tiles[bucket] = [];
}
else if(tiles[bucket].length >= MAX_TILES_PER_BUCKET) {
//too many items in bucket. rename it, and create a new empty one
tiles[bucket+'_'+fullBucketCount] = tiles[bucket];
fullBucketCount++;
tiles[bucket] = [];
var latNorth = tileToLat(y,z);
var latSouth = tileToLat(y+1,z);
var lngWest = tileToLng(x,z);
var lngEast = tileToLng(x+1,z);
debugCreateTile(tile_id,[[latSouth,lngWest],[latNorth,lngEast]]);
window.statusTotalMapTiles++;
// TODO?: if the selected portal is in this tile, always fetch the data
if (isDataCacheFresh(tile_id)) {
// TODO: don't add tiles from the cache when 1. they were fully visible before, and 2. the zoom level is unchanged
// TODO?: if a closer zoom level has all four tiles in the cache, use them instead?
cachedData.result.map[tile_id] = getDataCache(tile_id);
debugSetTileColour(tile_id,'#0f0','#ff0');
window.statusCachedMapTiles++;
} else {
// group requests into buckets based on the tile coordinate.
var bucket = Math.floor(x+y*(BUCKET_COUNT/2))%BUCKET_COUNT;
if (!tiles[bucket]) {
//create empty bucket
tiles[bucket] = [];
}
else if(tiles[bucket].length >= MAX_TILES_PER_BUCKET) {
//too many items in bucket. rename it, and create a new empty one
tiles[bucket+'_'+fullBucketCount] = tiles[bucket];
fullBucketCount++;
tiles[bucket] = [];
}
requestTileCount++;
var boundsParam = generateBoundsParams(
tile_id,
latSouth,
lngWest,
latNorth,
lngEast
);
// when the server is returning 'timeout' errors for some tiles in the list, it's always the tiles
// at the end of the request. therefore, let's push tiles we don't have cache entries for to the front, and those we do to the back
if (getDataCache(tile_id)) {
// cache entry exists - push to back
tiles[bucket].push(boundsParam);
} else {
// no cache entry - unshift to front
tiles[bucket].unshift(boundsParam);
}
debugSetTileColour(tile_id,'#00f','#000');
}
tiles[bucket].push(generateBoundsParams(
tile_id,
tileToLat(y + 1, z),
tileToLng(x, z),
tileToLat(y, z),
tileToLng(x + 1, z)
));
}
}
// Reset previous result of Portal Render Limit handler
portalRenderLimit.init();
// finally send ajax requests
// send ajax requests
console.log('requesting '+requestTileCount+' tiles in '+Object.keys(tiles).length+' requests');
$.each(tiles, function(ind, tls) {
data = { zoom: z };
data.boundsParamsList = tls;
window.requests.add(window.postAjax('getThinnedEntitiesV2', data, window.handleDataResponse, window.handleFailedRequest));
// keep a list of tile_ids with each request. in the case of a server error, we can try and use cached tiles if available
var tile_ids = []
$.each(tls,function(i,req) { tile_ids.push(req.qk); });
window.requests.add(window.postAjax('getThinnedEntitiesV2', data, function(data, textStatus, jqXHR) { window.handleDataResponse(data,false,tile_ids); }, function() { window.handleFailedRequest(tile_ids); }));
});
// process the requests from the cache
console.log('got '+Object.keys(cachedData.result.map).length+' data tiles from cache');
if(Object.keys(cachedData.result.map).length > 0) {
handleDataResponse(cachedData, true);
}
}
// Handle failed map data request
window.handleFailedRequest = function() {
window.handleFailedRequest = function(tile_ids) {
console.log('request failed: tiles '+tile_ids.join(','));
var cachedData = { result: { map: {} } };
$.each(tile_ids, function(ind,tile_id) {
var cached = getDataCache(tile_id);
if (cached) {
// we have stale cached data - use it
cachedData.result.map[tile_id] = cached;
debugSetTileColour(tile_id,'#800','#ff0');
console.log('(using stale cache entry for map tile '+tile_id+')');
window.statusStaleMapTiles++;
} else {
// no cached data
debugSetTileColour(tile_id,'#800','#f00');
window.statusErrorMapTiles++;
}
});
if(Object.keys(cachedData.result.map).length > 0) {
handleDataResponse(cachedData, true);
}
if(requests.isLastRequest('getThinnedEntitiesV2')) {
var leftOverPortals = portalRenderLimit.mergeLowLevelPortals(null);
handlePortalsRender(leftOverPortals);
@ -76,12 +249,12 @@ window.handleFailedRequest = function() {
}
// works on map data response and ensures entities are drawn/updated.
window.handleDataResponse = function(data, textStatus, jqXHR) {
window.handleDataResponse = function(data, fromCache, tile_ids) {
// remove from active ajax queries list
if(!data || !data.result) {
window.failedRequestCount++;
console.warn(data);
handleFailedRequest();
handleFailedRequest(tile_ids);
return;
}
@ -94,8 +267,35 @@ window.handleDataResponse = function(data, textStatus, jqXHR) {
var ppp = {};
var p2f = {};
$.each(m, function(qk, val) {
if('error' in val) {
console.log('map data tile '+qk+' response error: '+val.error);
// if this request wasn't from the cache, check it's status. store in the cache if good
// for debugging, we set the debug tile colours. cached tiles have colours set elsewhere so are not set here
if (!fromCache) {
if('error' in val) {
console.log('map data tile '+qk+' response error: '+val.error);
// try to use data in the cache, even if it's stale
var cacheVal = getDataCache(qk);
if (!cacheVal) {
debugSetTileColour(qk, '#f00','#f00');
// no data in cache for this tile. continue processing - it's possible it also has some valid data
window.statusErrorMapTiles++;
} else {
// stale cache entry exists - use it
val = cacheVal;
debugSetTileColour(qk, '#f00','#ff0');
console.log('(using stale cache entry for map tile '+qk+')');
window.statusStaleMapTiles++;
}
} else {
// not an error - store this tile into the cache
storeDataCache(qk,val);
debugSetTileColour(qk, '#0f0','#0f0');
window.statusSuccessMapTiles++;
}
}
$.each(val.deletedGameEntityGuids || [], function(ind, guid) {
@ -299,6 +499,32 @@ window.removeByGuid = function(guid) {
}
// Separation of marker style setting from the renderPortal method
// Having this as a separate function allows subsituting alternate marker rendering (for plugins)
window.getMarker = function(ent, portalLevel, latlng, team) {
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),
color: ent[0] === selectedPortal ? COLOR_SELECTED_PORTAL : COLORS[team],
opacity: 1,
weight: lvWeight,
fillColor: COLORS[team],
fillOpacity: 0.5,
clickable: true,
level: portalLevel,
team: team,
ent: ent,
details: ent[2],
guid: ent[0]});
return p;
}
// renders a portal on the map from the given entity
window.renderPortal = function(ent) {
@ -347,25 +573,7 @@ window.renderPortal = function(ent) {
// pre-loads player names for high zoom levels
loadPlayerNamesForPortal(ent[2]);
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),
color: ent[0] === selectedPortal ? COLOR_SELECTED_PORTAL : COLORS[team],
opacity: 1,
weight: lvWeight,
fillColor: COLORS[team],
fillOpacity: 0.5,
clickable: true,
level: portalLevel,
team: team,
ent: ent,
details: ent[2],
guid: ent[0]});
var p = getMarker(ent, portalLevel, latlng, team);
p.on('remove', function() {
var portalGuid = this.options.guid

View File

@ -2,6 +2,9 @@
//
window.show = function(id) {
window.hideall();
if (typeof android !== 'undefined' && android && android.switchToPane) {
android.switchToPane(id);
}
switch(id) {
case 'full':
window.chat.show('full');

View File

@ -80,7 +80,11 @@ window.resolvePlayerNames = function() {
}
window.setPlayerName = function(guid, nick) {
window.setPlayerName = function(guid, nick, uncertain) {
// the 'uncertain' flag is set when we're scrolling back through chat. it's possible in this case
// to come across a message from before a name change. these should be ignored if existing cache entries exist
if(uncertain && guid in localStorage) return;
if($.trim(('' + nick)).slice(0, 5) === '{"L":' && !window.alertFor37WasShown) {
window.alertFor37WasShown = true;
alert('You have run into bug #37. Please help me solve it!\nCopy and paste this text and post it here:\nhttps://github.com/breunigs/ingress-intel-total-conversion/issues/37\nIf copy & pasting doesnt work, make a screenshot instead.\n\n\n' + window.debug.printStackTrace() + '\n\n\n' + JSON.stringify(nick));

View File

@ -50,6 +50,41 @@ window.renderPortalDetails = function(guid) {
var perma = '/intel?ll='+lat+','+lng+'&z=17&pll='+lat+','+lng;
var imgTitle = 'title="'+getPortalDescriptionFromDetails(d)+'\n\nClick to show full image."';
var poslinks = 'window.showPortalPosLinks('+lat+','+lng+',\''+escapeJavascriptString(d.portalV2.descriptiveText.TITLE)+'\')';
var portalDetailObj = window.getPortalDescriptionFromDetailsExtended(d);
var portalDetailedDescription = '';
if(portalDetailObj) {
portalDetailedDescription = '<table description="Portal Photo Details" class="portal_details">';
// TODO (once the data supports it) - portals can have multiple photos. display all, with navigation between them
// (at this time the data isn't returned from the server - although a count of images IS returned!)
if(portalDetailObj.submitter.name.length > 0) {
if(portalDetailObj.submitter.team) {
submitterSpan = '<span class="' + (portalDetailObj.submitter.team === 'RESISTANCE' ? 'res' : 'enl') + ' nickname">';
} else {
submitterSpan = '<span class="none">';
}
portalDetailedDescription += '<tr><th>Photo by:</th><td>' + submitterSpan
+ escapeHtmlSpecialChars(portalDetailObj.submitter.name) + '</span> (' + portalDetailObj.submitter.voteCount + ' votes)</td></tr>';
}
if(portalDetailObj.submitter.link.length > 0) {
portalDetailedDescription += '<tr><th>Photo from:</th><td><a href="'
+ escapeHtmlSpecialChars(portalDetailObj.submitter.link) + '">' + escapeHtmlSpecialChars(portalDetailObj.submitter.link) + '</a></td></tr>';
}
if(portalDetailObj.description) {
portalDetailedDescription += '<tr class="padding-top"><th>Description:</th><td>' + escapeHtmlSpecialChars(portalDetailObj.description) + '</td></tr>';
}
// if(d.portalV2.descriptiveText.ADDRESS) {
// portalDetailedDescription += '<tr><th>Address:</th><td>' + escapeHtmlSpecialChars(d.portalV2.descriptiveText.ADDRESS) + '</td></tr>';
// }
portalDetailedDescription += '</table>';
}
$('#portaldetails')
.attr('class', TEAM_TO_CSS[getTeam(d)])
@ -58,8 +93,9 @@ window.renderPortalDetails = function(guid) {
+ '<span class="close" onclick="unselectOldPortal();" title="Close">X</span>'
// help cursor via ".imgpreview img"
+ '<div class="imgpreview" '+imgTitle+' style="background-image: url('+img+')">'
+ '<img class="hide" src="'+img+'"/>'
+ '<span id="level">'+Math.floor(getPortalLevel(d))+'</span>'
+ '<div class="portalDetails">'+ portalDetailedDescription + '</div>'
+ '<img class="hide" src="'+img+'"/></div>'
+ '</div>'
+ '<div class="mods">'+getModDetails(d)+'</div>'
+ randDetails
@ -129,5 +165,9 @@ window.unselectOldPortal = function() {
if(oldPortal) portalResetColor(oldPortal);
selectedPortal = null;
$('#portaldetails').html('');
if(isSmartphone()) {
$('.fullimg').remove();
$('#mobileinfo').html('');
}
clearPortalIndicators();
}

View File

@ -8,8 +8,8 @@ window.getRangeText = function(d) {
return ['range',
'<a onclick="window.rangeLinkClick()">'
+ (range > 1000
? Math.round(range/1000) + ' km'
: Math.round(range) + ' m')
? Math.floor(range/1000) + ' km'
: Math.floor(range) + ' m')
+ '</a>'];
}
@ -23,6 +23,43 @@ window.getPortalDescriptionFromDetails = function(details) {
return desc;
}
// Grabs more info, including the submitter name for the current main
// portal image
window.getPortalDescriptionFromDetailsExtended = function(details) {
var descObj = details.portalV2.descriptiveText;
var photoStreamObj = details.photoStreamInfo;
var submitterObj = new Object();
submitterObj.type = "";
submitterObj.name = "Unknown";
submitterObj.team = "";
submitterObj.link = "";
submitterObj.voteCount = 0;
if(photoStreamObj && photoStreamObj.hasOwnProperty("coverPhoto") && photoStreamObj.coverPhoto.hasOwnProperty("attributionMarkup")) {
var attribution = photoStreamObj.coverPhoto.attributionMarkup;
submitterObj.type = attribution[0];
if(attribution[1].hasOwnProperty("plain"))
submitterObj.name = attribution[1].plain;
if(attribution[1].hasOwnProperty("team"))
submitterObj.team = attribution[1].team;
if(attribution[1].hasOwnProperty("attributionLink"))
submitterObj.link = attribution[1].attributionLink;
if(photoStreamObj.coverPhoto.hasOwnProperty("voteCount"))
submitterObj.voteCount = photoStreamObj.coverPhoto.voteCount;
}
var portalDetails = {
title: descObj.TITLE,
description: descObj.DESCRIPTION,
address: descObj.ADDRESS,
submitter: submitterObj
};
return portalDetails;
}
// given portal details, returns html code to display mod details.
window.getModDetails = function(d) {
@ -30,29 +67,61 @@ window.getModDetails = function(d) {
var modsTitle = [];
var modsColor = [];
$.each(d.portalV2.linkedModArray, function(ind, mod) {
if(!mod) {
mods.push('');
modsTitle.push('');
modsColor.push('#000');
} else if(mod.type === 'RES_SHIELD') {
var modName = '';
var modTooltip = '';
var modColor = '#000';
var title = mod.rarity.capitalize() + ' ' + mod.displayName + '\n';
title += 'Installed by: '+ getPlayerName(mod.installingUser);
if (mod) {
// all mods seem to follow the same pattern for the data structure
// but let's try and make this robust enough to handle possible future differences
title += '\nStats:';
for (var key in mod.stats) {
if (!mod.stats.hasOwnProperty(key)) continue;
title += '\n+' + mod.stats[key] + ' ' + key.capitalize();
if (mod.displayName) {
modName = mod.displayName;
} else if (mod.type) {
modName = mod.type;
} else {
modName = '(unknown mod)';
}
mods.push(mod.rarity.capitalize().replace('_', ' ') + ' ' + mod.displayName);
modsTitle.push(title);
modsColor.push(COLORS_MOD[mod.rarity]);
} else {
mods.push(mod.type);
modsTitle.push('Unknown mod. No further details available.');
modsColor.push('#FFF');
if (mod.rarity) {
modName = mod.rarity.capitalize().replace(/_/g,' ') + ' ' + modName;
}
modTooltip = modName + '\n';
if (mod.installingUser) {
modTooltip += 'Installed by: '+ getPlayerName(mod.installingUser) + '\n';
}
if (mod.stats) {
modTooltip += 'Stats:';
for (var key in mod.stats) {
if (!mod.stats.hasOwnProperty(key)) continue;
var val = mod.stats[key];
if (key === 'REMOVAL_STICKINESS' && val == 0) continue; // stat on all mods recently - unknown meaning, not displayed in stock client
// special formatting for known mod stats, where the display of the raw value is less useful
if (mod.type === 'HEATSINK' && key === 'HACK_SPEED') val = (val/10000)+'%'; // 500000 = 50%
else if (mod.type === 'FORCE_AMP' && key === 'FORCE_AMPLIFIER') val = (val/1000)+'x'; // 2000 = 2x
else if (mod.type === 'LINK_AMPLIFIER' && key === 'LINK_RANGE_MULTIPLIER') val = (val/1000)+'x' // 2000 = 2x
else if (mod.type === 'TURRET' && key === 'HIT_BONUS') val = (val/10000)+'%'; // 2000 = 0.2% (although this seems pretty small to be useful?)
else if (mod.type === 'TURRET' && key === 'ATTACK_FREQUENCY') val = (val/1000)+'x' // 2000 = 2x
// else display unmodified. correct for shield mitigation and multihack - unknown for future/other mods
modTooltip += '\n+' + val + ' ' + key.capitalize().replace(/_/g,' ');
}
}
if (mod.rarity) {
modColor = COLORS_MOD[mod.rarity];
} else {
modColor = '#fff';
}
}
mods.push(modName);
modsTitle.push(modTooltip);
modsColor.push(modColor);
});
var t = '<span'+(modsTitle[0].length ? ' title="'+modsTitle[0]+'"' : '')+' style="color:'+modsColor[0]+'">'+mods[0]+'</span>'

View File

@ -54,9 +54,39 @@ window.getPortalRange = function(d) {
lvl += parseInt(reso.level);
});
if(resoMissing) return 0;
return 160*Math.pow(getPortalLevel(d), 4);
var range = 160*Math.pow(getPortalLevel(d), 4);
var boost = getLinkAmpRangeBoost(d);
return range*boost;
}
window.getLinkAmpRangeBoost = function(d) {
// additional range boost calculation
// (at the time of writing, only rare link amps have been seen in the wild, so there's a little guesswork at how
// the stats work and combine - jon 2013-06-26)
// link amps scale: first is full, second half, the last two a quarter
var scale = [1.0, 0.5, 0.25, 0.25];
var boost = 1.0; // initial boost is 1.0 (i.e. no boost over standard range)
var count = 0;
$.each(d.portalV2.linkedModArray, function(ind, mod) {
if(mod && mod.type === 'LINK_AMPLIFIER' && mod.stats && mod.stats.LINK_RANGE_MULTIPLIER) {
// link amp stat LINK_RANGE_MULTIPLIER is 2000 for rare, and gives 2x boost to the range
var baseMultiplier = mod.stats.LINK_RANGE_MULTIPLIER/1000;
boost += (baseMultiplier-1)*scale[count];
count++;
}
});
return boost;
}
window.getAvgResoDist = function(d) {
var sum = 0, resos = 0;
$.each(d.resonatorArray.resonators, function(ind, reso) {

View File

@ -18,6 +18,36 @@ window.REDEEM_RESOURCES = {
return {long: 'Portal Shield', short: 'S'};
}
},
FORCE_AMP: {
format: function(acquired) {
return {long: 'Force Amp', short: 'FA'};
}
},
LINK_AMP: {
format: function(acquired) {
return {long: 'Link Amp', short: 'LA'};
}
},
HEATSINK: {
format: function(acquired) {
return {long: 'Heatsink', short: 'H'};
}
},
MULTIHACK: {
format: function(acquired) {
return {long: 'Multihack', short: 'M'};
}
},
TURRET: {
format: function(acquired) {
return {long: 'Turret', short: 'T'};
}
},
UNUSUAL: {
format: function(acquired) {
return {long: 'Unusual Object', short: 'U'};
}
},
EMITTER_A: {
/* resourceWithLevels */
format: function(acquired) {

View File

@ -5,6 +5,12 @@
window.activeRequests = [];
window.failedRequestCount = 0;
window.statusTotalMapTiles = 0;
window.statusCachedMapTiles = 0;
window.statusSuccessMapTiles = 0;
window.statusStaleMapTiles = 0;
window.statusErrorMapTiles = 0;
window.requests = function() {}
@ -39,7 +45,7 @@ window.requests.abort = function() {
// to website. Updates info in layer chooser.
window.renderUpdateStatus = function() {
var t = '<div><span class="help portallevel" title="Indicates portal levels displayed. Zoom in to display lower level portals."><b>portals</b>: ';
var t = '<span class="help portallevel" title="Indicates portal levels displayed. Zoom in to display lower level portals."><b>portals</b>: ';
var minlvl = getMinPortalLevel();
if(minlvl === 0)
t += 'all';
@ -52,12 +58,22 @@ window.renderUpdateStatus = function() {
t += '<span class="help" title="Paused due to user interaction">paused</span';
else if(isIdle())
t += '<span style="color:#888">Idle</span>';
else if(window.activeRequests.length > 0)
t += window.activeRequests.length + ' requests';
else if(window.requests._quickRefreshPending)
t += 'refreshing';
else
t += 'Up to date';
else if(window.activeRequests.length > 0)
t += window.activeRequests.length + ' requests';
else {
// tooltip with detailed tile counts
t += '<span class="help" title="'+window.statusTotalMapTiles+' tiles: '+window.statusCachedMapTiles+' cached, '+window.statusSuccessMapTiles+' successful, '+window.statusStaleMapTiles+' stale, '+window.statusErrorMapTiles+' failed">';
// basic error/out of date/up to date message
if (window.statusErrorMapTiles) t += '<span style="color:#f66">Errors</span>';
else if (window.statusStaleMapTiles) t += '<span style="color:#fa6">Out of date</span>';
else t += 'Up to date';
t += '</span>';
}
t += '</span>';
if(renderLimitReached())
@ -66,8 +82,6 @@ window.renderUpdateStatus = function() {
if(window.failedRequestCount > 0)
t += ' <span style="color:#f66">' + window.failedRequestCount + ' failed</span>'
t += '</div>';
var portalSelection = $('.leaflet-control-layers-overlays label');
//it's an array - 0=unclaimed, 1=lvl 1, 2=lvl 2, ..., 8=lvl 8 - 9 relevant entries
//mark all levels below (but not at) minlvl as disabled
@ -76,7 +90,7 @@ window.renderUpdateStatus = function() {
portalSelection.slice(minlvl, 8+1).removeClass('disabled').attr('title', '');
$('#updatestatus').html(t);
$('#innerstatus').html(t);
//$('#updatestatus').click(function() { startRefreshTimeout(10); });
//. <a style="cursor: pointer" onclick="startRefreshTimeout(10)" title="Refresh">⟳</a>';
}
@ -120,7 +134,7 @@ window.requests._callOnRefreshFunctions = function() {
startRefreshTimeout();
if(isIdle()) {
console.log('user has been idle for ' + idleTime + ' minutes. Skipping refresh.');
console.log('user has been idle for ' + idleTime + ' seconds, or window hidden. Skipping refresh.');
renderUpdateStatus();
return;
}

View File

@ -68,12 +68,30 @@ window.runOnSmartphonesBeforeBoot = function() {
});
}
window.smartphoneInfo = function(data) {
var d = data.portalDetails;
var t = 'L' + Math.floor(getPortalLevel(d));
var percentage = '0%';
var totalEnergy = getTotalPortalEnergy(d);
if(getTotalPortalEnergy(d) > 0) {
percentage = Math.floor((getCurrentPortalEnergy(d) / getTotalPortalEnergy(d) * 100)) + '%';
}
t += ' ' + percentage + ' ';
t += d.portalV2.descriptiveText.TITLE;
$('#mobileinfo').html(t);
}
window.runOnSmartphonesAfterBoot = function() {
if(!isSmartphone()) return;
console.warn('running smartphone post boot stuff');
smartphone.mapButton.click();
// add a div/hook for updating mobile info
$('#updatestatus').prepend('<div id="mobileinfo"></div>');
window.addHook('portalDetailsUpdated', window.smartphoneInfo);
// disable img full view
$('#portaldetails').off('click', '**');
@ -90,12 +108,8 @@ window.runOnSmartphonesAfterBoot = function() {
// this is a hack, accessing Leaflets private _container is evil
$(this._container).on('taphold', function() {
if (typeof android !== 'undefined' && android && android.portalLongPressed) {
android.portalLongPressed();
} else {
window.renderPortalDetails(guid);
window.smartphone.sideButton.click();
}
window.renderPortalDetails(guid);
window.show('info');
});
});
});

View File

@ -249,23 +249,20 @@ window.getPortalDataZoom = function() {
// limiting the mazimum zoom level for data retrieval reduces the number of requests at high zoom levels
// (as all portal data is retrieved at z=17, why retrieve multiple z=18 tiles when fewer z=17 would do?)
// a potential downside - we end up requesting more data than we needed from the larger tiles that go off
// the window edge.
// very effective along with the new cache code
if (z > 17) z=17;
// we could consider similar zoom-level consolidation, as, e.g. level 16 and 15 both return L1+, always
// request zoom 15 tiles. however, there are quirks in the current data stream, where small fields aren't
// returned by the server. using larger tiles always would amplify this issue.
//sanity check - should never happen
if (z < 0) z=0;
return z;
}
window.getMinPortalLevel = function() {
var z = getPortalDataZoom();
window.getMinPortalLevelForZoom = function(z) {
if(z >= 17) return 0;
if(z < 0) return 8;
var conv = [8,8,8,8,7,7,6,6,5,4,4,3,3,2,2,1,1];
@ -276,6 +273,12 @@ window.getMinPortalLevel = function() {
return result;
}
window.getMinPortalLevel = function() {
var z = getPortalDataZoom();
return getMinPortalLevelForZoom(z);
}
// returns number of pixels left to scroll down before reaching the
// bottom. Works similar to the native scrollTop function.
window.scrollBottom = function(elm) {

31
external/Control.MiniMap.css vendored Normal file
View File

@ -0,0 +1,31 @@
.leaflet-control-minimap {
border:solid rgba(255, 255, 255, 0.7) 3px;
box-shadow: 0 1px 7px #999;
background: #f8f8f9;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
border-radius: 8px;
}
.leaflet-control-minimap a {
background-color: rgba(255, 255, 255, 0.75);
background-position: 1px 2px;
background-repeat: no-repeat;
display: block;
outline: none;
z-index: 99999;
}
.leaflet-control-minimap a.minimized {
background-position: 1px -18px;
}
.leaflet-control-minimap-toggle-display {
background-image: url(@@INCLUDEIMAGE:images/minimap-toggle.png@@);
border-radius: 4px 4px 4px 4px;
height: 19px;
width: 19px;
position: absolute;
bottom: 0;
right: 0;
}

243
external/Control.MiniMap.js vendored Normal file
View File

@ -0,0 +1,243 @@
L.Control.MiniMap = L.Control.extend({
options: {
position: 'bottomright',
toggleDisplay: false,
zoomLevelOffset: -5,
zoomLevelFixed: false,
zoomAnimation: false,
autoToggleDisplay: false,
width: 150,
height: 150
},
hideText: 'Hide MiniMap',
showText: 'Show MiniMap',
//layer is the map layer to be shown in the minimap
initialize: function (layer, options) {
L.Util.setOptions(this, options);
this._layer = layer;
},
onAdd: function (map) {
this._mainMap = map;
//Creating the container and stopping events from spilling through to the main map.
this._container = L.DomUtil.create('div', 'leaflet-control-minimap');
this._container.style.width = this.options.width + 'px';
this._container.style.height = this.options.height + 'px';
L.DomEvent.disableClickPropagation(this._container);
L.DomEvent.on(this._container, 'mousewheel', L.DomEvent.stopPropagation);
this._miniMap = new L.Map(this._container,
{
attributionControl: false,
zoomControl: false,
zoomAnimation: this.options.zoomAnimation,
autoToggleDisplay: this.options.autoToggleDisplay,
touchZoom: !this.options.zoomLevelFixed,
scrollWheelZoom: !this.options.zoomLevelFixed,
doubleClickZoom: !this.options.zoomLevelFixed,
boxZoom: !this.options.zoomLevelFixed,
crs: map.options.crs
});
this._miniMap.addLayer(this._layer);
//These bools are used to prevent infinite loops of the two maps notifying each other that they've moved.
this._mainMapMoving = false;
this._miniMapMoving = false;
//Keep a record of this to prevent auto toggling when the user explicitly doesn't want it.
this._userToggledDisplay = false;
this._minimized = false;
if (this.options.toggleDisplay) {
this._addToggleButton();
}
this._miniMap.whenReady(L.Util.bind(function () {
this._aimingRect = L.rectangle(this._mainMap.getBounds(), {color: "#ff7800", weight: 1, clickable: false}).addTo(this._miniMap);
this._shadowRect = L.rectangle(this._mainMap.getBounds(), {color: "#000000", weight: 1, clickable: false,opacity:0,fillOpacity:0}).addTo(this._miniMap);
this._mainMap.on('moveend', this._onMainMapMoved, this);
this._mainMap.on('move', this._onMainMapMoving, this);
this._miniMap.on('movestart', this._onMiniMapMoveStarted, this);
this._miniMap.on('move', this._onMiniMapMoving, this);
this._miniMap.on('moveend', this._onMiniMapMoved, this);
}, this));
return this._container;
},
addTo: function (map) {
L.Control.prototype.addTo.call(this, map);
this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true));
this._setDisplay(this._decideMinimized());
return this;
},
onRemove: function (map) {
this._mainMap.off('moveend', this._onMainMapMoved, this);
this._mainMap.off('move', this._onMainMapMoving, this);
this._miniMap.off('moveend', this._onMiniMapMoved, this);
this._miniMap.removeLayer(this._layer);
},
_addToggleButton: function () {
this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton(
'', this.hideText, 'leaflet-control-minimap-toggle-display', this._container, this._toggleDisplayButtonClicked, this) : undefined;
},
_createButton: function (html, title, className, container, fn, context) {
var link = L.DomUtil.create('a', className, container);
link.innerHTML = html;
link.href = '#';
link.title = title;
var stop = L.DomEvent.stopPropagation;
L.DomEvent
.on(link, 'click', stop)
.on(link, 'mousedown', stop)
.on(link, 'dblclick', stop)
.on(link, 'click', L.DomEvent.preventDefault)
.on(link, 'click', fn, context);
return link;
},
_toggleDisplayButtonClicked: function () {
this._userToggledDisplay = true;
if (!this._minimized) {
this._minimize();
this._toggleDisplayButton.title = this.showText;
}
else {
this._restore();
this._toggleDisplayButton.title = this.hideText;
}
},
_setDisplay: function (minimize) {
if (minimize != this._minimized) {
if (!this._minimized) {
this._minimize();
}
else {
this._restore();
}
}
},
_minimize: function () {
// hide the minimap
if (this.options.toggleDisplay) {
this._container.style.width = '19px';
this._container.style.height = '19px';
this._toggleDisplayButton.className += ' minimized';
}
else {
this._container.style.display = 'none';
}
this._minimized = true;
},
_restore: function () {
if (this.options.toggleDisplay) {
this._container.style.width = this.options.width + 'px';
this._container.style.height = this.options.height + 'px';
this._toggleDisplayButton.className = this._toggleDisplayButton.className
.replace(/(?:^|\s)minimized(?!\S)/g, '');
}
else {
this._container.style.display = 'block';
}
this._minimized = false;
},
_onMainMapMoved: function (e) {
if (!this._miniMapMoving) {
this._mainMapMoving = true;
this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true));
this._setDisplay(this._decideMinimized());
} else {
this._miniMapMoving = false;
}
this._aimingRect.setBounds(this._mainMap.getBounds());
},
_onMainMapMoving: function (e) {
this._aimingRect.setBounds(this._mainMap.getBounds());
},
_onMiniMapMoveStarted:function (e) {
var lastAimingRect = this._aimingRect.getBounds();
var sw = this._miniMap.latLngToContainerPoint(lastAimingRect.getSouthWest());
var ne = this._miniMap.latLngToContainerPoint(lastAimingRect.getNorthEast());
this._lastAimingRectPosition = {sw:sw,ne:ne};
},
_onMiniMapMoving: function (e) {
if (!this._mainMapMoving && this._lastAimingRectPosition) {
this._shadowRect.setBounds(new L.LatLngBounds(this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.sw),this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.ne)));
this._shadowRect.setStyle({opacity:1,fillOpacity:0.3});
}
},
_onMiniMapMoved: function (e) {
if (!this._mainMapMoving) {
this._miniMapMoving = true;
this._mainMap.setView(this._miniMap.getCenter(), this._decideZoom(false));
this._shadowRect.setStyle({opacity:0,fillOpacity:0});
} else {
this._mainMapMoving = false;
}
},
_decideZoom: function (fromMaintoMini) {
if (!this.options.zoomLevelFixed) {
if (fromMaintoMini)
return this._mainMap.getZoom() + this.options.zoomLevelOffset;
else
return this._miniMap.getZoom() - this.options.zoomLevelOffset;
} else {
if (fromMaintoMini)
return this.options.zoomLevelFixed;
else
return this._mainMap.getZoom();
}
},
_decideMinimized: function () {
if (this._userToggledDisplay) {
return this._minimized;
}
if (this.options.autoToggleDisplay) {
if (this._mainMap.getBounds().contains(this._miniMap.getBounds())) {
return true;
}
return false;
}
return this._minimized;
}
});
L.Map.mergeOptions({
miniMapControl: false
});
L.Map.addInitHook(function () {
if (this.options.miniMapControl) {
this.miniMapControl = (new L.Control.MiniMap()).addTo(this);
}
});
L.control.minimap = function (options) {
return new L.Control.MiniMap(options);
};

View File

@ -18,7 +18,7 @@
/* If the points of the triangle are collinear, then just find the
* extremes and use the midpoint as the center of the circumcircle. */
if(Math.abs(G) < 0.000001) {
if(Math.abs(G) < 1e-12) {
minx = Math.min(a.x, b.x, c.x)
miny = Math.min(a.y, b.y, c.y)
dx = (Math.max(a.x, b.x, c.x) - minx) * 0.5
@ -166,4 +166,4 @@
/* Yay, we're done! */
return closed
}
}

BIN
images/minimap-toggle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

14
main.js
View File

@ -1,7 +1,7 @@
// ==UserScript==
// @id ingress-intel-total-conversion@jonatkins
// @name IITC: Ingress intel map total conversion
// @version 0.12.1.@@DATETIMEVERSION@@
// @version 0.12.3.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@ -21,6 +21,7 @@ window.iitcBuildDate = '@@BUILDDATE@@';
// disable vanilla JS
window.onload = function() {};
document.body.onload = function() {};
// rescue user data from original page
@ -92,14 +93,15 @@ document.getElementsByTagName('body')[0].innerHTML = ''
+ ' <img src="@@INCLUDEIMAGE:images/current-location.png@@"/ title="Current Location">'
+ ' </div>'
+ ' <div id="portaldetails"></div>'
+ ' <input id="redeem" placeholder="Redeem code…" type="text"/>'
// redeeming removed from stock site, so commented out for now. it may return...
// + ' <input id="redeem" placeholder="Redeem code…" type="text"/>'
+ ' <div id="toolbox">'
+ ' <a onmouseover="setPermaLink(this)" onclick="setPermaLink(this);return androidCopy(this.href)" title="URL link to this map view">Permalink</a>'
+ ' <a onclick="window.aboutIITC()" style="cursor: help">About IITC</a>'
+ ' </div>'
+ ' </div>'
+ '</div>'
+ '<div id="updatestatus"></div>';
+ '<div id="updatestatus"><div id="innerstatus"></div></div>';
// putting everything in a wrapper function that in turn is placed in a
// script tag on the website allows us to execute in the sites context
@ -113,12 +115,12 @@ function wrapper() {
L_PREFER_CANVAS = false;
// CONFIG OPTIONS ////////////////////////////////////////////////////
window.REFRESH = 60; // refresh view every 60s (base time)
window.REFRESH = 30; // refresh view every 30s (base time)
window.ZOOM_LEVEL_ADJ = 5; // add 5 seconds per zoom level
window.ON_MOVE_REFRESH = 1.25; //refresh time to use after a movement event
window.MINIMUM_OVERRIDE_REFRESH = 5; //limit on refresh time since previous refresh, limiting repeated move refresh rate
window.REFRESH_GAME_SCORE = 15*60; // refresh game score every 15 minutes
window.MAX_IDLE_TIME = 4; // stop updating map after 4min idling
window.MAX_IDLE_TIME = 4*60; // stop updating map after 4min idling
window.PRECACHE_PLAYER_NAMES_ZOOM = 17; // zoom level to start pre-resolving player names
window.HIDDEN_SCROLLBAR_ASSUMED_WIDTH = 20;
window.SIDEBAR_WIDTH = 300;
@ -161,6 +163,8 @@ window.COLORS_MOD = {VERY_RARE: '#F78AF6', RARE: '#AD8AFF', COMMON: '#84FBBD'};
window.OPTIONS_RESONATOR_SELECTED = {color: '#fff', weight: 2, radius: 4, opacity: 1, clickable: false};
window.OPTIONS_RESONATOR_NON_SELECTED = {color: '#aaa', weight: 1, radius: 3, opacity: 1, clickable: false};
window.MOD_TYPE = {RES_SHIELD:'Shield', MULTIHACK:'Multi-hack', FORCE_AMP:'Force Amp', HEATSINK:'Heat Sink', TURRET:'Turret', LINK_AMPLIFIER: 'Link Amp'};
window.OPTIONS_RESONATOR_LINE_SELECTED = {
opacity: 0.7,
weight: 3,

2
mobile/.idea/misc.xml generated
View File

@ -3,7 +3,7 @@
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="Android 4.2.2 Platform" project-jdk-type="Android SDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="Android 4.2.2" project-jdk-type="Android SDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

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

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="SetJavaScriptEnabled">
<ignore path="src/com/cradle/ittc_mobile/iitc_webview.java" />
</issue>
</lint>

View File

@ -1,7 +1,7 @@
// ==UserScript==
// @id iitc-plugin-user-location@cradle
// @name IITC plugin: User Location
// @version 0.1.0.@@DATETIMEVERSION@@
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@ -12,10 +12,7 @@
// @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() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -34,10 +31,21 @@ window.plugin.userLocation.setup = function() {
iconRetinaUrl: iconRetImage
}});
var cssClass = PLAYER.team === 'ALIENS' ? 'enl' : 'res';
var title = '<span class="nickname '+ cssClass+'" style="font-weight:bold;">' + PLAYER.nickname + '</span>\'s location';
var marker = L.marker(window.map.getCenter(), {
title: "User Location",
title: title,
icon: new plugin.userLocation.icon()
});
// copy location to android clipboard on marker click
marker.on('click', function(e) {
window.console.log('marker location');
var ll = e.target.getLatLng();
window.androidCopy('https://maps.google.com/?q='+ll.lat+','+ll.lng+'%20('+PLAYER.nickname+')');
});
plugin.userLocation.marker = marker;
marker.addTo(window.map);
// jQueryUI doesnt automatically notice the new markers
@ -53,16 +61,4 @@ var setup = window.plugin.userLocation.setup;
// 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);
@@PLUGINEND@@

View File

@ -32,7 +32,7 @@
<string name="pref_ui_cat">UI</string>
<string name="pref_misc_cat">Misc</string>
<string name="pref_plugins">Plugins</string>
<string name="pref_plugins">IITC Plugins</string>
<string name="pref_plugins_title">Available plugins</string>
<string name="pref_user_loc">Display user location</string>
<string name="pref_user_loc_sum">Show users position on map</string>
@ -44,11 +44,14 @@
<string name="pref_force_desktop_sum">Nice for tablets, looks awful on smartphones</string>
<string name="pref_force_https">Force https</string>
<string name="pref_force_https_sum">Disabling may improve performance</string>
<string name="pref_press_twice_to_exit">Press back button twice to exit</string>
<string name="pref_press_twice_to_exit_sum">Avoids accidental exits</string>
<string name="pref_developer_options">Developer options</string>
<string name="pref_enable_dev_mode">Enable developer mode</string>
<string name="pref_enable_dev_mode_sum">If enabled, all IITC sources will be loaded from external storage of the Android device.
Please copy all sources from $IITC_folder/build/mobile/ to /sdcard/IITC_Mobile/dev/.</string>
<string name="pref_select_iitc">IITC source</string>
<string name="pref_select_iitc_sum">Load IITC main script from url or use local script. Currently used source:</string>
<string name="menu_chat">Chat</string>
<string name="menu_full">Full</string>

View File

@ -37,20 +37,24 @@
<PreferenceCategory
android:key="pref_mics"
android:title="@string/pref_misc_cat">
<!-- summary is set in settings fragment -->
<EditTextPreference
android:key="pref_iitc_source"
android:title="@string/pref_select_iitc"
android:summary="Load IITC main script from url or use local script. Currently used source: "
android:defaultValue="local"/>
<MultiSelectListPreference
android:key="pref_plugins"
android:title="@string/pref_plugins"
android:dialogTitle="@string/pref_plugins_title"/>
<PreferenceScreen
android:key="pref_plugins"
android:title="@string/pref_plugins" />
<CheckBoxPreference
android:key="pref_force_https"
android:title="@string/pref_force_https"
android:summary="@string/pref_force_https_sum"
android:defaultValue="true" />
<CheckBoxPreference
android:key="pref_press_twice_to_exit"
android:title="@string/pref_press_twice_to_exit"
android:summary="@string/pref_press_twice_to_exit_sum"
android:defaultValue="false" />
</PreferenceCategory>
<PreferenceCategory

View File

@ -3,8 +3,31 @@ body {
color: #fff;
}
#sidebar, #updatestatus, #chatcontrols, #chat, #chatinput {
background: #0B3351 !important
#updatestatus {
background: #262c32;
width: 100%;
color: #d4d5d6;
border: 0;
}
#innerstatus {
float: right;
max-width: 50%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
#mobileinfo {
float: left;
max-width: 50%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
#sidebar, #chatcontrols, #chat, #chatinput {
background: #0B3351 !important;
}
.leaflet-top .leaflet-control {

View File

@ -12,7 +12,7 @@ import android.widget.TextView;
public class IITC_AboutDialogPreference extends DialogPreference {
private Context context;
private final Context context;
public IITC_AboutDialogPreference(Context context, AttributeSet attrs) {
super(context, attrs);

View File

@ -54,30 +54,32 @@ public class IITC_DeviceAccountLogin implements AccountManagerCallback<Bundle> {
}
private Account mAccount;
private AccountAdapter mAccountAdapter;
private AccountManager mAccountManager;
private final AccountAdapter mAccountAdapter;
private final AccountManager mAccountManager;
private Account[] mAccounts;
private IITC_Mobile mActivity;
private final IITC_Mobile mActivity;
private String mAuthToken;
private AlertDialog mProgressbar;
private WebView mWebView;
private final AlertDialog mProgressbar;
private final WebView mWebView;
/**
* This listener is invoked when an item in the account list is selected. (It is also used when the 'cancel' button
* is clicked, (in which case `index` is <0)
* This listener is invoked when an item in the account list is selected.
* (It is also used when the 'cancel' button is clicked, (in which case `index` is <0)
*/
private DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int index) {
if (index >= 0 && index < mAccounts.length) {
mAccount = mAccounts[index];
startAuthentication();
}
dialog.cancel();
}
};
private final DialogInterface.OnClickListener onClickListener =
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int index) {
if (index >= 0 && index < mAccounts.length) {
mAccount = mAccounts[index];
startAuthentication();
}
dialog.cancel();
}
};
public IITC_DeviceAccountLogin(IITC_Mobile activity, WebView webView, WebViewClient webViewClient) {
public IITC_DeviceAccountLogin(IITC_Mobile activity, WebView webView,
WebViewClient webViewClient) {
mActivity = activity;
mWebView = webView;
mAccountManager = AccountManager.get(activity);
@ -112,7 +114,7 @@ public class IITC_DeviceAccountLogin implements AccountManagerCallback<Bundle> {
/**
* called to start authenticating using AccountManager.
*
* <p/>
* After a token is created, AccountManager will call the run() method.
*/
private void startAuthentication() {
@ -142,16 +144,17 @@ public class IITC_DeviceAccountLogin implements AccountManagerCallback<Bundle> {
try {
Intent launch = (Intent) value.getResult().get(AccountManager.KEY_INTENT);
if (launch != null) {
// There is a reason we need to start the given activity if we want an authentication token.
// (Could be user confirmation or something else. Whatever, we have to start it)
// IITC_Mobile will call it using startActivityForResult
// There is a reason we need to start the given activity if we want an
// authentication token. (Could be user confirmation or something else. Whatever,
// we have to start it) IITC_Mobile will call it using startActivityForResult
mActivity.startLoginActivity(launch);
return;
}
String result = value.getResult().getString(AccountManager.KEY_AUTHTOKEN);
if (result != null) {
// authentication succeded, we can load the given url, which will redirect back to the intel map
// authentication succeded, we can load the given url, which will redirect
// back to the intel map
mWebView.loadUrl(result);
mActivity.loginSucceeded();
} else {
@ -164,9 +167,9 @@ public class IITC_DeviceAccountLogin implements AccountManagerCallback<Bundle> {
/**
* start authentication
*
* if we already have a username (e.g. because the existing login has timed out), we can directly start
* authentication if an account with that username is found.
* <p/>
* if we already have a username (e.g. because the existing login has timed out),
* we can directly start authentication if an account with that username is found.
*/
public void startLogin(String realm, String accountName, String args) {
mAccounts = mAccountManager.getAccountsByType(realm);

View File

@ -1,10 +1,5 @@
package com.cradle.iitc_mobile;
import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import android.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
@ -18,17 +13,22 @@ import android.util.Log;
import android.webkit.JavascriptInterface;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import java.util.HashMap;
// provide communication between IITC script and android app
public class IITC_JSInterface {
// context of main activity
Context context;
HashMap<String, String> layer_ids;
boolean[] overlay_is_active;
int active_base_layer;
String[] overlay_layers, base_layers;
int num_base_layers;
int num_overlay_layers;
private final Context context;
private final HashMap<String, String> layer_ids;
private boolean[] overlay_is_active;
private int active_base_layer;
private String[] overlay_layers, base_layers;
private int num_base_layers;
private int num_overlay_layers;
IITC_JSInterface(Context c) {
layer_ids = new HashMap<String, String>();
@ -65,22 +65,68 @@ public class IITC_JSInterface {
}
@JavascriptInterface
public void portalLongPressed() {
public void switchToPane(String id) {
final IITC_Mobile iitcm = (IITC_Mobile) context;
final int button_id;
final String title;
if (id.equals("map")) {
button_id = android.R.id.home;
title = iitcm.getString(R.string.app_name);
} else if (id.equals("info")) {
button_id = R.id.menu_info;
title = "Info";
} else if (id.equals("full")) {
button_id = R.id.menu_full;
title = "Full";
} else if (id.equals("compact")) {
button_id = R.id.menu_compact;
title = "Compact";
} else if (id.equals("public")) {
button_id = R.id.menu_public;
title = "Public";
} else if (id.equals("faction")) {
button_id = R.id.menu_faction;
title = "Faction";
} else if (id.equals("debug")) {
button_id = R.id.menu_debug;
title = "Debug";
}
// default
else {
button_id = android.R.id.home;
title = iitcm.getString(R.string.app_name);
}
Log.d("iitcm", "switch to pane " + id);
iitcm.runOnUiThread(new Runnable() {
@Override
public void run() {
iitcm.handleMenuItemSelected(R.id.menu_info, true);
iitcm.getActionBar().setTitle(title);
iitcm.backStackUpdate(button_id);
}
});
}
@JavascriptInterface
public void dialogOpened(String id, boolean open) {
((IITC_Mobile) context).dialogOpened(id, open);
}
@JavascriptInterface
public void dialogFocused(String id) {
((IITC_Mobile) context).setFocusedDialog(id);
}
// get layers and list them in a dialog
@JavascriptInterface
public void setLayers(String base_layer, String overlay_layer) {
/*
* the layer strings have a form like:
* [{"layerId":27,"name":"MapQuest OSM","active":true},{"layerId":28,"name":"Default Ingress Map","active":false}]
* [{"layerId":27,"name":"MapQuest OSM","active":true},
* {"layerId":28,"name":"Default Ingress Map","active":false}]
* Put it in a JSONArray and parse it
*/
JSONArray base_layersJSON = null;
@ -121,8 +167,8 @@ public class IITC_JSInterface {
String id = "";
String name = "";
boolean isActive = false;
for (int j = 0; j < layers.length; ++j) {
String[] values = layers[j].split(":");
for (String b_layer : layers) {
String[] values = b_layer.split(":");
if (values[0].contains("active")) isActive = values[1].equals("true");
if (values[0].contains("layerId")) id = values[1];
if (values[0].contains("name")) name = values[1];
@ -147,8 +193,8 @@ public class IITC_JSInterface {
String id = "";
String name = "";
boolean isActive = false;
for (int j = 0; j < layers.length; ++j) {
String[] values = layers[j].split(":");
for (String o_layer : layers) {
String[] values = o_layer.split(":");
if (values[0].contains("active")) isActive = values[1].equals("true");
if (values[0].contains("layerId")) id = values[1];
if (values[0].contains("name")) name = values[1];
@ -169,32 +215,33 @@ public class IITC_JSInterface {
// show all overlay layers in a multi selection list dialog
private void show_multi_selection() {
// build the layer chooser dialog
AlertDialog.Builder d_m = new AlertDialog.Builder(context);
AlertDialog.Builder d_m = new AlertDialog.Builder(context);
OnMultiChoiceClickListener m_listener = new OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
// activate clicked layer
((IITC_Mobile) context).getWebView().loadUrl("javascript: window.layerChooser.showLayer("
((IITC_Mobile) context).getWebView().loadUrl("javascript: " +
"window.layerChooser.showLayer("
+ layer_ids.get(overlay_layers[which]) + ","
+ overlay_is_active[which] + ");");
}
};
d_m.setMultiChoiceItems(overlay_layers, overlay_is_active , m_listener);
d_m.setMultiChoiceItems(overlay_layers, overlay_is_active, m_listener);
// switch to base layers
d_m.setPositiveButton("Base Layers", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
show_single_selection();
dialog.cancel();
}
@Override
public void onClick(DialogInterface dialog, int which) {
show_single_selection();
dialog.cancel();
}
});
d_m.setNegativeButton("Close", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
d_m.setTitle("Overlay Layers");
d_m.show();
@ -206,11 +253,12 @@ public class IITC_JSInterface {
@Override
public void onClick(DialogInterface dialog, int which) {
// activate clicked layer
((IITC_Mobile) context).getWebView().loadUrl("javascript: window.layerChooser.showLayer("
((IITC_Mobile) context).getWebView().loadUrl("javascript: " +
"window.layerChooser.showLayer("
+ layer_ids.get(base_layers[which]) + ","
+ true + ");");
active_base_layer = which;
}
}
};
AlertDialog.Builder d_s = new AlertDialog.Builder(context);
d_s.setSingleChoiceItems(base_layers, active_base_layer, s_listener);

View File

@ -1,8 +1,5 @@
package com.cradle.iitc_mobile;
import java.io.IOException;
import java.util.ArrayList;
import android.app.ActionBar;
import android.app.Activity;
import android.app.SearchManager;
@ -19,6 +16,7 @@ import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.util.Log;
@ -26,18 +24,23 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.SearchView;
import android.widget.Toast;
import java.io.IOException;
import java.util.ArrayList;
public class IITC_Mobile extends Activity {
private static final int REQUEST_LOGIN = 1;
private IITC_WebView iitc_view;
private OnSharedPreferenceChangeListener listener;
private String intel_url = "https://www.ingress.com/intel";
private boolean user_loc = false;
private final String intel_url = "https://www.ingress.com/intel";
private boolean is_loc_enabled = false;
private Location last_location = null;
private LocationManager loc_mngr = null;
private LocationListener loc_listener = null;
private boolean fullscreen_mode = false;
@ -47,10 +50,14 @@ public class IITC_Mobile extends Activity {
private MenuItem searchMenuItem;
private boolean desktop = false;
private boolean reload_needed = false;
private final ArrayList<String> dialogStack = new ArrayList<String>();
private SharedPreferences sharedPref;
// Used for custom back stack handling
private ArrayList<Integer> backStack = new ArrayList<Integer>();
private final ArrayList<Integer> backStack = new ArrayList<Integer>();
private boolean backStack_push = true;
private int currentPane = android.R.id.home;
private boolean back_button_pressed = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -59,10 +66,6 @@ public class IITC_Mobile extends Activity {
// enable progress bar above action bar
requestWindowFeature(Window.FEATURE_PROGRESS);
// TODO build an async task for url.openStream() in IITC_WebViewClient
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
setContentView(R.layout.activity_main);
iitc_view = (IITC_WebView) findViewById(R.id.iitc_webview);
@ -75,7 +78,7 @@ public class IITC_Mobile extends Activity {
actionBar.setHomeButtonEnabled(true);
// do something if user changed something in the settings
SharedPreferences sharedPref = PreferenceManager
sharedPref = PreferenceManager
.getDefaultSharedPreferences(this);
listener = new OnSharedPreferenceChangeListener() {
@Override
@ -86,12 +89,11 @@ public class IITC_Mobile extends Activity {
if (desktop) {
setActionBarHomeEnabledWithUp(false);
actionBar.setTitle(getString(R.string.app_name));
}
else actionBar.setHomeButtonEnabled(true);
} else actionBar.setHomeButtonEnabled(true);
invalidateOptionsMenu();
}
if (key.equals("pref_user_loc"))
user_loc = sharedPreferences.getBoolean("pref_user_loc",
is_loc_enabled = sharedPreferences.getBoolean("pref_user_loc",
false);
if (key.equals("pref_fullscreen_actionbar")) {
fullscreen_actionbar = sharedPreferences.getBoolean("pref_fullscreen_actionbar",
@ -101,6 +103,10 @@ public class IITC_Mobile extends Activity {
// no iitc reload needed here
return;
}
// no reload needed
if (key.equals("pref_press_twice_to_exit"))
return;
reload_needed = true;
}
};
@ -119,6 +125,7 @@ public class IITC_Mobile extends Activity {
// Called when a new location is found by the network location
// provider.
drawMarker(location);
last_location = location;
}
public void onStatusChanged(String provider, int status,
@ -132,8 +139,8 @@ public class IITC_Mobile extends Activity {
}
};
user_loc = sharedPref.getBoolean("pref_user_loc", false);
if (user_loc == true) {
is_loc_enabled = sharedPref.getBoolean("pref_user_loc", false);
if (is_loc_enabled) {
// Register the listener with the Location Manager to receive
// location updates
loc_mngr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
@ -163,8 +170,6 @@ public class IITC_Mobile extends Activity {
if (Intent.ACTION_VIEW.equals(action)) {
Uri uri = intent.getData();
String url = uri.toString();
if (intent.getScheme().equals("http"))
url = url.replace("http://", "https://");
Log.d("iitcm", "intent received url: " + url);
if (url.contains("ingress.com")) {
Log.d("iitcm", "loading url...");
@ -195,7 +200,7 @@ public class IITC_Mobile extends Activity {
iitc_view.loadUrl("javascript: window.renderUpdateStatus()");
iitc_view.updateCaching();
if (user_loc == true) {
if (is_loc_enabled) {
// Register the listener with the Location Manager to receive
// location updates
loc_mngr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
@ -213,7 +218,8 @@ public class IITC_Mobile extends Activity {
@Override
protected void onStop() {
ConnectivityManager conMan = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
ConnectivityManager conMan =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mobile = conMan
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
@ -246,7 +252,7 @@ public class IITC_Mobile extends Activity {
}
Log.d("iitcm", "stopping iitcm");
if (user_loc == true)
if (is_loc_enabled)
loc_mngr.removeUpdates(loc_listener);
super.onStop();
@ -264,14 +270,37 @@ public class IITC_Mobile extends Activity {
// we want a self defined behavior for the back button
@Override
public void onBackPressed() {
// exit fullscreen mode if it is enabled and action bar is disabled or the back stack is empty
// first kill all open iitc dialogs
if (!dialogStack.isEmpty()) {
int last = dialogStack.size() - 1;
String id = dialogStack.get(last);
iitc_view.loadUrl("javascript: " +
"var selector = $(window.DIALOGS['" + id + "']); " +
"selector.dialog('close'); " +
"selector.remove();");
return;
}
// exit fullscreen mode if it is enabled and action bar is disabled
// or the back stack is empty
if (fullscreen_mode && (backStack.isEmpty() || fullscreen_actionbar)) {
this.toggleFullscreen();
} else if (!backStack.isEmpty()) {
// Pop last item from backStack and pretend the relevant menu item was clicked
backStackPop();
} else {
super.onBackPressed();
if (back_button_pressed || !sharedPref.getBoolean("pref_press_twice_to_exit", false))
super.onBackPressed();
else {
back_button_pressed = true;
Toast.makeText(this, "Press twice to exit", Toast.LENGTH_SHORT).show();
// reset back button after 2 seconds
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
back_button_pressed = false;
}
}, 2000);
}
}
}
@ -293,20 +322,31 @@ public class IITC_Mobile extends Activity {
}
int index = backStack.size() - 1;
int itemId = backStack.remove(index);
currentPane = itemId;
handleMenuItemSelected(itemId, false);
// if we popped our last item from stack...illustrate it on home button
if (backStack.isEmpty()) {
// Empty back stack means we should be at home (ie map) screen
setActionBarHomeEnabledWithUp(false);
}
backStack_push = false;
handleMenuItemSelected(itemId);
}
public void backStackUpdate(int itemId) {
// ensure no double adds
if (itemId == currentPane) return;
backStack.add(currentPane);
if (itemId == android.R.id.home) {
backStack.clear();
backStack_push = true;
} else {
if (backStack_push)
backStack.add(currentPane);
else
backStack_push = true;
}
currentPane = itemId;
if (backStack.size() == 1) setActionBarHomeEnabledWithUp(true);
if (backStack.size() >= 1) {
setActionBarHomeEnabledWithUp(true);
} else {
// if we popped our last item from stack...illustrate it on home button
// Empty back stack means we should be at home (ie map) screen
setActionBarHomeEnabledWithUp(false);
}
}
@Override
@ -330,24 +370,21 @@ public class IITC_Mobile extends Activity {
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
final int itemId = item.getItemId();
boolean result = handleMenuItemSelected(itemId, true);
if (!result) return super.onOptionsItemSelected(item);
return true;
boolean result = handleMenuItemSelected(itemId);
return result || super.onOptionsItemSelected(item);
}
public boolean handleMenuItemSelected(int itemId, boolean addToBackStack) {
public boolean handleMenuItemSelected(int itemId) {
switch (itemId) {
case android.R.id.home:
iitc_view.loadUrl("javascript: window.show('map');");
actionBar.setTitle(getString(R.string.app_name));
this.backStack.clear();
setActionBarHomeEnabledWithUp(false);
currentPane = android.R.id.home;
return true;
case R.id.reload_button:
actionBar.setTitle(getString(R.string.app_name));
backStack.clear();
setActionBarHomeEnabledWithUp(false);
// iitc starts on map after reload
currentPane = android.R.id.home;
this.loadUrl(intel_url);
return true;
case R.id.toggle_fullscreen:
@ -359,15 +396,21 @@ public class IITC_Mobile extends Activity {
iitc_view.loadUrl("javascript: window.show('map');");
// the getLayers function calls the setLayers method of IITC_JSInterface
iitc_view.loadUrl("javascript: window.layerChooser.getLayers()");
actionBar.setTitle(getString(R.string.app_name));
backStackUpdate(android.R.id.home);
return true;
// get the users current location and focus it on map
case R.id.locate:
iitc_view.loadUrl("javascript: window.show('map');");
iitc_view.loadUrl("javascript: window.map.locate({setView : true, maxZoom: 15});");
actionBar.setTitle(getString(R.string.app_name));
backStackUpdate(android.R.id.home);
// get location from network by default
if (!is_loc_enabled) {
iitc_view.loadUrl("javascript: " +
"window.map.locate({setView : true, maxZoom: 15});");
// if gps location is displayed we can use a better location without any costs
} else {
if (last_location != null)
iitc_view.loadUrl("javascript: window.map.setView(new L.LatLng(" +
last_location.getLatitude() + "," +
last_location.getLongitude() + "), 15);");
}
return true;
// start settings activity
case R.id.action_settings:
@ -378,33 +421,21 @@ public class IITC_Mobile extends Activity {
return true;
case R.id.menu_info:
iitc_view.loadUrl("javascript: window.show('info');");
actionBar.setTitle(getString(R.string.menu_info));
if (addToBackStack) backStackUpdate(itemId);
return true;
case R.id.menu_full:
iitc_view.loadUrl("javascript: window.show('full');");
actionBar.setTitle(getString(R.string.menu_full));
if (addToBackStack) backStackUpdate(itemId);
return true;
case R.id.menu_compact:
iitc_view.loadUrl("javascript: window.show('compact');");
actionBar.setTitle(getString(R.string.menu_compact));
if (addToBackStack) backStackUpdate(itemId);
return true;
case R.id.menu_public:
iitc_view.loadUrl("javascript: window.show('public');");
actionBar.setTitle(getString(R.string.menu_public));
if (addToBackStack) backStackUpdate(itemId);
return true;
case R.id.menu_faction:
iitc_view.loadUrl("javascript: window.show('faction');");
actionBar.setTitle(getString(R.string.menu_faction));
if (addToBackStack) backStackUpdate(itemId);
return true;
case R.id.menu_debug:
iitc_view.loadUrl("javascript: window.show('debug')");
actionBar.setTitle(getString(R.string.menu_debug));
if (addToBackStack) backStackUpdate(itemId);
return true;
default:
return false;
@ -475,8 +506,8 @@ public class IITC_Mobile extends Activity {
}
/**
* It can occur that in order to authenticate, an external activity has to be launched. (This could for example be a
* confirmation dialog.)
* It can occur that in order to authenticate, an external activity has to be launched.
* (This could for example be a confirmation dialog.)
*/
public void startLoginActivity(Intent launch) {
startActivityForResult(launch, REQUEST_LOGIN); // REQUEST_LOGIN is to recognize the result
@ -500,6 +531,8 @@ public class IITC_Mobile extends Activity {
*/
public void onReceivedLoginRequest(IITC_WebViewClient client, WebView view,
String realm, String account, String args) {
Log.d("iitcm", "logging in...set caching mode to default");
iitc_view.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
mLogin = new IITC_DeviceAccountLogin(this, view, client);
mLogin.startLogin(realm, account, args);
}
@ -522,4 +555,24 @@ public class IITC_Mobile extends Activity {
item = menu.findItem(R.id.menu_debug);
item.setVisible(!desktop);
}
// remove dialog and add it back again
// to ensure it is the last element of the list
// focused dialogs should be closed first
public void setFocusedDialog(String id) {
Log.d("iitcm", "Dialog " + id + " focused");
dialogStack.remove(id);
dialogStack.add(id);
}
// called by the javascript interface
public void dialogOpened(String id, boolean open) {
if (open) {
Log.d("iitcm", "Dialog " + id + " added");
dialogStack.add(id);
} else {
Log.d("iitcm", "Dialog " + id + " closed");
dialogStack.remove(id);
}
}
}

View File

@ -0,0 +1,34 @@
package com.cradle.iitc_mobile;
import android.content.Context;
import android.preference.CheckBoxPreference;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
// multiline checkbox preference
public class IITC_PluginPreference extends CheckBoxPreference {
public IITC_PluginPreference(Context context) {
super(context);
}
protected void onBindView(View view) {
super.onBindView(view);
makeMultiline(view);
}
protected void makeMultiline(View view) {
if (view instanceof ViewGroup) {
ViewGroup grp = (ViewGroup) view;
for (int index = 0; index < grp.getChildCount(); index++) {
makeMultiline(grp.getChildAt(index));
}
} else if (view instanceof TextView) {
TextView t = (TextView) view;
t.setSingleLine(false);
t.setEllipsize(null);
}
}
}

View File

@ -1,16 +1,7 @@
package com.cradle.iitc_mobile;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.MenuItem;
public class IITC_Settings extends Activity {
@ -21,70 +12,12 @@ public class IITC_Settings extends Activity {
IITC_SettingsFragment settings = new IITC_SettingsFragment();
AssetManager am = this.getAssets();
String[] asset_array = null;
try {
asset_array = am.list("plugins");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// set action bar title
this.getActionBar().setTitle("IITC Mobile Settings");
this.getActionBar().setHomeButtonEnabled(true);
ArrayList<String> asset_list = new ArrayList<String>();
ArrayList<String> asset_values = new ArrayList<String>();
for (int i = 0; i < asset_array.length; i++) {
// 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 plugin_name = getPluginName(src);
asset_list.add(plugin_name);
// real value
asset_values.add(asset_array[i]);
}
// load additional plugins from <storage-path>/IITC_Mobile/plugins/
String iitc_path = Environment.getExternalStorageDirectory().getPath()
+ "/IITC_Mobile/";
File directory = new File(iitc_path + "plugins/");
File[] files = directory.listFiles();
if (files != null) {
Scanner s = null;
String src = "";
for (int i = 0; i < files.length; ++i) {
try {
s = new Scanner(files[i]).useDelimiter("\\A");
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.d("iitcm", "failed to parse file " + files[i]);
}
if (s != null)
src = s.hasNext() ? s.next() : "";
String plugin_name = getPluginName(src);
asset_list.add("[User] " + plugin_name);
// real value
asset_values.add(files[i].toString());
}
}
getActionBar().setTitle("IITC Mobile Settings");
getActionBar().setHomeButtonEnabled(true);
// iitc version
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.
@ -92,30 +25,12 @@ public class IITC_Settings extends Activity {
.replace(android.R.id.content, settings).commit();
}
// parse header for @name of plugin
public String getPluginName(String src) {
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];
}
return plugin_name;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// exit settings when home button (iitc icon) is pressed
case android.R.id.home :
this.finish();
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);

View File

@ -3,17 +3,25 @@ package com.cradle.iitc_mobile;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.Environment;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.MultiSelectListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
public class IITC_SettingsFragment extends PreferenceFragment {
String iitc_version;
private String iitc_version;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -24,10 +32,7 @@ public class IITC_SettingsFragment extends PreferenceFragment {
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"));
setUpPluginPreferenceScreen();
// set build version
ListPreference pref_build_version = (ListPreference) findPreference("pref_build_version");
@ -52,16 +57,131 @@ public class IITC_SettingsFragment extends PreferenceFragment {
.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference,
Object newValue) {
preference.setSummary((CharSequence) newValue);
Object newValue) {
preference.setSummary(getString(R.string.pref_select_iitc_sum) +
" " + newValue);
// TODO: update iitc_version when iitc source has
// changed
return true;
}
});
// first init of summary
String pref_iitc_source_sum = (String) pref_iitc_source.getSummary()
+ pref_iitc_source.getText();
String pref_iitc_source_sum = getString(R.string.pref_select_iitc_sum)
+ " " + pref_iitc_source.getText();
pref_iitc_source.setSummary(pref_iitc_source_sum);
}
void setUpPluginPreferenceScreen() {
PreferenceScreen root = (PreferenceScreen) findPreference("pref_plugins");
// alphabetical order
root.setOrderingAsAdded(false);
root.setPersistent(true);
// get all plugins from asset manager
AssetManager am = this.getActivity().getAssets();
String[] asset_array = null;
try {
asset_array = am.list("plugins");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (String anAsset_array : asset_array) {
// find user plugin name for user readable entries
Scanner s = null;
String src = "";
try {
s = new Scanner(am.open("plugins/" + anAsset_array))
.useDelimiter("\\A");
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
if (s != null)
src = s.hasNext() ? s.next() : "";
// now we have all stuff together and can build the pref screen
addPluginPreference(root, src, anAsset_array, false);
}
// load additional plugins from <storage-path>/IITC_Mobile/plugins/
String iitc_path = Environment.getExternalStorageDirectory().getPath()
+ "/IITC_Mobile/";
File directory = new File(iitc_path + "plugins/");
File[] files = directory.listFiles();
if (files != null) {
Scanner s = null;
String src = "";
for (File file : files) {
try {
s = new Scanner(file).useDelimiter("\\A");
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.d("iitcm", "failed to parse file " + file);
}
if (s != null)
src = s.hasNext() ? s.next() : "";
// now we have all stuff together and can build the pref screen
addPluginPreference(root, src, file.toString(), true);
}
}
}
void addPluginPreference(PreferenceScreen root, String src, String plugin_key,
boolean additional) {
// now parse plugin name, description and category
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";
String plugin_desc = "not found";
String plugin_cat = "Misc";
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];
if (attributes[j].equals("@description"))
plugin_desc = attributes[j + 1];
if (attributes[j].equals("@category"))
plugin_cat = attributes[j + 1];
}
// remove IITC plugin prefix from plugin_name
plugin_name = plugin_name.replace("IITC Plugin: ", "");
plugin_name = plugin_name.replace("IITC plugin: ", "");
// add [User] tag to additional plugins
if (additional)
plugin_cat = "[User] " + plugin_cat;
// now we have all stuff together and can build the pref screen
PreferenceScreen pref_screen;
if (root.findPreference(plugin_cat) == null) {
Log.d("iitcm", "create " + plugin_cat + " and add " + plugin_name);
pref_screen = getPreferenceManager().createPreferenceScreen(root.getContext());
pref_screen.setTitle(plugin_cat);
pref_screen.setKey(plugin_cat);
// alphabetical order
pref_screen.setOrderingAsAdded(false);
pref_screen.setPersistent(true);
root.addPreference(pref_screen);
} else {
Log.d("iitcm", "add " + plugin_name + " to " + plugin_cat);
pref_screen = (PreferenceScreen) findPreference(plugin_cat);
}
// now build a new checkable preference for the plugin
IITC_PluginPreference plugin_pref = new IITC_PluginPreference(pref_screen.getContext());
plugin_pref.setKey(plugin_key);
plugin_pref.setTitle(plugin_name);
plugin_pref.setSummary(plugin_desc);
plugin_pref.setDefaultValue(false);
plugin_pref.setPersistent(true);
pref_screen.addPreference(plugin_pref);
}
}

View File

@ -11,10 +11,10 @@ import android.os.Build;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.util.Log;
import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.GeolocationPermissions;
@SuppressLint("SetJavaScriptEnabled")
public class IITC_WebView extends WebView {
@ -26,7 +26,7 @@ public class IITC_WebView extends WebView {
// init web view
private void iitc_init(Context c) {
if ( this.isInEditMode() ) return;
if (this.isInEditMode()) return;
settings = this.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
@ -37,19 +37,18 @@ public class IITC_WebView extends WebView {
+ "/databases/");
settings.setAppCachePath(this.getContext().getCacheDir()
.getAbsolutePath());
// use cache if on mobile network...saves traffic
this.js_interface = new IITC_JSInterface(c);
this.addJavascriptInterface(js_interface, "android");
this.setWebChromeClient(new WebChromeClient() {
/**
* our webchromeclient should share geolocation with the iitc script
*
*
* allow access by default
*/
@Override
public void onGeolocationPermissionsShowPrompt(String origin,
GeolocationPermissions.Callback callback) {
GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
}
@ -95,8 +94,8 @@ public class IITC_WebView extends WebView {
public void loadUrl(String url) {
// if in edit text mode, don't load javascript otherwise the keyboard closes.
HitTestResult testResult = this.getHitTestResult();
if (url.startsWith("javascript:") && testResult != null && testResult.getType() == HitTestResult.EDIT_TEXT_TYPE)
{
if (url.startsWith("javascript:") && testResult != null &&
testResult.getType() == HitTestResult.EDIT_TEXT_TYPE) {
// let window.show(...) interupt input
// window.show(...) is called if one of the action bar buttons
// is clicked
@ -106,7 +105,7 @@ public class IITC_WebView extends WebView {
}
}
// do nothing if script is enabled;
if (this.disableJS == true) {
if (this.disableJS) {
Log.d("iitcm", "javascript injection disabled...return");
return;
}
@ -132,6 +131,7 @@ public class IITC_WebView extends WebView {
}
public void updateCaching() {
// use cache if on mobile network...saves traffic
if (!this.isConnectedToWifi()) {
Log.d("iitcm", "not connected to wifi...load tiles from cache");
settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
@ -152,7 +152,8 @@ public class IITC_WebView extends WebView {
// is ticked as mobile hotspot or not.
// --> IITC_WebView.isConnectedToWifi should return 'false' if connected to mobile hotspot
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
return ((wifi.getState() == NetworkInfo.State.CONNECTED) && !conMan.isActiveNetworkMetered());
return ((wifi.getState() == NetworkInfo.State.CONNECTED) &&
!conMan.isActiveNetworkMetered());
}
return (wifi.getState() == NetworkInfo.State.CONNECTED);
}

View File

@ -12,17 +12,23 @@ import android.preference.PreferenceManager;
import android.util.Log;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import com.cradle.iitc_mobile.async.UrlContentToString;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class IITC_WebViewClient extends WebViewClient {
private static final ByteArrayInputStream style = new ByteArrayInputStream(
@ -34,7 +40,7 @@ public class IITC_WebViewClient extends WebViewClient {
private WebResourceResponse iitcjs;
private String js = null;
private String iitc_path = null;
Context context;
private final Context context;
public IITC_WebViewClient(Context c) {
this.context = c;
@ -76,7 +82,7 @@ public class IITC_WebViewClient extends WebViewClient {
js = this.fileToString(iitc_path
+ "dev/total-conversion-build.user.js", false);
if (js.equals("false")) {
Toast.makeText( context, "File " + iitc_path +
Toast.makeText(context, "File " + iitc_path +
"dev/total-conversion-build.user.js not found. " +
"Disable developer mode or add iitc files to the dev folder.",
Toast.LENGTH_LONG).show();
@ -89,8 +95,19 @@ public class IITC_WebViewClient extends WebViewClient {
// load iitc script from web or asset folder
if (iitc_source.contains("http")) {
URL url = new URL(iitc_source);
js = new Scanner(url.openStream(), "UTF-8").useDelimiter("\\A")
.next();
// if parsing of the online iitc source timed out, use the script from assets
try {
js = new UrlContentToString().execute(url).get(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
js = this.fileToString("total-conversion-build.user.js", true);
} catch (ExecutionException e) {
e.printStackTrace();
js = this.fileToString("total-conversion-build.user.js", true);
} catch (TimeoutException e) {
e.printStackTrace();
js = this.fileToString("total-conversion-build.user.js", true);
}
} else {
js = this.fileToString("total-conversion-build.user.js", true);
}
@ -125,20 +142,21 @@ public class IITC_WebViewClient extends WebViewClient {
iitcjs = new WebResourceResponse("text/javascript", "UTF-8",
new ByteArrayInputStream(js.getBytes()));
};
}
// enable https
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error) {
SslError error) {
handler.proceed();
};
}
/**
* this method is called automatically when the Google login form is opened.
*/
@Override
public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
Log.d("iitcm", "Login requested: " + realm + " " + account + " " + args);
((IITC_Mobile) context).onReceivedLoginRequest(this, view, realm, account, args);
}
@ -149,26 +167,26 @@ public class IITC_WebViewClient extends WebViewClient {
// get the plugin preferences
SharedPreferences sharedPref = PreferenceManager
.getDefaultSharedPreferences(context);
Set<String> plugin_list = sharedPref.getStringSet("pref_plugins", null);
boolean dev_enabled = sharedPref.getBoolean("pref_dev_checkbox", false);
// iterate through all enabled plugins and load them
if (plugin_list != null) {
String[] plugin_array = plugin_list.toArray(new String[0]);
Map<String, ?> all_prefs = sharedPref.getAll();
for (int i = 0; i < plugin_list.size(); i++) {
// iterate through all plugins
for (Map.Entry<String, ?> entry : all_prefs.entrySet()) {
String plugin = entry.getKey();
if (plugin.endsWith("user.js") && entry.getValue().toString().equals("true")) {
// load default iitc plugins
if (!plugin_array[i].startsWith(iitc_path)) {
Log.d("iitcm", "adding plugin " + plugin_array[i]);
if (!plugin.startsWith(iitc_path)) {
Log.d("iitcm", "adding plugin " + plugin);
if (dev_enabled)
js += this.removePluginWrapper(iitc_path + "dev/plugins/"
+ plugin_array[i], false);
+ plugin, false);
else
js += this.removePluginWrapper("plugins/" + plugin_array[i], true);
// load additional iitc plugins
js += this.removePluginWrapper("plugins/" + plugin, true);
// load additional iitc plugins
} else {
Log.d("iitcm", "adding additional plugin " + plugin_array[i]);
js += this.removePluginWrapper(plugin_array[i], false);
Log.d("iitcm", "adding additional plugin " + plugin);
js += this.removePluginWrapper(plugin, false);
}
}
}
@ -244,30 +262,28 @@ public class IITC_WebViewClient extends WebViewClient {
public String removePluginWrapper(String file, boolean asset) {
if (!file.endsWith("user.js")) return "";
String js = fileToString(file, asset);
if (js == "false") return "";
if (js.equals("false")) return "";
js = js.replaceAll("\r\n", "\n"); //convert CR-LF pairs to LF - windows format text files
js = js.replaceAll("\r", "\n"); //convert remaining CR to LF - Mac format files(?)
String wrapper_start = "function wrapper() {";
String wrapper_end = "} // wrapper end";
String injection_code = "// inject code into site context\n" +
"var script = document.createElement('script');\n" +
"script.appendChild(document.createTextNode('('+ wrapper +')();'));\n" +
"(document.body || document.head || document.documentElement).appendChild(script);";
"var script = document.createElement('script');\n" +
"script.appendChild(document.createTextNode('('+ wrapper +')();'));\n" +
"(document.body || document.head || document.documentElement).appendChild(script);";
if (js.contains(wrapper_start) && js.contains(wrapper_end) && js.contains(injection_code)) {
js = js.replace("function wrapper() {", "");
js = js.replace(wrapper_start, "");
// remove the wrapper function
js = js.replace("} // wrapper end", "");
js = js.replace(wrapper_end, "");
// and the code injection
js = js.replace("// inject code into site context\n" +
"var script = document.createElement('script');\n" +
"script.appendChild(document.createTextNode('('+ wrapper +')();'));\n" +
"(document.body || document.head || document.documentElement).appendChild(script);", "");
js = js.replace(injection_code, "");
} else {
Log.d("iitcm", "Removal of wrapper/injection code failed for " + file);
return "";
}
return js;
}
// 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
@ -275,7 +291,7 @@ public class IITC_WebViewClient extends WebViewClient {
// via http://stackoverflow.com/a/8274881/1684530
@Override
public WebResourceResponse shouldInterceptRequest(final WebView view,
String url) {
String url) {
if (url.contains("/css/common.css")) {
return new WebResourceResponse("text/css", "UTF-8", style);
} else if (url.contains("gen_dashboard.js")) {
@ -308,6 +324,10 @@ public class IITC_WebViewClient extends WebViewClient {
+ url);
((IITC_Mobile) context).loadUrl(url);
}
if (url.contains("logout")) {
Log.d("iitcm", "logging out...set caching mode to default");
view.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
}
return false;
} else {
Log.d("iitcm",

View File

@ -0,0 +1,31 @@
package com.cradle.iitc_mobile.async;
import android.os.AsyncTask;
import com.cradle.iitc_mobile.IITC_Mobile;
import java.io.IOException;
import java.net.URL;
import java.util.Scanner;
/*
* this class parses the content of a web page.
* since network operations shouldn't be done on main UI thread
* (NetworkOnMainThread exception is thrown) we use an async task for this.
*/
public class UrlContentToString extends AsyncTask<URL, Integer, String> {
@Override
protected String doInBackground(URL... urls) {
String js = "";
URL url = urls[0];
try {
js = new Scanner(url.openStream(), "UTF-8").useDelimiter("\\A")
.next();
} catch (IOException e) {
e.printStackTrace();
}
return js;
}
}

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-ap-list@xelio
// @name IITC plugin: AP List
// @category Info
// @version 0.5.3.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -947,16 +945,4 @@ var setup = function() {
}
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-basemap-blank@jonatkins
// @name IITC plugin: Blank map
// @category Map Tiles
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -36,16 +34,4 @@ var setup = window.plugin.mapTileBlank.addLayer;
// 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);
@@PLUGINEND@@

View File

@ -24,6 +24,7 @@
// ==UserScript==
// @id iitc-plugin-cloudmade-maps
// @name IITC plugin: CloudMade.com maps
// @category Map Tiles
// @version 0.0.1
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @description TEMPLATE PLUGIN - add back the CloudMade.com map layers. YOU WILL NEED TO EDIT THIS PLUGIN BEFORE IT WILL RUN
@ -33,10 +34,7 @@
// @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() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -87,16 +85,4 @@ var setup = window.plugin.mapTileCloudMade.setup;
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-basemap-opencyclepam@jonatkins
// @name IITC plugin: OpenCycleMap.org map tiles
// @category Map Tiles
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -43,16 +41,4 @@ var setup = window.plugin.mapTileOpenCycleMap.addLayer;
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-basemap-openstreetpam@jonatkins
// @name IITC plugin: OpenStreetMap.org map tiles
// @category Map Tiles
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -40,16 +38,4 @@ var setup = window.plugin.mapTileOpenStreetMap.addLayer;
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-basemap-yandex@jonatkins
// @name IITC plugin: Yandex maps
// @category Map Tiles
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -61,16 +59,4 @@ var setup = window.plugin.mapTileYandex.setup;
// 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);
@@PLUGINEND@@

View File

@ -0,0 +1,324 @@
#bookmarksBox *{
display:block;
padding:0;
margin:0;
width:auto;
height:auto;
font-family:Verdana, Geneva, sans-serif;
font-size:13px;
line-height:22px;
text-indent:0;
text-decoration:none;
}
#bookmarksBox{
margin-top:-200%;
position:absolute !important;
z-index:4001;
top:100px;
left:100px;
}
#bookmarksBox .addForm, #bookmarksBox #bookmarksTypeBar, #bookmarksBox h5{
height:28px;
overflow:hidden;
color:#fff;
font-size:14px;
}
#bookmarksBox #topBar, #bookmarksBox #topBar *{
height:15px !important;
}
#bookmarksBox #topBar *{
float:left !important;
}
#bookmarksBox .handle{
text-indent:-20px;
width:209px;
text-align:center;
color:#fff;
line-height:8px;
cursor:move;
}
#bookmarksBox #topBar .btn{
display:block;
width:19px;
cursor:pointer;
color:#20a8b1;
}
#bookmarksBox #topBar #bookmarksMin{
font-weight:bold;
text-align:center;
line-height:14px;
font-size:18px;
}
#bookmarksBox #topBar #bookmarksMin:hover{
color:gold;
}
#bookmarksBox #bookmarksTypeBar{
clear:both;
}
#bookmarksBox h5{
padding:4px 0;
width:114px;
text-align:center;
color:#788;
}
#bookmarksBox h5.current{
cursor:default;
background:0;
color:#fff !important;
}
#bookmarksBox h5:hover{
color:gold;
background:rgba(0,0,0,0);
}
#bookmarksBox #topBar .btn, #bookmarksBox .addForm, #bookmarksBox .handle, #bookmarksBox #bookmarksTypeBar, #bookmarksBox .bookmarkList li.bookmarksEmpty, #bookmarksBox .bookmarkList li.bkmrk a, #bookmarksBox .bookmarkList li.bkmrk:hover{
background-color:rgba(8,48,78,.85);
}
#bookmarksBox h5, #bookmarksBox .bookmarkList li.bkmrk:hover .bookmarksLink, #bookmarksBox .addForm *{
background:rgba(0,0,0,.3);
}
#bookmarksBox .addForm *{
display:block;
float:left;
padding:4px 8px 3px;
}
#bookmarksBox .addForm a{
cursor:pointer;
color:#20a8b1;
font-size:12px;
width:65px;
text-align:center;
line-height:20px;
padding:4px 0 3px;
}
#bookmarksBox .addForm a:hover{
background:gold;
color:#000;
text-decoration:none;
}
#bookmarksBox .addForm input{
font-size:11px !important;
color:#ffce00;
width:81px;
line-height:11px;
font-size:12px;
-webkit-box-sizing:content-box;
-moz-box-sizing:content-box;
box-sizing:content-box;
}
#bookmarksBox #bkmrk_portals .addForm input{
width:147px;
}
#bookmarksBox .addForm input:hover, #bookmarksBox .addForm input:focus{
outline:0;
background:rgba(0,0,0,.6);
}
#bookmarksBox .bookmarkList>ul{
width:231px;
clear:both;
list-style-type:none;
color:#fff;
overflow:hidden;
max-height:550px;
}
#bookmarksBox .sortable-placeholder{
background:rgba(8,48,78,.55);
box-shadow:inset 1px 0 0 #20a8b1;
}
#bookmarksBox .ui-sortable-helper{
border-top-width:1px;
}
#bookmarksBox .bookmarkList{
display:none;
}
#bookmarksBox .bookmarkList.current{
display:block;
}
#bookmarksBox h5, #bookmarksBox .addForm *, #bookmarksBox ul li.bkmrk, #bookmarksBox ul li.bkmrk a{
height:22px;
}
#bookmarksBox h5, #bookmarksBox ul li.bkmrk a{
overflow:hidden;
cursor:pointer;
float:left;
}
#bookmarksBox ul .bookmarksEmpty{
text-indent:27px;
color:#eee;
}
#bookmarksBox ul .bookmarksRemoveFrom{
width:19px;
text-align:center;
color:#fff;
}
#bookmarksBox ul .bookmarksLink{
width:171px;
padding:0 10px 0 8px;
color:gold;
}
#bookmarksBox ul .bookmarksLink.selected{
color:#03fe03;
}
#bookmarksBox ul .othersBookmarks .bookmarksLink{
width:190px;
}
#bookmarksBox ul .bookmarksLink:hover{
color:#03fe03;
}
#bookmarksBox ul .bookmarksRemoveFrom:hover{
color:#fff;
background:#e22;
}
#bookmarksBox, #bookmarksBox *{
border-color:#20a8b1;
border-style:solid;
border-width:0;
}
#bookmarksBox #topBar, #bookmarksBox ul .bookmarkFolder{
border-top-width:1px;
}
#bookmarksBox #topBar, #bookmarksBox #bookmarksTypeBar, #bookmarksBox .addForm, #bookmarksBox ul .bookmarkFolder .folderLabel, #bookmarksBox ul li.bkmrk{
border-bottom-width:1px;
}
#bookmarksBox ul .bookmarkFolder, #bookmarksBox ul .bookmarksRemoveFrom{
border-right-width:1px;
border-left-width:1px;
}
#bookmarksBox #topBar *, #bookmarksBox #bookmarksTypeBar *, #bookmarksBox .addForm *{
border-left-width:1px;
}
#bookmarksBox #topBar, #bookmarksBox #bookmarksTypeBar, #bookmarksBox .addForm{
border-right-width:1px;
}
#bookmarksBox ul .othersBookmarks .bookmarksRemoveFrom, #bookmarksBox ul .bookmarkFolder .folderLabel .bookmarksRemoveFrom{
border-left-width:0;
}
#bookmarksShow{
display:block;
position:absolute;
top:0;
left:250px;
width:47px;
margin-top:-36px;
height:64px;
cursor:pointer;
z-index:2999;
background-position:center bottom;
background-repeat:no-repeat;
transition:margin-top 100ms ease-in-out;
background-image:url(@@INCLUDEIMAGE:plugins/bookmarks-by-zaso-logo.png@@);
}
#bookmarksShow:hover{
margin-top:0 !important;
}
#sidebar #portaldetails h3.title{
width:auto;
}
#bookmarkStar{
display:inline-block;
float:left;
margin:3px 1px 0 4px;
width:16px;
height:15px;
overflow:hidden;
background-image:url(@@INCLUDEIMAGE:plugins/bookmarks-by-zaso-star.png@@);
background-position:left center;
background-repeat:no-repeat;
}
#bookmarkStar:hover, #bookmarkStar.favorite{
background-position:right center;
}
#bookmarksBox .handleScroll{
cursor:s-resize;
width:3px;
right:3px;
background:gold;
opacity:.7;
}
#bookmarksBox .bookmarkList .bookmarkFolder{
overflow:hidden;
margin-top:-1px;
height:auto;
background:rgba(8,58,78,.7);
}
#bookmarksBox .bookmarkList ul li.sortable-placeholder{
box-shadow:inset -1px 0 0 #20a8b1, inset 1px 0 0 #20a8b1, 0 -1px 0 #20a8b1;
background:rgba(8,58,78,.9);
}
#bookmarksBox .bookmarkList .bkmrk.ui-sortable-helper{
border-right-width:1px;
border-left-width:1px;
}
#bookmarksBox .bookmarkList ul li ul li.sortable-placeholder{
height:23px;
box-shadow:inset 0 -1px 0 #20a8b1, inset 1px 0 0 #20a8b1;
}
#bookmarksBox .bookmarkList ul li.bookmarkFolder.ui-sortable-helper, #bookmarksBox .bookmarkList ul li.othersBookmarks ul, #bookmarksBox .bookmarkList ul li.othersBookmarks ul li.sortable-placeholder{
box-shadow:inset 0 -1px 0 #20a8b1;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor span, #bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span, #bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span, #bookmarksBox .bookmarkList .triangle{
width:0;
height:0;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel{
overflow:visible;
height:25px;
cursor:pointer;
background:#069;
text-indent:0;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>*{
height:25px;
float:left;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor{
line-height:25px;
color:#fff;
width:209px;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor span{
float:left;
border-width:5px 0 5px 7px;
border-color:transparent transparent transparent white;
margin:7px 7px 0 6px;
}
#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel .bookmarksAnchor span{
margin:9px 5px 0 5px;
border-width:7px 5px 0 5px;
border-color:white transparent transparent transparent;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span, #bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span{
display:none;
border-width:0 12px 10px 0;
border-color:transparent #20a8b1 transparent transparent;
margin:-20px 0 0;
position:relative;
top:21px;
left:219px;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span{
top:18px;
left:0;
border-width:0 10px 9px 0;
border-color:transparent #069 transparent transparent;
}
#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel>span, #bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel>span>span{
display:block;
}
#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel:hover>span>span{
border-color:transparent #036 transparent transparent;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel:hover .bookmarksAnchor{
background:#036;
}
#bookmarksBox .bookmarkList .bookmarkFolder ul{
display:none;
margin-left:19px;
}
#bookmarksBox .bookmarkList .bookmarkFolder.active ul{
display:block;
min-height:22px;
}
#bookmarksBox .bookmarkFolder.othersBookmarks ul{
margin-left:0;
}
)

View File

@ -0,0 +1,136 @@
#sidebar #bookmarksBox{
position:static !important;
width:auto !important;
margin:0 !important;
width:100%;
}
#sidebar #bookmarksBox .bookmarkList > ul > li, #sidebar #bookmarksBox .bookmarkList > ul > li > ul, #sidebar #bookmarksBox .bookmarkList > ul > li > ul > li{
width:100% !important;
}
#sidebar #bookmarksBox *{
box-shadow:none !important;
border-width:0 !important
}
#sidebar #bookmarksBox #topBar{
display:none !important;
}
#sidebar #bookmarksBox #bookmarksTypeBar h5{
cursor:pointer;
text-align:center;
float:left;
width:50%;
padding:7px 0;
}
#sidebar #bookmarksBox #bookmarksTypeBar h5.current{
cursor:default;
color:#fff;
}
#sidebar #bookmarksBox #bookmarksTypeBar, #sidebar #bookmarksBox .bookmarkList .addForm{
border-bottom:1px solid #20a8b1 !important;
}
#sidebar #bookmarksBox .bookmarkList ul li ul li.bkmrk{
height:36px !important;
clear:both;
}
#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder .folderLabel{
height:36px;
}
#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder .folderLabel a, #sidebar #bookmarksBox .bookmarkList ul li ul li.bkmrk a{
background:none;
padding:7px 0;
height:auto;
box-shadow:inset 0 1px 0 #20a8b1 !important;
}
#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder a.bookmarksRemoveFrom, #sidebar #bookmarksBox .bookmarkList li.bkmrk a.bookmarksRemoveFrom{
box-shadow:inset 0 1px 0 #20a8b1, inset -1px 0 0 #20a8b1 !important;
width:15%;
}
#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder a.bookmarksAnchor, #sidebar #bookmarksBox .bookmarkList li.bkmrk a.bookmarksLink{
text-indent:10px;
width:85%;
height:21px /*22*/;
overflow:hidden;
}
#sidebar #bookmarksBox .bookmarkList ul li.bookmarkFolder ul{
margin-left:0 !important;
}
#sidebar #bookmarksBox .bookmarkList ul, #bookmarksBox .bookmarkList ul li, #sidebar #bookmarksBox .bookmarkList ul li ul, #sidebar #bookmarksBox .bookmarkList ul li ul li{
display:block !important;
}
#sidebar #bookmarksBox .bookmarkList{
display:none !important;
}
#sidebar #bookmarksBox .bookmarkList > ul{
border-bottom:1px solid #20a8b1 !important;
border-right:1px solid #20a8b1 !important;
}
#sidebar #bookmarksBox .bookmarkList.current{
display:block !important;
}
#sidebar #bookmarksBox .bookmarkList .bookmarkFolder.othersBookmarks ul{
border-top:5px solid #20a8b1 !important;
}
#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder, #sidebar #bookmarksBox .bookmarkList li.bkmrk{
box-shadow:inset 0 1px 0 #20a8b1, 1px 0 0 #20a8b1, -1px 1px 0 #20a8b1 !important;
}
#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder .bkmrk.sortable-placeholder{
height:36px !important;
}
#sidebar #bookmarksBox .bookmarkList .sortable-placeholder{
box-shadow:inset 0 1px 0 #20a8b1 !important;
}
#sidebar #bookmarksBox .ui-sortable .ui-sortable-helper{
border-top:0;
width:85% !important;
}
#sidebar #bookmarksBox .bookmarkList > ul{
max-height:none;
width:85% !important;
}
#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder .folderLabel{
box-shadow:0 1px 0 #20a8b1 !important;
}
#sidebar #bookmarksBox .bookmarkList ul li.bookmarkFolder ul{
width:85% !important;
margin-left:15% !important;
}
#sidebar #bookmarksBox .bookmarkList ul li.bookmarkFolder.othersBookmarks ul{
width:100% !important;
margin-left:0% !important;
}
#sidebar #bookmarksShowMobile{
text-decoration:none;
display:block !important;
padding:11px 0 9px;
text-align:center;
}
#sidebar #portaldetails{
margin-top:25px;
}
#sidebar #bookmarksBox #bookmarksTypeBar{
height:auto;
}
#sidebar #bookmarksBox .addForm, #sidebar #bookmarksBox .addForm *{
height:35px;
padding:0;
}
#sidebar #bookmarksBox .addForm a{
line-height:37px;
}
#sidebar #bookmarksBox .addForm a{
width:25% !important;
}
#sidebar #bookmarksBox .addForm input{
width:50% !important;
text-indent:10px;
}
#sidebar #bookmarksBox #bkmrk_portals .addForm input{
width:75% !important;
}
#sidebar #bookmarksBox #bookmarksTypeBar h5, #sidebar #bookmarksBox .bookmarkList .addForm a{
box-shadow:-1px 0 0 #20a8b1 !important;
}
#sidebar #bookmarksBox .bookmarkList li.bookmarkFolder ul{
display:block !important;
min-height:37px !important;
}

View File

@ -1,368 +0,0 @@
#bookmarksBox * {
display: block;
width: auto;
height: auto;
font-family: Verdana,Geneva,sans-serif;
font-size: 13px;
line-height: 22px;
text-indent: 0;
text-decoration: none;
margin: 0;
padding: 0;
}
#bookmarksBox {
margin-top: -100%;
position: absolute!important;
z-index: 4001;
top: 100px;
left: 100px;
}
#bookmarksBox .addForm,#bookmarksBox #bookmarksTypeBar,#bookmarksBox h5 {
height: 28px;
overflow: hidden;
color: #fff;
font-size: 14px;
}
#bookmarksBox #topBar,#bookmarksBox #topBar * {
height: 15px!important;
}
#bookmarksBox #topBar * {
float: left!important;
}
#bookmarksBox .handle {
text-indent: -20px;
width: 209px;
text-align: center;
color: #fff;
line-height: 8px;
cursor: move;
}
#bookmarksBox #topBar .btn {
display: block;
width: 19px;
cursor: pointer;
color: #20a8b1;
}
#bookmarksBox #topBar #bookmarksMin {
font-weight: 700;
text-align: center;
line-height: 14px;
font-size: 18px;
}
#bookmarksBox #topBar #bookmarksMin: hover {
color: #FFD700;
}
#bookmarksBox #bookmarksTypeBar {
clear: both;
}
#bookmarksBox h5 {
width: 114px;
text-align: center;
color: #788;
padding: 4px 0;
}
#bookmarksBox h5.current {
cursor: default;
background: 0;
color: #fff!important;
}
#bookmarksBox h5: hover {
color: #FFD700;
background: rgba(0,0,0,0);
}
#bookmarksBox #topBar .btn,#bookmarksBox .addForm,#bookmarksBox .handle,#bookmarksBox #bookmarksTypeBar,#bookmarksBox .bookmarkList li.bookmarksEmpty,#bookmarksBox .bookmarkList li.bkmrk a,#bookmarksBox .bookmarkList li.bkmrk: hover {
background-color: rgba(8,48,78,.85);
}
#bookmarksBox h5,#bookmarksBox .bookmarkList li.bkmrk: hover .bookmarksLink,#bookmarksBox .addForm * {
background: rgba(0,0,0,.3);
}
#bookmarksBox .addForm * {
display: block;
float: left;
padding: 4px 8px 3px;
}
#bookmarksBox .addForm a {
cursor: pointer;
color: #20a8b1;
font-size: 12px;
width: 65px;
text-align: center;
line-height: 20px;
padding: 4px 0 3px;
}
#bookmarksBox .addForm a: hover {
background: #FFD700;
color: #000;
text-decoration: none;
}
#bookmarksBox .addForm input {
font-size: 11px!important;
color: #ffce00;
width: 81px;
line-height: 11px;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
#bookmarksBox #bkmrk_portals .addForm input {
width: 147px;
}
#bookmarksBox .addForm input: hover,#bookmarksBox .addForm input: focus {
outline: 0;
background: rgba(0,0,0,.6);
}
#bookmarksBox .bookmarkList>ul {
width: 231px;
clear: both;
list-style-type: none;
color: #fff;
overflow: hidden;
max-height: 550px;
}
#bookmarksBox .sortable-placeholder {
background: rgba(8,48,78,.55);
box-shadow: inset 1px 0 0 #20a8b1;
}
#bookmarksBox .bookmarkList {
display: none;
}
#bookmarksBox h5,#bookmarksBox .addForm *,#bookmarksBox ul li.bkmrk,#bookmarksBox ul li.bkmrk a {
height: 22px;
}
#bookmarksBox h5,#bookmarksBox ul li.bkmrk a {
overflow: hidden;
cursor: pointer;
float: left;
}
#bookmarksBox ul .bookmarksEmpty {
text-indent: 27px;
color: #eee;
}
#bookmarksBox ul .bookmarksRemoveFrom {
width: 19px;
text-align: center;
color: #fff;
}
#bookmarksBox ul .bookmarksLink {
width: 171px;
color: #FFD700;
padding: 0 10px 0 8px;
}
#bookmarksBox ul .othersBookmarks .bookmarksLink {
width: 190px;
}
#bookmarksBox ul .bookmarksRemoveFrom: hover {
color: #fff;
background: #e22;
}
#bookmarksBox,#bookmarksBox * {
border-color: #20a8b1;
border-style: solid;
border-width: 0;
}
#bookmarksBox #topBar,#bookmarksBox #bookmarksTypeBar,#bookmarksBox .addForm,#bookmarksBox ul .bookmarkFolder .folderLabel,#bookmarksBox ul li.bkmrk {
border-bottom-width: 1px;
}
#bookmarksBox #topBar *,#bookmarksBox #bookmarksTypeBar *,#bookmarksBox .addForm * {
border-left-width: 1px;
}
#bookmarksBox #topBar,#bookmarksBox #bookmarksTypeBar,#bookmarksBox .addForm {
border-right-width: 1px;
}
#bookmarksBox ul .othersBookmarks .bookmarksRemoveFrom,#bookmarksBox ul .bookmarkFolder .folderLabel .bookmarksRemoveFrom {
border-left-width: 0;
}
#bookmarksShow {
display: block;
position: absolute;
top: 0;
left: 250px;
width: 47px;
margin-top: -100%;
height: 64px;
cursor: pointer;
z-index: 4005;
background-position: center bottom;
background-repeat: no-repeat;
transition: margin-top 100ms ease-in-out;
background-image: url(@@INCLUDEIMAGE:plugins/bookmarks-by-zaso-logo.png@@);
}
#bookmarksShow: hover {
margin-top: 0!important;
}
#bookmarkStar {
display: inline-block;
position: relative;
top: 1px;
margin-right: 3px;
width: 16px;
height: 15px;
overflow: hidden;
background-image: url(@@INCLUDEIMAGE:plugins/bookmarks-by-zaso-star.png@@);
background-position: left center;
background-repeat: no-repeat;
}
#bookmarkStar: hover,#bookmarkStar.favorite {
background-position: right center;
}
#bookmarksBox .handleScroll {
cursor: s-resize;
width: 3px;
right: 3px;
background: #FFD700;
opacity: .7;
}
#bookmarksBox .bookmarkList .bookmarkFolder {
overflow: hidden;
margin-top: -1px;
height: auto;
background: rgba(8,58,78,.7);
}
#bookmarksBox .bookmarkList ul li.sortable-placeholder {
box-shadow: inset -1px 0 0 #20a8b1,inset 1px 0 0 #20a8b1,0 -1px 0 #20a8b1;
background: rgba(8,58,78,.9);
}
#bookmarksBox .bookmarkList ul li ul li.sortable-placeholder {
height: 23px;
box-shadow: inset 0 -1px 0 #20a8b1,inset 1px 0 0 #20a8b1;
}
#bookmarksBox .bookmarkList ul li.bookmarkFolder.ui-sortable-helper,#bookmarksBox .bookmarkList ul li.othersBookmarks ul,#bookmarksBox .bookmarkList ul li.othersBookmarks ul li.sortable-placeholder {
box-shadow: inset 0 -1px 0 #20a8b1;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor span,#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span,#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span,#bookmarksBox .bookmarkList .triangle {
width: 0;
height: 0;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel {
overflow: visible;
height: 25px;
cursor: pointer;
background: #069;
text-indent: 0;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>* {
height: 25px;
float: left;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor {
line-height: 25px;
color: #fff;
width: 209px;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel .bookmarksAnchor span {
float: left;
border-color: transparent transparent transparent #FFF;
border-width: 5px 0 5px 7px;
margin: 7px 7px 0 6px;
}
#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel .bookmarksAnchor span {
border-color: #FFF transparent transparent;
border-width: 7px 5px 0;
margin: 9px 5px 0;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span,#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span {
display: none;
position: relative;
top: 21px;
left: 219px;
border-color: transparent #20a8b1 transparent transparent;
border-width: 0 12px 10px 0;
margin: -20px 0 0;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel>span>span {
top: 18px;
left: 0;
border-color: transparent #069 transparent transparent;
border-width: 0 10px 9px 0;
}
#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel: hover>span>span {
border-color: transparent #036 transparent transparent;
}
#bookmarksBox .bookmarkList .bookmarkFolder .folderLabel: hover .bookmarksAnchor {
background: #036;
}
#bookmarksBox .bookmarkList .bookmarkFolder ul {
display: none;
margin-left: 19px;
}
#bookmarksBox .bookmarkList .bookmarkFolder.active ul {
display: block;
min-height: 22px;
}
#bookmarksBox .bookmarkFolder.othersBookmarks ul {
margin-left: 0;
}
#bookmarksBox .ui-sortable-helper,#bookmarksBox #topBar,#bookmarksBox ul .bookmarkFolder {
border-top-width: 1px;
}
#bookmarksBox .bookmarkList.current,#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel>span,#bookmarksBox .bookmarkList .bookmarkFolder.active .folderLabel>span>span {
display: block;
}
#bookmarksBox ul .bookmarksLink.selected,#bookmarksBox ul .bookmarksLink: hover {
color: #03fe03;
}
#bookmarksBox ul .bookmarkFolder,#bookmarksBox ul .bookmarksRemoveFrom,#bookmarksBox .bookmarkList .bkmrk.ui-sortable-helper {
border-right-width: 1px;
border-left-width: 1px;
}

View File

@ -1,388 +1,534 @@
// ==UserScript==
// @id iitc-plugin-bookmarks@zaso
// @id iitc-plugin-bookmarks@ZasoGD
// @name IITC plugin: Bookmarks for maps and portals
// @version 0.1.3.@@DATETIMEVERSION@@
// @category Controls
// @version 0.1.55.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Save your favorite Maps and Portals.
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Save your favorite Maps and Portals and move the intelmap view in a second. The ingress world just a click.
// @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() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.bookmarks = function() {};
window.plugin.bookmarks.bkmrk_portals = {};
window.plugin.bookmarks.bkmrk_maps = {};
// use own namespace for plugin
window.plugin.bookmarks = function() {};
window.plugin.bookmarks.disabledMessage;
window.plugin.bookmarks.contentStarHTML;
window.plugin.bookmarks.KEY_OTHER_BKMRK = 'idOthers';
window.plugin.bookmarks.LOCAL_STORAGE_status_box = 'plugin-bookmarks-status-box';
window.plugin.bookmarks.LOCAL_STORAGE_bkmrk_portals = 'plugin-bookmarks-portals-data';
window.plugin.bookmarks.LOCAL_STORAGE_bkmrk_maps = 'plugin-bookmarks-maps-data';
window.plugin.bookmarks.KEY_OTHER_BKMRK = 'idOthers';
window.plugin.bookmarks.LOCAL_STORAGE_status_box = 'plugin-bookmarks-status-box';
window.plugin.bookmarks.LOCAL_STORAGE_bkmrk_portals = 'plugin-bookmarks-portals-data';
window.plugin.bookmarks.LOCAL_STORAGE_bkmrk_maps = 'plugin-bookmarks-maps-data';
window.plugin.bookmarks.bkmrk_portals = {};
window.plugin.bookmarks.bkmrk_maps = {};
/*********************************************************************************************************************/
window.plugin.bookmarks.disabledMessage;
window.plugin.bookmarks.contentStarHTML;
window.plugin.bookmarks.bkmrkBox;
window.plugin.bookmarks.bkmrkRibbon;
window.plugin.bookmarks.loadList;
window.plugin.bookmarks.setupJS;
//---------------------------------------------------------------------------------------
// Append a 'star' flag in sidebar.
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.addToSidebar = function(){
if(typeof(Storage) === "undefined"){ $('#portaldetails > .imgpreview').after(plugin.bookmarks.disabledMessage); return; }
$('#portaldetails > h3.title').before(plugin.bookmarks.contentStarHTML);
plugin.bookmarks.updateStarPortal();
}
//---------------------------------------------------------------------------------------
// Update the status of the star (when a portal is selected from the map/bookmarks-list)
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.updateStarPortal = function(){
window.plugin.bookmarks.loadBookmarks('bkmrk_portals');
var guid = window.selectedPortal;
$('#bookmarkStar').removeClass('favorite');
$('.bkmrk a.bookmarksLink.selected').removeClass('selected');
//If current portal is into bookmarks: select bookmark portal from portals list and select the star
if(localStorage[window.plugin.bookmarks.LOCAL_STORAGE_bkmrk_portals].search(guid) != -1){
$('#bookmarkStar').addClass('favorite');
var list = plugin.bookmarks['bkmrk_portals'];
for(var idFolders in list){
for(var idBkmrk in list[idFolders]['bkmrk']){
var portalGuid = list[idFolders]['bkmrk'][idBkmrk]['guid'];
if(guid == portalGuid){
$('.bkmrk#'+idBkmrk+' a.bookmarksLink').addClass('selected');
}
}
}
}
}
//---------------------------------------------------------------------------------------
// Switch the status of the star
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.switchStarPortal = function(){
var guid = window.selectedPortal;
//If portal is saved in bookmarks: Remove this bookmark
if($('#bookmarkStar').hasClass('favorite')){
var list = plugin.bookmarks['bkmrk_portals'];
for(var idFolders in list){
for(var idBkmrk in list[idFolders]['bkmrk']){
var portalGuid = list[idFolders]['bkmrk'][idBkmrk]['guid'];
if(guid == portalGuid){
delete list[idFolders]['bkmrk'][idBkmrk];
$('.bkmrk#'+idBkmrk+'').remove();
}
}
}
}
//If portal isn't saved in bookmarks: Add this bookmark
else{
// Get the bookmark data (name, coordinates, portal id) from the portal link
var linka = $('#portaldetails .linkdetails aside a:contains("Portal link")').attr('href');
var namePortal = $('#portaldetails h3').text();
var ID = window.plugin.bookmarks.generateID();
var spac = linka.split('pll=');
var latlng = spac[1] ;
// Add bookmark in the localStorage
plugin.bookmarks['bkmrk_portals'][plugin.bookmarks.KEY_OTHER_BKMRK]['bkmrk'][ID] = {"guid":guid,"latlng":latlng,"label":namePortal};
//Append the new bookmark to the map list
$('#bkmrk_portals li.othersBookmarks ul').append('<li class="bkmrk" id="'+ID+'"><a class="bookmarksRemoveFrom" title="Remove from bookmarks">X</a><a class="bookmarksLink selected" onclick="window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false;">'+namePortal+'</a></li>');
}
window.plugin.bookmarks.storeBookmarks('bkmrk_portals');
window.plugin.bookmarks.updateStarPortal();
}
//---------------------------------------------------------------------------------------
// Save a bookmark map
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.addBookmarkMap = function(elem){
// Get the coordinates and zoom level from the permalink
var mapLink = $(elem).attr('href');
var pars = new RegExp('[\\?&amp;]ll=([^&amp;#]*)[&amp;]z=([^&amp;#]*)').exec(mapLink);
var res = pars[1].split(',');
res[2] = pars[2];
var latlng = res[0]+','+res[1];
var zoom = res[2];
var ID = window.plugin.bookmarks.generateID();
//Get the label | Convert some characters | Set the input (empty)
var nameMap = $(elem).siblings('input').val();
nameMap = nameMap.replace(/\//g, '&#47;').replace(/\\/g, '&#92;').replace(/"/g, '&#34;').replace(/"/g, '&#39;');
$(elem).siblings('input').val('');
// Add bookmark in the localStorage
plugin.bookmarks['bkmrk_maps'][plugin.bookmarks.KEY_OTHER_BKMRK]['bkmrk'][ID] = {"label":nameMap,"latlng":latlng,"z":parseInt(zoom)};
plugin.bookmarks.storeBookmarks('bkmrk_maps');
//Append the new bookmark to the map list
if(nameMap==''){ nameMap = latlng+' ['+zoom+']'; }
$('#bkmrk_maps li.othersBookmarks ul').append('<li class="bkmrk" id="'+ID+'"><a class="bookmarksRemoveFrom" title="Remove from bookmarks">X</a><a class="bookmarksLink" onclick="map.setView(['+latlng+'], '+zoom+');return false;">'+nameMap+'</a></li>');
}
/*********************************************************************************************************************/
//---------------------------------------------------------------------------------------
// Generate an ID for the bookmark (date time + random number)
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.generateID = function(){
var d = new Date();
var ID = d.getTime()+(Math.floor(Math.random()*99)+1);
var ID = 'id'+ID.toString();
return ID;
}
//---------------------------------------------------------------------------------------
// Switch the status folder to open/close (in the localStorage)
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.openFolder = function(elem){
var typeList = $(elem).parent().parent().parent().parent('div').attr('id');
var ID = $(elem).parent().parent('li').attr('id');
var newFlag;
var flag = plugin.bookmarks[typeList][ID]['state'];
if(flag){ newFlag = 0; }
else if(!flag){ newFlag = 1; }
window.plugin.bookmarks[typeList][ID]['state'] = newFlag;
window.plugin.bookmarks.storeBookmarks(typeList);
}
//---------------------------------------------------------------------------------------
// Switch the status folder to open/close (in the localStorage)
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.addFolder = function(typeList){
var ID = window.plugin.bookmarks.generateID();
var input = '#'+typeList+' .addForm input';
//Get the label | Convert some characters | Set the input (empty)
var nameFolder = $(input).val();
nameFolder = nameFolder.replace(/\//g, '&#47;').replace(/\\/g, '&#92;').replace(/"/g, '&#34;').replace(/"/g, '&#39;');
if(nameFolder == ''){ nameFolder = 'Folder'; }
$(input).val('');
// Add new folder in the localStorage
plugin.bookmarks[typeList][ID] = {"label":nameFolder,"state":1,"bkmrk":{}};
plugin.bookmarks.storeBookmarks(typeList);
//Append the new folder to the list
$('#'+typeList+' li.othersBookmarks').before('<li class="bookmarkFolder active" id="'+ID+'"><span class="folderLabel"><a class="bookmarksRemoveFrom">X</a><a class="bookmarksAnchor"><span></span>'+nameFolder+'</a><span><span></span></span></span><ul></ul></li>');
}
//---------------------------------------------------------------------------------------
// Remove the bookmark (from the localStorage)
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.deletBookmark = function(elem){
var typeList = $(elem).parent().parent().parent().parent().parent('div').attr('id');
var ID = $(elem).parent('li').attr('id');
var IDfold = $(elem).parent().parent().parent('li').attr('id');
delete window.plugin.bookmarks[typeList][IDfold]['bkmrk'][ID];
window.plugin.bookmarks.storeBookmarks(typeList);
if(typeList == 'bkmrk_portals'){ window.plugin.bookmarks.updateStarPortal(); }
}
//---------------------------------------------------------------------------------------
// Remove the folder (from the localStorage)
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.deletFolder = function(elem){
var typeList = $(elem).parent().parent().parent().parent('div').attr('id');
var ID = $(elem).parent().parent('li').attr('id');
delete plugin.bookmarks[typeList][ID];
window.plugin.bookmarks.storeBookmarks(typeList);
if(typeList == 'bkmrk_portals'){ window.plugin.bookmarks.updateStarPortal(); }
}
//---------------------------------------------------------------------------------------
// Saved the new sort of the folders (in the localStorage)
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.sortBookmarksFolder = function(typeList){
window.plugin.bookmarks.loadBookmarks(typeList);
var newArr = {};
$('#'+typeList+' li.bookmarkFolder').each(function(){
var idFold = $(this).attr('id');
newArr[idFold] = window.plugin.bookmarks[typeList][idFold];
});
window.plugin.bookmarks[typeList] = newArr;
window.plugin.bookmarks.storeBookmarks(typeList);
}
//---------------------------------------------------------------------------------------
// Saved the new sort of the bookmarks (in the localStorage)
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.sortBookmarks = function(typeList){
window.plugin.bookmarks.loadBookmarks(typeList);
var list = window.plugin.bookmarks[typeList];
var newArr = {};
$('#'+typeList+' li.bookmarkFolder').each(function(){
var idFold = $(this).attr('id');
newArr[idFold] = window.plugin.bookmarks[typeList][idFold];
newArr[idFold].bkmrk = {};
});
$('#'+typeList+' li.bkmrk').each(function(){
window.plugin.bookmarks.loadBookmarks(typeList);
var idFold = $(this).parent().parent('li').attr('id');
var id = $(this).attr('id');
var list = window.plugin.bookmarks[typeList];
for(var idFoldersOrigin in list){
for(var idBkmrk in list[idFoldersOrigin]['bkmrk']){
if(idBkmrk == id){
newArr[idFold].bkmrk[id] = window.plugin.bookmarks[typeList][idFoldersOrigin].bkmrk[id];
}
}
}
});
window.plugin.bookmarks[typeList] = newArr;
window.plugin.bookmarks.storeBookmarks(typeList);
}
//---------------------------------------------------------------------------------------
// Update the localStorage
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.storeBookmarks = function(typeList){
var bookmarksObject = {};
bookmarksObject[typeList] = plugin.bookmarks[typeList];
var bookmarksObjectJSON = JSON.stringify(bookmarksObject);
localStorage[plugin.bookmarks['LOCAL_STORAGE_'+typeList]] = bookmarksObjectJSON;
}
//---------------------------------------------------------------------------------------
// Load the localStorage
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.loadBookmarks = function(typeList){
var bookmarksObjectJSON = localStorage[plugin.bookmarks['LOCAL_STORAGE_'+typeList]];
if(!bookmarksObjectJSON) return;
var bookmarksObject = JSON.parse(bookmarksObjectJSON);
plugin.bookmarks[typeList] = bookmarksObject[typeList];
}
//---------------------------------------------------------------------------------------
// Load the bookmarks
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.loadList = function(typeList){
window.plugin.bookmarks.loadBookmarks(typeList);
var element = '';
var elementTemp = '';
var elementExc = '';
// For each folder
var list = window.plugin.bookmarks[typeList];
for(var idFolders in list){
var folders = list[idFolders];
var active = '';
// Create a label and a anchor for the sortable
var folderLabel = '<span class="folderLabel"><a class="bookmarksRemoveFrom" title="Remove this folder">X</a>';
folderLabel += '<a class="bookmarksAnchor"><span></span>'+folders['label']+'</a><span><span></span></span></span>';
if(folders['state']){ active = ' active'; }
if(idFolders == window.plugin.bookmarks.KEY_OTHER_BKMRK){
folderLabel = ''; active= ' othersBookmarks active';
}
// Create a folder
elementTemp = '<li class="bookmarkFolder'+active+'" id="'+idFolders+'">'+folderLabel+'<ul>';
// For each bookmark
var fold = folders['bkmrk'];
for(var idBkmrk in fold){
var btn_link;
var btn_remove = '<a class="bookmarksRemoveFrom" title="Remove from bookmarks">X</a>';
var bkmrk = fold[idBkmrk];
var label = bkmrk['label'];
var latlng = bkmrk['latlng'];
// If it's a map
if(typeList == 'bkmrk_maps'){
if(bkmrk['label']==''){ label = bkmrk['latlng']+' ['+bkmrk['z']+']'; }
btn_link = '<a class="bookmarksLink" onclick="map.setView(['+latlng+'], '+bkmrk['z']+');return false;">'+label+'</a>';
}
// If it's a portal
else if(typeList == 'bkmrk_portals'){
var guid = bkmrk['guid'];
var btn_link = '<a class="bookmarksLink" onclick="window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false;">'+label+'</a>';
}
// Create the bookmark
elementTemp += '<li class="bkmrk" id="'+idBkmrk+'">'+btn_remove+btn_link+'</li>';
}
elementTemp += '</li></ul>';
//Add folder 'Others' in last position
if(idFolders != window.plugin.bookmarks.KEY_OTHER_BKMRK){ element += elementTemp; }
else{ elementExc = elementTemp; }
}
element += elementExc;
// Append all folders and bookmarks
$('#'+typeList+' ul').html(element);
}
/*********************************************************************************************************************/
//---------------------------------------------------------------------------------------
// Append the stylesheet
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.setupCSS = function(){
$('<style>').prop('type', 'text/css').html('@@INCLUDESTRING:plugins/bookmarks-by-zaso-css-desktop.css@@').appendTo('head');
}
//---------------------------------------------------------------------------------------
// Append the stylesheet for mobile app
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.setupCSS_mobile = function(){
$('<style>').prop('type', 'text/css').html('@@INCLUDESTRING:plugins/bookmarks-by-zaso-css-mobile.css@@').appendTo('head');
}
//---------------------------------------------------------------------------------------
// Append the js script
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.setupJS = function(){$(document).ready(function(){
//ENABLED THE DRAGGABLE PROPERTY OF THE BOX
$('#bookmarksBox').draggable({ handle:'.handle', containment:'window' });
$("#bookmarksBox #bookmarksMin , #bookmarksBox ul li, #bookmarksBox ul li a, #bookmarksBox h5, #bookmarksBox .addForm a").disableSelection();
//SWICTH VISIBILITY PROPERTY OF THE BOX
$('#bookmarksMin').click(function(){
$('#bookmarksBox').animate({marginTop:'-200%'}, {duration:600, queue:false}); $('#bookmarksShow').animate({marginTop:-36}, {duration:400, queue:false}); localStorage[window.plugin.bookmarks['LOCAL_STORAGE_status_box']] = 0;
});
$('#bookmarksShow').click(function(){ $('#bookmarksBox').animate({marginTop:0}, {duration:600, queue:false}); $('#bookmarksShow').animate({marginTop:-100}, {duration:400, queue:false}); localStorage[window.plugin.bookmarks['LOCAL_STORAGE_status_box']]= 1; });
if(localStorage[window.plugin.bookmarks['LOCAL_STORAGE_status_box']] == 1){ $('#bookmarksShow').trigger('click'); }else{ $('#bookmarksMin').trigger('click'); }
//SWITCH LIST (MAPS/PORTALS)
$('#bookmarksBox h5').click(function(){
$('h5').removeClass('current');
$(this).addClass('current');
var sectList = '#'+$(this).attr('class').replace(' current', '');
$('#bookmarksBox .bookmarkList').removeClass('current');
$(sectList).addClass('current');
});
if(!window.isSmartphone()){
//DESTOP: active vertical scroll-bar on the long lists
$('.bookmarkList > ul').enscroll({ showOnHover: true, verticalTrackClass: 'trackScroll', verticalHandleClass: 'handleScroll', minScrollbarLength:28 });
//OPEN/CLOSE FOLDER (to be corrected in mobile mode)---------------
$('#bookmarksBox').on('click', '.bookmarksAnchor', function(e){
window.plugin.bookmarks.openFolder(this);
$(this).parent().parent('li').toggleClass('active');
e.preventDefault();
});
}
//ENABLED THE SORTABLE PROPERTY OF THE FOLDERS AND BOOKMARKS
$(".bookmarkList > ul").sortable({
items:"li.bookmarkFolder:not(.othersBookmarks)",
handle:".bookmarksAnchor",
placeholder:"sortable-placeholder",
forcePlaceholderSize:true,
helper:'clone',
distance:5,
update:function(event, ui){
var typeList = $('#'+ui.item.context.id).parent().parent('.bookmarkList').attr('id');
window.plugin.bookmarks.sortBookmarksFolder(typeList);
}
});
$(".bookmarkList ul li ul").sortable({
items:"li.bkmrk",
connectWith:".bookmarkList ul ul",
handle:".bookmarksLink",
placeholder:"sortable-placeholder",
forcePlaceholderSize:true,
helper:'clone',
distance:5,
update:function(event, ui){
var typeList = $('#'+ui.item.context.id).parent().parent().parent().parent('.bookmarkList').attr('id');
window.plugin.bookmarks.sortBookmarks(typeList);
}
});
//ADD BOOKMARK/FOLDER
$('#bookmarksBox .addForm a').click(function(e){
var typeList = $(this).parent().parent('div').attr('id');
if($(this).hasClass('newMap')){ window.plugin.bookmarks.addBookmarkMap(this); }
else{ window.plugin.bookmarks.addFolder(typeList); }
//REFRESS SORTABLE EVENT FOR BKMRK
$(".bookmarkList ul li ul").sortable({
items:"li.bkmrk",
connectWith:".bookmarkList ul ul",
handle:".bookmarksLink",
placeholder:"sortable-placeholder",
forcePlaceholderSize:true,
helper:'clone',
distance:5,
update:function(event, ui){
var typeList = $('#'+ui.item.context.id).parent().parent().parent().parent('.bookmarkList').attr('id');
window.plugin.bookmarks.sortBookmarks(typeList);
}
});
if(window.isSmartphone()){
// The clone not working in mobile mode (to be corrected)---------------
$(".bookmarkList ul li ul").sortable("option", "helper", "original");
};
e.preventDefault();
});
//REMOVE FOLDER
$('.bookmarkList').on('click', '.folderLabel .bookmarksRemoveFrom', function(e){
window.plugin.bookmarks.deletFolder(this);
$(this).parent().parent('li').remove();
e.preventDefault();
});
//REMOVE BOOKMARK
$('.bookmarkList').on('click', '.bkmrk .bookmarksRemoveFrom', function(e){
window.plugin.bookmarks.deletBookmark(this);
$(this).parent('li').remove();
e.preventDefault();
});
if(window.isSmartphone()){
//FOR MOBILE
// The clone not working in mobile mode (to be corrected)---------------
$(".bookmarkList > ul").sortable("option", "helper", "original");
$(".bookmarkList ul li ul").sortable("option", "helper", "original");
//Show/Hide the box
$('#bookmarksBox').hide();
$('#bookmarksShowMobile').click(function(){
$(this).toggleClass('open');
$('#bookmarksBox').toggle();
if($(this).hasClass('open')){ $(this).text('[-] Bookmarks'); }
else{ $(this).text('[+] Bookmarks'); }
});
//Return to map when a bookmark is clicked
$('.bookmarkList').on('click', '.bkmrk .bookmarksLink', function(){
window.show("map");
});
}
});}
//---------------------------------------------------------------------------------------
// HTML element
//---------------------------------------------------------------------------------------
window.plugin.bookmarks.setupContent = function(){
plugin.bookmarks.contentStarHTML = '<a id="bookmarkStar" onclick="window.plugin.bookmarks.switchStarPortal();return false;" title="Save this portal in your bookmarks"><span></span></a>';
plugin.bookmarks.disabledMessage = '<div title="Your browser do not support localStorage">Plugin Bookmarks disabled</div>';
plugin.bookmarks.bkmrkRibbon = '<a id="bookmarksShow"></a>';
plugin.bookmarks.bkmrkBox = '<div id="bookmarksBox">'
+'<div id="topBar"><a id="bookmarksMin" class="btn" title="Minimize">-</a><div class="handle">...</div></div>'
+'<div id="bookmarksTypeBar"><h5 class="bkmrk_maps current">Maps</h5><h5 class="bkmrk_portals">Portals</h5><div style="clear:both !important;"></div></div>'
+'<div id="bkmrk_maps" class="bookmarkList current"><div class="addForm"><input placeholder="Insert label"><a class="newMap" onmouseover="setPermaLink(this);return false">+ Map</a><a class="newFolder">+ Folder</a></div><ul></ul></div>'
+'<div id="bkmrk_portals" class="bookmarkList"><div class="addForm"><input placeholder="Insert label"><a class="newFolder">+ Folder</a></div><ul></ul></div>'
+'</div>';
plugin.bookmarks.bkmrkTriggerMobile= '<a id="bookmarksShowMobile">[+] Bookmarks</a>';
}
/***************************************************************************************************************************************************************/
window.plugin.bookmarks.addStarToSidebar = function() {
if(typeof(Storage) === "undefined") { $('#portaldetails > .imgpreview').after(plugin.bookmarks.disabledMessage); return; }
var title = $('#portaldetails > h3').text();
$('#portaldetails > h3').html(plugin.bookmarks.contentStarHTML+title);
plugin.bookmarks.updateStarPortal();
}
window.plugin.bookmarks.updateStarPortal = function() {
window.plugin.bookmarks.loadBookmarks('bkmrk_portals');
var guid = window.selectedPortal;
var list = plugin.bookmarks['bkmrk_portals'];
$('#bookmarkStar').removeClass('favorite');
$('.bkmrk a.bookmarksLink.selected').removeClass('selected');
for(var idFolders in list) {
for(var idBkmrk in list[idFolders]['bkmrk']) {
var portalGuid = list[idFolders]['bkmrk'][idBkmrk]['guid'];
if(guid == portalGuid) {
$('#bookmarkStar').addClass('favorite');
$('.bkmrk#'+idBkmrk+' a.bookmarksLink').addClass('selected');
}
}
}
}
window.plugin.bookmarks.switchStarPortal = function() {
var guid = window.selectedPortal;
var setup = function(){
//Set the localStorage (if not exist)
if(!localStorage[window.plugin.bookmarks['LOCAL_STORAGE_bkmrk_portals']]){localStorage[plugin.bookmarks['LOCAL_STORAGE_bkmrk_portals']] = '{"bkmrk_portals":{"'+window.plugin.bookmarks.KEY_OTHER_BKMRK+'":{"label":"Others","state":1,"bkmrk":{}}}}'; }
if(!localStorage[window.plugin.bookmarks['LOCAL_STORAGE_bkmrk_maps']]){localStorage[plugin.bookmarks['LOCAL_STORAGE_bkmrk_maps']] = '{"bkmrk_maps":{"'+window.plugin.bookmarks.KEY_OTHER_BKMRK+'":{"label":"Others","state":1,"bkmrk":{}}}}'; }
if(!localStorage[window.plugin.bookmarks['LOCAL_STORAGE_status_box']]){localStorage[plugin.bookmarks['LOCAL_STORAGE_status_box']] = 1;}
if($('#bookmarkStar').hasClass('favorite')) {
var list = plugin.bookmarks['bkmrk_portals'];
//Load data from localStorage
window.plugin.bookmarks.loadBookmarks('bkmrk_portals');
window.plugin.bookmarks.loadBookmarks('bkmrk_maps');
for(var idFolders in list) {
for(var idBkmrk in list[idFolders]['bkmrk']) {
var portalGuid = list[idFolders]['bkmrk'][idBkmrk]['guid'];
if(guid == portalGuid) {
delete list[idFolders]['bkmrk'][idBkmrk];
$('.bkmrk#'+idBkmrk+'').remove();
}
}
}
}
else {
var linka = $('#portaldetails .linkdetails aside a:contains("Portal link")').attr('href');
var namePortal = $('#portaldetails h3').text();
if(window.isSmartphone()){
//FOR MOBILE: load the script for the touch events
var script2 = document.createElement('script');
script2.type = 'text/javascript';
script2.src = 'https://raw.github.com/furf/jquery-ui-touch-punch/master/jquery.ui.touch-punch.min.js';
script2.appendChild(document.createTextNode('('+ wrapper +')();'));
(document.body || document.head || document.documentElement).appendChild(script2);
}else{
//FOR DESKTOP: load the script to active the vertical scrollbar (in the bookmarks box)
var script3 = document.createElement('script');
script3.type = 'text/javascript';
script3.src = 'http://enscrollplugin.com/releases/enscroll-0.4.0.min.js';
script3.appendChild(document.createTextNode('('+ wrapper +')();'));
(document.body || document.head || document.documentElement).appendChild(script3);
}
var ID = window.plugin.bookmarks.generateID();
if($.inArray('pluginBookmarksUpdate', window.VALID_HOOKS) < 0){ window.VALID_HOOKS.push('pluginBookmarksUpdate'); }
var spac = linka.split('pll=');
var latlng = spac[1] ;
plugin.bookmarks['bkmrk_portals'][plugin.bookmarks.KEY_OTHER_BKMRK]['bkmrk'][ID] = {"guid":guid,"latlng":latlng,"label":namePortal};
$('#bkmrk_portals li.othersBookmarks ul').append('<li class="bkmrk" id="'+ID+'"><a class="bookmarksRemoveFrom" title="Remove from bookmarks">X</a><a class="bookmarksLink" onclick="window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false;">'+namePortal+'</a></li>');
}
window.plugin.bookmarks.storeBookmarks('bkmrk_portals');
window.plugin.bookmarks.updateStarPortal();
}
window.plugin.bookmarks.addBookmarkMap = function(elem) {
var mapLink = $(elem).attr('href');
var pars = new RegExp('[\\?&amp;]ll=([^&amp;#]*)[&amp;]z=([^&amp;#]*)').exec(mapLink);
var res = pars[1].split(',');
res[2] = pars[2];
var latlng = res[0]+','+res[1];
var zoom = res[2];
window.plugin.bookmarks.setupCSS();
if(window.isSmartphone()){window.plugin.bookmarks.setupCSS_mobile();}
window.plugin.bookmarks.setupContent();
var ID = window.plugin.bookmarks.generateID();
//Append the bookmarks box
if(!window.isSmartphone()){ $('body').append(plugin.bookmarks.bkmrkRibbon+plugin.bookmarks.bkmrkBox); }
else{ $('#portaldetails').before(plugin.bookmarks.bkmrkTriggerMobile+plugin.bookmarks.bkmrkBox); }
var nameMap = $(elem).siblings('input').val();
nameMap = nameMap.replace(/\//g, '&#47;').replace(/\\/g, '&#92;').replace(/"/g, '&#34;').replace(/"/g, '&#39;');
//Load bookmarks and folders in the box
window.plugin.bookmarks.loadList('bkmrk_maps');
window.plugin.bookmarks.loadList('bkmrk_portals');
if(nameMap == '') { nameMap = ''; }
$(elem).siblings('input').val('');
plugin.bookmarks['bkmrk_maps'][plugin.bookmarks.KEY_OTHER_BKMRK]['bkmrk'][ID] = {"label":nameMap,"latlng":latlng,"z":parseInt(zoom)};
plugin.bookmarks.storeBookmarks('bkmrk_maps');
if(nameMap=='') { nameMap = latlng+' ['+zoom+']'; }
$('#bkmrk_maps li.othersBookmarks ul').append('<li class="bkmrk" id="'+ID+'"><a class="bookmarksRemoveFrom" title="Remove from bookmarks">X</a><a class="bookmarksLink" onclick="map.setView(['+latlng+'], '+zoom+');return false;">'+nameMap+'</a></li>');
}
/***************************************************************************************************************************************************************/
window.plugin.bookmarks.generateID = function() {
var d = new Date();
var ID = d.getTime()+(Math.floor(Math.random()*99)+1);
var ID = 'id'+ID.toString();
return ID;
}
window.plugin.bookmarks.openFolder = function(elem) {
var typeList = $(elem).parent().parent().parent().parent('div').attr('id');
var ID = $(elem).parent().parent('li').attr('id');
var newFlag;
var flag = plugin.bookmarks[typeList][ID]['state'];
if(flag) { newFlag = 0; }
else if(!flag) { newFlag = 1; }
window.plugin.bookmarks[typeList][ID]['state'] = newFlag;
window.plugin.bookmarks.storeBookmarks(typeList);
}
window.plugin.bookmarks.addFolder = function(typeList) {
var ID = window.plugin.bookmarks.generateID();
var input = '#'+typeList+' .addForm input';
var nameFolder = $(input).val();
nameFolder = nameFolder.replace(/\//g, '&#47;').replace(/\\/g, '&#92;').replace(/"/g, '&#34;').replace(/"/g, '&#39;');
if(nameFolder == '') { nameFolder = 'Folder'; }
$(input).val('');
plugin.bookmarks[typeList][ID] = {"label":nameFolder,"state":0,"bkmrk":{}};
plugin.bookmarks.storeBookmarks(typeList);
$('#'+typeList+' li.othersBookmarks').before('<li class="bookmarkFolder" id="'+ID+'"><span class="folderLabel"><a class="bookmarksRemoveFrom">X</a><a class="bookmarksAnchor"><span></span>'+nameFolder+'</a><span><span></span></span></span><ul></ul></li>');
}
window.plugin.bookmarks.deletBookmark = function(elem) {
var typeList = $(elem).parent().parent().parent().parent().parent('div').attr('id');
var ID = $(elem).parent('li').attr('id');
var IDfold = $(elem).parent().parent().parent('li').attr('id');
delete window.plugin.bookmarks[typeList][IDfold]['bkmrk'][ID];
window.plugin.bookmarks.storeBookmarks(typeList);
if(typeList == 'bkmrk_portals') { window.plugin.bookmarks.updateStarPortal(); }
}
window.plugin.bookmarks.deletFolder = function(elem) {
var typeList = $(elem).parent().parent().parent().parent('div').attr('id');
var ID = $(elem).parent().parent('li').attr('id');
delete plugin.bookmarks[typeList][ID];
window.plugin.bookmarks.storeBookmarks(typeList);
if(typeList == 'bkmrk_portals') { window.plugin.bookmarks.updateStarPortal(); }
}
window.plugin.bookmarks.sortBookmarksFolder = function(typeList) {
window.plugin.bookmarks.loadBookmarks(typeList);
var newArr = {};
$('#'+typeList+' li.bookmarkFolder').each(function() {
var idFold = $(this).attr('id');
newArr[idFold] = window.plugin.bookmarks[typeList][idFold];
});
window.plugin.bookmarks[typeList] = newArr;
window.plugin.bookmarks.storeBookmarks(typeList);
}
window.plugin.bookmarks.sortBookmarks = function(typeList) {
window.plugin.bookmarks.loadBookmarks(typeList);
var list = window.plugin.bookmarks[typeList];
var newArr = {};
$('#'+typeList+' li.bookmarkFolder').each(function() {
var idFold = $(this).attr('id');
newArr[idFold] = window.plugin.bookmarks[typeList][idFold];
newArr[idFold].bkmrk = {};
});
$('#'+typeList+' li.bkmrk').each(function() {
window.plugin.bookmarks.loadBookmarks(typeList);
var idFold = $(this).parent().parent('li').attr('id');
var id = $(this).attr('id');
var list = window.plugin.bookmarks[typeList];
for(var idFoldersOrigin in list) {
for(var idBkmrk in list[idFoldersOrigin]['bkmrk']) {
if(idBkmrk == id) {
newArr[idFold].bkmrk[id] = window.plugin.bookmarks[typeList][idFoldersOrigin].bkmrk[id];
}
}
}
});
window.plugin.bookmarks[typeList] = newArr;
window.plugin.bookmarks.storeBookmarks(typeList);
}
window.plugin.bookmarks.storeBookmarks = function(typeList) {
var bookmarksObject = {};
bookmarksObject[typeList] = plugin.bookmarks[typeList];
var bookmarksObjectJSON = JSON.stringify(bookmarksObject);
localStorage[plugin.bookmarks['LOCAL_STORAGE_'+typeList]] = bookmarksObjectJSON;
}
window.plugin.bookmarks.loadBookmarks = function(typeList) {
var bookmarksObjectJSON = localStorage[plugin.bookmarks['LOCAL_STORAGE_'+typeList]];
if(!bookmarksObjectJSON) return;
var bookmarksObject = JSON.parse(bookmarksObjectJSON);
plugin.bookmarks[typeList] = bookmarksObject[typeList];
}
window.plugin.bookmarks.loadList = function(typeList) {
window.plugin.bookmarks.loadBookmarks(typeList);
var element = '';
var list = window.plugin.bookmarks[typeList];
for(var idFolders in list) {
var folders = list[idFolders];
var active = '';
var folderLabel = '<span class="folderLabel"><a class="bookmarksRemoveFrom" title="Remove this folder">X</a>';
folderLabel += '<a class="bookmarksAnchor"><span></span>'+folders['label']+'</a><span><span></span></span></span>';
if(folders['state']) { active = ' active'; }
if(idFolders == window.plugin.bookmarks.KEY_OTHER_BKMRK) { folderLabel = ''; active= ' othersBookmarks active' }
element += '<li class="bookmarkFolder'+active+'" id="'+idFolders+'">'+folderLabel+'<ul>';
var fold = folders['bkmrk'];
for(var idBkmrk in fold) {
var btn_link;
var btn_remove = '<a class="bookmarksRemoveFrom" title="Remove from bookmarks">X</a>';
var bkmrk = fold[idBkmrk];
var label = bkmrk['label'];
var latlng = bkmrk['latlng'];
if(typeList == 'bkmrk_maps') {
if(bkmrk['label']=='') { label = bkmrk['latlng']+' ['+bkmrk['z']+']'; }
btn_link = '<a class="bookmarksLink" onclick="map.setView(['+latlng+'], '+bkmrk['z']+');return false;">'+label+'</a>';
}
else if(typeList == 'bkmrk_portals') {
var guid = bkmrk['guid'];
var btn_link = '<a class="bookmarksLink" onclick="window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false;">'+label+'</a>';
}
element += '<li class="bkmrk" id="'+idBkmrk+'">'+btn_remove+btn_link+'</li>';
}
element += '</li></ul>';
}
$('#'+typeList+' ul').html(element);
}
/***************************************************************************************************************************************************************/
window.plugin.bookmarks.setupJS = function() {
$(document).ready(function() {
//ENABLED THE DRAGGABLE PROPERTY OF THE BOX
$('#bookmarksBox').draggable({ handle:'.handle', containment:'window' });
$("#bookmarksBox #bookmarksMin , #bookmarksBox ul li, #bookmarksBox ul li a, #bookmarksBox h5, #bookmarksBox .addForm a").disableSelection();
//SWICTH VISIBILITY OF THE BOX
$('#bookmarksMin').click(function() { $('#bookmarksBox').animate({marginTop:'-100%'}, {duration:400, queue:false}); $('#bookmarksShow').animate({marginTop:-36}, {duration:400, queue:false}); localStorage[window.plugin.bookmarks['LOCAL_STORAGE_status_box']] = 0; });
$('#bookmarksShow').click(function() { $('#bookmarksBox').animate({marginTop:0}, {duration:400, queue:false}); $('#bookmarksShow').animate({marginTop:-100}, {duration:400, queue:false}); localStorage[window.plugin.bookmarks['LOCAL_STORAGE_status_box']]= 1; });
if(localStorage[window.plugin.bookmarks['LOCAL_STORAGE_status_box']] == 1) { $('#bookmarksShow').trigger('click'); }else { $('#bookmarksMin').trigger('click'); }
//SWITCH LIST (MAPS/PORTALS)
$('#bookmarksBox h5').click(function() {$('h5').removeClass('current');$(this).addClass('current');var sectList = '#'+$(this).attr('class').replace(' current', '');$('#bookmarksBox .bookmarkList').removeClass('current');$(sectList).addClass('current');});
//ACTIVE VERTICAL SCROLL-BAR ON THE LONG LISTS
$('.bookmarkList > ul').enscroll({ showOnHover: true, verticalTrackClass: 'trackScroll', verticalHandleClass: 'handleScroll', minScrollbarLength:28 });
//ENABLED THE SORTABLE PROPERTY OF THE FOLDERS AND BOOKMARKS
$(".bookmarkList > ul").sortable({items:"li.bookmarkFolder:not(.othersBookmarks)",handle:".bookmarksAnchor",placeholder:"sortable-placeholder",forcePlaceholderSize:true,
update:function(event, ui) {
var typeList = $('#'+ui.item.context.id).parent().parent('.bookmarkList').attr('id');
window.plugin.bookmarks.sortBookmarksFolder(typeList);
}
});
$(".bookmarkList ul li ul").sortable({items:"li.bkmrk",connectWith:".bookmarkList ul ul",handle:".bookmarksLink",placeholder:"sortable-placeholder",forcePlaceholderSize:true,
update:function(event, ui) {
var typeList = $('#'+ui.item.context.id).parent().parent().parent().parent('.bookmarkList').attr('id');
window.plugin.bookmarks.sortBookmarks(typeList);
}
});
//REMOVE FOLDER
$('.bookmarkList').on('click', '.folderLabel .bookmarksRemoveFrom', function(e) {
window.plugin.bookmarks.deletFolder(this);
$(this).parent().parent('li').remove();
e.preventDefault();
});
//REMOVE BOOKMARK
$('.bookmarkList').on('click', '.bkmrk .bookmarksRemoveFrom', function(e) {
window.plugin.bookmarks.deletBookmark(this);
$(this).parent('li').remove();
e.preventDefault();
});
//OPEN/CLOSE FOLDER
$('#bookmarksBox').on('click', '.bookmarksAnchor', function(e) {
window.plugin.bookmarks.openFolder(this);
$(this).parent().parent('li').toggleClass('active');
e.preventDefault();
});
//ADD BOOKMARK/FOLDER
$('#bookmarksBox .addForm a').click(function(e) {
var typeList = $(this).parent().parent('div').attr('id');
if($(this).hasClass('newMap')) { window.plugin.bookmarks.addBookmarkMap(this); }
else { window.plugin.bookmarks.addFolder(typeList); }
//REFRESS SORTABLE EVENT FOR BKMRK
$(".bookmarkList ul li ul").sortable({items:"li.bkmrk",connectWith:".bookmarkList ul ul",handle:".bookmarksLink",placeholder:"sortable-placeholder",forcePlaceholderSize:true,
update:function(event, ui) {
var typeList = $('#'+ui.item.context.id).parent().parent().parent().parent('.bookmarkList').attr('id');
window.plugin.bookmarks.sortBookmarks(typeList);
}
});
e.preventDefault();
});
});
}
window.plugin.bookmarks.setupCSS = function() {
$("<style>").prop("type", "text/css")
.html("@@INCLUDESTRING:plugins/bookmarks-by-zaso.css@@").appendTo("head");
}
window.plugin.bookmarks.setupContent = function() {
plugin.bookmarks.contentStarHTML = '<a id="bookmarkStar" onclick="window.plugin.bookmarks.switchStarPortal();return false;" title="Save this portal in your bookmarks"><span></span></a>';
plugin.bookmarks.disabledMessage = '<div class="notStorageSupport" title="Your browser do not support localStorage">Plugin Bookmarks disabled</div>';
plugin.bookmarks.bkmrkBox = '<div id="bookmarksBox">'
+'<div id="topBar"><a id="bookmarksMin" class="btn" title="Minimize">-</a><div class="handle">...</div></div>'
+'<div id="bookmarksTypeBar"><h5 class="bkmrk_maps current">Maps</h5><h5 class="bkmrk_portals">Portals</h5></div>'
+'<div id="bkmrk_maps" class="bookmarkList current"><div class="addForm"><input placeholder="Insert label"><a class="newMap" onmouseover="setPermaLink(this);return false">+ Map</a><a class="newFolder">+ Folder</a></div><ul></ul></div>'
+'<div id="bkmrk_portals" class="bookmarkList"><div class="addForm"><input placeholder="Insert label"><a class="newFolder">+ Folder</a></div><ul></ul></div>'
+'</div>';
plugin.bookmarks.bkmrkRibbon = '<a id="bookmarksShow"></a>';
}
/***************************************************************************************************************************************************************/
var setup = function() {
if(!localStorage[window.plugin.bookmarks['LOCAL_STORAGE_bkmrk_portals']]) {localStorage[plugin.bookmarks['LOCAL_STORAGE_bkmrk_portals']] = '{"bkmrk_portals":{"'+window.plugin.bookmarks.KEY_OTHER_BKMRK+'":{"label":"Others","state":1,"bkmrk":{}}}}'; }
if(!localStorage[window.plugin.bookmarks['LOCAL_STORAGE_bkmrk_maps']]) {localStorage[plugin.bookmarks['LOCAL_STORAGE_bkmrk_maps']] = '{"bkmrk_maps":{"'+window.plugin.bookmarks.KEY_OTHER_BKMRK+'":{"label":"Others","state":1,"bkmrk":{}}}}'; }
if(!localStorage[window.plugin.bookmarks['LOCAL_STORAGE_status_box']]) {localStorage[plugin.bookmarks['LOCAL_STORAGE_status_box']] = 0;}
if($.inArray('pluginBookmarksUpdate', window.VALID_HOOKS) < 0) { window.VALID_HOOKS.push('pluginBookmarksUpdate'); }
window.plugin.bookmarks.setupCSS();
window.plugin.bookmarks.setupJS();
window.plugin.bookmarks.setupContent();
window.plugin.bookmarks.loadBookmarks('bkmrk_portals');
window.plugin.bookmarks.loadBookmarks('bkmrk_maps');
window.addHook('portalDetailsUpdated', window.plugin.bookmarks.addStarToSidebar);
//Add to DOM the element of the plugin and load data from localStorage
$('body').append(plugin.bookmarks.bkmrkRibbon);
$('body').append(plugin.bookmarks.bkmrkBox);
window.plugin.bookmarks.loadList('bkmrk_maps');
window.plugin.bookmarks.loadList('bkmrk_portals');
//Load the js page for the scrollbar
var script2 = document.createElement('script');
script2.type = 'text/javascript';
script2.src = 'http://enscrollplugin.com/releases/enscroll-0.4.0.min.js';
script2.appendChild(document.createTextNode('('+ wrapper +')();'));
(document.body || document.head || document.documentElement).appendChild(script2);
}
window.plugin.bookmarks.setupJS();
window.addHook('portalDetailsUpdated', window.plugin.bookmarks.addToSidebar);
}
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-compute-ap-stats@Hollow011
// @name IITC plugin: Compute AP statistics
// @category Info
// @version 0.3.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -143,16 +141,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-draw-tools@breunigs
// @name IITC plugin: draw tools
// @category Layer
// @version 0.4.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -158,16 +156,4 @@ var setup = window.plugin.drawTools.loadExternals;
// 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);
@@PLUGINEND@@

View File

@ -12,11 +12,11 @@
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
function wrapper() {
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
window.plugin.favoritePortals = function() {};
window.plugin.favoritePortals.portalList = {};
@ -169,17 +169,4 @@ var setup = window.plugin.favoritePortals.setup;
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id force-https@jonatkins
// @name IITC plugin: force https access for ingress.com/intel
// @category Tweaks
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@

View File

@ -1,7 +1,8 @@
// ==UserScript==
// @id iitc-plugin-guess-player-levels@breunigs
// @name IITC plugin: guess player level
// @version 0.4.5.@@DATETIMEVERSION@@
// @category Info
// @version 0.4.6.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -156,6 +154,23 @@ window.plugin.guessPlayerLevels.guess = function() {
title: 'Player levels: R' + averageR.toFixed(2) + ', E' + averageE.toFixed(2),
id: 'guess-player-levels',
width: 350,
buttons: {
'RESET GUESSES': function() {
// clear all guessed levels from local storage
$.each(Object.keys(localStorage), function(ind,key) {
if(key.lastIndexOf("level-",0)===0) {
localStorage.removeItem(key);
}
});
// now force all portals through the callback manually
$.each(window.portals, function(guid,p) {
window.plugin.guessPlayerLevels.extractPortalData({portal: p});
});
// and re-open the dialog (on a minimal timeout - so it's not closed while processing this callback)
setTimeout(window.plugin.guessPlayerLevels.guess,1);
},
},
});
//run the name resolving process
@ -181,16 +196,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-ipas-link@graphracer
// @name IITC Plugin: simulate an attack on portal
// @category Portal Info
// @version 0.2.0.@@DATETIMEVERSION@@
// @namespace https://github.com/xosofox/IPAS
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -110,16 +108,4 @@ var setup = function () {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-keys-on-map@xelio
// @name IITC plugin: Keys on map
// @category Keys
// @version 0.2.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -135,16 +133,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-keys@xelio
// @name IITC plugin: Keys
// @category Keys
// @version 0.2.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -209,16 +207,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,10 +1,11 @@
// ==UserScript==
// @id max-links@boombuler
// @name IITC plugin: Max Links
// @version 0.3.1.@@DATETIMEVERSION@@
// @category Layer
// @version 0.4.0.@@DATETIMEVERSION@@
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Calculates how to link the portals to create the maximum number of fields.
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Calculates how to link the portals to create the maximum number of fields. Enable from the layer chooser.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
@ -12,11 +13,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function')
window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -29,15 +26,24 @@ window.plugin.maxLinks.MAX_DRAWN_LINKS_INCREASED_LIMIT = 1000;
window.plugin.maxLinks.STROKE_STYLE = {
color: '#FF0000',
opacity: 1,
weight:2,
weight: 2,
clickable: false,
smoothFactor: 10
dashArray: [8,6],
smoothFactor: 10,
};
window.plugin.maxLinks.layer = null;
window.plugin.maxLinks._updating = false;
window.plugin.maxLinks._renderLimitReached = false;
window.plugin.maxLinks.Point = function(x,y) {
this.x=x;
this.y=y;
}
window.plugin.maxLinks.Point.prototype.toString = function() {
return this.x+","+this.y;
}
window.plugin.maxLinks.updateLayer = function() {
if (window.plugin.maxLinks._updating ||
window.plugin.maxLinks.layer === null ||
@ -47,36 +53,62 @@ window.plugin.maxLinks.updateLayer = function() {
window.plugin.maxLinks.layer.clearLayers();
var locations = [];
var minX = 0;
var minY = 0;
$.each(window.portals, function(guid, portal) {
var loc = portal.options.details.locationE6;
var nloc = { x: loc.lngE6, y: loc.latE6 };
if (nloc.x < minX)
minX = nloc.x;
if (nloc.y < minY)
minY = nloc.y;
var nloc = new window.plugin.maxLinks.Point(loc.latE6/1E6, loc.lngE6/1E6);
locations.push(nloc);
});
$.each(locations, function(idx, nloc) {
nloc.x += Math.abs(minX);
nloc.y += Math.abs(minY);
});
var triangles = window.delaunay.triangulate(locations);
var drawnLinks = 0;
var drawnLinkCount = 0;
window.plugin.maxLinks._renderLimitReached = false;
var renderlimit = window.USE_INCREASED_RENDER_LIMIT ?
var renderLimit = window.USE_INCREASED_RENDER_LIMIT ?
window.plugin.maxLinks.MAX_DRAWN_LINKS_INCREASED_LIMIT :
window.plugin.maxLinks.MAX_DRAWN_LINKS;
var orderedPoints = function(a,b) {
if(a.x<b.x) return [a,b];
if(a.x==b.x && a.y<b.y) return [a,b];
return [b,a];
}
var drawnLinks = {};
//draw a link, but only if it hasn't already been drawn
var drawLink = function(a,b) {
//order the points, so a pair of coordinates in any order is handled in one direction only
var points = orderedPoints(a,b);
a=points[0];
b=points[1];
//do we have a line already drawn from a to b?
if(!(a in drawnLinks)) {
//no lines from a to anywhere yet - create an empty target array
drawnLinks[a] = {};
}
if (!(b in drawnLinks[a])) {
//no line from a to b yet
//using drawnLinks[a] as a set - so the stored value is of no importance
drawnLinks[a][b] = null;
var poly = L.polyline([[a.x,a.y],[b.x,b.y]], window.plugin.maxLinks.STROKE_STYLE);
poly.addTo(window.plugin.maxLinks.layer);
drawnLinkCount++;
}
}
$.each(triangles, function(idx, triangle) {
if (drawnLinks <= renderlimit) {
triangle.draw(window.plugin.maxLinks.layer, minX, minY)
drawnLinks += 3;
} else {
drawLink(triangle.a,triangle.b);
drawLink(triangle.b,triangle.c);
drawLink(triangle.c,triangle.a);
// we only check the render limit after drawing all three edges of a triangle, for efficency
if (drawnLinkCount > renderLimit ) {
window.plugin.maxLinks._renderLimitReached = true;
return false; //$.each break
}
});
window.plugin.maxLinks._updating = false;
@ -88,17 +120,6 @@ window.plugin.maxLinks.setup = function() {
@@INCLUDERAW:external/delaunay.js@@
try { console.log('done loading delaunay JS'); } catch(e) {}
window.delaunay.Triangle.prototype.draw = function(layer, divX, divY) {
var drawLine = function(src, dest) {
var poly = L.polyline([[(src.y + divY)/1E6, (src.x + divX)/1E6], [(dest.y + divY)/1E6, (dest.x + divX)/1E6]], window.plugin.maxLinks.STROKE_STYLE);
poly.addTo(layer);
};
drawLine(this.a, this.b);
drawLine(this.b, this.c);
drawLine(this.c, this.a);
}
window.plugin.maxLinks.layer = L.layerGroup([]);
window.addHook('checkRenderLimit', function(e) {
@ -107,9 +128,8 @@ window.plugin.maxLinks.setup = function() {
e.reached = true;
});
window.addHook('portalDataLoaded', function(e) {
if (window.map.hasLayer(window.plugin.maxLinks.layer))
window.plugin.maxLinks.updateLayer();
window.addHook('requestFinished', function(e) {
window.plugin.maxLinks.updateLayer();
});
window.map.on('layeradd', function(e) {
@ -122,18 +142,5 @@ window.plugin.maxLinks.setup = function() {
var setup = window.plugin.maxLinks.setup;
// 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);
@@PLUGINEND@@

61
plugins/minimap.user.js Normal file
View File

@ -0,0 +1,61 @@
// ==UserScript==
// @id iitc-plugin-minimap@breunigs
// @name IITC plugin: Mini map
// @category Controls
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Shows a mini map on the corner of the map
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.miniMap = function() {};
window.plugin.miniMap.setup = function() {
try { console.log('Loading leaflet.draw JS now'); } catch(e) {}
@@INCLUDERAW:external/Control.MiniMap.js@@
try { console.log('done loading leaflet.draw JS'); } catch(e) {}
// we can't use the same TileLayer as the main map uses - it causes issues.
// stick with the MapQuest tiles for now
//OpenStreetMap attribution - required by several of the layers
osmAttribution = 'Map data © OpenStreetMap contributors';
//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)
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', maxZoom: 18, subdomains: mqSubdomains};
var mqMap = new L.TileLayer(mqTileUrlPrefix+'/tiles/1.0.0/map/{z}/{x}/{y}.jpg',mqMapOpt);
if(!isSmartphone()) {
// desktop mode - bottom-left, so it doesn't clash with the sidebar
new L.Control.MiniMap(mqMap, {toggleDisplay: true, position: 'bottomleft'}).addTo(window.map);
} else {
// mobile mode - bottom-right - so it floats above the map copyright text
new L.Control.MiniMap(mqMap, {toggleDisplay: true, position: 'bottomright'}).addTo(window.map);
}
$('head').append('<style>@@INCLUDESTRING:external/Control.MiniMap.css@@</style>');
};
var setup = window.plugin.miniMap.setup;
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-pan-control@fragger
// @name IITC plugin: pan control
// @category Controls
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -45,16 +43,4 @@ var setup = window.plugin.panControl.setup;
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-player-tracker@breunigs
// @name IITC Plugin: Player tracker
// @category Layer
// @version 0.9.4.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
window.PLAYER_TRACKER_MAX_TIME = 3*60*60*1000; // in milliseconds
@ -411,16 +409,4 @@ var setup = plugin.playerTracker.setup;
// 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);
@@PLUGINEND@@

View File

@ -13,6 +13,10 @@
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
/*********************************************************************************************************
* Changelog:
*
@ -24,13 +28,6 @@
* 0.1.0 First public release
*********************************************************************************************************/
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.playersResonators = function() {};
@ -107,16 +104,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-portals-count@yenky
// @name IITC plugin: Show total counts of portals
// @category Info
// @version 0.0.8.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,6 +14,10 @@
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
/* whatsnew
* 0.0.8 : use dialog() instead of alert()
* 0.0.6 : ignoring outside bounds portals (even if close to)
@ -24,12 +29,6 @@
* todo :
*/
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.portalcounts = function() {};
@ -131,16 +130,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-upgrade@vita10gy
// @name IITC plugin: highlight portals you can upgrade to a specific level
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -78,16 +76,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-level-color@vita10gy
// @name IITC plugin: highlight portals by level color
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,14 +14,11 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
// use own namespace for plugin
window.plugin.portalHighligherPortalsLevelColor = function() {};
window.plugin.portalHighligherPortalsLevelColor.colorLevel = function(data) {
@ -37,16 +35,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-missing-resonators@vita10gy
// @name IITC plugin: highlight portals missing resonators
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -63,16 +61,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -0,0 +1,70 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-mods@vita10gy
// @name IITC plugin: highlight portal mods
// @category Highlighter
// @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 to denote if the portal has the selected mod.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.portalHighligherMods = function() {};
window.plugin.portalHighligherMods.highlight = function(data, mod_type) {
var d = data.portal.options.details;
var mod_effect = 0;
$.each(d.portalV2.linkedModArray, function(ind, mod) {
if(mod !== null && mod.type == mod_type) {
switch(mod.rarity){
case 'COMMON':
mod_effect++;
break;
case 'RARE':
mod_effect+=2;
break;
case 'VERY_RARE':
mod_effect+=3;
break;
}
}
});
if(mod_effect > 0) {
var fill_opacity = mod_effect/12*.85 + .15;
var color = 'red';
fill_opacity = Math.round(fill_opacity*100)/100;
var params = {fillColor: color, fillOpacity: fill_opacity};
data.portal.setStyle(params);
}
window.COLOR_SELECTED_PORTAL = '#f0f';
}
window.plugin.portalHighligherMods.getHighlighter = function(type) {
return(function(data){
window.plugin.portalHighligherMods.highlight(data,type);
});
}
var setup = function() {
$.each(MOD_TYPE, function(ind, name){
window.addPortalHighlighter('Mod: '+name, window.plugin.portalHighligherMods.getHighlighter(ind));
});
}
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-my-8-portals@vita10gy
// @name IITC plugin: highlight my level 8's on portals
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -53,16 +51,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-my-portals@vita10gy
// @name IITC plugin: highlight my portals
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -73,16 +71,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-needs-recharge@vita10gy
// @name IITC plugin: hightlight portals that need recharging
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -46,16 +44,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-by-ap-by-energy-relative@vita10gy
// @name IITC plugin: highlight portals by ap/energy (relative)
// @category Highlighter
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -104,16 +102,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-by-ap-relative@vita10gy
// @name IITC plugin: highlight portals by ap relative
// @category Highlighter
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -99,16 +97,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-by-ap@vita10gy
// @name IITC plugin: highlight portals by ap
// @category Highlighter
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -60,16 +58,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-my-level@vita10gy
// @name IITC plugin: highlight portals by my level
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -54,16 +52,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-upgrade@vita10gy
// @name IITC plugin: highlight portals you can upgrade
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -57,16 +55,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-highlight-portals-with-L8-resonators@superd
// @name IITC plugin: highlight portals with L8 resonators
// @category Highlighter
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -54,16 +52,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-portal-level-numbers@rongou
// @name IITC plugin: Portal Level Numbers
// @category Layer
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -85,16 +83,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,7 +1,8 @@
// ==UserScript==
// @id iitc-plugin-portals-list@teo96
// @name IITC plugin: show list of portals
// @version 0.0.13.@@DATETIMEVERSION@@
// @category Info
// @version 0.0.14.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
@ -13,7 +14,12 @@
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
/* whatsnew
* 0.0.14: Add support to new mods (S:Shield - T:Turret - LA:Link Amp - H:Heat-sink - M:Multi-hack - FA:Force Amp)
* 0.0.12: Use dialog() instead of alert so the user can drag the box around
* 0.0.11: Add nominal energy column and # links, fix sort bug when opened even amounts of times, nits
* 0.0.10: Fixed persistent css problem with alert
@ -33,12 +39,6 @@
* todo : export as GPX, Open in Google Maps, more statistics in the header, what else ?
*/
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.portalslist = function() {};
@ -94,19 +94,44 @@ window.plugin.portalslist.getPortals = function() {
// Sort resonators array by resonator level
resonators.sort(function (a, b) {return b[0] - a[0]});
//get shield informations
var shields = [];
//get mods informations
var mods = [];
$.each(d.portalV2.linkedModArray, function(ind, mod) {
if (mod) {
//shields[ind] = mod.rarity.capitalize().replace('_', ' ');
shields[ind] = [mod.rarity.substr(0,1).capitalize(), getPlayerName(mod.installingUser)] ;
} else {
shields[ind] = ['', ''];
}
var modShortName='';
if (mod) {
switch (mod.displayName) {
case 'Portal Shield':
modShortName = 'S';
break;
case 'Force Amp':
modShortName = 'FA';
break;
case 'Link Amp':
modShortName = 'LA';
break;
case 'Heat Sink':
modShortName = 'H';
break;
case 'Multi-hack':
modShortName = 'M';
break;
case 'Turret':
modShortName = 'T';
break;
default:
modShortName = '';
break;
}
if (modShortName === '') {
mods[ind] = ['', '', ''];
} else {
mods[ind] = [mod.rarity, getPlayerName(mod.installingUser), modShortName, mod.displayName];
}
}else { mods[ind] = ['', '', '']; }
});
console.log(mods);
var APgain= getAttackApGain(d).enemyAp;
var thisPortal = {'portal': d, 'name': name, 'team': team, 'level': level, 'guid': guid, 'resonators': resonators, 'energyratio': maxenergy ? Math.floor(energy/maxenergy*100) : 0, 'shields': shields, 'APgain': APgain, 'EAP': (energy/APgain).toFixed(2), 'energy': energy, 'maxenergy': maxenergy, 'links': d.portalV2.linkedEdges.length, 'lat': portal._latlng.lat, 'lng': portal._latlng.lng, 'address': address, 'img': img};
var thisPortal = {'portal': d, 'name': name, 'team': team, 'level': level, 'guid': guid, 'resonators': resonators, 'energyratio': maxenergy ? Math.floor(energy/maxenergy*100) : 0, 'mods': mods, 'APgain': APgain, 'EAP': (energy/APgain).toFixed(2), 'energy': energy, 'maxenergy': maxenergy, 'links': d.portalV2.linkedEdges.length, 'lat': portal._latlng.lat, 'lng': portal._latlng.lng, 'address': address, 'img': img};
window.plugin.portalslist.listPortals.push(thisPortal);
});
@ -199,16 +224,16 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) {
retVal = b.resonators[7][0] - a.resonators[7][0];
break;
case 's1':
retVal = a.shields[0].toLowerCase() > b.shields[0].toLowerCase() ? -1 : 1;
retVal = a.mods[0][2] > b.mods[0][2] ? -1 : 1;
break;
case 's2':
retVal = a.shields[1].toLowerCase() > b.shields[1].toLowerCase() ? -1 : 1;
retVal = a.mods[1][2] > b.mods[1][2] ? -1 : 1;
break;
case 's3':
retVal = a.shields[2].toLowerCase() > b.shields[2].toLowerCase() ? -1 : 1;
retVal = a.mods[2][2] > b.mods[2][2] ? -1 : 1;
break;
case 's4':
retVal = a.shields[3].toLowerCase() > b.shields[3].toLowerCase() ? -1 : 1;
retVal = a.mods[3][2] > b.mods[3][2] ? -1 : 1;
break;
default:
retVal = b[sortBy] - a[sortBy];
@ -235,10 +260,10 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) {
+ '<th ' + sort('energy', sortBy, -1) + '>Energy</th>'
+ '<th ' + sort('energyratio', sortBy, -1) + '>%</th>'
+ '<th ' + sort('links', sortBy, -1) + '>Links</th>'
+ '<th ' + sort('s1', sortBy, -1) + '>S1</th>'
+ '<th ' + sort('s2', sortBy, -1) + '>S2</th>'
+ '<th ' + sort('s3', sortBy, -1) + '>S3</th>'
+ '<th ' + sort('s4', sortBy, -1) + '>S4</th>'
+ '<th ' + sort('s1', sortBy, -1) + '>M1</th>'
+ '<th ' + sort('s2', sortBy, -1) + '>M2</th>'
+ '<th ' + sort('s3', sortBy, -1) + '>M3</th>'
+ '<th ' + sort('s4', sortBy, -1) + '>M4</th>'
+ '<th ' + sort('APgain', sortBy, -1) + '>AP Gain</th>'
+ '<th title="Energy / AP Gain ratio" ' + sort('EAP', sortBy, -1) + '>E/AP</th></tr>';
@ -263,13 +288,13 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) {
});
html += '<td style="cursor:help" title="'+ portal.energy +'">' + prettyEnergy(portal.energy) + '</td>'
html += '<td style="cursor:help" title="'+ portal.energy +'">' + prettyEnergy(portal.energy) + '</td>'
+ '<td style="cursor:help" title="' + portal.energy + ' / ' + portal.maxenergy +'">' + portal.energyratio + '%</td>'
+ '<td style="cursor:help" title="' + portal.links + '">' + portal.links + '</td>'
+ '<td style="cursor:help" title="'+ portal.shields[0][1] +'">' + portal.shields[0][0] + '</td>'
+ '<td style="cursor:help" title="'+ portal.shields[1][1] +'">' + portal.shields[1][0] + '</td>'
+ '<td style="cursor:help" title="'+ portal.shields[2][1] +'">' + portal.shields[2][0] + '</td>'
+ '<td style="cursor:help" title="'+ portal.shields[3][1] +'">' + portal.shields[3][0] + '</td>'
+ '<td style="cursor:help; background-color: '+COLORS_MOD[portal.mods[0][0]]+';" title="Mod : ' + portal.mods[0][3] + '\nInstalled by : ' + portal.mods[0][1] + '\nRarity : ' + portal.mods[0][0] + '">' + portal.mods[0][2] + '</td>'
+ '<td style="cursor:help; background-color: '+COLORS_MOD[portal.mods[1][0]]+';" title="Mod : ' + portal.mods[1][3] + '\nInstalled by : ' + portal.mods[1][1] + '\nRarity : ' + portal.mods[1][0] + '">' + portal.mods[1][2] + '</td>'
+ '<td style="cursor:help; background-color: '+COLORS_MOD[portal.mods[2][0]]+';" title="Mod : ' + portal.mods[2][3] + '\nInstalled by : ' + portal.mods[2][1] + '\nRarity : ' + portal.mods[2][0] + '">' + portal.mods[2][2] + '</td>'
+ '<td style="cursor:help; background-color: '+COLORS_MOD[portal.mods[3][0]]+';" title="Mod : ' + portal.mods[3][3] + '\nInstalled by : ' + portal.mods[3][1] + '\nRarity : ' + portal.mods[3][0] + '">' + portal.mods[3][2] + '</td>'
+ '<td>' + portal.APgain + '</td>'
+ '<td>' + portal.EAP + '</td>';
@ -363,16 +388,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -13,11 +13,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function')
window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -114,18 +110,4 @@ var setup = window.plugin.privacyView.setup;
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-render-limit-increase@jonatkins
// @name IITC plugin: render limit increase
// @category Tweaks
// @version 0.3.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,8 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -49,16 +48,4 @@ var setup = window.plugin.renderLimitIncrease.setHigherLimits;
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-reso-energy-pct-in-portal-detail@xelio
// @name IITC plugin: reso energy pct in portal detail
// @category Portal Info
// @version 0.1.2.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -46,16 +44,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-resonator-display-zoom-level-decrease@xelio
// @name IITC plugin: resonator display zoom level decrease
// @category Tweaks
// @version 1.0.2.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -34,16 +32,4 @@ var setup = window.plugin.resonatorDisplayZoomLevelDecrease.changeConstant;
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-scale-bar@breunigs
// @name IITC plugin: scale bar
// @category Controls
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -41,16 +39,4 @@ var setup = window.plugin.scaleBar.setup;
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-scoreboard@vita10gy
// @name IITC plugin: show a localized scoreboard.
// @category Info
// @version 0.1.8.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -426,16 +424,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -0,0 +1,36 @@
// ==UserScript==
// @id iitc-plugin-scroll-wheel-zoom-disable@jonatkins
// @name IITC plugin: disable mouse wheel zoom
// @category Tweaks
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Disable the use of mouse wheel to zoom. The map zoom controls or keyboard are still available.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.scrollWheelZoomDisable = function() {};
window.plugin.scrollWheelZoomDisable.setup = function() {
window.map.scrollWheelZoom.disable();
};
var setup = window.plugin.scrollWheelZoomDisable.setup;
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-show-address@vita10gy
// @name IITC plugin: show portal address in sidebar
// @category Portal Info
// @version 0.2.2.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -43,16 +41,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-show-linked-portals@fstopienski
// @name IITC plugin: Show linked portals
// @category Portal Info
// @version 0.0.4.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,21 +14,16 @@
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
/*
* 0.0.1 initial release, show images, names and addresses of linked portal in portal detailview
* - mouse click of the linked portal image selected the portal and adjust map
* - click of "Linked Portal is out of range" zoom a step out
*/
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.showLinkedPortal = function () {
};
@ -120,16 +116,4 @@ var setup = function () {
}
// 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);
@@PLUGINEND@@

View File

@ -0,0 +1,61 @@
// ==UserScript==
// @id iitc-plugin-show-more-portals@jonatkins
// @name IITC plugin: Show more portals
// @category Tweaks
// @version 0.1.0.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
// @downloadURL @@DOWNLOADURL@@
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Boost the detail level of portals shown on the map by one zoom level. Good for small screens. Likely to increase request failed errors on larger screens.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
// @match http://www.ingress.com/intel*
// @grant none
// ==/UserScript==
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
// use own namespace for plugin
window.plugin.showMorePortals = function() {};
window.plugin.showMorePortals.setup = function() {
// replace the window.getPortalDataZoom function
window.getPortalDataZoom = function() {
var mapZoom = map.getZoom();
// yes, it is possible to increase this beyond "+1" - however, that will end up producing a rediculous number
// of requests to the Niantic servers, giving many request failed errors/tile timeouts
// (every increase by one requests four times as many data tiles)
var z = mapZoom + 1;
// limiting the mazimum zoom level for data retrieval reduces the number of requests at high zoom levels
// (as all portal data is retrieved at z=17, why retrieve multiple z=18 tiles when fewer z=17 would do?)
// very effective along with the new cache code
if (z > 17) z=17;
// if the data zoom is above the map zoom we can step back if the detail level is the same
// with the new cache code this works rather well
while (z > mapZoom && getMinPortalLevelForZoom(z) == getMinPortalLevelForZoom(z-1)) {
z = z-1;
}
//sanity check - should never happen
if (z < 0) z=0;
return z;
}
};
var setup = window.plugin.showMorePortals.setup;
// PLUGIN END //////////////////////////////////////////////////////////
@@PLUGINEND@@

View File

@ -1,11 +1,12 @@
// ==UserScript==
// @id iitc-plugin-show-portal-weakness@vita10gy
// @name IITC plugin: show portal weakness
// @version 0.7.0.@@DATETIMEVERSION@@
// @category Highlighter
// @version 0.7.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 if the portal is weak (Needs recharging, missing a resonator, needs shields) Red, needs energy and shields. Orange, only needs energy (either recharge or resonators). Yellow, only needs shields.
// @description [@@BUILDNAME@@-@@BUILDDATE@@] Uses the fill color of the portals to denote if the portal is weak (Needs recharging, missing a resonator, needs mods) Red, needs energy and mods. Orange, only needs energy (either recharge or resonators). Yellow, only needs mods.
// @include https://www.ingress.com/intel*
// @include http://www.ingress.com/intel*
// @match https://www.ingress.com/intel*
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -27,17 +25,19 @@ window.plugin.portalWeakness.highlightWeakness = function(data) {
var d = data.portal.options.details;
var portal_weakness = 0;
if(getTeam(d) !== 0) {
var only_shields = true;
var missing_shields = 0;
var only_mods = true;
var missing_mods = 0;
if(window.getTotalPortalEnergy(d) > 0 && window.getCurrentPortalEnergy(d) < window.getTotalPortalEnergy(d)) {
portal_weakness = 1 - (window.getCurrentPortalEnergy(d)/window.getTotalPortalEnergy(d));
only_shields = false;
only_mods = false;
}
//Ding the portal for every missing sheild.
//Ding the portal for every unapplicable mod.
$.each(d.portalV2.linkedModArray, function(ind, mod) {
if(mod === null) {
missing_shields++;
portal_weakness += .03;
if(mod === null || mod.type == 'MULTIHACK' || mod.type == 'HEATSINK' || mod.type == 'LINK_AMPLIFIER') {
if(mod === null) {
missing_mods++;
}
portal_weakness += .08;
}
});
//Ding the portal for every missing resonator.
@ -45,7 +45,7 @@ window.plugin.portalWeakness.highlightWeakness = function(data) {
$.each(d.resonatorArray.resonators, function(ind, reso) {
if(reso === null) {
portal_weakness += .125;
only_shields = false;
only_mods = false;
} else {
resCount++;
}
@ -60,12 +60,12 @@ window.plugin.portalWeakness.highlightWeakness = function(data) {
if(portal_weakness > 0) {
var fill_opacity = portal_weakness*.85 + .15;
var color = 'orange';
if(only_shields) {
if(only_mods) {
color = 'yellow';
//If only shields are missing, make portal yellow
//If only mods are missing, make portal yellow
// but fill more than usual since pale yellow is basically invisible
fill_opacity = missing_shields*.15 + .1;
} else if(missing_shields > 0) {
fill_opacity = missing_mods*.15 + .1;
} else if(missing_mods > 0) {
color = 'red';
}
fill_opacity = Math.round(fill_opacity*100)/100;
@ -91,16 +91,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -13,10 +13,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if (typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -36,16 +33,4 @@ var setup = window.plugin.speechSearch.setup;
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-sync@xelio
// @name IITC plugin: Sync
// @category Keys
// @version 0.2.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -753,16 +751,4 @@ var setup = function() {
// 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);
@@PLUGINEND@@

View File

@ -1,6 +1,7 @@
// ==UserScript==
// @id iitc-plugin-zoom-slider@fragger
// @name IITC plugin: zoom slider
// @category Controls
// @version 0.1.1.@@DATETIMEVERSION@@
// @namespace https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL @@UPDATEURL@@
@ -13,10 +14,7 @@
// @grant none
// ==/UserScript==
function wrapper() {
// ensure plugin framework is there, even if iitc is not yet loaded
if(typeof window.plugin !== 'function') window.plugin = function() {};
@@PLUGINSTART@@
// PLUGIN START ////////////////////////////////////////////////////////
@ -41,16 +39,4 @@ var setup = window.plugin.zoomSlider.setup;
// 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);
@@PLUGINEND@@

View File

@ -514,6 +514,10 @@ h3 {
display: none;
}
.imgpreview .portalDetails {
display: none;
}
#level {
font-size: 40px;
text-shadow: -1px -1px #000, 1px -1px #000, -1px 1px #000, 1px 1px #000, 0 0 5px #fff;
@ -824,6 +828,7 @@ h3 {
overflow-x: hidden;
max-height: 600px !important;
max-width: 700px !important;
position: relative;
}
.ui-dialog-content-hidden {
@ -938,3 +943,17 @@ td + td {
}
.portal_details th, .portal_details td {
vertical-align: top;
text-align: left;
}
.portal_details th {
white-space: nowrap;
padding-right: 1em;
}
.portal_details tr.padding-top th, .portal_details tr.padding-top td {
padding-top: 0.7em;
}

View File

@ -3,3 +3,7 @@ body {
background: url('../img/bg.jpg');
}
table tr.category_header {
background: #ddd;
}

View File

@ -16,8 +16,41 @@ function iitcDesktopDownload ( $build )
function iitcDesktopPluginDownloadTable ( $build )
{
$categories = Array (
'Portal Info' => "Enhanced information on the selected portal",
'Info' => "Display additional information",
'Keys' => "Manual key management",
'Controls' => "Map controls/widgets",
'Highlighter' => "Portal highlighters",
'Layer' => "Additional map layers",
'Map Tiles' => "Alternative map layers",
'Tweaks' => "Adjust IITC settings",
'Misc' => "Unclassified plugins",
);
$plugins = Array();
foreach ( glob ( "$build/plugins/*.user.js" ) as $path )
{
$basename = basename ( $path, ".user.js" );
$details = loadUserScriptHeader ( $path );
$plugins[$basename] = $details;
$category = array_key_exists('@category',$details) ? $details['@category'] : 'Misc';
if ( !array_key_exists($category,$categories) )
{
# add missing categories
$categories[$category] = '';
}
}
ksort ( $plugins );
?>
<table class="table table-condensed table-hover">
<table class="table table-condensed">
<thead>
<tr>
<th>Name</th>
@ -29,30 +62,43 @@ function iitcDesktopPluginDownloadTable ( $build )
<tbody>
<?php
foreach ( glob ( "$build/plugins/*.user.js" ) as $path )
{
$basename = basename ( $path, ".user.js" );
foreach ( $categories as $category => $category_desc )
{
print "<tr class=\"category_header\"><th colspan=\"2\">Category: $category</th><td colspan=\"2\">$category_desc</td></tr>\n";
$details = loadUserScriptHeader ( $path );
$empty = True;
foreach ( $plugins as $basename => $details )
{
$path = "$build/plugins/$basename.user.js";
print "<tr id=\"plugin-$basename\">\n";
$this_category = array_key_exists('@category',$details) ? $details['@category'] : 'Misc';
# remove 'IITC Plugin: ' prefix if it's there, for neatness
$name = preg_replace ( '/^IITC plugin: /i', '', $details['@name'] );
if ( $category != $this_category )
continue;
# format extended version info in less prominant font
$version = preg_replace ( '/^(\d+\.\d+\.\d+)\.(\d{8}\.\d{6})/', '\1<small class="muted">.\2</small>', $details['@version'] );
$empty = False;
# remove unneeded prefix from description
$description = preg_replace ( '/^\[[^]]*\] */', '', $details['@description'] );
print "<tr id=\"plugin-$basename\">\n";
print "<td>$name</td>";
print "<td>$basename<br />$version</td>";
print "<td>$description</td>";
print "<td><a onclick=\"if(track){track('desktop','iitc-plugin-$basename','$build');}\" href=\"$path\" class=\"btn btn-small btn-primary\">Download</a></td>";
print "</tr>\n";
}
# remove 'IITC Plugin: ' prefix if it's there, for neatness
$name = preg_replace ( '/^IITC plugin: /i', '', $details['@name'] );
# format extended version info in less prominant font
$version = preg_replace ( '/^(\d+\.\d+\.\d+)\.(\d{8}\.\d{6})/', '\1<small class="muted">.\2</small>', $details['@version'] );
# remove unneeded prefix from description
$description = preg_replace ( '/^\[[^]]*\] */', '', $details['@description'] );
print "<td>$name</td>";
print "<td>$basename<br />$version</td>";
print "<td>$description</td>";
print "<td><a onclick=\"if(track){track('desktop','iitc-plugin-$basename','$build');}\" href=\"$path\" class=\"btn btn-small btn-primary\">Download</a></td>";
print "</tr>\n";
}
if ( $empty )
print "<tr><td colspan=\"4\">(no plugins in this category)</td></tr>\n";
}
?>
</tbody>
</table>

View File

@ -13,21 +13,25 @@ offers many more features. It is available for
<h3>Latest news</h3>
<h4>22nd May 2013</h4>
<h4>1st July 2013</h4>
<p>
IITC version 0.12.0 has been released. This contains quite a few changes and new features, including
IITC version 0.12.2 released, and IITC Mobile 0.4.8.
<ul>
<li>Portal highlighter system - and many portal highlighter plugins</li>
<li>Dialogs - can be kept open and dragged while viewing the map</li>
<li>Layers - the enabled layers are now remembered when you next load the intel site</li>
<li>Improved request limits - more improvements have been made in this area</li>
<li>Sync plugin - to sync data from the 'Keys' addon to multiple computers via Google Drive</li>
<li>... and many other tweaks, bug fixes, etc</li>
<li>Various internal improvements to reduce requests to the Niantic servers and improve performance;
a data tile cache, and fixes to idle code when the user isn't interacting.</li>
<li>Improved display of stats for the new mods.</li>
<li>Portal range calculation now includes boost from link amps.</li>
<li>Removed 'redeem code' input box - not sure when it's returning.</li>
</ul>
Plugin changes:
<ul>
<li>Guess player levels - option to reset guesses.</li>
<li>New highlighter plugins for the new mods.</li>
<li>Max-links plugin - fixed problems with very narrow triangles causing overlapping links sometimes.</li>
<li>Portals-list plugin - support for the new mods.</li>
<li>Show portal weakness plugin - tweaks to highlight portals with non-defensive mods.</li>
<li>Plugin to show increased portal detail (intended for mobile and smaller screens. Can cause more errors on larger screens)</li>
</ul>
IITC Mobile 0.4.0 is also released. THis has also had major work. Along with the above, it includes a
new in-app layer chooser and chat/map switcher, and authentication has been revamped to use the native
Android authentication rather than entering your password.
</p>
<a class="btn btn-small" href="?page=news">Older news</a>

View File

@ -1,5 +1,41 @@
<h2>News</h2>
<h4>1st July 2013</h4>
<p>
IITC version 0.12.2 released, and IITC Mobile 0.4.8.
<ul>
<li>Various internal improvements to reduce requests to the Niantic servers and improve performance;
a data tile cache, and fixes to idle code when the user isn't interacting.</li>
<li>Improved display of stats for the new mods.</li>
<li>Portal range calculation now includes boost from link amps.</li>
<li>Removed 'redeem code' input box - not sure when it's returning.</li>
</ul>
Plugin changes:
<ul>
<li>Guess player levels - option to reset guesses.</li>
<li>New highlighter plugins for the new mods.</li>
<li>Max-links plugin - fixed problems with very narrow triangles causing overlapping links sometimes.</li>
<li>Portals-list plugin - support for the new mods.</li>
<li>Show portal weakness plugin - tweaks to highlight portals with non-defensive mods.</li>
<li>Plugin to show increased portal detail (intended for mobile and smaller screens. Can cause more errors on larger screens)</li>
</ul>
</p>
<h4>12th June 2013</h4>
<p>
IITC version 0.12.1 released, and IITC Mobile 0.4.6. Changes include:
<ul>
<li>Display details about the new portal mods</li>
<li>Updated Leaflet.js version - may reduce issues found on some Samsung devices running Android 4.1 (Jellybean)</li>
<li>Fix resolving a large number of player names in one go</li>
<li>Prevent refreshing old chat messages on small map movements - can vastly reduce repeated requests in some cases</li>
<li>Various improvements/tweaks to the mobile version</li>
<li>AP list plugin: fixed shield mitigation calculation</li>
<li>New basemap plugins: OpenStreetMap, OpenCycleMap, Yandex (Russian), and a template for CloudMade.com to restore the original blue map</li>
<li>Guess player level plugin: attempt to spot when a Jarvis Virus/ADA Refactor has been used and ignore that player's resonators when guessing the level</li>
<li>Max links plugin: optimisations and dashed lines</li>
</ul>
<h4>22nd May 2013</h4>
<p>
IITC version 0.12.0 has been released. This contains quite a few changes and new features, including