diff --git a/code/portal_detail_display.js b/code/portal_detail_display.js index 7405b37a..81c3d4b2 100644 --- a/code/portal_detail_display.js +++ b/code/portal_detail_display.js @@ -52,7 +52,7 @@ window.renderPortalDetails = function(guid) { var lng = d.locationE6.lngE6; var perma = 'https://ingress.com/intel?latE6='+lat+'&lngE6='+lng+'&z=17&pguid='+guid; var imgTitle = 'title="'+getPortalDescriptionFromDetails(d)+'\n\nClick to show full image."'; - var poslinks = 'window.showPortalPosLinks('+lat/1E6+','+lng/1E6+')'; + var poslinks = 'window.showPortalPosLinks('+lat/1E6+','+lng/1E6+',\'' + d.portalV2.descriptiveText.TITLE + '\')'; var postcard = 'Send in a postcard. Will put it online after receiving. Address:\\n\\nStefan Breunig\\nINF 305 – R045\\n69120 Heidelberg\\nGermany'; $('#portaldetails') diff --git a/code/smartphone.js b/code/smartphone.js index 37c89a4a..8cd4ad02 100644 --- a/code/smartphone.js +++ b/code/smartphone.js @@ -2,6 +2,15 @@ window.isSmartphone = function() { // this check is also used in main.js. Note it should not detect // tablets because their display is large enough to use the desktop // version. + + // The stock intel site allows forcing mobile/full sites with a vp=m or vp=f + // parameter - let's support the same. (stock only allows this for some + // browsers - e.g. android phone/tablet. let's allow it for all, but + // no promises it'll work right) + var viewParam = getURLParam('vp'); + if (viewParam == 'm') return true; + if (viewParam == 'f') return false; + return navigator.userAgent.match(/Android.*Mobile/); } diff --git a/code/utils_misc.js b/code/utils_misc.js index 10f0d4a0..5e9f367c 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -106,13 +106,17 @@ window.rangeLinkClick = function() { window.smartphone.mapButton.click(); } -window.showPortalPosLinks = function(lat, lng) { +window.showPortalPosLinks = function(lat, lng, name) { + var portal_name = ''; + if(name !== undefined) { + portal_name = encodeURIComponent(' (' + name + ')'); + } if (typeof android !== 'undefined' && android && android.intentPosLink) { android.intentPosLink(window.location.protocol + '//maps.google.com/?q='+lat+','+lng); } else { var qrcode = '
'; var script = ''; - var gmaps = 'gmaps'; + var gmaps = 'gmaps'; var osm = 'OSM'; alert('
' + qrcode + script + gmaps + ' ' + osm + '
'); } diff --git a/main.js b/main.js index a165c3b6..d47c8acc 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.9.1.@@DATETIMEVERSION@@ +// @version 0.10.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ diff --git a/mobile/AndroidManifest.xml b/mobile/AndroidManifest.xml index e060b7b8..ee24a714 100644 --- a/mobile/AndroidManifest.xml +++ b/mobile/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="0.2.3" > "iitc-debug.user.js" +./build.py local8000 +cd build/local8000 +compressed="$(uglifyjs total-conversion-build.user.js)" +echo "${compressed}" > "total-conversion-build.user.js" -cd mobile +cd ../../mobile ant release diff --git a/mobile/res/layout/activity_main.xml b/mobile/res/layout/activity_main.xml index 1353be2c..9abfe63c 100644 --- a/mobile/res/layout/activity_main.xml +++ b/mobile/res/layout/activity_main.xml @@ -1,6 +1,11 @@ - - \ No newline at end of file + android:orientation="vertical" > + + + + \ No newline at end of file diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java index 0dbd3901..8cd5b218 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java @@ -25,15 +25,15 @@ public class IITC_Mobile extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + iitc_view = (IITC_WebView) findViewById(R.id.iitc_webview); // we do not want to reload our page every time we switch orientations... // so restore state if activity was already created if(savedInstanceState != null) { - ((IITC_WebView)findViewById(R.id.webview)).restoreState(savedInstanceState); + iitc_view.restoreState(savedInstanceState); } else { // load new iitc web view with ingress intel page - iitc_view= (IITC_WebView) findViewById(R.id.webview); Intent intent = getIntent(); String action = intent.getAction(); if (Intent.ACTION_VIEW.equals(action)) { @@ -99,6 +99,8 @@ public class IITC_Mobile extends Activity { iitc_view.getWebViewClient().loadIITC_JS(this); } catch (IOException e1) { e1.printStackTrace(); + } catch (NullPointerException e2) { + e2.printStackTrace(); } return true; // print version number diff --git a/plugins/ap-list.css b/plugins/ap-list.css index 2e73f3b4..c4857820 100644 --- a/plugins/ap-list.css +++ b/plugins/ap-list.css @@ -90,4 +90,69 @@ .ap-list-link-selected { font-style:italic; -} \ No newline at end of file +} + +.ap-list-center-div { + width: 55%; + margin: 0px auto; +} + +.ap-list-page-control { + float:left; + padding: 0 5px; +} + +.ap-list-page-text { + float:left; + text-align: center; + color: rgb(32, 168, 177); +} + +#ap-list-current-p { + width: 20px; +} + +#ap-list-total-p { + width: 20px; +} + +.ap-list-triangle { + float:left; + clear:none; + border-style:solid; +} + +.ap-list-triangle-left { + border-color: transparent rgb(32, 168, 177) transparent transparent; +} + +.ap-list-triangle-left-half { + border-width: 7.5px 7.5px 7.5px 0px; +} + +.ap-list-triangle-left-full { + border-width: 7.5px 13px 7.5px 0px; +} + +.ap-list-triangle-right { + border-color: transparent transparent transparent rgb(32, 168, 177); +} + +.ap-list-triangle-right-half { + border-width: 7.5px 0px 7.5px 7.5px; +} + +.ap-list-triangle-right-full { + border-width: 7.5px 0px 7.5px 13px; +} +#ap-list-pagination { + display: inline-block; + width: 90%; + vertical-align: bottom; +} + +#ap-list-misc-info { + display: inline-block; + vertical-align: bottom; + padding: 0px 6px; +} diff --git a/plugins/ap-list.user.js b/plugins/ap-list.user.js index 882a4ef9..3bc172a1 100644 --- a/plugins/ap-list.user.js +++ b/plugins/ap-list.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @id iitc-plugin-ap-list@xelio // @name IITC plugin: AP List -// @version 0.4.5.@@DATETIMEVERSION@@ +// @version 0.5.0.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -31,7 +31,16 @@ window.plugin.apList.sides = new Array(2); window.plugin.apList.sortedPortals = new Array(2); window.plugin.apList.playerApGainFunc = new Array(2); -window.plugin.apList.topMaxCount = 10; +window.plugin.apList.SORT_BY_AP = 'AP'; +window.plugin.apList.SORT_BY_EL = 'EL'; +window.plugin.apList.sortBy = window.plugin.apList.SORT_BY_AP; +window.plugin.apList.SORT_ASC = 1; +window.plugin.apList.SORT_DESC = -1; +window.plugin.apList.sortOptions = {}; + +window.plugin.apList.currentPage = [1,1]; +window.plugin.apList.totalPage = [1,1]; +window.plugin.apList.portalPerPage = 10; window.plugin.apList.sideLabelClass = {}; window.plugin.apList.tableColumns = new Array(2); @@ -60,13 +69,17 @@ window.plugin.apList.updatePortalTable = function(side) { + plugin.apList.tableHeaderBuilder(side) + ''; - table += '' - for(var i = 0; i < plugin.apList.topMaxCount; i++) { + table += ''; + var startingPortal = (plugin.apList.currentPage[side] - 1) * plugin.apList.portalPerPage; + for(var i = startingPortal; i < startingPortal + plugin.apList.portalPerPage; i++) { var portal = plugin.apList.sortedPortals[side][i]; table += plugin.apList.tableRowBuilder(side, portal); } table += ''; $('div#ap-list-table').html(table); + + plugin.apList.updatePaginationControl(); + plugin.apList.updateStats(); } window.plugin.apList.tableHeaderBuilder = function(side) { @@ -75,8 +88,10 @@ window.plugin.apList.tableHeaderBuilder = function(side) { $.each(plugin.apList.tableColumns[side], function(ind, column) { var cssClass = column.headerTooltip ? (column.cssClass + ' help') : column.cssClass; var title = column.headerTooltip ? column.headerTooltip : ''; + var onclick = column.headerOnClick ? column.headerOnClick: ''; headerRow += '' + column.header + ''; @@ -155,7 +170,7 @@ window.plugin.apList.getPortalApTitle = function(portal) { window.plugin.apList.getPortalEffectiveLvText = function(portal) { var title = plugin.apList.getPortalEffectiveLvTitle(portal); - return '
' + portal.effectiveLevel.effectiveLevel + '
'; + return '
' + portal.effectiveLevel.effectiveLevel.toFixed(1) + '
'; } window.plugin.apList.getPortalEffectiveLvTitle = function(portal) { @@ -192,6 +207,33 @@ window.plugin.apList.getPortalLink = function(portal) { return div; } +window.plugin.apList.updatePaginationControl = function() { + $('#ap-list-current-p').html(plugin.apList.currentPage[plugin.apList.displaySide]); + $('#ap-list-total-p').html(plugin.apList.totalPage[plugin.apList.displaySide]); +} + +window.plugin.apList.updateStats = function() { + var destroyPortals = plugin.apList.destroyPortalsGuid.length; + if(destroyPortals === 0) { + title = 'Stats'; + } else { + var destroyAP = 0; + var averageEL = 0; + $.each(plugin.apList.destroyPortalsGuid, function(ind,guid) { + destroyAP += plugin.apList.cachedPortals[guid].playerApGain.totalAp; + averageEL += plugin.apList.cachedPortals[guid].effectiveLevel.effectiveLevel; + }); + averageEL = Math.round(averageEL / destroyPortals * 10) / 10; + + var title = 'Stats\n' + + 'Selected portal(s)\t=\t' + destroyPortals + '\n' + + 'Total AP\t=\t' + destroyAP + '\n' + + 'Average EL\t=\t' + averageEL; + } + + $('#ap-list-misc-info').attr('title', title); +} + // MAIN LOGIC FUNCTIONS ////////////////////////////////////////////////////////// // Loop through portals and get playerApGain, then put in sortedPortals by side and sort them by AP. @@ -234,20 +276,20 @@ window.plugin.apList.updateSortedPortals = function() { plugin.apList.sortedPortals[side].push(portal); }); $.each(plugin.apList.sides, function(ind, side) { - plugin.apList.sortedPortals[side].sort(function(a, b) { - return b.playerApGain.totalAp - a.playerApGain.totalAp; - }); + plugin.apList.sortedPortals[side].sort(plugin.apList.comparePortal); }); // Modify sortedPortals if any portal selected for destroy - if(plugin.apList.destroyPortalsGuid.length > 0) { - plugin.apList.handleDestroyPortal() - } + plugin.apList.handleDestroyPortal(); + // Update pagination control data + plugin.apList.updateTotalPages(); } // This function will make AP gain of field and link only count once if // one of the connected portal is selected for destroy window.plugin.apList.handleDestroyPortal = function() { + if(plugin.apList.destroyPortalsGuid.length === 0) return; + var enemy = window.plugin.apList.SIDE_ENEMY; var destroyedLinks = {}; var destroyedFields = {}; @@ -310,8 +352,13 @@ window.plugin.apList.handleDestroyPortal = function() { }); // Sorting portals with updated AP - plugin.apList.sortedPortals[enemy].sort(function(a, b) { - return b.playerApGain.totalAp - a.playerApGain.totalAp; + plugin.apList.sortedPortals[enemy].sort(plugin.apList.comparePortal); +} + +window.plugin.apList.updateTotalPages = function() { + $.each(plugin.apList.sortedPortals, function(side, portals) { + plugin.apList.totalPage[side] = Math.max(Math.ceil(portals.length / plugin.apList.portalPerPage), 1); + plugin.apList.currentPage[side] = Math.min(plugin.apList.totalPage[side], plugin.apList.currentPage[side]); }); } @@ -350,22 +397,16 @@ window.plugin.apList.getDeployOrUpgradeApGain = function(d) { // by others(only level lower than player level) or by player. for(var i = 0; i < 8; i++) { var reso = d.resonatorArray.resonators[i]; - + // Empty reso if(!reso) { - // Empty reso - reso = {slot: i, level: 0}; - otherReso.push(reso); + otherReso.push({slot: i, level: 0}); continue; } - // By player if(reso.ownerGuid === window.PLAYER.guid) { - if(!playerResoCount[reso.level]) - playerResoCount[reso.level] = 0; - playerResoCount[reso.level]++; + playerResoCount[reso.level] = (playerResoCount[reso.level] || 0) + 1; continue; } - // By others and level lower than player if(reso.level < window.PLAYER.level) { otherReso.push(reso); @@ -389,9 +430,6 @@ window.plugin.apList.getDeployOrUpgradeApGain = function(d) { upgradedReso.push(targetReso); // Counting upgrade or deploy (targetReso.level === 0) ? deployCount++ : upgradedCount++; - totalAp += (targetReso.level === 0) - ? DEPLOY_RESONATOR - : UPGRADE_ANOTHERS_RESONATOR; availableCount--; } @@ -483,10 +521,10 @@ window.plugin.apList.getEffectiveLevel = function(portal) { } return { - effectiveLevel: effectiveLevel.toFixed(1), + effectiveLevel: Math.round(effectiveLevel * 10) / 10, effectiveEnergy: parseInt(effectiveEnergy), - effectOfShields: effectOfShields.toFixed(2), - effectOfResoDistance: effectOfResoDistance.toFixed(2), + effectOfShields: Math.round(effectOfShields * 100) / 100, + effectOfResoDistance: Math.round(effectOfResoDistance * 100) / 100, originLevel: portalLevel }; } @@ -519,6 +557,36 @@ window.plugin.apList.getShieldsMitigation = function(portal) { return shieldsMitigation; } +// For using in .sort(func) of sortedPortals +// Use options in plugin.apList.sortOptions. Each type of sortBy has +// array of options. Option consist of an ordering and a property chain. +// +// Sorting done by loop through the options, get the property by +// property chain of each option, compare the property of two object +// with the ordering of option and return the result when the first +// differece is found. +window.plugin.apList.comparePortal = function(a,b) { + var result = 0; + var options = plugin.apList.sortOptions[plugin.apList.sortBy]; + + $.each(options, function(indO, option) { + var aProperty = a; + var bProperty = b; + // Walking down the chain + $.each(option.chain, function(indPN, propertyName) { + aProperty = aProperty[propertyName]; + bProperty = bProperty[propertyName]; + }); + // compare next porperty if equal + if(aProperty === bProperty) return true; + + result = (aProperty > bProperty ? 1 : -1) * option.order; + return false; + }); + + return result; +} + // FEATURE TOGGLES AND INTERACTION HANDLER /////////////////////////////////////// window.plugin.apList.enableCache = function() { @@ -535,7 +603,15 @@ window.plugin.apList.disableCache = function() { } window.plugin.apList.selectPortal = function(guid) { - renderPortalDetails(guid); + // Add error catching to avoid following link of portal if error + // occured in renderPortalDetails or hooked plugin + try { + renderPortalDetails(guid); + } catch(e) { + console.error(e.message); + console.log(e.stack); + console.log('Skipping error in renderPortalDetails or hooked plugin') + } plugin.apList.setPortalLocationIndicator(guid); } @@ -578,6 +654,34 @@ window.plugin.apList.animPortalLocationIndicator = function() { } } +window.plugin.apList.changePage = function(step, toEnd) { + var side = plugin.apList.displaySide; + var oldPage = plugin.apList.currentPage[side]; + + if(toEnd) { + if(step < 0) plugin.apList.currentPage[side] = 1; + if(step > 0) plugin.apList.currentPage[side] = plugin.apList.totalPage[side] + } else { + plugin.apList.currentPage[side] += step; + if(plugin.apList.currentPage[side] < 1) + plugin.apList.currentPage[side] = 1; + if(plugin.apList.currentPage[side] > plugin.apList.totalPage[side]) + plugin.apList.currentPage[side] = plugin.apList.totalPage[side]; + } + + if(plugin.apList.currentPage[side] !== oldPage) + plugin.apList.updatePortalTable(side); +} + +window.plugin.apList.changeSorting = function(sortBy) { + var oldSortBy = plugin.apList.sortBy; + plugin.apList.sortBy = sortBy; + if(plugin.apList.sortBy !== oldSortBy) { + plugin.apList.updateSortedPortals(); + plugin.apList.updatePortalTable(plugin.apList.displaySide); + } +} + window.plugin.apList.destroyPortal = function(guid) { // Add to destroyPortalsGuid if not yet added, remove if already added var portalIndex = plugin.apList.destroyPortalIndex(guid); @@ -648,6 +752,25 @@ window.plugin.apList.setupVar = function() { = "#ap-list-frd"; plugin.apList.sideLabelClass[plugin.apList.SIDE_ENEMY] = "#ap-list-eny"; + plugin.apList.sortedPortals[plugin.apList.SIDE_FRIENDLY] = new Array(); + plugin.apList.sortedPortals[plugin.apList.SIDE_ENEMY] = new Array(); +} + +window.plugin.apList.setupSorting = function() { + var optionELAsc = { + order: plugin.apList.SORT_ASC, + chain: ['effectiveLevel','effectiveLevel']}; + var optionAPDesc = { + order: plugin.apList.SORT_DESC, + chain: ['playerApGain','totalAp']}; + var optionGuidDesc = { + order: plugin.apList.SORT_DESC, + chain: ['guid']}; + + // order by EL -> AP -> guid + plugin.apList.sortOptions[plugin.apList.SORT_BY_EL] = [optionELAsc, optionAPDesc, optionGuidDesc]; + // order by AP -> EL -> guid + plugin.apList.sortOptions[plugin.apList.SORT_BY_AP] = [optionAPDesc, optionELAsc, optionGuidDesc]; } // Setup table columns for header builder and row builder @@ -658,12 +781,15 @@ window.plugin.apList.setupTableColumns = function() { // AP and Eff. LV columns are same in enemy and friendly table var apColumn = { header: 'AP', + headerOnClick: 'plugin.apList.changeSorting(plugin.apList.SORT_BY_AP);', + headerTooltip: 'Click to sort by AP', cssClass: 'ap-list-td-ap', contentFunction: plugin.apList.getPortalApText }; var effectiveLevelColumn = { header: 'EL', - headerTooltip: 'Effective Level', + headerOnClick: 'plugin.apList.changeSorting(plugin.apList.SORT_BY_EL);', + headerTooltip: 'Effective Level\nClick to sort by EL', cssClass: 'ap-list-td-eff-lv', contentFunction: plugin.apList.getPortalEffectiveLvText }; @@ -718,12 +844,38 @@ window.plugin.apList.setupList = function() { + 'plugin.apList.hideReloadLabel();return false;">↻ R' + '' + '
' + + '...' + + '' + ''; $('#sidebar').append(content); $('#ap-list-reload').hide(); } +window.plugin.apList.setupPagination = function() { + var content = '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
1
' + + '
/
' + + '
1
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
'// fix collapsion of parent caused by inner div's float:left + + '
'; + $('#ap-list-pagination').html(content); +} + window.plugin.apList.setupMapEvent = function() { map.on('zoomstart', function() { plugin.apList.setupMapEvent.zoomLevelBefore = map.getZoom(); @@ -755,9 +907,11 @@ window.plugin.apList.setupMapEvent = function() { var setup = function() { window.plugin.apList.setupVar(); + window.plugin.apList.setupSorting(); window.plugin.apList.setupTableColumns(); window.plugin.apList.setupCSS(); window.plugin.apList.setupList(); + window.plugin.apList.setupPagination(); window.plugin.apList.setupMapEvent(); window.addHook('requestFinished', window.plugin.apList.handleUpdate); } diff --git a/plugins/keys-on-map.user.js b/plugins/keys-on-map.user.js new file mode 100644 index 00000000..02658585 --- /dev/null +++ b/plugins/keys-on-map.user.js @@ -0,0 +1,132 @@ +// ==UserScript== +// @id iitc-plugin-keys-on-map@xelio +// @name IITC plugin: Keys on map +// @version 0.1.0.@@DATETIMEVERSION@@ +// @namespace https://github.com/jonatkins/ingress-intel-total-conversion +// @updateURL @@UPDATEURL@@ +// @downloadURL @@DOWNLOADURL@@ +// @description [@@BUILDNAME@@-@@BUILDDATE@@] Show keys in keys plugin on map. +// @include https://www.ingress.com/intel* +// @include http://www.ingress.com/intel* +// @match https://www.ingress.com/intel* +// @match http://www.ingress.com/intel* +// ==/UserScript== + +function wrapper() { +// ensure plugin framework is there, even if iitc is not yet loaded +if(typeof window.plugin !== 'function') window.plugin = function() {}; + + +// PLUGIN START //////////////////////////////////////////////////////// + +// use own namespace for plugin +window.plugin.keysOnMap = function() {}; + +window.plugin.keysOnMap.keyLayers = {}; +window.plugin.keysOnMap.keyLayerGroup = new L.LayerGroup(); + +// Use portal add and remove event to control render of keys +window.plugin.keysOnMap.portalAdded = function(data) { + // Disable if Plugin Keys is not there + if(!plugin.keys) { + plugin.keysOnMap.disableMessage(); + return; + } + + data.portal.on('add', function() { + plugin.keysOnMap.renderKey(this.options.guid, this.getLatLng()); + }); + + data.portal.on('remove', function() { + plugin.keysOnMap.removeKey(this.options.guid); + }); +} + +window.plugin.keysOnMap.keyUpdate = function(data) { + // Disable if Plugin Keys is not there + if(!plugin.keys) { + plugin.keysOnMap.disableMessage(); + return; + } + var portal = window.portals[data.guid]; + if(!portal) return; + var latLng = portal.getLatLng(); + + plugin.keysOnMap.renderKey(data.guid, latLng) +} + +window.plugin.keysOnMap.renderKey = function(guid,latLng) { + plugin.keysOnMap.removeKey(guid); + + var keyCount = plugin.keys.keys[guid]; + if (keyCount > 0) { + var key = L.marker(latLng, { + icon: L.divIcon({ + className: 'plugin-keys-on-map-key', + iconAnchor: [6,7], + iconSize: [12,10], + html: keyCount + }), + guid: guid + }); + + plugin.keysOnMap.keyLayers[guid] = key; + key.addTo(plugin.keysOnMap.keyLayerGroup); + } +} + +window.plugin.keysOnMap.removeKey = function(guid) { + var previousLayer = plugin.keysOnMap.keyLayers[guid]; + if(previousLayer) { + plugin.keysOnMap.keyLayerGroup.removeLayer(previousLayer); + delete plugin.keysOnMap.keyLayers[guid]; + } +} + +window.plugin.keysOnMap.disableMessage = function() { + if(!plugin.keysOnMap.messageShown) { + alert('Plugin "Keys On Map" need plugin "Keys" to run!'); + plugin.keysOnMap.messageShown = true; + } +} + +var setup = function() { + $("'); +} + +// PLUGIN END ////////////////////////////////////////////////////////// + +if(window.iitcLoaded && typeof setup === 'function') { + setup(); +} else { + if(window.bootPlugins) + window.bootPlugins.push(setup); + else + window.bootPlugins = [setup]; +} +} // wrapper end +// inject code into site context +var script = document.createElement('script'); +script.appendChild(document.createTextNode('('+ wrapper +')();')); +(document.body || document.head || document.documentElement).appendChild(script); diff --git a/plugins/portals-list.user.js b/plugins/portals-list.user.js index 8e1ad525..7da32e3a 100644 --- a/plugins/portals-list.user.js +++ b/plugins/portals-list.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @id iitc-plugin-portals-list@teo96 // @name IITC plugin: show list of portals -// @version 0.0.6.@@DATETIMEVERSION@@ +// @version 0.0.9.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -13,16 +13,20 @@ // ==/UserScript== /* whatsnew +* 0.0.9 : bugs hunt +* 0.0.8 : Aborted to avoid problems with Niantic (export portals informations as csv or kml file) +* 0.0.7 : more informations avalaible via tooltips (who deployed, energy, ...), new E/AP column * 0.0.6 : Add power charge information into a new column + bugfix * 0.0.5 : Filter portals by clicking on 'All portals', 'Res Portals' or 'Enl Portals' * 0.0.4 : Add link to portals name, one click to display full information in portal panel, double click to zoom on portal, hover to show address * 0.0.3 : sorting ascending/descending and add numbers of portals by faction on top on table * 0.0.2 : add sorting feature when click on header column * 0.0.1 : initial release, show list of portals with level, team, resonators and shield information +* * Display code inspired from @vita10gy's scoreboard plugin : iitc-plugin-scoreboard@vita10gy - https://github.com/breunigs/ingress-intel-total-conversion * Portal link code from xelio - iitc: AP List - https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/ap-list.user.js * -* todo : +* todo : export as GPX, Open in Google Maps, more statistics in the header, what else ? */ function wrapper() { @@ -53,7 +57,8 @@ window.plugin.portalslist.getPortals = function(){ retval=true; var d = portal.options.details; var name = d.portalV2.descriptiveText.TITLE; - + var address = d.portalV2.descriptiveText.ADDRESS; + var img = d.imageByUrl && d.imageByUrl.imageUrl ? d.imageByUrl.imageUrl : DEFAULT_PORTAL_IMG; var team = portal.options.team; switch (team){ case 1 : @@ -85,22 +90,25 @@ window.plugin.portalslist.getPortals = function(){ var shields = []; $.each(d.portalV2.linkedModArray, function(ind, mod) { if (mod) - shields[ind] = mod.rarity.capitalize().replace('_', ' '); + //shields[ind] = mod.rarity.capitalize().replace('_', ' '); + shields[ind] = [mod.rarity.substr(0,1).capitalize(), getPlayerName(mod.installingUser)] ; else - shields[ind] = ''; + shields[ind] = ['', '']; }); var APgain= getAttackApGain(d).enemyAp; - var thisPortal = {'portal':d,'name':name,'team':team,'level':level,'guid':guid, 'resonators':resonators,'energy' : Math.floor(energy/maxenergy*100), 'shields':shields,'APgain':APgain}; + var thisPortal = {'portal':d,'name':name,'team':team,'level':level,'guid':guid, 'resonators':resonators,'energyratio' : Math.floor(energy/maxenergy*100), 'shields':shields, 'APgain':APgain, 'EAP' : (energy/APgain).toFixed(2), 'energy': energy, 'maxenergy':maxenergy, 'lat':portal._latlng.lat, 'lng':portal._latlng.lng, 'address': address, 'img' : img}; window.plugin.portalslist.listPortals.push(thisPortal); }); return retval; - } window.plugin.portalslist.displayPL = function() { - //console.log('** displayPL'); + // debug tools + //var start = new Date().getTime(); + //console.log('***** Start ' + start); + var html = ''; window.plugin.portalslist.sortOrder=-1; window.plugin.portalslist.enlP = 0; @@ -127,14 +135,17 @@ window.plugin.portalslist.displayPL = function() { $(document).on('click', '#portalslist .filterEnl', function() { $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,2)); }); + + //debug tools + //end = new Date().getTime(); + //console.log('***** end : ' + end + ' and Elapse : ' + (end - start)); } window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { // sortOrder <0 ==> desc, >0 ==> asc, i use sortOrder * -1 to change the state window.plugin.portalslist.filter=filter; var portals=window.plugin.portalslist.listPortals; - // console.log('********************* Sort by ' + sortBy + ' order : ' + sortOrder + ' filter : ' + filter); - + //Array sort window.plugin.portalslist.listPortals.sort(function(a, b) { var retVal = 0; @@ -191,7 +202,7 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { html += '' + '' + '' - + '' + + '' + '' + '' + '' @@ -200,63 +211,164 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { + '' + '' + '' - + '' - + '' - + '' - + '' - + '' - + ''; + + '' + + '' + + '' + + '' + + '' + + '' + + ''; $.each(portals, function(ind, portal) { if (filter === 0 || filter === portal.team){ html += '' - + '' - //+ '' + + '' + '' - + '' - + '' - //+ '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + ''; + + ''; + + $.each([0, 1, 2, 3 ,4 ,5 ,6 ,7], function(ind, slot) { + + var title = 'title="owner: ' + portal.resonators[slot][1] + '
' + + 'energy: ' + portal.resonators[slot][3] + ' / ' + portal.resonators[slot][4] + ' (' + Math.floor(portal.resonators[slot][3]/portal.resonators[slot][4]*100) + '%)
' + + 'distance: ' + portal.resonators[slot][2] + 'm'; + + html += ''; + + }); + + html += '' + + '' + + '' + + '' + + '' + + '' + + ''; html+= ''; } - }); - html+='
PortalLevelTeamTR1R2R3R6R7R8EnergyShield 1Shield 2Shield 3Shield 4AP Gain
EnergyS1S2S3S4AP GainE/AP
' + window.plugin.portalslist.getPortalLink(portal.portal, portal.guid) + '' + portal.name + '' + window.plugin.portalslist.getPortalLink(portal.portal, portal.guid) + '' + portal.level + '' + portal.team + '' + portal.resonators[0][0] + '6' - + '' + portal.resonators[1][0] + '' + portal.resonators[2][0] + '' + portal.resonators[3][0] + '' + portal.resonators[4][0] + '' + portal.resonators[5][0] + '' + portal.resonators[6][0] + '' + portal.resonators[7][0] + '' + portal.energy + '%' + portal.shields[0] + '' + portal.shields[1] + '' + portal.shields[2] + '' + portal.shields[3] + '' + portal.APgain + '' + portal.team + '' + portal.resonators[slot][0] + '' + portal.energyratio + '%' + portal.shields[0][0] + '' + portal.shields[1][0] + '' + portal.shields[2][0] + '' + portal.shields[3][0] + '' + portal.APgain + '' + portal.EAP + '
'; - html+= '
Click on portals table headers to sort by that column.
' - + 'Click on All Portals, Resistant Portals, Enlightened Portals to filter
' + html += ''; + + //html += window.plugin.portalslist.exportLinks(); + + html += '
Click on portals table headers to sort by that column. ' + + 'Click on All Portals, Resistant Portals, Enlightened Portals to filter
' + 'Thanks to @vita10gy & @xelio for their IITC plugins who inspired me. A @teo96 production. Vive la Résistance !
'; window.plugin.portalslist.sortOrder = window.plugin.portalslist.sortOrder*-1; return html; } - window.plugin.portalslist.stats = function(sortBy) { //console.log('** stats'); var html = '' - + '' - + '' - + '' + + '' + + '' + + '' + '' + '
All Portals : (click to filter)' + window.plugin.portalslist.listPortals.length +'Resistant Portals : ' + window.plugin.portalslist.resP + 'Enlightened Portals : '+ window.plugin.portalslist.enlP + 'All Portals : (click to filter)' + window.plugin.portalslist.listPortals.length + 'Resistant Portals : ' + window.plugin.portalslist.resP +' (' + Math.floor(window.plugin.portalslist.resP/window.plugin.portalslist.listPortals.length*100) + '%)Enlightened Portals : '+ window.plugin.portalslist.enlP +' (' + Math.floor(window.plugin.portalslist.enlP/window.plugin.portalslist.listPortals.length*100) + '%)
'; return html; } +//return Html generated to export links +window.plugin.portalslist.exportLinks = function(){ + var html=''; + var stamp = new Date().getTime(); + + html+=''; + return html; +} + +window.plugin.portalslist.export = function(fileformat){ + //alert('format :' + fileformat); + var file = ''; + var uri = ''; + + switch (fileformat) { + case 'csv': + file = window.plugin.portalslist.exportCSV(); + break; + case 'kml': + file = window.plugin.portalslist.exportKML(); + break; + } + + if (file !== '') { + //http://stackoverflow.com/questions/4639372/export-to-csv-in-jquery + var uri = 'data:application/' + fileformat + 'csv;charset=UTF-8,' + encodeURIComponent(file); + //window.open(uri); + } + return uri; +} +window.plugin.portalslist.exportCSV = function(){ + var csv = ''; + var filter = window.plugin.portalslist.filter; + var portals = window.plugin.portalslist.listPortals; + + //headers + csv += 'Portal\tLevel\tTeam\tR1\tR2\tR3\tR4\tR5\tR6\tR7\tR8\tEnergy\tS1\tS2\tS3\tS4\tAP Gain\tE/AP\tlat\tlong\n'; + + $.each(portals, function(ind, portal) { + + if (filter === 0 || filter === portal.team){ + csv += portal.name + '\t' + + portal.level + '\t' + + portal.team + '\t'; + + $.each([0, 1, 2, 3 ,4 ,5 ,6 ,7], function(ind, slot) { + csv += portal.resonators[slot][0] + '\t'; + }); + + csv += portal.energyratio + '\t' + portal.shields[0][0] + '\t' + portal.shields[1][0] + '\t' + portal.shields[2][0] + '\t' + portal.shields[3][0] + '\t' + portal.APgain + '\t' + portal.EAP + '\t'; + csv += portal.lat + '\t' + portal.lng; + csv += '\n'; + } + }); + + return csv; +} + +window.plugin.portalslist.exportKML = function(){ + var kml = ''; + var filter = window.plugin.portalslist.filter; + // all portals informations are avalaible in the listPortals array + var portals = window.plugin.portalslist.listPortals; + + //headers + kml = '\n' + + 'Ingress Export'; + + // define colored markers as style0 (neutral), style1 (Resistance), style2 (Enlight) + kml += '' + + '' + + '\n'; + + $.each(portals, function(ind, portal) { + // add the portal in the kml file only if part of the filter choice + if (filter === 0 || filter === portal.team){ + // description contain picture of the portal, address and link to the Intel map + var description = '
' + portal.address + + '
Link to Intel Map
' + + ']]>'; + + kml += 'L' + Math.floor(portal.level) + ' - ' + portal.name + '' + + '' + description + '' + + '#style' + portal.team + ''; + + //coordinates + kml += '' + portal.lng + ',' + portal.lat + ',0'; + kml += '\n'; + } + }); + kml += '
'; + return kml; +} + // A little helper functon so the above isn't so messy window.plugin.portalslist.portalTableSort = function(name, by) { var retVal = 'data-sort="' + name + '"'; @@ -286,7 +398,7 @@ window.plugin.portalslist.getPortalLink = function(portal,guid) { onClick: jsSingleClick, onDblClick: jsDoubleClick })[0].outerHTML; - var div = '
'+a+'
'; + var div = '
'+a+'
'; return div; } @@ -302,15 +414,15 @@ var setup = function() { '#portalslist table tr.neutral td { background-color: #000000; }' + '#portalslist table th { text-align:center;}' + '#portalslist table td { text-align: center;}' + - '#portalslist table td.L0 { background-color: #000000 !important;}' + - '#portalslist table td.L1 { background-color: #FECE5A !important;}' + - '#portalslist table td.L2 { background-color: #FFA630 !important;}' + - '#portalslist table td.L3 { background-color: #FF7315 !important;}' + - '#portalslist table td.L4 { background-color: #E40000 !important;}' + - '#portalslist table td.L5 { background-color: #FD2992 !important;}' + - '#portalslist table td.L6 { background-color: #EB26CD !important;}' + - '#portalslist table td.L7 { background-color: #C124E0 !important;}' + - '#portalslist table td.L8 { background-color: #9627F4 !important;}' + + '#portalslist table td.L0 { cursor: help; background-color: #000000 !important;}' + + '#portalslist table td.L1 { cursor: help; background-color: #FECE5A !important;}' + + '#portalslist table td.L2 { cursor: help; background-color: #FFA630 !important;}' + + '#portalslist table td.L3 { cursor: help; background-color: #FF7315 !important;}' + + '#portalslist table td.L4 { cursor: help; background-color: #E40000 !important;}' + + '#portalslist table td.L5 { cursor: help; background-color: #FD2992 !important;}' + + '#portalslist table td.L6 { cursor: help; background-color: #EB26CD !important;}' + + '#portalslist table td.L7 { cursor: help; background-color: #C124E0 !important;}' + + '#portalslist table td.L8 { cursor: help; background-color: #9627F4 !important;}' + '#portalslist table td:nth-child(1) { text-align: left;}' + '#portalslist table th { cursor:pointer; text-align: right;}' + '#portalslist table th:nth-child(1) { text-align: left;}' + diff --git a/plugins/privacy-view.user.js b/plugins/privacy-view.user.js new file mode 100644 index 00000000..a04e358d --- /dev/null +++ b/plugins/privacy-view.user.js @@ -0,0 +1,130 @@ +// ==UserScript== +// @id iitc-plugin-privacy-view@Scrool +// @name IITC plugin: Privacy view on Intel +// @version 1.0.0.@@DATETIMEVERSION@@ +// @namespace https://github.com/jonatkins/ingress-intel-total-conversion +// @description [@@BUILDNAME@@-@@BUILDDATE@@] From Intel hides info which shouldn't leak to players of other fraction +// @updateURL @@UPDATEURL@@ +// @downloadURL @@DOWNLOADURL@@ +// @include https://www.ingress.com/intel* +// @include http://www.ingress.com/intel* +// @match https://www.ingress.com/intel* +// @match http://www.ingress.com/intel* +// ==/UserScript== + +function wrapper() { + +// ensure plugin framework is there, even if iitc is not yet loaded +if(typeof window.plugin !== 'function') + window.plugin = function() {}; + +// PLUGIN START //////////////////////////////////////////////////////// + +// use own namespace for plugin +window.plugin.privacyView = function() {}; + +window.plugin.privacyView.chatExpanded = function() { + return $('#chat, #chatcontrols').hasClass('expand'); +}; + +window.plugin.privacyView.toggle = function() { + var b = $('body'); + var t = $('#privacycontrols .toggle'); + if(b.hasClass('privacy_active')) { + b.removeClass('privacy_active').addClass('privacy_inactive'); + t.text('Privacy inactive'); + } else { + b.removeClass('privacy_inactive').addClass('privacy_active'); + t.text('Privacy active'); + if(window.plugin.privacyView.chatExpanded()) { + window.plugin.privacyView.wrapChatToggle(); + } + } +}; + +window.plugin.privacyView.wrapChatToggle = function() { + window.chat.toggle(); + var c = $('#chat, #chatcontrols'); + if(c.hasClass('expand')) { + $('#privacycontrols').removeClass('shrinked').addClass('expanded'); + } else { + $('#privacycontrols').removeClass('expanded').addClass('shrinked'); + } +}; + +window.plugin.privacyView.setup = function() { + var privacy_button_width = 135; + $('head').append(''); + + $('body').addClass('privacy_inactive'); + + //Wrap iitc chat toggle to update our elements + $('#chatcontrols a:first').unbind('click'); + $('#chatcontrols a:first').click(window.plugin.privacyView.wrapChatToggle); + + $('#chatcontrols').before('
' + + ' ' + + '
'); + $('#privacycontrols a').click(window.plugin.privacyView.toggle); + + window.plugin.privacyView.toggle(); +}; + +var setup = window.plugin.privacyView.setup; + +// PLUGIN END ////////////////////////////////////////////////////////// + +if(window.iitcLoaded && typeof setup === 'function') { + setup(); +} else { + if(window.bootPlugins) + window.bootPlugins.push(setup); + else + window.bootPlugins = [setup]; +} + +} // wrapper end + +// inject code into site context +var script = document.createElement('script'); +script.appendChild(document.createTextNode('('+ wrapper +')();')); +(document.body || document.head || document.documentElement).appendChild(script); diff --git a/plugins/show-linked-portals.user.js b/plugins/show-linked-portals.user.js index e39719cd..99b4f27d 100644 --- a/plugins/show-linked-portals.user.js +++ b/plugins/show-linked-portals.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @id iitc-plugin-show-linked-portals@fstopienski // @name IITC plugin: Show linked portals -// @version 0.0.1.@@DATETIMEVERSION@@ +// @version 0.0.2.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -79,7 +79,8 @@ window.plugin.showLinkedPortal.getPortalByGuid = function (guid) { portalInfoString = ''; var portalNameAdressAlt = "'" + portalDetails.portalV2.descriptiveText.TITLE + "' (" + portalDetails.portalV2.descriptiveText.ADDRESS + ")"; var portalNameAdressTitle = "'" + portalDetails.portalV2.descriptiveText.TITLE + "'
(" + portalDetails.portalV2.descriptiveText.ADDRESS + ")"; - portalInfoString = '' + portalNameAdressAlt + ''; + var imageUrl = (portalDetails.imageByUrl ? portalDetails.imageByUrl.imageUrl : window.DEFAULT_PORTAL_IMG); + portalInfoString = '' + portalNameAdressAlt + ''; } return portalInfoString; }; diff --git a/plugins/show-portal-weakness.user.js b/plugins/show-portal-weakness.user.js index 389d5db9..4815d5b2 100644 --- a/plugins/show-portal-weakness.user.js +++ b/plugins/show-portal-weakness.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @id iitc-plugin-show-portal-weakness@vita10gy // @name IITC plugin: show portal weakness -// @version 0.6.1.@@DATETIMEVERSION@@ +// @version 0.6.2.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -58,7 +58,7 @@ window.plugin.portalWeakness.portalAdded = function(data) { } if(portal_weakness > 0) { - var fill_opacity = portal_weakness*.7 + .3; + var fill_opacity = portal_weakness*.85 + .15; var color = 'orange'; if(only_shields) { color = 'yellow'; diff --git a/screenshots/plugin_keys.png b/screenshots/plugin_keys.png new file mode 100644 index 00000000..fe8dcead Binary files /dev/null and b/screenshots/plugin_keys.png differ diff --git a/screenshots/plugin_keys_on_map.png b/screenshots/plugin_keys_on_map.png new file mode 100644 index 00000000..015aa32b Binary files /dev/null and b/screenshots/plugin_keys_on_map.png differ diff --git a/screenshots/plugin_portal_counts.png b/screenshots/plugin_portal_counts.png new file mode 100755 index 00000000..0a5985ea Binary files /dev/null and b/screenshots/plugin_portal_counts.png differ diff --git a/style.css b/style.css index 5cc5249b..8190eb7b 100644 --- a/style.css +++ b/style.css @@ -14,7 +14,8 @@ body { } #scrollwrapper { - overflow: hidden; + overflow-x: hidden; + overflow-y: auto; position: fixed; right: -38px; top: 0;