From 1d2eec7f8042843a41b84118ed40768bd99dd202 Mon Sep 17 00:00:00 2001 From: vita10gy Date: Tue, 3 Sep 2013 18:42:45 -0700 Subject: [PATCH 001/126] Feedback when geosearch finds nothing Subtle, but it's driven me crazy in the past where seemingly reasonable searches do nothing and "worked - but found nothing" and "maybe it's just taking a second to work" aren't apparent. --- code/geosearch.js | 6 +++++- style.css | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/code/geosearch.js b/code/geosearch.js index ab67a56c..0a3165c8 100644 --- a/code/geosearch.js +++ b/code/geosearch.js @@ -14,6 +14,7 @@ window.setupGeosearch = function() { $('#geosearchwrapper img').click(function(){ map.locate({setView : true, maxZoom: 13}); }); + $('#geosearch').keyup(function(){$(this).removeClass('search_not_found')}); } window.search = function(search) { @@ -22,7 +23,10 @@ window.search = function(search) { } $.getJSON(NOMINATIM + encodeURIComponent(search), function(data) { - if(!data || !data[0]) return true; + if(!data || !data[0]) { + $('#geosearch').addClass('search_not_found'); + return true; + } var b = data[0].boundingbox; if(!b) return true; var southWest = new L.LatLng(b[0], b[2]), diff --git a/style.css b/style.css index 532bc501..c72baec6 100644 --- a/style.css +++ b/style.css @@ -469,6 +469,12 @@ input { margin-bottom: 2px; cursor: pointer; } + +.search_not_found{ + color:red; + font-style: italic; +} + ::-webkit-input-placeholder { font-style: italic; } From dfd91de6dca0c107fb09abc741d7eb203a91e195 Mon Sep 17 00:00:00 2001 From: Xelio Date: Fri, 20 Sep 2013 13:40:26 +0800 Subject: [PATCH 002/126] New hook: playerNameResolved Called when unresolved player name get resolved. Argument is {names: object} which names[guid] is the resolved player name --- code/hooks.js | 5 ++++- code/player_names.js | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/code/hooks.js b/code/hooks.js index f415fe62..b6a7ef6c 100644 --- a/code/hooks.js +++ b/code/hooks.js @@ -15,6 +15,9 @@ // required to successfully boot the plugin. // // Here’s more specific information about each event: +// playerNameResolved: called when unresolved player name get resolved. +// Argument is {names: object} which names[guid] is the +// resolved player name. // portalSelected: called when portal on map is selected/unselected. // Provide guid of selected and unselected portal. // mapDataRefreshStart: called when we start refreshing map data @@ -49,7 +52,7 @@ window._hooks = {} window.VALID_HOOKS = [ - 'portalSelected', + 'playerNameResolved', 'portalSelected', 'mapDataRefreshStart', 'mapDataRefreshEnd', 'portalAdded', 'linkAdded', 'fieldAdded', 'portalDetailsUpdated', diff --git a/code/player_names.js b/code/player_names.js index d8bfda37..0f895d53 100644 --- a/code/player_names.js +++ b/code/player_names.js @@ -68,9 +68,11 @@ window.resolvePlayerNames = function() { window.playersInResolving = window.playersInResolving.concat(p); postAjax('getPlayersByGuids', d, function(dat) { + var resolvedName = {}; if(dat.result) { $.each(dat.result, function(ind, player) { window.setPlayerName(player.guid, player.nickname); + resolvedName[player.guid] = player.nickname; // remove from array window.playersInResolving.splice(window.playersInResolving.indexOf(player.guid), 1); }); @@ -82,6 +84,9 @@ window.resolvePlayerNames = function() { //therefore, not a good idea to automatically retry by adding back to the playersToResolve list } + // Run hook 'playerNameResolved' with the resolved player names + window.runHooks('playerNameResolved', {names: resolvedName}); + //TODO: have an event triggered for this instead of hard-coded single function call if(window.selectedPortal) window.renderPortalDetails(window.selectedPortal); From ca8c8bb806947e2b8f83a061fb72d133f90bc029 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Tue, 24 Sep 2013 13:26:35 +1000 Subject: [PATCH 003/126] Added KML plugin --- external/KML.js | 336 ++++++++++++++++++++++++++++++++++ external/leaflet.filelayer.js | 168 +++++++++++++++++ external/togeojson.js | 224 +++++++++++++++++++++++ plugins/kml_plugin.user.js | 62 +++++++ 4 files changed, 790 insertions(+) create mode 100755 external/KML.js create mode 100755 external/leaflet.filelayer.js create mode 100755 external/togeojson.js create mode 100755 plugins/kml_plugin.user.js diff --git a/external/KML.js b/external/KML.js new file mode 100755 index 00000000..22659777 --- /dev/null +++ b/external/KML.js @@ -0,0 +1,336 @@ +/*global L: true */ + +L.KML = L.FeatureGroup.extend({ + options: { + async: true + }, + + initialize: function(kml, options) { + L.Util.setOptions(this, options); + this._kml = kml; + this._layers = {}; + + if (kml) { + this.addKML(kml, options, this.options.async); + } + }, + + loadXML: function(url, cb, options, async) { + if (async == undefined) async = this.options.async; + if (options == undefined) options = this.options; + + var req = new window.XMLHttpRequest(); + req.open('GET', url, async); + try { + req.overrideMimeType('text/xml'); // unsupported by IE + } catch(e) {} + req.onreadystatechange = function() { + if (req.readyState != 4) return; + if(req.status == 200) cb(req.responseXML, options); + }; + req.send(null); + }, + + addKML: function(url, options, async) { + var _this = this; + var cb = function(gpx, options) { _this._addKML(gpx, options) }; + this.loadXML(url, cb, options, async); + }, + + _addKML: function(xml, options) { + var layers = L.KML.parseKML(xml); + if (!layers || !layers.length) return; + for (var i = 0; i < layers.length; i++) + { + this.fire('addlayer', { + layer: layers[i] + }); + this.addLayer(layers[i]); + } + this.latLngs = L.KML.getLatLngs(xml); + this.fire("loaded"); + }, + + latLngs: [] +}); + +L.Util.extend(L.KML, { + + parseKML: function (xml) { + var style = this.parseStyle(xml); + var el = xml.getElementsByTagName("Folder"); + var layers = [], l; + for (var i = 0; i < el.length; i++) { + if (!this._check_folder(el[i])) { continue; } + l = this.parseFolder(el[i], style); + if (l) { layers.push(l); } + } + el = xml.getElementsByTagName('Placemark'); + for (var j = 0; j < el.length; j++) { + if (!this._check_folder(el[j])) { continue; } + l = this.parsePlacemark(el[j], xml, style); + if (l) { layers.push(l); } + } + return layers; + }, + + // Return false if e's first parent Folder is not [folder] + // - returns true if no parent Folders + _check_folder: function (e, folder) { + e = e.parentElement; + while (e && e.tagName !== "Folder") + { + e = e.parentElement; + } + return !e || e === folder; + }, + + parseStyle: function (xml) { + var style = {}; + var sl = xml.getElementsByTagName("Style"); + + //for (var i = 0; i < sl.length; i++) { + var attributes = {color: true, width: true, Icon: true, href: true, + hotSpot: true}; + + function _parse(xml) { + var options = {}; + for (var i = 0; i < xml.childNodes.length; i++) { + var e = xml.childNodes[i]; + var key = e.tagName; + if (!attributes[key]) { continue; } + if (key === 'hotSpot') + { + for (var j = 0; j < e.attributes.length; j++) { + options[e.attributes[j].name] = e.attributes[j].nodeValue; + } + } else { + var value = e.childNodes[0].nodeValue; + if (key === 'color') { + options.opacity = parseInt(value.substring(0, 2), 16) / 255.0; + options.color = "#" + value.substring(6, 8) + value.substring(4, 6) + value.substring(2, 4); + } else if (key === 'width') { + options.weight = value; + } else if (key === 'Icon') { + ioptions = _parse(e); + if (ioptions.href) { options.href = ioptions.href; } + } else if (key === 'href') { + options.href = value; + } + } + } + return options; + } + + for (var i = 0; i < sl.length; i++) { + var e = sl[i], el; + var options = {}, poptions = {}, ioptions = {}; + el = e.getElementsByTagName("LineStyle"); + if (el && el[0]) { options = _parse(el[0]); } + el = e.getElementsByTagName("PolyStyle"); + if (el && el[0]) { poptions = _parse(el[0]); } + if (poptions.color) { options.fillColor = poptions.color; } + if (poptions.opacity) { options.fillOpacity = poptions.opacity; } + el = e.getElementsByTagName("IconStyle"); + if (el && el[0]) { ioptions = _parse(el[0]); } + if (ioptions.href) { + // save anchor info until the image is loaded + options.icon = new L.KMLIcon({ + iconUrl: ioptions.href, + shadowUrl: null, + iconAnchorRef: {x: ioptions.x, y: ioptions.y}, + iconAnchorType: {x: ioptions.xunits, y: ioptions.yunits} + }); + } + style['#' + e.getAttribute('id')] = options; + } + return style; + }, + + parseFolder: function (xml, style) { + var el, layers = [], l; + el = xml.getElementsByTagName('Folder'); + for (var i = 0; i < el.length; i++) { + if (!this._check_folder(el[i], xml)) { continue; } + l = this.parseFolder(el[i], style); + if (l) { layers.push(l); } + } + el = xml.getElementsByTagName('Placemark'); + for (var j = 0; j < el.length; j++) { + if (!this._check_folder(el[j], xml)) { continue; } + l = this.parsePlacemark(el[j], xml, style); + if (l) { layers.push(l); } + } + if (!layers.length) { return; } + if (layers.length === 1) { return layers[0]; } + return new L.FeatureGroup(layers); + }, + + parsePlacemark: function (place, xml, style) { + var i, j, el, options = {}; + el = place.getElementsByTagName('styleUrl'); + for (i = 0; i < el.length; i++) { + var url = el[i].childNodes[0].nodeValue; + for (var a in style[url]) + { + // for jshint + if (true) + { + options[a] = style[url][a]; + } + } + } + var layers = []; + + var parse = ['LineString', 'Polygon', 'Point']; + for (j in parse) { + // for jshint + if (true) + { + var tag = parse[j]; + el = place.getElementsByTagName(tag); + for (i = 0; i < el.length; i++) { + var l = this["parse" + tag](el[i], xml, options); + if (l) { layers.push(l); } + } + } + } + + if (!layers.length) { + return; + } + var layer = layers[0]; + if (layers.length > 1) { + layer = new L.FeatureGroup(layers); + } + + var name, descr = ""; + el = place.getElementsByTagName('name'); + if (el.length) { + name = el[0].childNodes[0].nodeValue; + } + el = place.getElementsByTagName('description'); + for (i = 0; i < el.length; i++) { + for (j = 0; j < el[i].childNodes.length; j++) { + descr = descr + el[i].childNodes[j].nodeValue; + } + } + + if (name) { + layer.bindPopup("

" + name + "

" + descr); + } + + return layer; + }, + + parseCoords: function (xml) { + var el = xml.getElementsByTagName('coordinates'); + return this._read_coords(el[0]); + }, + + parseLineString: function (line, xml, options) { + var coords = this.parseCoords(line); + if (!coords.length) { return; } + return new L.Polyline(coords, options); + }, + + parsePoint: function (line, xml, options) { + var el = line.getElementsByTagName('coordinates'); + if (!el.length) { + return; + } + var ll = el[0].childNodes[0].nodeValue.split(','); + return new L.KMLMarker(new L.LatLng(ll[1], ll[0]), options); + }, + + parsePolygon: function (line, xml, options) { + var el, polys = [], inner = [], i, coords; + el = line.getElementsByTagName('outerBoundaryIs'); + for (i = 0; i < el.length; i++) { + coords = this.parseCoords(el[i]); + if (coords) { + polys.push(coords); + } + } + el = line.getElementsByTagName('innerBoundaryIs'); + for (i = 0; i < el.length; i++) { + coords = this.parseCoords(el[i]); + if (coords) { + inner.push(coords); + } + } + if (!polys.length) { + return; + } + if (options.fillColor) { + options.fill = true; + } + if (polys.length === 1) { + return new L.Polygon(polys.concat(inner), options); + } + return new L.MultiPolygon(polys, options); + }, + + getLatLngs: function (xml) { + var el = xml.getElementsByTagName('coordinates'); + var coords = []; + for (var j = 0; j < el.length; j++) { + // text might span many childnodes + coords = coords.concat(this._read_coords(el[j])); + } + return coords; + }, + + _read_coords: function (el) { + var text = "", coords = [], i; + for (i = 0; i < el.childNodes.length; i++) { + text = text + el.childNodes[i].nodeValue; + } + text = text.split(/[\s\n]+/); + for (i = 0; i < text.length; i++) { + var ll = text[i].split(','); + if (ll.length < 2) { + continue; + } + coords.push(new L.LatLng(ll[1], ll[0])); + } + return coords; + } + +}); + +L.KMLIcon = L.Icon.extend({ + + createIcon: function () { + var img = this._createIcon('icon'); + img.onload = function () { + var i = new Image(); + i.src = this.src; + this.style.width = i.width + 'px'; + this.style.height = i.height + 'px'; + + if (this.anchorType.x === 'UNITS_FRACTION' || this.anchorType.x === 'fraction') { + img.style.marginLeft = (-this.anchor.x * i.width) + 'px'; + } + if (this.anchorType.y === 'UNITS_FRACTION' || this.anchorType.x === 'fraction') { + img.style.marginTop = (-(1 - this.anchor.y) * i.height) + 'px'; + } + this.style.display = ""; + }; + return img; + }, + + _setIconStyles: function (img, name) { + L.Icon.prototype._setIconStyles.apply(this, [img, name]) + // save anchor information to the image + img.anchor = this.options.iconAnchorRef; + img.anchorType = this.options.iconAnchorType; + } +}); + + +L.KMLMarker = L.Marker.extend({ + options: { + icon: new L.KMLIcon.Default() + } +}); \ No newline at end of file diff --git a/external/leaflet.filelayer.js b/external/leaflet.filelayer.js new file mode 100755 index 00000000..7eab6a50 --- /dev/null +++ b/external/leaflet.filelayer.js @@ -0,0 +1,168 @@ +/* + * Load files *locally* (GeoJSON, KML, GPX) into the map + * using the HTML5 File API. + * + * Requires Pavel Shramov's GPX.js + * https://github.com/shramov/leaflet-plugins/blob/d74d67/layer/vector/GPX.js + */ +var FileLoader = L.Class.extend({ + includes: L.Mixin.Events, + options: { + layerOptions: {} + }, + + initialize: function (map, options) { + this._map = map; + L.Util.setOptions(this, options); + + this._parsers = { + 'geojson': this._loadGeoJSON, + 'gpx': this._convertToGeoJSON, + 'kml': this._convertToGeoJSON + }; + }, + + load: function (file /* File */) { + // Check file extension + var ext = file.name.split('.').pop(), + parser = this._parsers[ext]; + if (!parser) { + window.alert("Unsupported file type " + file.type + '(' + ext + ')'); + return; + } + // Read selected file using HTML5 File API + var reader = new FileReader(); + reader.onload = L.Util.bind(function (e) { + this.fire('data:loading', {filename: file.name, format: ext}); + var layer = parser.call(this, e.target.result, ext); + this.fire('data:loaded', {layer: layer, filename: file.name, format: ext}); + }, this); + reader.readAsText(file); + }, + + _loadGeoJSON: function (content) { + if (typeof content == 'string') { + content = JSON.parse(content); + } + return L.geoJson(content, this.options.layerOptions).addTo(this._map); + }, + + _convertToGeoJSON: function (content, format) { + // Format is either 'gpx' or 'kml' + if (typeof content == 'string') { + content = ( new window.DOMParser() ).parseFromString(content, "text/xml"); + } + var geojson = toGeoJSON[format](content); + return this._loadGeoJSON(geojson); + } +}); + + +L.Control.FileLayerLoad = L.Control.extend({ + statics: { + TITLE: 'Load local file (GPX, KML, GeoJSON)', + LABEL: '⌅' + }, + options: { + position: 'topleft', + fitBounds: true, + layerOptions: {} + }, + + initialize: function (options) { + L.Util.setOptions(this, options); + this.loader = null; + }, + + onAdd: function (map) { + this.loader = new FileLoader(map, {layerOptions: this.options.layerOptions}); + + this.loader.on('data:loaded', function (e) { + // Fit bounds after loading + if (this.options.fitBounds) { + window.setTimeout(function () { + map.fitBounds(e.layer.getBounds()).zoomOut(); + }, 500); + } + }, this); + + // Initialize Drag-and-drop + this._initDragAndDrop(map); + + // Initialize map control + return this._initContainer(); + }, + + _initDragAndDrop: function (map) { + var fileLoader = this.loader, + dropbox = map._container; + + var callbacks = { + dragenter: function () { + map.scrollWheelZoom.disable(); + }, + dragleave: function () { + map.scrollWheelZoom.enable(); + }, + dragover: function (e) { + e.stopPropagation(); + e.preventDefault(); + }, + drop: function (e) { + e.stopPropagation(); + e.preventDefault(); + + var files = Array.prototype.slice.apply(e.dataTransfer.files), + i = files.length; + setTimeout(function(){ + fileLoader.load(files.shift()); + if (files.length > 0) { + setTimeout(arguments.callee, 25); + } + }, 25); + map.scrollWheelZoom.enable(); + } + }; + for (var name in callbacks) + dropbox.addEventListener(name, callbacks[name], false); + }, + + _initContainer: function () { + // Create an invisible file input + var fileInput = L.DomUtil.create('input', 'hidden', container); + fileInput.type = 'file'; + fileInput.accept = '.gpx,.kml,.geojson'; + fileInput.style.display = 'none'; + // Load on file change + var fileLoader = this.loader; + fileInput.addEventListener("change", function (e) { + fileLoader.load(this.files[0]); + }, false); + + // Create a button, and bind click on hidden file input + var zoomName = 'leaflet-control-filelayer leaflet-control-zoom', + barName = 'leaflet-bar', + partName = barName + '-part', + container = L.DomUtil.create('div', zoomName + ' ' + barName); + var link = L.DomUtil.create('a', zoomName + '-in ' + partName, container); + link.innerHTML = L.Control.FileLayerLoad.LABEL; + link.href = '#'; + link.title = L.Control.FileLayerLoad.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', function (e) { + fileInput.click(); + e.preventDefault(); + }); + return container; + } +}); + +L.Control.fileLayerLoad = function (options) { + return new L.Control.FileLayerLoad(options); +}; \ No newline at end of file diff --git a/external/togeojson.js b/external/togeojson.js new file mode 100755 index 00000000..cd980b92 --- /dev/null +++ b/external/togeojson.js @@ -0,0 +1,224 @@ +toGeoJSON = (function() { + 'use strict'; + + var removeSpace = (/\s*/g), + trimSpace = (/^\s*|\s*$/g), + splitSpace = (/\s+/); + // generate a short, numeric hash of a string + function okhash(x) { + if (!x || !x.length) return 0; + for (var i = 0, h = 0; i < x.length; i++) { + h = ((h << 5) - h) + x.charCodeAt(i) | 0; + } return h; + } + // all Y children of X + function get(x, y) { return x.getElementsByTagName(y); } + function attr(x, y) { return x.getAttribute(y); } + function attrf(x, y) { return parseFloat(attr(x, y)); } + // one Y child of X, if any, otherwise null + function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; } + // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize + function norm(el) { if (el.normalize) { el.normalize(); } return el; } + // cast array x into numbers + function numarray(x) { + for (var j = 0, o = []; j < x.length; j++) o[j] = parseFloat(x[j]); + return o; + } + function clean(x) { + var o = {}; + for (var i in x) if (x[i]) o[i] = x[i]; + return o; + } + // get the content of a text node, if any + function nodeVal(x) { if (x) {norm(x);} return x && x.firstChild && x.firstChild.nodeValue; } + // get one coordinate from a coordinate array, if any + function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); } + // get all coordinates from a coordinate array as [[],[]] + function coord(v) { + var coords = v.replace(trimSpace, '').split(splitSpace), + o = []; + for (var i = 0; i < coords.length; i++) { + o.push(coord1(coords[i])); + } + return o; + } + function coordPair(x) { return [attrf(x, 'lon'), attrf(x, 'lat')]; } + + // create a new feature collection parent object + function fc() { + return { + type: 'FeatureCollection', + features: [] + }; + } + + var serializer; + if (typeof XMLSerializer !== 'undefined') { + serializer = new XMLSerializer(); + } else if (typeof require !== 'undefined') { + serializer = new (require('xmldom').XMLSerializer)(); + } + function xml2str(str) { return serializer.serializeToString(str); } + + var t = { + kml: function(doc, o) { + o = o || {}; + + var gj = fc(), + // styleindex keeps track of hashed styles in order to match features + styleIndex = {}, + // atomic geospatial types supported by KML - MultiGeometry is + // handled separately + geotypes = ['Polygon', 'LineString', 'Point', 'Track'], + // all root placemarks in the file + placemarks = get(doc, 'Placemark'), + styles = get(doc, 'Style'); + + for (var k = 0; k < styles.length; k++) { + styleIndex['#' + attr(styles[k], 'id')] = okhash(xml2str(styles[k])).toString(16); + } + for (var j = 0; j < placemarks.length; j++) { + gj.features = gj.features.concat(getPlacemark(placemarks[j])); + } + function gxCoord(v) { return numarray(v.split(' ')); } + function gxCoords(root) { + var elems = get(root, 'coord', 'gx'), coords = []; + for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i]))); + return coords; + } + function getGeometry(root) { + var geomNode, geomNodes, i, j, k, geoms = []; + if (get1(root, 'MultiGeometry')) return getGeometry(get1(root, 'MultiGeometry')); + if (get1(root, 'MultiTrack')) return getGeometry(get1(root, 'MultiTrack')); + for (i = 0; i < geotypes.length; i++) { + geomNodes = get(root, geotypes[i]); + if (geomNodes) { + for (j = 0; j < geomNodes.length; j++) { + geomNode = geomNodes[j]; + if (geotypes[i] == 'Point') { + geoms.push({ + type: 'Point', + coordinates: coord1(nodeVal(get1(geomNode, 'coordinates'))) + }); + } else if (geotypes[i] == 'LineString') { + geoms.push({ + type: 'LineString', + coordinates: coord(nodeVal(get1(geomNode, 'coordinates'))) + }); + } else if (geotypes[i] == 'Polygon') { + var rings = get(geomNode, 'LinearRing'), + coords = []; + for (k = 0; k < rings.length; k++) { + coords.push(coord(nodeVal(get1(rings[k], 'coordinates')))); + } + geoms.push({ + type: 'Polygon', + coordinates: coords + }); + } else if (geotypes[i] == 'Track') { + geoms.push({ + type: 'LineString', + coordinates: gxCoords(geomNode) + }); + } + } + } + } + return geoms; + } + function getPlacemark(root) { + var geoms = getGeometry(root), i, properties = {}, + name = nodeVal(get1(root, 'name')), + styleUrl = nodeVal(get1(root, 'styleUrl')), + description = nodeVal(get1(root, 'description')), + extendedData = get1(root, 'ExtendedData'); + + if (!geoms.length) return []; + if (name) properties.name = name; + if (styleUrl && styleIndex[styleUrl]) { + properties.styleUrl = styleUrl; + properties.styleHash = styleIndex[styleUrl]; + } + if (description) properties.description = description; + if (extendedData) { + var datas = get(extendedData, 'Data'), + simpleDatas = get(extendedData, 'SimpleData'); + + for (i = 0; i < datas.length; i++) { + properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value')); + } + for (i = 0; i < simpleDatas.length; i++) { + properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]); + } + } + return [{ + type: 'Feature', + geometry: (geoms.length === 1) ? geoms[0] : { + type: 'GeometryCollection', + geometries: geoms + }, + properties: properties + }]; + } + return gj; + }, + gpx: function(doc, o) { + var i, + tracks = get(doc, 'trk'), + routes = get(doc, 'rte'), + waypoints = get(doc, 'wpt'), + // a feature collection + gj = fc(); + for (i = 0; i < tracks.length; i++) { + gj.features.push(getLinestring(tracks[i], 'trkpt')); + } + for (i = 0; i < routes.length; i++) { + gj.features.push(getLinestring(routes[i], 'rtept')); + } + for (i = 0; i < waypoints.length; i++) { + gj.features.push(getPoint(waypoints[i])); + } + function getLinestring(node, pointname) { + var j, pts = get(node, pointname), line = []; + for (j = 0; j < pts.length; j++) { + line.push(coordPair(pts[j])); + } + return { + type: 'Feature', + properties: getProperties(node), + geometry: { + type: 'LineString', + coordinates: line + } + }; + } + function getPoint(node) { + var prop = getProperties(node); + prop.ele = nodeVal(get1(node, 'ele')); + prop.sym = nodeVal(get1(node, 'sym')); + return { + type: 'Feature', + properties: prop, + geometry: { + type: 'Point', + coordinates: coordPair(node) + } + }; + } + function getProperties(node) { + var meta = ['name', 'desc', 'author', 'copyright', 'link', + 'time', 'keywords'], + prop = {}, + k; + for (k = 0; k < meta.length; k++) { + prop[meta[k]] = nodeVal(get1(node, meta[k])); + } + return clean(prop); + } + return gj; + } + }; + return t; +})(); + +if (typeof module !== 'undefined') module.exports = toGeoJSON; diff --git a/plugins/kml_plugin.user.js b/plugins/kml_plugin.user.js new file mode 100755 index 00000000..d87199a3 --- /dev/null +++ b/plugins/kml_plugin.user.js @@ -0,0 +1,62 @@ +// ==UserScript== +// @id overlay-kml@danielatkins +// @name IITC plugin: overlay KML +// @category Info +// @version 0.1.@@DATETIMEVERSION@@ +// @namespace https://github.com/jonatkins/ingress-intel-total-conversion +// @updateURL @@UPDATEURL@@ +// @downloadURL @@DOWNLOADURL@@ +// @description [@@BUILDNAME@@-@@BUILDDATE@@] Allows users to overlay their own KML / GPX files on top of IITC +// @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.overlayKML = function() {}; + +window.plugin.overlayKML.loadExternals = function() { + try { console.log('Loading leaflet.filelayer JS now'); } catch(e) {} + @@INCLUDERAW:external/leaflet.filelayer.js@@ + try { console.log('done loading leaflet.filelayer JS'); } catch(e) {} + + try { console.log('Loading KML JS now'); } catch(e) {} + @@INCLUDERAW:external/KML.js@@ + try { console.log('done loading KML JS'); } catch(e) {} + + try { console.log('Loading togeojson JS now'); } catch(e) {} + @@INCLUDERAW:external/togeojson.js@@ + try { console.log('done loading togeojson JS'); } catch(e) {} + + window.plugin.overlayKML.load(); +} + +// window.plugin.overlayKML.setupCallback = function() { +// $('#toolbox').append(' Overlay KML'); +// } + +window.plugin.overlayKML.load = function() { + // Provide popup window allow user to select KML to overlay +L.Control.FileLayerLoad.LABEL = 'O'; +L.Control.fileLayerLoad({ + fitBounds: true, + layerOptions: { + pointToLayer: function (data, latlng) { + return L.marker(latlng); + }}, +}).addTo(map); +} + +var setup = function() { + window.plugin.overlayKML.loadExternals(); +} + +// PLUGIN END ////////////////////////////////////////////////////////// + +@@PLUGINEND@@ \ No newline at end of file From 24eb531ef081af60776f567b3b32b352efe496fb Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Tue, 24 Sep 2013 13:45:07 +1000 Subject: [PATCH 004/126] Added KML plugin --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 509ecd94..adde0f02 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +Forked to test a plugin to add a KML overlay over the map, chosen by file + ingress intel total conversion (IITC) ===================================== From d008e37200f07d0ed220b7856acced38f6ef98c5 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Tue, 24 Sep 2013 14:29:58 +1000 Subject: [PATCH 005/126] Modified KML Plugin to work with points --- plugins/{kml_plugin.user.js => add-kml.user.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/{kml_plugin.user.js => add-kml.user.js} (100%) diff --git a/plugins/kml_plugin.user.js b/plugins/add-kml.user.js similarity index 100% rename from plugins/kml_plugin.user.js rename to plugins/add-kml.user.js From bac7ef7d2212eae1d2b43a3612fcbf87422f1938 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Tue, 24 Sep 2013 15:13:56 +1000 Subject: [PATCH 006/126] Shifted point anchors to be on top of portals --- plugins/add-kml.user.js | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/plugins/add-kml.user.js b/plugins/add-kml.user.js index d87199a3..5a24ea41 100755 --- a/plugins/add-kml.user.js +++ b/plugins/add-kml.user.js @@ -29,28 +29,34 @@ window.plugin.overlayKML.loadExternals = function() { try { console.log('Loading KML JS now'); } catch(e) {} @@INCLUDERAW:external/KML.js@@ try { console.log('done loading KML JS'); } catch(e) {} - + try { console.log('Loading togeojson JS now'); } catch(e) {} @@INCLUDERAW:external/togeojson.js@@ try { console.log('done loading togeojson JS'); } catch(e) {} window.plugin.overlayKML.load(); } - -// window.plugin.overlayKML.setupCallback = function() { -// $('#toolbox').append(' Overlay KML'); -// } window.plugin.overlayKML.load = function() { // Provide popup window allow user to select KML to overlay -L.Control.FileLayerLoad.LABEL = 'O'; -L.Control.fileLayerLoad({ - fitBounds: true, - layerOptions: { - pointToLayer: function (data, latlng) { - return L.marker(latlng); - }}, -}).addTo(map); + + L.Icon.Default.imagePath = '@@INCLUDEIMAGE:images/marker-icon.png@@'; + var KMLIcon = L.icon({ + iconUrl: '@@INCLUDEIMAGE:images/marker-icon.png@@', + + iconSize: [16, 24], // size of the icon + iconAnchor: [8, 24], // point of the icon which will correspond to marker's location + popupAnchor: [-3, 16] // point from which the popup should open relative to the iconAnchor + }); + + L.Control.FileLayerLoad.LABEL = 'O'; + L.Control.fileLayerLoad({ + fitBounds: true, + layerOptions: { + pointToLayer: function (data, latlng) { + return L.marker(latlng, {icon: KMLIcon}); + }}, + }).addTo(map); } var setup = function() { @@ -59,4 +65,4 @@ var setup = function() { // PLUGIN END ////////////////////////////////////////////////////////// -@@PLUGINEND@@ \ No newline at end of file +@@PLUGINEND@@ From 841497f53b44c1957cc788611762367501c2c4a3 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Tue, 24 Sep 2013 15:36:08 +1000 Subject: [PATCH 007/126] Added folder icon for opening KML files --- images/open-folder-icon_sml.png | Bin 0 -> 345 bytes plugins/add-kml.user.js | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 images/open-folder-icon_sml.png diff --git a/images/open-folder-icon_sml.png b/images/open-folder-icon_sml.png new file mode 100644 index 0000000000000000000000000000000000000000..afeda49e6c66e8f5a643ab7c8aed41ed8214a2e7 GIT binary patch literal 345 zcmeAS@N?(olHy`uVBq!ia0vp^5| zgW!U_%O?XxI14-?iy0WWg+Z8+Vb&aw0qiB7zOL+dIVD&{C2rhi`3V%d>FMGaVsZNF z6@RZLM~UMf{gYVM-qGBWAl!}Y`p5Tu#q)Dp43DY^ z1;nYAd=xECQ+#!$H26zXXo+r&>XJQe(Kg2!-miEdxZj##+QV}^*9{K{@E^4E&Y1VF zDljZ6q2-y}uFc}iHSK?vW_6ucI&f5uLHW-ShU5_Eg+X5eStJ&0JZg}8DSP7MPZyfa l4huiyym Date: Tue, 24 Sep 2013 22:23:43 +1000 Subject: [PATCH 008/126] Replaced folder icon with 'O' --- plugins/add-kml.user.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/add-kml.user.js b/plugins/add-kml.user.js index dc7ff2e3..98784036 100755 --- a/plugins/add-kml.user.js +++ b/plugins/add-kml.user.js @@ -49,8 +49,10 @@ window.plugin.overlayKML.load = function() { popupAnchor: [-3, 16] // point from which the popup should open relative to the iconAnchor }); - L.Control.FileLayerLoad.LABEL = 'Open'; - L.Control.fileLayerLoad({ +// Implementing a folder icon instead of default 'O' icon to open KML. Not yet useable +// L.Control.FileLayerLoad.LABEL = 'Open'; +L.Control.FileLayerLoad.LABEL = 'O'; +L.Control.fileLayerLoad({ fitBounds: true, layerOptions: { pointToLayer: function (data, latlng) { From 39ea0a4a854a3492cf6c08c965970bbbe81c9ea5 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Tue, 24 Sep 2013 23:10:49 +1000 Subject: [PATCH 009/126] Added clickable folder icon --- plugins/add-kml.user.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/plugins/add-kml.user.js b/plugins/add-kml.user.js index 98784036..3a549f92 100755 --- a/plugins/add-kml.user.js +++ b/plugins/add-kml.user.js @@ -42,17 +42,15 @@ window.plugin.overlayKML.load = function() { L.Icon.Default.imagePath = '@@INCLUDEIMAGE:images/marker-icon.png@@'; var KMLIcon = L.icon({ - iconUrl: '@@INCLUDEIMAGE:images/marker-icon.png@@';, + iconUrl: '@@INCLUDEIMAGE:images/marker-icon.png@@', iconSize: [16, 24], // size of the icon iconAnchor: [16, 8], // point of the icon which will correspond to marker's location popupAnchor: [-3, 16] // point from which the popup should open relative to the iconAnchor }); -// Implementing a folder icon instead of default 'O' icon to open KML. Not yet useable -// L.Control.FileLayerLoad.LABEL = 'Open'; -L.Control.FileLayerLoad.LABEL = 'O'; -L.Control.fileLayerLoad({ + L.Control.FileLayerLoad.LABEL = 'Open'; + L.Control.fileLayerLoad({ fitBounds: true, layerOptions: { pointToLayer: function (data, latlng) { From 773c7d4a6fcc0b2d18dbbcc5ece5020e197ed514 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Tue, 24 Sep 2013 23:36:17 +1000 Subject: [PATCH 010/126] Updated README.md file --- README.md | 53 ++++------------------------------------- plugins/add-kml.user.js | 2 +- 2 files changed, 6 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index adde0f02..0fd79e86 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,7 @@ -Forked to test a plugin to add a KML overlay over the map, chosen by file +Forked to test a plugin to add a KML, GPX or GeoJSON overlay over the map, chosen by file. -ingress intel total conversion (IITC) -===================================== +Run the ```build.py local``` script to build the code, as per jonatkins' fork. -Since the [breunigs](https://github.com/breunigs/ingress-intel-total-conversion) IITC branch was deleted, -I've created this one to continue some development. - -## Users - -Just want to download/install IITC? Go to http://iitc.jonatkins.com/ - -For keeping up with the latest news, release announcements, etc, Follow IITC on G+ -https://plus.google.com/105383756361375410867/posts - -If you have questions, need help or advice with IITC, the Google+ community is a good place to start. -https://plus.google.com/communities/105647403088015055797 - -Want to report a bug? Post it to the issues page -https://github.com/jonatkins/ingress-intel-total-conversion/issues - -## Developers - -This Github page is for those interested in developing IITC further. - -### Quickstart - -To build the browser scripts from source you will need Python (either a late version 2.x, or 3.0+). It should -build correctly on Linux and Windows (and, probably, Macs, FreeBSD, etc) - -Fork this project, clone to your local machine. - -Run the ```build.py local``` script to build the code. - -If all goes well, output of the build will end up in ```build/local``` subfolder. - -You can create a custom build settings file, ```localbuildsettings.py``` - look in the supplied -```buildsettings.py``` for details. - -#### Mobile - -To build the mobile app, along with python, you will need - -- The Java JDK (development kit - the runtime JRE is not enough) -- The Android SDK - -Run ``build.py mobile``` to build IITC Mobile in debug mode. - -Note that part of the build.py process includes copying the IITC script files into the ```mobile/res``` subfolder. -If this isn't done (e.g. you build IITC Mobile directly from Eclipse) you will end up with a broken build. +#Instructions +If you just want to download the plugin to try it out: http://goo.gl/h0GmoT +(Note: you have to download a new version of the original IITC script, there are some updated things in there) diff --git a/plugins/add-kml.user.js b/plugins/add-kml.user.js index 3a549f92..45c4ce2c 100755 --- a/plugins/add-kml.user.js +++ b/plugins/add-kml.user.js @@ -45,7 +45,7 @@ window.plugin.overlayKML.load = function() { iconUrl: '@@INCLUDEIMAGE:images/marker-icon.png@@', iconSize: [16, 24], // size of the icon - iconAnchor: [16, 8], // point of the icon which will correspond to marker's location + iconAnchor: [8, 24], // point of the icon which will correspond to marker's location popupAnchor: [-3, 16] // point from which the popup should open relative to the iconAnchor }); From 0a4ad93472cce79e6def87f0f3460ad152a44371 Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Wed, 25 Sep 2013 02:40:46 +1000 Subject: [PATCH 011/126] reverted README changes --- README.md | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0fd79e86..509ecd94 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,48 @@ -Forked to test a plugin to add a KML, GPX or GeoJSON overlay over the map, chosen by file. +ingress intel total conversion (IITC) +===================================== -Run the ```build.py local``` script to build the code, as per jonatkins' fork. +Since the [breunigs](https://github.com/breunigs/ingress-intel-total-conversion) IITC branch was deleted, +I've created this one to continue some development. -#Instructions -If you just want to download the plugin to try it out: http://goo.gl/h0GmoT -(Note: you have to download a new version of the original IITC script, there are some updated things in there) +## Users + +Just want to download/install IITC? Go to http://iitc.jonatkins.com/ + +For keeping up with the latest news, release announcements, etc, Follow IITC on G+ +https://plus.google.com/105383756361375410867/posts + +If you have questions, need help or advice with IITC, the Google+ community is a good place to start. +https://plus.google.com/communities/105647403088015055797 + +Want to report a bug? Post it to the issues page +https://github.com/jonatkins/ingress-intel-total-conversion/issues + +## Developers + +This Github page is for those interested in developing IITC further. + +### Quickstart + +To build the browser scripts from source you will need Python (either a late version 2.x, or 3.0+). It should +build correctly on Linux and Windows (and, probably, Macs, FreeBSD, etc) + +Fork this project, clone to your local machine. + +Run the ```build.py local``` script to build the code. + +If all goes well, output of the build will end up in ```build/local``` subfolder. + +You can create a custom build settings file, ```localbuildsettings.py``` - look in the supplied +```buildsettings.py``` for details. + +#### Mobile + +To build the mobile app, along with python, you will need + +- The Java JDK (development kit - the runtime JRE is not enough) +- The Android SDK + +Run ``build.py mobile``` to build IITC Mobile in debug mode. + +Note that part of the build.py process includes copying the IITC script files into the ```mobile/res``` subfolder. +If this isn't done (e.g. you build IITC Mobile directly from Eclipse) you will end up with a broken build. From c2912d97679ededdc5a350269b9716b46e41c4bf Mon Sep 17 00:00:00 2001 From: Nihal Mirpuri Date: Wed, 25 Sep 2013 02:46:03 +1000 Subject: [PATCH 012/126] Added attributions for KML files --- ATTRIBUTION.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md index 81723e1f..edb3f828 100644 --- a/ATTRIBUTION.md +++ b/ATTRIBUTION.md @@ -10,5 +10,8 @@ This project is licensed under the permissive [ISC license](http://www.isc.org/d - [taphold.js by Rich Adams; unknown](https://github.com/richadams/jquery-taphold) - [L.Control.Pan.js by Kartena AB; same as Leaflet](https://github.com/kartena/Leaflet.Pancontrol) - [L.Control.Zoomslider.js by Kartena AB; same as Leaflet](https://github.com/kartena/Leaflet.zoomslider) +- [KML.js by shramov; same as Leaflet](https://github.com/shramov/leaflet-plugins) +- [leaflet.filelayer.js by shramov; same as Leaflet](https://github.com/shramov/leaflet-plugins) +- [togeojson.js by shramov; same as Leaflet](https://github.com/shramov/leaflet-plugins) - StackOverflow-CopyPasta is attributed in the source; [CC-Wiki](https://creativecommons.org/licenses/by-sa/3.0/) - all Ingress/Niantic related stuff obviously remains non-free and is still copyrighted by Niantic/Google From 12f8c89fb444df0903d27623f9400919978e7cb5 Mon Sep 17 00:00:00 2001 From: Peter Sorger Date: Wed, 25 Sep 2013 10:20:28 +0200 Subject: [PATCH 013/126] Added Mitigation column Added mitigation column to portals list --- plugins/portals-list.user.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/portals-list.user.js b/plugins/portals-list.user.js index 84dfa1a1..089e0966 100644 --- a/plugins/portals-list.user.js +++ b/plugins/portals-list.user.js @@ -301,6 +301,7 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { + 'M2' + 'M3' + 'M4' + + 'Mit.' + 'AP Gain' + 'E/AP' + 'Age'; @@ -314,6 +315,9 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { + '' + portal.level + '' + '' + portal.team + ''; + var mitigationDetails = getPortalMitigationDetails(portal.portal); + portal.mitigation = mitigationDetails.total + mitigationDetails.excess; + var title; var percent; $.each([0, 1, 2, 3 ,4 ,5 ,6 ,7], function(ind, slot) { @@ -333,6 +337,7 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { + '' + portal.mods[1][2] + '' + '' + portal.mods[2][2] + '' + '' + portal.mods[3][2] + '' + + '' + portal.mitigation + '' + '' + portal.APgain + '' + '' + portal.EAP + '' + '' + portal.age_string_short + ''; From 1e3efd7d3b48c268bd6f4ec58d89a06ce0e044e5 Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Sun, 29 Sep 2013 00:38:38 +0200 Subject: [PATCH 014/126] bugfix: run setLoadingState on UI thread in CheckHttpResponse --- .../com/cradle/iitc_mobile/async/CheckHttpResponse.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mobile/src/com/cradle/iitc_mobile/async/CheckHttpResponse.java b/mobile/src/com/cradle/iitc_mobile/async/CheckHttpResponse.java index 431dee3c..057b0c74 100644 --- a/mobile/src/com/cradle/iitc_mobile/async/CheckHttpResponse.java +++ b/mobile/src/com/cradle/iitc_mobile/async/CheckHttpResponse.java @@ -43,7 +43,13 @@ public class CheckHttpResponse extends AsyncTask { int code = response.getStatusLine().getStatusCode(); if (code != HttpStatus.SC_OK) { Log.d("iitcm", "received error code: " + code); - ((IITC_Mobile) mContext).setLoadingState(false); + final IITC_Mobile iitc = (IITC_Mobile) mContext; + iitc.runOnUiThread(new Runnable() { + @Override + public void run() { + iitc.setLoadingState(false); + } + }); // TODO: remove when google login issue is fixed if (urls[0].contains("uberauth=WILL_NOT_SIGN_IN")) { return true; From 3ac2490c0c84a576567309e7eb93e6b19da1ab73 Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Sun, 29 Sep 2013 00:59:02 +0200 Subject: [PATCH 015/126] added status bar tap to the info-screen hint --- mobile/res/values/strings.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mobile/res/values/strings.xml b/mobile/res/values/strings.xml index 8699ebec..6c810a6f 100644 --- a/mobile/res/values/strings.xml +++ b/mobile/res/values/strings.xml @@ -63,7 +63,9 @@ to evoke the Layer Drawer]]> - +
+ • tap and hold a portal for a second
+ • tap on the left half of the status bar]]>
UI @@ -109,4 +111,4 @@ Base Layer Overlay Layers - \ No newline at end of file + From fe1d7fb3370f6d631c9edce00cc177893d39df61 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Sun, 29 Sep 2013 00:11:48 +0100 Subject: [PATCH 016/126] draw-tools: update edit colour to match that used while drawing - with only dashed lines being used as in stock Leaflet.Draw --- plugins/draw-tools.user.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/plugins/draw-tools.user.js b/plugins/draw-tools.user.js index a9ee160d..335825f3 100644 --- a/plugins/draw-tools.user.js +++ b/plugins/draw-tools.user.js @@ -33,6 +33,7 @@ window.plugin.drawTools.loadExternals = function() { } window.plugin.drawTools.setOptions = function() { + window.plugin.drawTools.lineOptions = { stroke: true, color: '#a24ac3', @@ -42,16 +43,15 @@ window.plugin.drawTools.setOptions = function() { clickable: true }; - window.plugin.drawTools.polygonOptions = { - stroke: true, - color: '#a24ac3', - weight: 4, - opacity: 0.5, + window.plugin.drawTools.polygonOptions = L.extend({}, window.plugin.drawTools.lineOptions, { fill: true, - fillColor: null, - fillOpacity: 0.2, - clickable: true - }; + fillColor: null, // to use the same as 'color' for fill + fillOpacity: 0.2 + }); + + window.plugin.drawTools.editOptions = L.extend({}, window.plugin.drawTools.polygonOptions, { + dashArray: [10,10] + }); window.plugin.drawTools.markerOptions = { icon: new L.Icon.Default(), @@ -113,7 +113,8 @@ window.plugin.drawTools.addDrawControl = function() { featureGroup: window.plugin.drawTools.drawnItems, edit: { - title: 'Edit drawn items' + title: 'Edit drawn items', + selectedPathOptions: window.plugin.drawTools.editOptions, }, remove: { From c82cd1464151c58ffe3c0474d9fd091e3ce983a9 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Mon, 30 Sep 2013 22:43:35 +0100 Subject: [PATCH 017/126] first attempt at updating munge parameters for new niantic intel site update have commented out old munges for now - they don't include parameters needed in some new requests, so are unlikely to be used again for #589 --- code/utils_misc.js | 181 +++++++++++++++++++++++++++------------------ 1 file changed, 108 insertions(+), 73 deletions(-) diff --git a/code/utils_misc.js b/code/utils_misc.js index e559a974..f2d7e4bd 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -96,82 +96,116 @@ window.digits = function(d) { window.requestParameterMunges = [ +// set 0 and 1 were brought online at the same time - an attempt to confuse us, or others hacking on the web interface? // set 0 - { - method: '4kr3ofeptwgary2j', - boundsParamsList: 'n27qzc8389kgakyv', - id: '39031qie1i4aq563', - minLatE6: 'pg98bwox95ly0ouu', - minLngE6: 'eib1bkq8znpwr0g7', - maxLatE6: 'ilfap961rwdybv63', - maxLngE6: 'lpf7m1ifx0ieouzq', - timestampMs: '2ewujgywmum1yp49', - qk: 'bgxibcomzoto63sn', - desiredNumItems: 'tmb0vgxgp5grsnhp', - minTimestampMs: 'hljqffkpwlx0vtjt', - maxTimestampMs: 'sw317giy6x2xj9zm', - guids: 'pusjrhxxtyp5nois', - inviteeEmailAddress: 'cltkepgqkepfsyaq', - message: 'q0d6n7t1801bb6xu', - latE6: '5ygbhpxfnt1u9e4t', - lngE6: 'ak6twnljwwcgd7cj', - factionOnly: '0dvtbatgzcfccchh', - ascendingTimestampOrder: 'f6u1iqep9s2lc5y5' - }, +// { +// method: '4kr3ofeptwgary2j', +// boundsParamsList: 'n27qzc8389kgakyv', +// id: '39031qie1i4aq563', +// minLatE6: 'pg98bwox95ly0ouu', +// minLngE6: 'eib1bkq8znpwr0g7', +// maxLatE6: 'ilfap961rwdybv63', +// maxLngE6: 'lpf7m1ifx0ieouzq', +// timestampMs: '2ewujgywmum1yp49', +// qk: 'bgxibcomzoto63sn', +// desiredNumItems: 'tmb0vgxgp5grsnhp', +// minTimestampMs: 'hljqffkpwlx0vtjt', +// maxTimestampMs: 'sw317giy6x2xj9zm', +// guids: 'pusjrhxxtyp5nois', +// inviteeEmailAddress: 'cltkepgqkepfsyaq', +// message: 'q0d6n7t1801bb6xu', +// latE6: '5ygbhpxfnt1u9e4t', +// lngE6: 'ak6twnljwwcgd7cj', +// factionOnly: '0dvtbatgzcfccchh', +// ascendingTimestampOrder: 'f6u1iqep9s2lc5y5' +// }, // set 1 - { - method: 'uuo2zqhhy5bw80fu', - boundsParamsList: '5rc0561uauf6x13u', - id: 'bzeizowtguoyrrtt', - minLatE6: '7qej3eqg4sefuaac', - minLngE6: 'yqegc976egk5q9vo', - maxLatE6: '2odsgh99ix9bbtsb', - maxLngE6: 'g9jess8dwa2j8pwi', - timestampMs: '604f34zcu9zna0a5', - qk: 'y853tux9h7cb6xp3', - desiredNumItems: 'sfv5i7l6ouljz8vf', - minTimestampMs: 'y3g07dbnw6sklloj', - maxTimestampMs: '3pdl28aa27xvyhke', - guids: 'xp1pl2jm5hrh3bna', - inviteeEmailAddress: '2pyrttrp3gh38mmu', - message: 'zz54435vfc57nlg9', - latE6: 'cyltxjod3jhxgj8q', - lngE6: 'h9whcgcz6kpqkz80', - factionOnly: '37okcr7gvd5yn2lj', - ascendingTimestampOrder: 'iimftkq7flskwrx9' - }, +// { +// method: 'uuo2zqhhy5bw80fu', +// boundsParamsList: '5rc0561uauf6x13u', +// id: 'bzeizowtguoyrrtt', +// minLatE6: '7qej3eqg4sefuaac', +// minLngE6: 'yqegc976egk5q9vo', +// maxLatE6: '2odsgh99ix9bbtsb', +// maxLngE6: 'g9jess8dwa2j8pwi', +// timestampMs: '604f34zcu9zna0a5', +// qk: 'y853tux9h7cb6xp3', +// desiredNumItems: 'sfv5i7l6ouljz8vf', +// minTimestampMs: 'y3g07dbnw6sklloj', +// maxTimestampMs: '3pdl28aa27xvyhke', +// guids: 'xp1pl2jm5hrh3bna', +// inviteeEmailAddress: '2pyrttrp3gh38mmu', +// message: 'zz54435vfc57nlg9', +// latE6: 'cyltxjod3jhxgj8q', +// lngE6: 'h9whcgcz6kpqkz80', +// factionOnly: '37okcr7gvd5yn2lj', +// ascendingTimestampOrder: 'iimftkq7flskwrx9' +// }, // set 2 - first seen 2013-09-12 21:30 - { - method: '42suxeca8ttud7je', - boundsParamsList: '5uwd21hkedg3zh2c', - id: 'drtt302ebaj6ek2g', - minLatE6: 'l933r0l8brrt1x5b', - minLngE6: 'qg3xb340zed41jof', - maxLatE6: 'sw485z1n3tusdkul', - maxLngE6: '6meahm3f9xup9krb', - timestampMs: '6meahm3f9xup9krb', - qk: 'fpi9b1z0os0x9yjj', - desiredNumItems: 'inr3js77cetyibi6', - minTimestampMs: 'zfb2e5iqmggrxe98', - maxTimestampMs: '8c4imy17gfpfrl9l', - guids: '5d5hp2p3rkmanqn7', - inviteeEmailAddress: 'i1a5yp6p1l6iqk08', - message: 'xzhbk3ri04lx9xvj', - latE6: 'njg0zny4fb39mf0a', - lngE6: 'ti2rx4ltmg6d1zsr', - factionOnly: 'jegpo8rwhtuuuuhh', - ascendingTimestampOrder: '1ennke6gykwzziun', - // in this set, also the request method names are obsfucated! - 'dashboard.getThinnedEntitiesV4': 'ufxcmvve3eirsf2b', - 'dashboard.getPaginatedPlextsV2': 'd9dgziiw8vzhyecv', - 'dashboard.getPlayersByGuids': 's53izqpxedtd0hv8', - 'dashboard.sendInviteEmail': 'kn9plnbree2aeuh9', - 'dashboard.redeemReward': 'les8vribyxb899wd', - 'dashboard.sendPlext': '9u1ukkkx1euxf02a' - }, + // (very briefly - and removed a few hours later) +// { +// method: '42suxeca8ttud7je', +// boundsParamsList: '5uwd21hkedg3zh2c', +// id: 'drtt302ebaj6ek2g', +// minLatE6: 'l933r0l8brrt1x5b', +// minLngE6: 'qg3xb340zed41jof', +// maxLatE6: 'sw485z1n3tusdkul', +// maxLngE6: '6meahm3f9xup9krb', +// timestampMs: '6meahm3f9xup9krb', +// qk: 'fpi9b1z0os0x9yjj', +// desiredNumItems: 'inr3js77cetyibi6', +// minTimestampMs: 'zfb2e5iqmggrxe98', +// maxTimestampMs: '8c4imy17gfpfrl9l', +// guids: '5d5hp2p3rkmanqn7', +// inviteeEmailAddress: 'i1a5yp6p1l6iqk08', +// message: 'xzhbk3ri04lx9xvj', +// latE6: 'njg0zny4fb39mf0a', +// lngE6: 'ti2rx4ltmg6d1zsr', +// factionOnly: 'jegpo8rwhtuuuuhh', +// ascendingTimestampOrder: '1ennke6gykwzziun', +// // in this set, also the request method names are obsfucated! +// 'dashboard.getThinnedEntitiesV4': 'ufxcmvve3eirsf2b', +// 'dashboard.getPaginatedPlextsV2': 'd9dgziiw8vzhyecv', +// 'dashboard.getPlayersByGuids': 's53izqpxedtd0hv8', +// 'dashboard.sendInviteEmail': 'kn9plnbree2aeuh9', +// 'dashboard.redeemReward': 'les8vribyxb899wd', +// 'dashboard.sendPlext': '9u1ukkkx1euxf02a' +// }, + // set 3 - in the update of 2013-09-30 (addition of 'alerts' chat tab) + { + method: '22ux2z96jwq5zn78', + version: 'kf6hgl9yau03ws0o', //guessed parameter name - only seen munged + boundsParamsList: '29t16cmsn6l3r2xg', + id: '7rogqhp5pzcqobcw', + minLatE6: 'yzbnp7z9bd28p0yr', + minLngE6: '2pdhntvo85cd90bw', + maxLatE6: 'c4ivr013h4dr68pd', + maxLngE6: '4p8oorcrwalc1mzf', + timestampMs: 'vd2rsa9v6f8q606s', + qk: 'cblh9xe0bgwjy5ij', + desiredNumItems: '3ymaq7slb165porj', + minTimestampMs: 's9jf2seni33y3gyu', + maxTimestampMs: '2kh3vti98rhp3g29', + chatTab: '7n7ocqfq1p18352b', //guessed parameter name - only seen munged + guids: '5hyiwhwc0jyljvro', + inviteeEmailAddress: 's9z6zt03eymzxhkj', + message: 'e8qm0kptw2trrcrw', + latE6: 'fja1phtsqxm71dqm', + lngE6: 'iut1tb7c0x726hwn', + factionOnly: 'p88a2ztchtjhiazl', + ascendingTimestampOrder: 'p88a2ztchtjhiazl', + // in this set, also the request method names are obsfucated! + 'dashboard.getGameScore': 'fhlzntzkl5v7hcfh', // GET_GAME_SCORE + 'dashboard.getPaginatedPlextsV2': 'wzuitnswoda7w028', // GET_PAGINATED_PLEXTS + 'dashboard.getThinnedEntitiesV4': 'scgrm4lf2371esgw', // GET_THINNED_ENTITIES + 'dashboard.getPlayersByGuids': '81l6usczczoi3lfi', // LOOKUP_PLAYERS + 'dashboard.redeemReward': '8kop2koeld9b4c26', // REDEEM_REWARD + 'dashboard.sendInviteEmail': 't0ccodsm1nuo5uso', // SEND_INVITE_EMAIL + 'dashboard.sendPlext': 'k04cfjwwsg3h3827' // SEND_PLEXT + }, ]; window.activeRequestMungeSet = undefined; @@ -179,10 +213,10 @@ window.activeRequestMungeSet = undefined; window.detectActiveMungeSet = function() { for (var m in window) { // try and find the stock page functions - if (typeof window[m] == 'function' && m.length <= 3) { + if (typeof window[m] == 'function') { var stockFunc = window[m].toString(); for (var i in window.requestParameterMunges) { - if (stockFunc.indexOf (window.requestParameterMunges[i]['id']) >= 0) { + if (stockFunc.indexOf (window.requestParameterMunges[i]['method']) >= 0) { console.log('IITC: found request munge set '+i+' in stock intel function "window.'+m+'()"'); window.activeRequestMungeSet = i; } @@ -248,9 +282,10 @@ window.postAjax = function(action, data, success, error) { var activeMunge = window.requestParameterMunges[window.activeRequestMungeSet]; var methodName = 'dashboard.'+action; + var versionStr = "4608f4356a6f55690f127fb542f557f98de66169"; // unsure of parameter value meaning. appears to be a constant used as a 'version'. added to all requests along with the method name in the stock site // optional munging of the method name - seen in Set 2 (onwards?) if (methodName in activeMunge) methodName = activeMunge[methodName]; - var post_data = JSON.stringify(window.requestDataMunge($.extend({method: methodName}, data))); + var post_data = JSON.stringify(window.requestDataMunge($.extend({method: methodName, version: versionStr}, data))); var remove = function(data, textStatus, jqXHR) { window.requests.remove(jqXHR); }; var errCnt = function(jqXHR) { window.failedRequestCount++; window.requests.remove(jqXHR); }; var result = $.ajax({ From 4c2bb5ecfab3ed829d2d814649087bacc2131514 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Mon, 30 Sep 2013 22:51:06 +0100 Subject: [PATCH 018/126] quick fix for chat, for protocol changes for #589 --- code/chat.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/chat.js b/code/chat.js index 747e23b9..f6749a71 100644 --- a/code/chat.js +++ b/code/chat.js @@ -81,7 +81,8 @@ window.chat.genPostData = function(isFaction, storageHash, getOlderMsgs) { maxLngE6: Math.round(ne.lng*1E6), minTimestampMs: -1, maxTimestampMs: -1, - factionOnly: isFaction + factionOnly: isFaction, + chatTab: isFaction ? 'faction' : 'all' } if(getOlderMsgs) { @@ -689,7 +690,8 @@ window.chat.postMsg = function() { var data = {message: msg, latE6: Math.round(latlng.lat*1E6), lngE6: Math.round(latlng.lng*1E6), - factionOnly: !publik}; + factionOnly: !publik, + chatTab: publik ? 'all' : 'faction'}; var errMsg = 'Your message could not be delivered. You can copy&' + 'paste it here and try again if you want:\n\n' + msg; From 8cc246c5f73ba9112ba8ff8888044dd0049440d5 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Mon, 30 Sep 2013 23:13:53 +0100 Subject: [PATCH 019/126] remove old factionOnly flag from chat requests. although the stock site appears to send it still at first glance of the code, this appears to be incorrect - and sending it causes old messages to come first rather than new ones! (perhaps i've mis-identified the flag - and it's the one for getting older messages first?) for #589 --- code/chat.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/code/chat.js b/code/chat.js index f6749a71..ad1032ce 100644 --- a/code/chat.js +++ b/code/chat.js @@ -81,7 +81,6 @@ window.chat.genPostData = function(isFaction, storageHash, getOlderMsgs) { maxLngE6: Math.round(ne.lng*1E6), minTimestampMs: -1, maxTimestampMs: -1, - factionOnly: isFaction, chatTab: isFaction ? 'faction' : 'all' } @@ -690,7 +689,6 @@ window.chat.postMsg = function() { var data = {message: msg, latE6: Math.round(latlng.lat*1E6), lngE6: Math.round(latlng.lng*1E6), - factionOnly: !publik, chatTab: publik ? 'all' : 'faction'}; var errMsg = 'Your message could not be delivered. You can copy&' + From 690b5d7e62283a58a11217dec7494bc38d39f828 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Mon, 30 Sep 2013 23:23:13 +0100 Subject: [PATCH 020/126] factionOnly was not correct - had mis-entered this mapping (and was already there for ascendingTimestampOrder - it's real meaning) --- code/utils_misc.js | 1 - 1 file changed, 1 deletion(-) diff --git a/code/utils_misc.js b/code/utils_misc.js index f2d7e4bd..d2a5a807 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -195,7 +195,6 @@ window.requestParameterMunges = [ message: 'e8qm0kptw2trrcrw', latE6: 'fja1phtsqxm71dqm', lngE6: 'iut1tb7c0x726hwn', - factionOnly: 'p88a2ztchtjhiazl', ascendingTimestampOrder: 'p88a2ztchtjhiazl', // in this set, also the request method names are obsfucated! 'dashboard.getGameScore': 'fhlzntzkl5v7hcfh', // GET_GAME_SCORE From 44dabe145d56d9c6e14db3908b4cc57e21fbc81e Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Mon, 30 Sep 2013 23:23:58 +0100 Subject: [PATCH 021/126] reduce faction messages to 50 at a time - as they're no longer cluttered with user-specific alerts (these now appear in a separate 'alerts' tab on the stock site - yet to be implemented in IITC) --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index 15169627..bf304d6d 100644 --- a/main.js +++ b/main.js @@ -137,7 +137,7 @@ window.VIEWPORT_PAD_RATIO = 0.3; // how many items to request each query window.CHAT_PUBLIC_ITEMS = 200; -window.CHAT_FACTION_ITEMS = 100; +window.CHAT_FACTION_ITEMS = 50; // how many pixels to the top before requesting new data window.CHAT_REQUEST_SCROLL_TOP = 200; window.CHAT_SHRINKED = 60; From 35e6921e1891327da0c73e819698c0d108bbf365 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Tue, 1 Oct 2013 00:25:56 +0100 Subject: [PATCH 022/126] website - remove old URL from commented out 'IITC broken' section --- website/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/index.php b/website/index.php index 8ac2c4c9..2d01c87b 100644 --- a/website/index.php +++ b/website/index.php @@ -71,7 +71,7 @@ if ( file_exists ( 'tracking.php' ) ) From 80157b98759246c562ea6bfbad3355120b240d9c Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Tue, 1 Oct 2013 01:02:08 +0100 Subject: [PATCH 023/126] another mungs set was pushed live. update the code also reordered munge list to match the order found in the stock page (makes it easier to update) and tweaked the code that detects and auto-tries munge sets --- code/game_status.js | 4 +- code/utils_misc.js | 167 ++++++++++++++++++-------------------------- 2 files changed, 69 insertions(+), 102 deletions(-) diff --git a/code/game_status.js b/code/game_status.js index 87e17e5c..5ae4bfa1 100644 --- a/code/game_status.js +++ b/code/game_status.js @@ -15,9 +15,9 @@ window.updateGameScore = function(data) { // detecting which munge set should be used is tricky - even the stock site gets it wrong sometimes // to detect the problem and try a different set is easiest in a place where there's only a single request of that type // sent at once, and it has no extra parameters. this method matches those requirements - if (data == '{"error": "invalid method params"}' || data.error) { + if (data.error || (data.indexOf && data.indexOf('"error"') != -1)) { window.window.updateGameScoreFailCount++; - if (window.window.updateGameScoreFailCount < 5) { + if (window.window.updateGameScoreFailCount <= window.requestParameterMunges.length) { window.activeRequestMungeSet = (window.activeRequestMungeSet+1) % window.requestParameterMunges.length; console.warn('IITC munge issue - cycling to set '+window.activeRequestMungeSet); diff --git a/code/utils_misc.js b/code/utils_misc.js index d2a5a807..1da80f29 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -96,88 +96,22 @@ window.digits = function(d) { window.requestParameterMunges = [ -// set 0 and 1 were brought online at the same time - an attempt to confuse us, or others hacking on the web interface? - // set 0 -// { -// method: '4kr3ofeptwgary2j', -// boundsParamsList: 'n27qzc8389kgakyv', -// id: '39031qie1i4aq563', -// minLatE6: 'pg98bwox95ly0ouu', -// minLngE6: 'eib1bkq8znpwr0g7', -// maxLatE6: 'ilfap961rwdybv63', -// maxLngE6: 'lpf7m1ifx0ieouzq', -// timestampMs: '2ewujgywmum1yp49', -// qk: 'bgxibcomzoto63sn', -// desiredNumItems: 'tmb0vgxgp5grsnhp', -// minTimestampMs: 'hljqffkpwlx0vtjt', -// maxTimestampMs: 'sw317giy6x2xj9zm', -// guids: 'pusjrhxxtyp5nois', -// inviteeEmailAddress: 'cltkepgqkepfsyaq', -// message: 'q0d6n7t1801bb6xu', -// latE6: '5ygbhpxfnt1u9e4t', -// lngE6: 'ak6twnljwwcgd7cj', -// factionOnly: '0dvtbatgzcfccchh', -// ascendingTimestampOrder: 'f6u1iqep9s2lc5y5' -// }, + // now obsolete (they don't have some of the new parameters) munge sets deleted - // set 1 -// { -// method: 'uuo2zqhhy5bw80fu', -// boundsParamsList: '5rc0561uauf6x13u', -// id: 'bzeizowtguoyrrtt', -// minLatE6: '7qej3eqg4sefuaac', -// minLngE6: 'yqegc976egk5q9vo', -// maxLatE6: '2odsgh99ix9bbtsb', -// maxLngE6: 'g9jess8dwa2j8pwi', -// timestampMs: '604f34zcu9zna0a5', -// qk: 'y853tux9h7cb6xp3', -// desiredNumItems: 'sfv5i7l6ouljz8vf', -// minTimestampMs: 'y3g07dbnw6sklloj', -// maxTimestampMs: '3pdl28aa27xvyhke', -// guids: 'xp1pl2jm5hrh3bna', -// inviteeEmailAddress: '2pyrttrp3gh38mmu', -// message: 'zz54435vfc57nlg9', -// latE6: 'cyltxjod3jhxgj8q', -// lngE6: 'h9whcgcz6kpqkz80', -// factionOnly: '37okcr7gvd5yn2lj', -// ascendingTimestampOrder: 'iimftkq7flskwrx9' -// }, - - // set 2 - first seen 2013-09-12 21:30 - // (very briefly - and removed a few hours later) -// { -// method: '42suxeca8ttud7je', -// boundsParamsList: '5uwd21hkedg3zh2c', -// id: 'drtt302ebaj6ek2g', -// minLatE6: 'l933r0l8brrt1x5b', -// minLngE6: 'qg3xb340zed41jof', -// maxLatE6: 'sw485z1n3tusdkul', -// maxLngE6: '6meahm3f9xup9krb', -// timestampMs: '6meahm3f9xup9krb', -// qk: 'fpi9b1z0os0x9yjj', -// desiredNumItems: 'inr3js77cetyibi6', -// minTimestampMs: 'zfb2e5iqmggrxe98', -// maxTimestampMs: '8c4imy17gfpfrl9l', -// guids: '5d5hp2p3rkmanqn7', -// inviteeEmailAddress: 'i1a5yp6p1l6iqk08', -// message: 'xzhbk3ri04lx9xvj', -// latE6: 'njg0zny4fb39mf0a', -// lngE6: 'ti2rx4ltmg6d1zsr', -// factionOnly: 'jegpo8rwhtuuuuhh', -// ascendingTimestampOrder: '1ennke6gykwzziun', -// // in this set, also the request method names are obsfucated! -// 'dashboard.getThinnedEntitiesV4': 'ufxcmvve3eirsf2b', -// 'dashboard.getPaginatedPlextsV2': 'd9dgziiw8vzhyecv', -// 'dashboard.getPlayersByGuids': 's53izqpxedtd0hv8', -// 'dashboard.sendInviteEmail': 'kn9plnbree2aeuh9', -// 'dashboard.redeemReward': 'les8vribyxb899wd', -// 'dashboard.sendPlext': '9u1ukkkx1euxf02a' -// }, // set 3 - in the update of 2013-09-30 (addition of 'alerts' chat tab) { + 'dashboard.getGameScore': 'fhlzntzkl5v7hcfh', // GET_GAME_SCORE + 'dashboard.getPaginatedPlextsV2': 'wzuitnswoda7w028', // GET_PAGINATED_PLEXTS + 'dashboard.getThinnedEntitiesV4': 'scgrm4lf2371esgw', // GET_THINNED_ENTITIES + 'dashboard.getPlayersByGuids': '81l6usczczoi3lfi', // LOOKUP_PLAYERS + 'dashboard.redeemReward': '8kop2koeld9b4c26', // REDEEM_REWARD + 'dashboard.sendInviteEmail': 't0ccodsm1nuo5uso', // SEND_INVITE_EMAIL + 'dashboard.sendPlext': 'k04cfjwwsg3h3827', // SEND_PLEXT + method: '22ux2z96jwq5zn78', version: 'kf6hgl9yau03ws0o', //guessed parameter name - only seen munged + version_parameter: '4608f4356a6f55690f127fb542f557f98de66169', // passed as the value to the above parameter boundsParamsList: '29t16cmsn6l3r2xg', id: '7rogqhp5pzcqobcw', minLatE6: 'yzbnp7z9bd28p0yr', @@ -190,36 +124,65 @@ window.requestParameterMunges = [ minTimestampMs: 's9jf2seni33y3gyu', maxTimestampMs: '2kh3vti98rhp3g29', chatTab: '7n7ocqfq1p18352b', //guessed parameter name - only seen munged - guids: '5hyiwhwc0jyljvro', - inviteeEmailAddress: 's9z6zt03eymzxhkj', + ascendingTimestampOrder: 'p88a2ztchtjhiazl', message: 'e8qm0kptw2trrcrw', latE6: 'fja1phtsqxm71dqm', lngE6: 'iut1tb7c0x726hwn', - ascendingTimestampOrder: 'p88a2ztchtjhiazl', - // in this set, also the request method names are obsfucated! - 'dashboard.getGameScore': 'fhlzntzkl5v7hcfh', // GET_GAME_SCORE - 'dashboard.getPaginatedPlextsV2': 'wzuitnswoda7w028', // GET_PAGINATED_PLEXTS - 'dashboard.getThinnedEntitiesV4': 'scgrm4lf2371esgw', // GET_THINNED_ENTITIES - 'dashboard.getPlayersByGuids': '81l6usczczoi3lfi', // LOOKUP_PLAYERS - 'dashboard.redeemReward': '8kop2koeld9b4c26', // REDEEM_REWARD - 'dashboard.sendInviteEmail': 't0ccodsm1nuo5uso', // SEND_INVITE_EMAIL - 'dashboard.sendPlext': 'k04cfjwwsg3h3827' // SEND_PLEXT + guids: '5hyiwhwc0jyljvro', + inviteeEmailAddress: 's9z6zt03eymzxhkj', }, + + // set 4 - second update of 2013-09-30 + { + 'dashboard.getGameScore': 'ija9jgrf5hj7wm9r', // GET_GAME_SCORE + 'dashboard.getPaginatedPlextsV2': '0elftx739mkbzi1b', // GET_PAGINATED_PLEXTS + 'dashboard.getThinnedEntitiesV4': 'prv0ez8cbsykh63g', // GET_THINNED_ENTITIES + 'dashboard.getPlayersByGuids': 'i0lxy6nc695z9ka3', // LOOKUP_PLAYERS + 'dashboard.redeemReward': '376oivna8rf8qbfj', // REDEEM_REWARD + 'dashboard.sendInviteEmail': '96y930v5q96nrcrw', // SEND_INVITE_EMAIL + 'dashboard.sendPlext': 'c04kceytofuqvyqg', // SEND_PLEXT + + method: '9we4b31i48ui4sdm', + version: 'q402kn5zqisuo1ym', //guessed parameter name - only seen munged + version_parameter: 'dbad4485024d446ae946e3d287b5d640029ef3e3', // passed as the value to the above parameter + boundsParamsList: '3r5ctyvc2f653zjd', + id: 'izey8ciqg2dz2oqc', + minLatE6: 'cein0n4jrifa7ui2', + minLngE6: 'lbd1juids3johtdo', + maxLatE6: 'h4kyot9kmvd3g284', + maxLngE6: 'sbci6jjc2d5g9uy4', + timestampMs: '2wurn9giagbvv6bt', + qk: 'hq73mwpjqyvcp6ul', + desiredNumItems: 'kyo6vh5n58hmrnua', + minTimestampMs: 'hu4swdftcp7mvkdi', + maxTimestampMs: 'ly6ylae5lv1z9072', + chatTab: 'q5kxut5rmbtlqbf9', //guessed parameter name - only seen munged + ascendingTimestampOrder: 'hvfd0io35rahwjgr', + message: 'z4hf7tzl27o14455', + latE6: 'zyzh3bdxyd47vk1x', + lngE6: 'n5d1f8pql51t641x', + guids: 'gl16ehqoc3i3oi07', + inviteeEmailAddress: 'orc9ufg7rp7g1y9j', + }, + ]; window.activeRequestMungeSet = undefined; // attempt to guess the munge set in use, by looking therough the functions of the stock intel page for one of the munged params window.detectActiveMungeSet = function() { - for (var m in window) { - // try and find the stock page functions - if (typeof window[m] == 'function') { - var stockFunc = window[m].toString(); - for (var i in window.requestParameterMunges) { - if (stockFunc.indexOf (window.requestParameterMunges[i]['method']) >= 0) { - console.log('IITC: found request munge set '+i+' in stock intel function "window.'+m+'()"'); - window.activeRequestMungeSet = i; - } - } + if (window.requestParameterMunges.length == 1) { + // no point in searching through the code when there's only one set in use + window.activeRequestMungeSet = 0; + return; + } + + // try and find the stock page functions + // FIXME? revert to searching through all the code? is that practical? + var stockFunc = nemesis.dashboard.network.DataFetcher.prototype.sendRequest_.toString() + for (var i in window.requestParameterMunges) { + if (stockFunc.indexOf (window.requestParameterMunges[i]['method']) >= 0) { + console.log('IITC: found request munge set index '+i+' in stock intel function nemesis.dashboard.network.DataFetcher.prototype.sendRequest_'); + window.activeRequestMungeSet = i; } } @@ -281,9 +244,13 @@ window.postAjax = function(action, data, success, error) { var activeMunge = window.requestParameterMunges[window.activeRequestMungeSet]; var methodName = 'dashboard.'+action; - var versionStr = "4608f4356a6f55690f127fb542f557f98de66169"; // unsure of parameter value meaning. appears to be a constant used as a 'version'. added to all requests along with the method name in the stock site - // optional munging of the method name - seen in Set 2 (onwards?) - if (methodName in activeMunge) methodName = activeMunge[methodName]; + var versionStr = 'version_parameter'; + + // munging of the method name - seen in Set 2 (onwards?) + methodName = activeMunge[methodName]; + // and of the 'version' parameter + versionStr = activeMunge[versionStr]; + var post_data = JSON.stringify(window.requestDataMunge($.extend({method: methodName, version: versionStr}, data))); var remove = function(data, textStatus, jqXHR) { window.requests.remove(jqXHR); }; var errCnt = function(jqXHR) { window.failedRequestCount++; window.requests.remove(jqXHR); }; From f1c1409859a856c835593c2eb21719db05be668a Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Tue, 1 Oct 2013 03:22:45 +0200 Subject: [PATCH 024/126] fixed typo --- website/page/faq.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/page/faq.php b/website/page/faq.php index f32d4843..c5d2572a 100644 --- a/website/page/faq.php +++ b/website/page/faq.php @@ -68,7 +68,7 @@ From here you can remove/disable individual plugins or IITC itself.

Is it possible to add external plugins to IITC Mobile?

Yes it is!
    -
  • Create a folder named "IITC Mobile" in your home directory.
  • +
  • Create a folder named "IITC_Mobile" in your home directory.
  • Inside this folder, create a new folder named "plugins".
  • Copy all your additional plugins to this folder.
  • You should see your plugins listed above the official plugins.
  • From b1e654e354b624941e08f300952619e42a03be26 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Tue, 1 Oct 2013 02:24:06 +0100 Subject: [PATCH 025/126] website: fix faq entry --- website/page/faq.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/page/faq.php b/website/page/faq.php index f32d4843..c5d2572a 100644 --- a/website/page/faq.php +++ b/website/page/faq.php @@ -68,7 +68,7 @@ From here you can remove/disable individual plugins or IITC itself.

    Is it possible to add external plugins to IITC Mobile?

    Yes it is!
      -
    • Create a folder named "IITC Mobile" in your home directory.
    • +
    • Create a folder named "IITC_Mobile" in your home directory.
    • Inside this folder, create a new folder named "plugins".
    • Copy all your additional plugins to this folder.
    • You should see your plugins listed above the official plugins.
    • From 278ecf67ee7951ce3d9cd22ed222734ab41af596 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Tue, 1 Oct 2013 04:43:18 +0100 Subject: [PATCH 026/126] tweak show-more-portals plugin - move switchoff point one level out, as this seems to result in fewer requests to the niantic servers --- plugins/show-more-portals.user.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/show-more-portals.user.js b/plugins/show-more-portals.user.js index 346d690a..0721cbbd 100644 --- a/plugins/show-more-portals.user.js +++ b/plugins/show-more-portals.user.js @@ -2,7 +2,7 @@ // @id iitc-plugin-show-more-portals@jonatkins // @name IITC plugin: Show more portals // @category Tweaks -// @version 0.1.3.@@DATETIMEVERSION@@ +// @version 0.1.4.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -32,9 +32,9 @@ window.plugin.showMorePortals.setup = function() { window.getPortalDataZoom = function() { var mapZoom = map.getZoom(); - // this plugin only cares about close in zoom levels (zoom 13 and higher) - run the original + // this plugin only cares about close in zoom levels (zoom 12 and higher) - run the original // code when this isn't the case. (this way, multiple zoom-modifying plugins can exist at once - in theory) - if (mapZoom < 13) { + if (mapZoom < 12) { return origGetPortalDataZoom(); } From 60d686d52b74f81a13b9f1ca3bbb8f6845874b73 Mon Sep 17 00:00:00 2001 From: Hexchain Tong Date: Tue, 1 Oct 2013 11:56:51 +0800 Subject: [PATCH 027/126] Prevent Google Fonts not being loaded due to security issue Chrome refuses to load http resources if the page was loaded using https. --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index bf304d6d..c7fdf7b8 100644 --- a/main.js +++ b/main.js @@ -63,7 +63,7 @@ document.getElementsByTagName('head')[0].innerHTML = '' + '' + '' //note: smartphone.css injection moved into code/smartphone.js - + ''; + + ''; document.getElementsByTagName('body')[0].innerHTML = '' + '
      Loading, please wait
      ' From db9956be7e53777392307f88171facdfe856624d Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Tue, 1 Oct 2013 05:06:38 +0100 Subject: [PATCH 028/126] update website for 0.14.2 release --- website/page/home.php | 11 +++++++++++ website/page/news.php | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/website/page/home.php b/website/page/home.php index e8fd2093..768a5b5b 100644 --- a/website/page/home.php +++ b/website/page/home.php @@ -13,6 +13,17 @@ offers many more features. It is available for

      Latest news

      +

      1st October 2013

      +

      +IITC 0.14.2 and IITC Mobile 0.7.1 have been released. This is a critical update required to work with changes made +to the standard intel site. Additionally, a major update to the mobile app interface has been made, and a handful +of tweaks and bugfixes to IITC and a few plugins. +

      +

      +The standard intel site now includes an 'alerts' chat tab. This will be coming to IITC in the future, but it's +better to get this working version released without it than hold things up just for that. +

      +

      22nd September 2013

      Update: IITC Mobile 0.6.5 replaces 0.6.4. This fixes a crash on entering plugin preferences on some tablets. diff --git a/website/page/news.php b/website/page/news.php index fea95b02..9cecae84 100644 --- a/website/page/news.php +++ b/website/page/news.php @@ -1,5 +1,16 @@

      News

      +

      1st October 2013

      +

      +IITC 0.14.2 and IITC Mobile 0.7.1 have been released. This is a critical update required to work with changes made +to the standard intel site. Additionally, a major update to the mobile app interface has been made, and a handful +of tweaks and bugfixes to IITC and a few plugins. +

      +

      +The standard intel site now includes an 'alerts' chat tab. This will be coming to IITC in the future, but it's +better to get this working version released without it than hold things up just for that. +

      +

      22nd September 2013

      Update: IITC Mobile 0.6.5 replaces 0.6.4. This fixes a crash on entering plugin preferences on some tablets. From b4ae95ce7391d81444897dab1cf299f25d5a4122 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Wed, 2 Oct 2013 05:00:08 +0100 Subject: [PATCH 029/126] bump version number --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index bf304d6d..8a80cce5 100644 --- a/main.js +++ b/main.js @@ -1,7 +1,7 @@ // ==UserScript== // @id ingress-intel-total-conversion@jonatkins // @name IITC: Ingress intel map total conversion -// @version 0.14.2.@@DATETIMEVERSION@@ +// @version 0.14.3.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ From 975db0ec7b56e33af046efc7aa7e59670fffceef Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Wed, 2 Oct 2013 05:00:27 +0100 Subject: [PATCH 030/126] add special case for name->guid lookup for our own name IITC relies on this being available early, but the new sessionStorage for player name cache means it often isn't (still, it's not perfect - as IITC still requires a lookup from guid->name for us to store the reverse mapping - this has always been a theoretical issue though) likely fix for #577 --- code/player_names.js | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/code/player_names.js b/code/player_names.js index e79cf874..d2acee5a 100644 --- a/code/player_names.js +++ b/code/player_names.js @@ -39,6 +39,10 @@ window.playerNameToGuid = function(playerName) { var cachedGuid = window._playerNameToGuidCache[playerName]; if (cachedGuid !== undefined) return cachedGuid; + // IITC needs our own player GUID, from a lookup by name. so we retrieve this from localstorage (if available) + cachedGuid = localStorage['PLAYER-'+PLAYER.nickname]; + if (cachedGuid !== undefined) return cachedGuid; + var guid = null; $.each(Object.keys(sessionStorage), function(ind,key) { if(playerName === sessionStorage[key]) { @@ -107,22 +111,17 @@ window.setPlayerName = function(guid, nick, uncertain) { 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 doesn’t work, make a screenshot instead.\n\n\n' + window.debug.printStackTrace() + '\n\n\n' + JSON.stringify(nick)); } sessionStorage[guid] = nick; + + // IITC needs our own player ID early on in startup. the only way we can find this is by something else + // doing a guid->name lookup for our own name. as this doesn't always happen - and likely won't happen when needed + // we'll store our own name->guid lookup in localStorage + if (nick == PLAYER.nickname) { + localStorage['PLAYER-'+PLAYER.nickname] = guid; + PLAYER.guid = guid; // set it in PLAYER in case it wasn't already done + } } -window.loadPlayerNamesForPortal = function(portal_details) { - if(map.getZoom() < PRECACHE_PLAYER_NAMES_ZOOM) return; - var e = portal_details; - - if(e.captured && e.captured.capturingPlayerId) - getPlayerName(e.captured.capturingPlayerId); - - if(!e.resonatorArray || !e.resonatorArray.resonators) return; - - $.each(e.resonatorArray.resonators, function(ind, reso) { - if(reso) getPlayerName(reso.ownerGuid); - }); -} // test to see if a specific player GUID is a special system account (e.g. __JARVIS__, __ADA__) that shouldn't From 7fd3cb7fd6265667c6fc30dd7e445315f0a8d490 Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Wed, 2 Oct 2013 23:33:09 +0200 Subject: [PATCH 031/126] show a hint for the user that a tap leads to the info screen in mobile status bar, when no portal is selected. --- code/smartphone.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/smartphone.js b/code/smartphone.js index 64142803..3efa7948 100644 --- a/code/smartphone.js +++ b/code/smartphone.js @@ -117,6 +117,8 @@ window.runOnSmartphonesAfterBoot = function() { // add a div/hook for updating mobile info $('#updatestatus').prepend('

      '); window.addHook('portalDetailsUpdated', window.smartphoneInfo); + // init msg of status bar. hint for the user that a tap leads to the info screen + $('#mobileinfo').html('
      tap here for info screen
      '); // disable img full view $('#portaldetails').off('click', '**'); From 72620ed668afaba1afa353142962bb8b1f4e565f Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Wed, 2 Oct 2013 23:40:51 +0200 Subject: [PATCH 032/126] got rid of redundant code --- code/chat.js | 1 - code/debugging.js | 4 ---- code/geosearch.js | 2 +- code/smartphone.js | 5 +---- code/utils_misc.js | 2 +- 5 files changed, 3 insertions(+), 11 deletions(-) diff --git a/code/chat.js b/code/chat.js index ad1032ce..71d0196c 100644 --- a/code/chat.js +++ b/code/chat.js @@ -540,7 +540,6 @@ window.chat.show = function(name) { ? $('#updatestatus').hide() : $('#updatestatus').show(); $('#chat, #chatinput').show(); - $('#map').css('visibility', 'hidden'); var t = $(''+name+''); window.chat.chooseAnchor(t); diff --git a/code/debugging.js b/code/debugging.js index 14663184..b1d2bbe8 100644 --- a/code/debugging.js +++ b/code/debugging.js @@ -23,10 +23,6 @@ window.debug.console = function() { } window.debug.console.show = function() { - if (window.isSmartphone()) { - $('#scrollwrapper, #updatestatus').hide(); - $('#map').css('visibility', 'hidden'); - } $('#chat, #chatinput').show(); window.debug.console.create(); $('#chatinput mark').css('cssText', 'color: #bbb !important').text('debug:'); diff --git a/code/geosearch.js b/code/geosearch.js index ab67a56c..b926e9d8 100644 --- a/code/geosearch.js +++ b/code/geosearch.js @@ -29,6 +29,6 @@ window.search = function(search) { northEast = new L.LatLng(b[1], b[3]), bounds = new L.LatLngBounds(southWest, northEast); window.map.fitBounds(bounds); - if(window.isSmartphone()) window.smartphone.mapButton.click(); + if(window.isSmartphone()) window.show('map'); }); } diff --git a/code/smartphone.js b/code/smartphone.js index 3efa7948..56e0c57c 100644 --- a/code/smartphone.js +++ b/code/smartphone.js @@ -35,7 +35,6 @@ window.runOnSmartphonesBeforeBoot = function() { } window.smartphone.mapButton = $('map').click(function() { - $('#chat, #chatinput, #scrollwrapper').hide(); $('#map').css('visibility', 'visible'); $('#updatestatus').show(); $('#chatcontrols a .active').removeClass('active'); @@ -43,8 +42,6 @@ window.runOnSmartphonesBeforeBoot = function() { }); window.smartphone.sideButton = $('info').click(function() { - $('#chat, #chatinput, #updatestatus').hide(); - $('#map').css('visibility', 'hidden'); $('#scrollwrapper').show(); $('.active').removeClass('active'); $("#chatcontrols a:contains('info')").addClass('active'); @@ -112,7 +109,7 @@ window.runOnSmartphonesAfterBoot = function() { if(!isSmartphone()) return; console.warn('running smartphone post boot stuff'); - smartphone.mapButton.click(); + window.show('map'); // add a div/hook for updating mobile info $('#updatestatus').prepend('
      '); diff --git a/code/utils_misc.js b/code/utils_misc.js index 1da80f29..c421bb52 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -328,7 +328,7 @@ window.rangeLinkClick = function() { if(window.portalRangeIndicator) window.map.fitBounds(window.portalRangeIndicator.getBounds()); if(window.isSmartphone()) - window.smartphone.mapButton.click(); + window.show('map'); } window.showPortalPosLinks = function(lat, lng, name) { From 4b0ff58a7b2e300277ea4d64598b4555470a3e3a Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Thu, 3 Oct 2013 11:27:57 +0200 Subject: [PATCH 033/126] commented out weblogin for now since it confuses the user --- mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java index b860ec17..e518aa0f 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java @@ -161,7 +161,7 @@ public class IITC_WebViewClient extends WebViewClient { @Override public void onReceivedLoginRequest(WebView view, String realm, String account, String args) { Log.d("iitcm", "Login requested: " + realm + " " + account + " " + args); - ((IITC_Mobile) mContext).onReceivedLoginRequest(this, view, realm, account, args); + //((IITC_Mobile) mContext).onReceivedLoginRequest(this, view, realm, account, args); } // parse all enabled iitc plugins From eeb24315fb4ae0c9fe6600ea72f0e6b48969a3ef Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Thu, 3 Oct 2013 16:52:33 +0200 Subject: [PATCH 034/126] moved login caching mode setting to webviewclient --- mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java | 2 -- mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java index af56d2c4..79439c65 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java @@ -572,8 +572,6 @@ 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"); - mIitcWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); mLogin = new IITC_DeviceAccountLogin(this, view, client); mLogin.startLogin(realm, account, args); } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java index e518aa0f..ca67e9f5 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java @@ -161,6 +161,8 @@ public class IITC_WebViewClient extends WebViewClient { @Override public void onReceivedLoginRequest(WebView view, String realm, String account, String args) { Log.d("iitcm", "Login requested: " + realm + " " + account + " " + args); + Log.d("iitcm", "logging in...set caching mode to default"); + view.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); //((IITC_Mobile) mContext).onReceivedLoginRequest(this, view, realm, account, args); } From 26754ac8c02b3d2faacfdede7c7d04be837fe919 Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Fri, 4 Oct 2013 16:03:58 +0200 Subject: [PATCH 035/126] moved some listeners from field attribute to class --- mobile/AndroidManifest.xml | 4 +- .../com/cradle/iitc_mobile/IITC_Mobile.java | 125 +++++++++--------- 2 files changed, 66 insertions(+), 63 deletions(-) diff --git a/mobile/AndroidManifest.xml b/mobile/AndroidManifest.xml index 29831632..d8fa1712 100644 --- a/mobile/AndroidManifest.xml +++ b/mobile/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="52" + android:versionName="0.7.2"> Date: Fri, 4 Oct 2013 16:15:58 +0200 Subject: [PATCH 036/126] some code formatting --- .../cradle/iitc_mobile/IITC_JSInterface.java | 4 ++-- .../cradle/iitc_mobile/IITC_MapSettings.java | 24 ++++++++----------- .../com/cradle/iitc_mobile/IITC_Mobile.java | 8 +++---- .../iitc_mobile/IITC_NavigationHelper.java | 20 +++++++--------- .../IITC_PluginPreferenceActivity.java | 8 +++---- .../com/cradle/iitc_mobile/IITC_WebView.java | 2 +- .../iitc_mobile/IITC_WebViewClient.java | 2 +- .../iitc_mobile/async/CheckHttpResponse.java | 6 ++--- .../share/IntentFragmentAdapter.java | 2 +- .../iitc_mobile/share/IntentListView.java | 6 ++--- .../iitc_mobile/share/ShareActivity.java | 2 +- 11 files changed, 37 insertions(+), 47 deletions(-) diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java b/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java index c26c8e21..93873162 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java @@ -18,7 +18,7 @@ import java.util.Locale; // provide communication between IITC script and android app public class IITC_JSInterface { // context of main activity - private IITC_Mobile mIitc; + private final IITC_Mobile mIitc; IITC_JSInterface(IITC_Mobile iitc) { mIitc = iitc; @@ -111,7 +111,7 @@ public class IITC_JSInterface { @Override public void run() { mIitc.setLoadingState(false); - + mIitc.getMapSettings().onBootFinished(); } }); diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_MapSettings.java b/mobile/src/com/cradle/iitc_mobile/IITC_MapSettings.java index c97c65a6..245aefd2 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_MapSettings.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_MapSettings.java @@ -22,7 +22,7 @@ import java.util.Comparator; public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickListener, OnItemLongClickListener { private class HighlighterAdapter extends ArrayAdapter { - private HighlighterComparator mComparator = new HighlighterComparator(); + private final HighlighterComparator mComparator = new HighlighterComparator(); private HighlighterAdapter(int resource) { super(mIitc, resource); @@ -67,8 +67,7 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList } } - private class LayerAdapter extends ArrayAdapter - { + private class LayerAdapter extends ArrayAdapter { public LayerAdapter(int resource) { super(mIitc, resource); } @@ -84,15 +83,15 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList } } - private IITC_Mobile mIitc; + private final IITC_Mobile mIitc; - private ArrayAdapter mHighlighters; - private ArrayAdapter mBaseLayers; - private ArrayAdapter mOverlayLayers; + private final ArrayAdapter mHighlighters; + private final ArrayAdapter mBaseLayers; + private final ArrayAdapter mOverlayLayers; - private Spinner mSpinnerBaseMap; - private Spinner mSpinnerHighlighter; - private ListView mListViewOverlayLayers; + private final Spinner mSpinnerBaseMap; + private final Spinner mSpinnerHighlighter; + private final ListView mListViewOverlayLayers; private String mActiveHighlighter; private int mActiveLayer; @@ -181,8 +180,7 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList if (parent.equals(mSpinnerHighlighter)) { String name = mHighlighters.getItem(position); mIitc.getWebView().loadUrl("javascript: window.changePortalHighlights('" + name + "')"); - } - else if (parent.equals(mSpinnerBaseMap)) { + } else if (parent.equals(mSpinnerBaseMap)) { mBaseLayers.getItem(mActiveLayer).active = false; // set old layer to hidden, but no need to really hide Layer layer = mBaseLayers.getItem(position); @@ -253,7 +251,6 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList mBaseLayers.add(layer); } catch (JSONException e) { e.printStackTrace(); - continue; } } mBaseLayers.notifyDataSetChanged(); @@ -273,7 +270,6 @@ public class IITC_MapSettings implements OnItemSelectedListener, OnItemClickList mOverlayLayers.add(layer); } catch (JSONException e) { e.printStackTrace(); - continue; } } mOverlayLayers.notifyDataSetChanged(); diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java index 5ebbf450..25c4cb9c 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java @@ -283,8 +283,7 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis if (mReloadNeeded) { Log.d("iitcm", "preference had changed...reload needed"); reloadIITC(); - } - else { + } else { // iitc is not fully booted...timer will be reset by the script itself if (findViewById(R.id.imageLoading).getVisibility() == View.GONE) { mIitcWebView.loadUrl("javascript: window.idleReset();"); @@ -353,7 +352,6 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis if (mBackButtonPressed || !mSharedPrefs.getBoolean("pref_press_twice_to_exit", false)) { super.onBackPressed(); - return; } else { mBackButtonPressed = true; Toast.makeText(this, "Press twice to exit", Toast.LENGTH_SHORT).show(); @@ -574,7 +572,7 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis * called by IITC_WebViewClient when the Google login form is opened. */ public void onReceivedLoginRequest(IITC_WebViewClient client, WebView view, - String realm, String account, String args) { + String realm, String account, String args) { mLogin = new IITC_DeviceAccountLogin(this, view, client); mLogin.startLogin(realm, account, args); } @@ -621,8 +619,8 @@ public class IITC_Mobile extends Activity implements OnSharedPreferenceChangeLis } /** - * @deprecated ActionBar related stuff should be handled by IITC_NavigationHelper * @see getNavigationHelper() + * @deprecated ActionBar related stuff should be handled by IITC_NavigationHelper */ @Deprecated @Override diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java b/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java index b7b7f629..1c0af426 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_NavigationHelper.java @@ -60,8 +60,7 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt view.setText(getPaneTitle(item)); int icon = 0; - switch (item) - { + switch (item) { case MAP: icon = R.drawable.location_map; break; @@ -100,13 +99,13 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt public static final int NOTICE_INFO = 1 << 1; // next one would be 1<<2; (this results in 1,2,4,8,...) - private IITC_Mobile mIitc; - private ActionBar mActionBar; - private SharedPreferences mPrefs; - private NavigationAdapter mNavigationAdapter; - private DrawerLayout mDrawerLayout; - private ListView mDrawerLeft; - private View mDrawerRight; + private final IITC_Mobile mIitc; + private final ActionBar mActionBar; + private final SharedPreferences mPrefs; + private final NavigationAdapter mNavigationAdapter; + private final DrawerLayout mDrawerLayout; + private final ListView mDrawerLeft; + private final View mDrawerRight; private boolean mDesktopMode = false; private boolean mFullscreen = false; @@ -236,8 +235,7 @@ public class IITC_NavigationHelper extends ActionBarDrawerToggle implements OnIt mDrawerLayout.closeDrawers(); } - public String getPaneTitle(Pane pane) - { + public String getPaneTitle(Pane pane) { switch (pane) { case INFO: return "Info"; diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_PluginPreferenceActivity.java b/mobile/src/com/cradle/iitc_mobile/IITC_PluginPreferenceActivity.java index 209db065..b8909fca 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_PluginPreferenceActivity.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_PluginPreferenceActivity.java @@ -62,7 +62,7 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { - if(onIsMultiPane()) getIntent() + if (onIsMultiPane()) getIntent() .putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, PluginsFragment.class.getName()); super.onCreate(savedInstanceState); } @@ -76,7 +76,7 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { // Select the displayed fragment in the headers (when using a tablet) : // This should be done by Android, it is a bug fix // thx to http://stackoverflow.com/a/16793839 - if(mHeaders != null) { + if (mHeaders != null) { final String displayedFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT); if (displayedFragment != null) { @@ -227,7 +227,7 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { // now we have all stuff together and can build the preference // first check if we need a new category - if (sPlugins.containsKey(plugin_cat) == false) { + if (!sPlugins.containsKey(plugin_cat)) { sPlugins.put(plugin_cat, new ArrayList()); Log.d("iitcm", "create " + plugin_cat + " and add " + plugin_name); } @@ -288,7 +288,7 @@ public class IITC_PluginPreferenceActivity extends PreferenceActivity { TextView summary; } - private LayoutInflater mInflater; + private final LayoutInflater mInflater; static int getHeaderType(Header header) { if (header.fragment == null && header.intent == null) { diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java index c0966c28..affa80c1 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java @@ -53,7 +53,7 @@ public class IITC_WebView extends WebView { */ @Override public void onGeolocationPermissionsShowPrompt(String origin, - GeolocationPermissions.Callback callback) { + GeolocationPermissions.Callback callback) { callback.invoke(origin, true, false); } diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java index ca67e9f5..3297447c 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebViewClient.java @@ -148,7 +148,7 @@ public class IITC_WebViewClient extends WebViewClient { @Override public void onPageFinished(WebView view, String url) { if (url.startsWith("http://www.ingress.com/intel") - || url.startsWith("https://www.ingress.com/intel")) { + || url.startsWith("https://www.ingress.com/intel")) { Log.d("iitcm", "injecting iitc.."); view.loadUrl("javascript: " + this.mIitcScript); } diff --git a/mobile/src/com/cradle/iitc_mobile/async/CheckHttpResponse.java b/mobile/src/com/cradle/iitc_mobile/async/CheckHttpResponse.java index 057b0c74..dde6e89c 100644 --- a/mobile/src/com/cradle/iitc_mobile/async/CheckHttpResponse.java +++ b/mobile/src/com/cradle/iitc_mobile/async/CheckHttpResponse.java @@ -24,13 +24,13 @@ import java.io.IOException; */ public class CheckHttpResponse extends AsyncTask { - private IITC_JSInterface mJsInterface; - private Context mContext; + private final IITC_JSInterface mJsInterface; + private final Context mContext; public CheckHttpResponse(IITC_JSInterface jsInterface, Context c) { mContext = c; mJsInterface = jsInterface; - }; + } @Override protected Boolean doInBackground(String... urls) { diff --git a/mobile/src/com/cradle/iitc_mobile/share/IntentFragmentAdapter.java b/mobile/src/com/cradle/iitc_mobile/share/IntentFragmentAdapter.java index 68743a08..fd803345 100644 --- a/mobile/src/com/cradle/iitc_mobile/share/IntentFragmentAdapter.java +++ b/mobile/src/com/cradle/iitc_mobile/share/IntentFragmentAdapter.java @@ -8,7 +8,7 @@ import java.util.ArrayList; import java.util.List; public class IntentFragmentAdapter extends FragmentPagerAdapter { - private List mTabs; + private final List mTabs; public IntentFragmentAdapter(FragmentManager fm) { super(fm); diff --git a/mobile/src/com/cradle/iitc_mobile/share/IntentListView.java b/mobile/src/com/cradle/iitc_mobile/share/IntentListView.java index d0a72cc6..9c6b16c1 100644 --- a/mobile/src/com/cradle/iitc_mobile/share/IntentListView.java +++ b/mobile/src/com/cradle/iitc_mobile/share/IntentListView.java @@ -74,7 +74,7 @@ public class IntentListView extends ListView { private IntentAdapter mAdapter; private PackageManager mPackageManager; - HashMap mActivities = new HashMap(); + private final HashMap mActivities = new HashMap(); public IntentListView(Context context) { super(context); @@ -155,7 +155,6 @@ public class IntentListView extends ListView { if (hasCopyIntent || !activity.name.equals(SendToClipboard.class.getCanonicalName())) { activityList.remove(i); i--; - continue; } } } @@ -172,8 +171,7 @@ public class IntentListView extends ListView { if (resolveInfo.activityInfo.packageName.equals(defaultTarget.activityInfo.packageName) && resolveInfo.activityInfo.name.equals(defaultTarget.activityInfo.name)) { allActivities.add(0, resolveInfo); - } - else { + } else { allActivities.add(resolveInfo); } } diff --git a/mobile/src/com/cradle/iitc_mobile/share/ShareActivity.java b/mobile/src/com/cradle/iitc_mobile/share/ShareActivity.java index 71200af3..aeec04cc 100644 --- a/mobile/src/com/cradle/iitc_mobile/share/ShareActivity.java +++ b/mobile/src/com/cradle/iitc_mobile/share/ShareActivity.java @@ -108,7 +108,7 @@ public class ShareActivity extends FragmentActivity implements ActionBar.TabList Intent intent = getIntent(); // from portallinks/permalinks we build 3 intents (share / geo / vanilla-intel-link) - if (intent.getBooleanExtra("onlyShare", false) == false) { + if (!intent.getBooleanExtra("onlyShare", false)) { mTitle = intent.getStringExtra("title"); mLl = intent.getDoubleExtra("lat", 0) + "," + intent.getDoubleExtra("lng", 0); mZoom = intent.getIntExtra("zoom", 0); From 7a6bf1eeef21b74a14b7c93adf7dd0dabc5f77ba Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Mon, 7 Oct 2013 20:18:09 +0100 Subject: [PATCH 037/126] only look to localStorage for our player guid WHEN WE'RE LOOKING UP OUR OWN NAME daft error! --- code/player_names.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/player_names.js b/code/player_names.js index d2acee5a..86062520 100644 --- a/code/player_names.js +++ b/code/player_names.js @@ -40,8 +40,10 @@ window.playerNameToGuid = function(playerName) { if (cachedGuid !== undefined) return cachedGuid; // IITC needs our own player GUID, from a lookup by name. so we retrieve this from localstorage (if available) - cachedGuid = localStorage['PLAYER-'+PLAYER.nickname]; - if (cachedGuid !== undefined) return cachedGuid; + if (playerName == PLAYER.nickname) { + cachedGuid = localStorage['PLAYER-'+PLAYER.nickname]; + if (cachedGuid !== undefined) return cachedGuid; + } var guid = null; $.each(Object.keys(sessionStorage), function(ind,key) { From d2661874c61d518324a6b05fa5155dd793dc00e3 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Mon, 7 Oct 2013 20:29:05 +0100 Subject: [PATCH 038/126] some work-in-progress. from a read of the far-less-obfsucated code on the stock site it looks like map data can be retrieved as an update to an earlier query i.e. pass the timestamp of the last data request, and the server should only send the changed data rather than everything --- code/map_data_cache.js | 10 ++++-- code/map_data_debug.js | 3 +- code/map_data_request.js | 74 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/code/map_data_cache.js b/code/map_data_cache.js index c143e9c9..6dcda1a8 100644 --- a/code/map_data_cache.js +++ b/code/map_data_cache.js @@ -2,8 +2,14 @@ // cache for map data tiles. window.DataCache = function() { - this.REQUEST_CACHE_FRESH_AGE = 60; // if younger than this, use data in the cache rather than fetching from the server - this.REQUEST_CACHE_MAX_AGE = 180; // maximum cache age. entries are deleted from the cache after this time + // stock site nemesis.dashboard.DataManager.CACHE_EXPIRY_MS_ = 18E4 - so should be 2 mins cache time + this.REQUEST_CACHE_FRESH_AGE = 120; // if younger than this, use data in the cache rather than fetching from the server + + // stale cache entries can be updated (that's what the optional 'timestampMs' field in getThinnedEntnties is + // for, retrieving deltas) so use a long max age to take advantage of this + // however, ther must be an overall limit on the maximum age of data from the servers, otherwise the deletedEntity + // entries would grow indefinitely. an hour seems reasonable from experience with the data, so 55 mins max cache time + this.REQUEST_CACHE_MAX_AGE = 55*60; // maximum cache age. entries are deleted from the cache after this time if (L.Browser.mobile) { // on mobile devices, smaller cache size diff --git a/code/map_data_debug.js b/code/map_data_debug.js index 4ecc27a8..dcede257 100644 --- a/code/map_data_debug.js +++ b/code/map_data_debug.js @@ -37,7 +37,8 @@ window.RenderDebugTiles.prototype.setState = function(id,state) { var col = '#f0f'; var fill = '#f0f'; switch(state) { - case 'ok': col='#0f0'; fill='#0f0'; break; + case 'ok': col='#080'; fill='#080'; break; + case 'ok-delta': col='#0f0'; fill='#0f0'; break; case 'error': col='#f00'; fill='#f00'; break; case 'cache-fresh': col='#0f0'; fill='#ff0'; break; case 'cache-stale': col='#f00'; fill='#ff0'; break; diff --git a/code/map_data_request.js b/code/map_data_request.js index e6fcb799..ff839663 100644 --- a/code/map_data_request.js +++ b/code/map_data_request.js @@ -11,6 +11,7 @@ window.MapDataRequest = function() { this.activeRequestCount = 0; this.requestedTiles = {}; + this.staleTileData = {}; this.idle = false; @@ -45,7 +46,7 @@ window.MapDataRequest = function() { // additionally, a delay before processing the queue after requeueing tiles // (this way, if multiple requeue delays finish within a short time of each other, they're all processed in one queue run) - this.RERUN_QUEUE_DELAY = 2; + this.RERUN_QUEUE_DELAY = 1; this.REFRESH_CLOSE = 120; // refresh time to use for close views z>12 when not idle and not moving this.REFRESH_FAR = 600; // refresh time for far views z <= 12 @@ -172,6 +173,9 @@ window.MapDataRequest.prototype.refresh = function() { // fill tileBounds with the data needed to request each tile this.tileBounds = {}; + // clear the stale tile data + this.staleTileData = {}; + var bounds = clampLatLngBounds(map.getBounds()); var zoom = getPortalDataZoom(); @@ -238,6 +242,7 @@ window.MapDataRequest.prototype.refresh = function() { this.render.processTileData (this.cache.get(tile_id)); this.cachedTileCount += 1; } else { + // no fresh data - queue a request var boundsParams = generateBoundsParams( tile_id, @@ -247,6 +252,30 @@ window.MapDataRequest.prototype.refresh = function() { lngEast ); + // however, the server does support delta requests - only returning the entities changed since a particular timestamp + // retrieve the stale cache entry and use it, if possible + var stale = (this.cache && this.cache.get(tile_id)); + var lastTimestamp = undefined; + if (stale) { + // find the timestamp of the latest entry in the stale records. the stock site appears to use the browser + // clock, but this isn't reliable. ideally the data set should include it's retrieval timestamp, set by the + // server, for use here. a good approximation is the highest timestamp of all entities + + for (var i in stale.gameEntities) { + var ent = stale.gameEntities[i]; + if (lastTimestamp===undefined || ent[1] > lastTimestamp) { + lastTimestamp = ent[1]; + } + } + +console.log('stale tile '+tile_id+': newest mtime '+lastTimestamp+(lastTimestamp?' '+new Date(lastTimestamp).toString():'')); + if (lastTimestamp) { + // we can issue a useful delta request - store the previous data, as we can't rely on the cache still having it later + this.staleTileData[tile_id] = stale; + boundsParams.timestampMs = lastTimestamp; + } + } + this.tileBounds[tile_id] = boundsParams; this.requestedTileCount += 1; } @@ -358,7 +387,7 @@ window.MapDataRequest.prototype.sendTileRequest = function(tiles) { this.debugTiles.setState (id, 'requested'); - this.requestedTiles[id] = true; + this.requestedTiles[id] = { staleData: this.staleTileData[id] }; var boundsParams = this.tileBounds[id]; if (boundsParams) { @@ -473,13 +502,52 @@ window.MapDataRequest.prototype.handleResponse = function (data, tiles, success) // no error for this data tile - process it successTiles.push (id); + var stale = this.requestedTiles[id].staleData; + if (stale) { + // we have stale data. therefore, a delta request was made for this tile. we need to merge the results with + // the existing stale data before proceeding + + var dataObj = {}; + // copy all entities from the stale data... + for (var i in stale.gameEntities||[]) { + var ent = stale.gameEntities[i]; + dataObj[ent[0]] = { timestamp: ent[1], data: ent[2] }; + } +var oldEntityCount = Object.keys(dataObj).length; + // and remove any entities in the deletedEntnties list + for (var i in val.deletedEntities||[]) { + var guid = val.deletedEntities[i]; + delete dataObj[guid]; + } +var oldEntityCount2 = Object.keys(dataObj).length; + // then add all entities from the new data + for (var i in val.gameEntities||[]) { + var ent = val.gameEntities[i]; + dataObj[ent[0]] = { timestamp: ent[1], data: ent[2] }; + } +var newEntityCount = Object.keys(dataObj).length; +console.log('processed delta mapData request:'+id+': '+oldEntityCount+' original entities, '+oldEntityCount2+' after deletion, '+val.gameEntities.length+' entities in the response'); + + // now reconstruct a new gameEntities array in val, with the updated data + val.gameEntities = []; + for (var guid in dataObj) { + var ent = [guid, dataObj[guid].timestamp, dataObj[guid].data]; + val.gameEntities.push(ent); + } + + // we can leave the returned 'deletedEntities' data unmodified - it's not critial to how IITC works anyway + + // also delete any staleTileData entries for this tile - no longer required + delete this.staleTileData[id]; + } + // store the result in the cache this.cache && this.cache.store (id, val); // if this tile was in the render list, render it // (requests aren't aborted when new requests are started, so it's entirely possible we don't want to render it!) if (id in this.tileBounds) { - this.debugTiles.setState (id, 'ok'); + this.debugTiles.setState (id, stale?'ok-delta':'ok'); this.render.processTileData (val); From 306de7e6dc47d461670550f78c45ceac7306ffc1 Mon Sep 17 00:00:00 2001 From: Morgan Jones Date: Mon, 7 Oct 2013 18:29:43 -0500 Subject: [PATCH 039/126] Load different versions of Roboto web font Use Roboto for COMM font rather than Verdana --- main.js | 8 +++++--- style.css | 12 +++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/main.js b/main.js index a651f80f..ff0fb77f 100644 --- a/main.js +++ b/main.js @@ -40,10 +40,10 @@ if(!d) { if(document.getElementById('header_email')) { // however, we are logged in. setTimeout('location.reload();', 3*1000); - throw('Page doesn’t have player data, but you are logged in. Reloading in 3s.'); + throw("Page doesn't have player data, but you are logged in. Reloading in 3s."); } // FIXME: handle nia takedown in progress - throw('Couldn’t retrieve player data. Are you logged in?'); + throw("Couldn't retrieve player data. Are you logged in?"); } @@ -63,7 +63,9 @@ document.getElementsByTagName('head')[0].innerHTML = '' + '' + '' //note: smartphone.css injection moved into code/smartphone.js - + ''; + + '