Actually no need for poly counts 2+new function ordering for readability

This commit is contained in:
cyi1341 2023-10-07 20:24:34 +08:00
parent aa60d60fd5
commit c6c255c7d1
1 changed files with 413 additions and 404 deletions

View File

@ -13,428 +13,437 @@
// ==/UserScript==
function wrapper(plugin_info) {
if (typeof window.plugin !== 'function') window.plugin = function() {};
plugin_info.pluginId = 'portalsJSON';
window.plugin.portalsJSON = function() {};
var portalsData = new Map(); // More efficient data lookup
let startTime = null;
let exportTime = null;
if (typeof window.plugin !== 'function') window.plugin = function() {};
plugin_info.pluginId = 'portalsJSON';
window.plugin.portalsJSON = function() {};
var portalsData = new Map(); // More efficient data lookup
let startTime = null;
let exportTime = null;
window.plugin.portalsJSON.pnpoly = function (latlngs, point) {
var length = latlngs.length, c = false;
for (var i = 0, j = length - 1; i < length; j = i++) {
if (((latlngs[i].lat > point.lat) != (latlngs[j].lat > point.lat)) &&
(point.lng < latlngs[i].lng + (latlngs[j].lng - latlngs[i].lng) * (point.lat - latlngs[i].lat) / (latlngs[j].lat - latlngs[i].lat))) {
c = !c;
}
}
return c;
}
window.plugin.portalsJSON.processPortal = function(portal) {
if (!('title' in portal.options.data)) return;
var portalData = {};
window.plugin.portalsJSON.fields.forEach(function(field) {
var value = field.value(portal);
portalData[field.title] = value;
});
portalsData.set(portal.options.guid, portalData);
};
window.plugin.portalsJSON.exportData = function() {
portalsData.clear(); // Clear the map before exporting
startTime = new Date();
var displayBounds = map.getBounds();
Object.values(window.portals).forEach(function (portal, index) {
if (!displayBounds.contains(portal.getLatLng())) return;
window.plugin.portalsJSON.processPortal(portal);
});
var jsonData = JSON.stringify(Array.from(portalsData.values()), null, 2);
var blob = new Blob([jsonData], { type: 'application/json' });
var url = URL.createObjectURL(blob);
var link = document.createElement('a');
link.href = url;
link.download = 'portals.json';
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
exportTime = new Date();
}
window.plugin.portalsJSON.circleToSearchCircle = function (drawnItem) {
var circleCenter = drawnItem.getLatLng();
var result = { type: 'circle', radius: drawnItem.getRadius(), center: new L.LatLng(circleCenter.lat, circleCenter.lng) };
return result;
};
window.plugin.portalsJSON.multiPolygonToSearchPolygons = function (drawnItem) {
var result = [];
var polygonArr = [];
if (drawnItem instanceof L.GeodesicPolygon) {
if (typeof drawnItem._latlngs != "undefined" && drawnItem._latlngs.length > 0) {
if (typeof drawnItem._latlngs[0].lng == "number") {
polygonArr = drawnItem._latlngs.map(function (item) { return [item.lng, item.lat] });
polygonArr = [polygonArr];
} else if (typeof drawnItem._latlngs[0][0].lng == "number") {
$.each(drawnItem._latlngs, function (i, latLngs) {
var innerPolygonArr = latLngs.map(function (item) { return [item.lng, item.lat] });
polygonArr.push(innerPolygonArr);
});
}
}
}
$.each(polygonArr, function (i, polygonCoords) {
var searchPolygon = {
type: 'polygon',
outerRing: [],
holes: []
};
if (polygonCoords[0].length == 2 && typeof polygonCoords[0][0] == "number") {
polygonCoords = [polygonCoords];
}
$.each(polygonCoords, function (j, linearRing) {
var latLngArr = [];
$.each(linearRing, function (k, latlng) {
var obj = { lng: latlng[0], lat: latlng[1] };
latLngArr.push(obj);
});
if (j == 0) {
searchPolygon.outerRing = latLngArr;
}
else {
searchPolygon.holes.push(latLngArr);
}
});
result.push(searchPolygon);
});
return result;
};
window.plugin.portalsJSON.pointIsInPolygon = function (point, searchItem) {
var nodeIn = window.plugin.portalsJSON.pnpoly(searchItem.outerRing, point);
$.each(searchItem.holes, function (index, hole) {
var inHole = window.plugin.portalsJSON.pnpoly(hole, point);
if (inHole) {
nodeIn = false;
return false;
}
});
return nodeIn;
};
window.plugin.portalsJSON.pointIsInCircle = function (point, searchItem) {
var found = false;
if (searchItem.center.distanceTo(point) <= searchItem.radius) {
found = true;
}
return found;
};
window.plugin.portalsJSON.exportPolygons = function() {
portalsData.clear(); // Clear the map before exporting
startTime = new Date();
var searchItems = []; // Data about shapes that will be searched for portals
// Process drawn items
if (window.plugin.drawTools && window.plugin.drawTools.drawnItems) {
window.plugin.drawTools.drawnItems.eachLayer(function (drawnItem) {
if (drawnItem instanceof L.GeodesicCircle) {
var searchCircle = window.plugin.portalsJSON.circleToSearchCircle(drawnItem);
searchItems.push(searchCircle);
}
else if (drawnItem instanceof L.GeodesicPolygon) {
var searchPolygons = window.plugin.portalsJSON.multiPolygonToSearchPolygons(drawnItem);
$.each(searchPolygons, function (index, searchItem) {
searchItems.push(searchItem);
});
}
});
}
// Process search result areas
if (window.search.lastSearch &&
window.search.lastSearch.selectedResult &&
window.search.lastSearch.selectedResult.layer) {
window.search.lastSearch.selectedResult.layer.eachLayer(function (drawnItem) {
if (drawnItem instanceof L.Polygon || (typeof L.MultiPolygon == "function" && drawnItem instanceof L.MultiPolygon)) {
var searchPolygons = window.plugin.portalsJSON.multiPolygonToSearchPolygons(drawnItem);
$.each(searchPolygons, function (index, searchItem) {
searchItems.push(searchItem);
window.plugin.portalsJSON.fields = [
{
title: 'Portal Name',
value: function(portal) {
return portal.options.data.title;
},
},
{
title: 'Level',
value: function(portal) {
return portal.options.data.level;
},
},
{
title: 'Team',
value: function(portal) {
var team = portal.options.team;
switch (team) {
case 0:
return 'Neutral';
case 1:
return 'Resistance';
case 2:
return 'Enlightened';
case 3:
return '_MACHINA_';
default:
return 'Unknown';
}
},
},
{
title: 'Health',
value: function(portal) {
return portal.options.data.health;
},
},
{
title: 'Resonators',
value: function(portal) {
return portal.options.data.resCount;
},
},
{
title: 'Links',
value: function(portal) {
var links = window.getPortalLinks(portal.options.guid);
portal.links = links; // Save the computed links for reuse
return links.in.length + links.out.length;
},
},
{
title: 'Fields',
value: function(portal) {
return getPortalFieldsCount(portal.options.guid);
},
},
{
title: 'AP',
value: function(portal) {
var links = portal.links; // Use the previously computed links
var fields = getPortalFieldsCount(portal.options.guid);
return portalApGainMaths(portal.options.data.resCount, links.in.length + links.out.length, fields);
},
},
{
title: 'Latitude',
value: function(portal) {
var latLng = portal.getLatLng();
return latLng.lat;
},
},
{
title: 'Longitude',
value: function(portal) {
var latLng = portal.getLatLng();
return latLng.lng;
},
},
{
title: 'Image URL',
value: function(portal) {
return portal.options.data.image;
}
},
{
title: 'GUID',
value: function(portal) {
return portal.options.guid;
}
},
{
title: 'Incoming Links',
value: function(portal) {
var links = portal.links; // Use the previously computed links
return links.in.map(function(linkGuid) {
var link = window.links[linkGuid].options.data;
var GUID = link.oGuid;
var Latitude = link.oLatE6 / 1E6;
var Longitude = link.oLngE6 / 1E6;
var data = (window.portals[GUID] && window.portals[GUID].options.data) || window.portalDetail.get(GUID) || {};
return {
'GUID': GUID,
'Latitude': Latitude,
'Longitude': Longitude,
'Portal Name': data.title
};
});
}
},
},
{
title: 'Outgoing Links',
value: function(portal) {
var links = portal.links; // Use the previously computed links
return links.out.map(function(linkGuid) {
var link = window.links[linkGuid].options.data;
var GUID = link.dGuid;
var Latitude = link.dLatE6 / 1E6;
var Longitude = link.dLngE6 / 1E6;
var data = (window.portals[GUID] && window.portals[GUID].options.data) || window.portalDetail.get(GUID) || {};
return {
'GUID': GUID,
'Latitude': Latitude,
'Longitude': Longitude,
'Portal Name': data.title
};
});
},
},
{
title: 'Scanner Link',
value: function(portal) {
var latLng = portal.getLatLng();
return 'https://link.ingress.com/?link=https%3A%2F%2Fintel.ingress.com%2Fportal%2F' + portal.options.guid + '&apn=com.nianticproject.ingress&isi=576505181&ibi=com.google.ingress&ifl=https%3A%2F%2Fapps.apple.com%2Fapp%2Fingress%2Fid576505181&ofl=https%3A%2F%2Fintel.ingress.com%2Fintel%3Fpll%3D' + latLng.lat + '%2C' + latLng.lng;
},
},
];
window.plugin.portalsJSON.processPortal = function(portal) {
if (!('title' in portal.options.data)) return;
var portalData = {};
window.plugin.portalsJSON.fields.forEach(function(field) {
var value = field.value(portal);
portalData[field.title] = value;
});
portalsData.set(portal.options.guid, portalData);
};
window.plugin.portalsJSON.exportData = function() {
portalsData.clear(); // Clear the map before exporting
startTime = new Date();
var displayBounds = map.getBounds();
Object.values(window.portals).forEach(function (portal, index) {
if (!displayBounds.contains(portal.getLatLng())) return;
window.plugin.portalsJSON.processPortal(portal);
});
var jsonData = JSON.stringify(Array.from(portalsData.values()), null, 2);
var blob = new Blob([jsonData], { type: 'application/json' });
var url = URL.createObjectURL(blob);
var link = document.createElement('a');
link.href = url;
link.download = 'portals.json';
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
exportTime = new Date();
}
// Process portals
$.each(window.portals, function (guid, portal) {
var point = portal.getLatLng();
var found = false;
$.each(searchItems, function (index, searchItem) {
switch (searchItem.type) {
case 'circle':
if (window.plugin.portalsJSON.pointIsInCircle(point, searchItem)) {
found = true;
return false; // Breaks the loop
window.plugin.portalsJSON.pnpoly = function (latlngs, point) {
var length = latlngs.length, c = false;
for (var i = 0, j = length - 1; i < length; j = i++) {
if (((latlngs[i].lat > point.lat) != (latlngs[j].lat > point.lat)) &&
(point.lng < latlngs[i].lng + (latlngs[j].lng - latlngs[i].lng) * (point.lat - latlngs[i].lat) / (latlngs[j].lat - latlngs[i].lat))) {
c = !c;
}
break;
case 'polygon':
if (window.plugin.portalsJSON.pointIsInPolygon(point, searchItem)) {
found = true;
return false; // Breaks the loop
}
break;
};
});
if (found) {
window.plugin.portalsJSON.processPortal(portal);
}
});
// Export data
var jsonData = JSON.stringify(Array.from(portalsData.values()), null, 2);
var blob = new Blob([jsonData], { type: 'application/json' });
var url = URL.createObjectURL(blob);
var link = document.createElement('a');
link.href = url;
link.download = 'polygons.json';
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
exportTime = new Date();
}
function downloadFile(data, filename) {
var link = document.createElement('a');
link.href = 'data:text/json;charset=utf-8,' + encodeURIComponent(data);
link.download = filename;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
window.plugin.portalsJSON.fields = [
{
title: 'Portal Name',
value: function(portal) {
return portal.options.data.title;
},
},
{
title: 'Level',
value: function(portal) {
return portal.options.data.level;
},
},
{
title: 'Team',
value: function(portal) {
var team = portal.options.team;
switch (team) {
case 0:
return 'Neutral';
case 1:
return 'Resistance';
case 2:
return 'Enlightened';
case 3:
return '_MACHINA_';
default:
return 'Unknown';
}
},
},
{
title: 'Health',
value: function(portal) {
return portal.options.data.health;
},
},
{
title: 'Resonators',
value: function(portal) {
return portal.options.data.resCount;
},
},
{
title: 'Links',
value: function(portal) {
var links = window.getPortalLinks(portal.options.guid);
portal.links = links; // Save the computed links for reuse
return links.in.length + links.out.length;
},
},
{
title: 'Fields',
value: function(portal) {
return getPortalFieldsCount(portal.options.guid);
},
},
{
title: 'AP',
value: function(portal) {
var links = portal.links; // Use the previously computed links
var fields = getPortalFieldsCount(portal.options.guid);
return portalApGainMaths(portal.options.data.resCount, links.in.length + links.out.length, fields);
},
},
{
title: 'Latitude',
value: function(portal) {
var latLng = portal.getLatLng();
return latLng.lat;
},
},
{
title: 'Longitude',
value: function(portal) {
var latLng = portal.getLatLng();
return latLng.lng;
},
},
{
title: 'Image URL',
value: function(portal) {
return portal.options.data.image;
}
},
{
title: 'GUID',
value: function(portal) {
return portal.options.guid;
}
},
{
title: 'Incoming Links',
value: function(portal) {
var links = portal.links; // Use the previously computed links
return links.in.map(function(linkGuid) {
var link = window.links[linkGuid].options.data;
var GUID = link.oGuid;
var Latitude = link.oLatE6 / 1E6;
var Longitude = link.oLngE6 / 1E6;
var data = (window.portals[GUID] && window.portals[GUID].options.data) || window.portalDetail.get(GUID) || {};
return {
'GUID': GUID,
'Latitude': Latitude,
'Longitude': Longitude,
'Portal Name': data.title
};
return c;
};
window.plugin.portalsJSON.pointIsInPolygon = function (point, searchItem) {
var nodeIn = window.plugin.portalsJSON.pnpoly(searchItem.outerRing, point);
$.each(searchItem.holes, function (index, hole) {
var inHole = window.plugin.portalsJSON.pnpoly(hole, point);
if (inHole) {
nodeIn = false;
return false;
}
});
},
},
{
title: 'Outgoing Links',
value: function(portal) {
var links = portal.links; // Use the previously computed links
return links.out.map(function(linkGuid) {
var link = window.links[linkGuid].options.data;
var GUID = link.dGuid;
var Latitude = link.dLatE6 / 1E6;
var Longitude = link.dLngE6 / 1E6;
var data = (window.portals[GUID] && window.portals[GUID].options.data) || window.portalDetail.get(GUID) || {};
return {
'GUID': GUID,
'Latitude': Latitude,
'Longitude': Longitude,
'Portal Name': data.title
};
return nodeIn;
};
window.plugin.portalsJSON.pointIsInMultiPolygon = function (point, searchItem) {
var nodeIn = false;
$.each(searchItem, function (index, polygon) {
if (window.plugin.portalsJSON.pointIsInPolygon(point, polygon)) {
nodeIn = true;
return false;
}
});
},
},
{
title: 'Scanner Link',
value: function(portal) {
var latLng = portal.getLatLng();
return 'https://link.ingress.com/?link=https%3A%2F%2Fintel.ingress.com%2Fportal%2F' + portal.options.guid + '&apn=com.nianticproject.ingress&isi=576505181&ibi=com.google.ingress&ifl=https%3A%2F%2Fapps.apple.com%2Fapp%2Fingress%2Fid576505181&ofl=https%3A%2F%2Fintel.ingress.com%2Fintel%3Fpll%3D' + latLng.lat + '%2C' + latLng.lng;
},
},
];
return nodeIn;
};
window.plugin.portalsJSON.multiPolygonToSearchPolygons = function (drawnItem) {
var result = [];
var polygonArr = [];
if (drawnItem instanceof L.GeodesicPolygon) {
if (typeof drawnItem._latlngs != "undefined" && drawnItem._latlngs.length > 0) {
if (typeof drawnItem._latlngs[0].lng == "number") {
polygonArr = drawnItem._latlngs.map(function (item) { return [item.lng, item.lat] });
polygonArr = [polygonArr];
} else if (typeof drawnItem._latlngs[0][0].lng == "number") {
$.each(drawnItem._latlngs, function (i, latLngs) {
var innerPolygonArr = latLngs.map(function (item) { return [item.lng, item.lat] });
polygonArr.push(innerPolygonArr);
});
}
}
}
else {
polygonArr = drawnItem.toGeoJSON().geometry.coordinates;
if (polygonArr[0].length == 2 && typeof polygonArr[0][0] == "number") {
polygonArr = [polygonArr];
}
}
window.plugin.portalsJSON.displayPL = function() {
var button = document.createElement('button');
button.textContent = 'Export Data to JSON';
button.addEventListener('click', window.plugin.portalsJSON.exportData);
var polygonButton = document.createElement('button');
polygonButton.textContent = 'Export Polygons';
polygonButton.addEventListener('click', window.plugin.portalsJSON.exportPolygons);
var breakLine = document.createElement('br'); // Line break
var timer = document.createElement('span');
timer.id = 'exportTimer';
var container = document.createElement('div');
container.appendChild(button);
container.appendChild(polygonButton);
container.appendChild(timer);
$.each(polygonArr, function (i, polygonCoords) {
var searchPolygon = {
type: 'polygon',
outerRing: [],
holes: []
};
if (polygonCoords[0].length == 2 && typeof polygonCoords[0][0] == "number") {
polygonCoords = [polygonCoords];
}
// create a separate div for timer
var timerDiv = document.createElement('div');
timerDiv.appendChild(timer);
container.appendChild(breakLine);
container.appendChild(timerDiv);
$.each(polygonCoords, function (j, linearRing) {
var latLngArr = [];
$.each(linearRing, function (k, latlng) {
var obj = { lng: latlng[0], lat: latlng[1] };
latLngArr.push(obj);
});
if (j == 0) {
searchPolygon.outerRing = latLngArr;
}
else {
searchPolygon.holes.push(latLngArr);
}
});
result.push(searchPolygon);
});
return result;
};
if (window.useAppPanes()) {
var pane = app.panes.find(function(pane) { return pane.name === 'plugin-portalsJSON'; });
pane.setContent(container);
} else {
var dialogContainer = document.createElement('div');
dialogContainer.appendChild(container);
dialogContainer.setAttribute('class', 'ui-dialog-portalsJSON');
dialogContainer.title = 'Portal JSON';
dialogContainer.id = 'portal-JSON';
dialogContainer.style.width = '400px';
dialog({
html: dialogContainer,
});
window.plugin.portalsJSON.exportPolygons = function() {
portalsData.clear(); // Clear the map before exporting
startTime = new Date();
var searchItems = []; // Data about shapes that will be searched for portals
// Process drawn items
if (window.plugin.drawTools && window.plugin.drawTools.drawnItems) {
window.plugin.drawTools.drawnItems.eachLayer(function (drawnItem) {
if (drawnItem instanceof L.GeodesicCircle) {
var searchCircle = window.plugin.portalsJSON.circleToSearchCircle(drawnItem);
searchItems.push(searchCircle);
}
else if (drawnItem instanceof L.GeodesicPolygon) {
var searchPolygons = window.plugin.portalsJSON.multiPolygonToSearchPolygons(drawnItem);
$.each(searchPolygons, function (index, searchItem) {
searchItems.push(searchItem);
});
}
});
}
// Process search result areas
if (window.search.lastSearch &&
window.search.lastSearch.selectedResult &&
window.search.lastSearch.selectedResult.layer) {
window.search.lastSearch.selectedResult.layer.eachLayer(function (drawnItem) {
if (drawnItem instanceof L.Polygon || (typeof L.MultiPolygon == "function" && drawnItem instanceof L.MultiPolygon)) {
var searchPolygons = window.plugin.portalsJSON.multiPolygonToSearchPolygons(drawnItem);
$.each(searchPolygons, function (index, searchItem) {
searchItems.push(searchItem);
});
}
});
}
// Process portals
$.each(window.portals, function (guid, portal) {
var point = portal.getLatLng();
var found = false;
$.each(searchItems, function (index, searchItem) {
switch (searchItem.type) {
case 'circle':
if (window.plugin.portalsJSON.pointIsInCircle(point, searchItem)) {
found = true;
return false; // Breaks the loop
}
break;
case 'polygon':
if (window.plugin.portalsJSON.pointIsInPolygon(point, searchItem)) {
found = true;
return false; // Breaks the loop
}
break;
case 'multipolygon':
if (window.plugin.portalsJSON.pointIsInMultiPolygon(point, searchItem.polygons)) {
found = true;
return false; // Breaks the loop
}
break;
};
});
if (found) {
window.plugin.portalsJSON.processPortal(portal);
}
});
// Export data
var jsonData = JSON.stringify(Array.from(portalsData.values()), null, 2);
var blob = new Blob([jsonData], { type: 'application/json' });
var url = URL.createObjectURL(blob);
var link = document.createElement('a');
link.href = url;
link.download = 'polygons.json';
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
exportTime = new Date();
}
};
window.plugin.portalsJSON.onPaneChanged = function(pane) {
if (pane === 'plugin-portalsJSON') {
window.plugin.portalsJSON.displayPL();
function downloadFile(data, filename) {
var link = document.createElement('a');
link.href = 'data:text/json;charset=utf-8,' + encodeURIComponent(data);
link.download = filename;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
};
setInterval(function() {
if (startTime && exportTime) {
var elapsedTime = (exportTime - startTime) / 1000;
document.querySelector('#exportTimer').textContent = `Export Time: ${elapsedTime} seconds`;
}
}, 1000);
window.plugin.portalsJSON.displayPL = function() {
var button = document.createElement('button');
button.textContent = 'Export Data to JSON';
button.addEventListener('click', window.plugin.portalsJSON.exportData);
var polygonButton = document.createElement('button');
polygonButton.textContent = 'Export Polygons';
polygonButton.addEventListener('click', window.plugin.portalsJSON.exportPolygons);
var breakLine = document.createElement('br'); // Line break
var timer = document.createElement('span');
timer.id = 'exportTimer';
var container = document.createElement('div');
container.appendChild(button);
container.appendChild(polygonButton);
container.appendChild(timer);
var setup = function() {
if (window.useAppPanes()) {
app.addPane('plugin-portalsJSON', 'Portals JSON', 'ic_action_paste');
addHook('paneChanged', window.plugin.portalsJSON.onPaneChanged);
window.plugin.portalsJSON.onPaneChanged('plugin-portalsJSON'); // Manually trigger pane changed to display button
} else {
var portalJSONLink = document.createElement('a');
portalJSONLink.setAttribute('title', 'Exports a JSON of portals in the current view [j]');
portalJSONLink.setAttribute('accesskey', 'j');
portalJSONLink.textContent = 'Portals JSON';
portalJSONLink.addEventListener('click', function() {
window.plugin.portalsJSON.displayPL();
});
document.querySelector('#toolbox').appendChild(portalJSONLink);
}
};
// inject code into site context
setup.info = plugin_info; //add the script info data to the function as a property
if (!window.bootPlugins) window.bootPlugins = [];
window.bootPlugins.push(setup);
if (window.iitcLoaded && typeof setup === 'function') setup();
// create a separate div for timer
var timerDiv = document.createElement('div');
timerDiv.appendChild(timer);
container.appendChild(breakLine);
container.appendChild(timerDiv);
if (window.useAppPanes()) {
var pane = app.panes.find(function(pane) { return pane.name === 'plugin-portalsJSON'; });
pane.setContent(container);
} else {
var dialogContainer = document.createElement('div');
dialogContainer.appendChild(container);
dialogContainer.setAttribute('class', 'ui-dialog-portalsJSON');
dialogContainer.title = 'Portal JSON';
dialogContainer.id = 'portal-JSON';
dialogContainer.style.width = '400px';
dialog({
html: dialogContainer,
});
}
};
window.plugin.portalsJSON.onPaneChanged = function(pane) {
if (pane === 'plugin-portalsJSON') {
window.plugin.portalsJSON.displayPL();
}
};
setInterval(function() {
if (startTime && exportTime) {
var elapsedTime = (exportTime - startTime) / 1000;
document.querySelector('#exportTimer').textContent = `Export Time: ${elapsedTime} seconds`;
}
}, 1000);
var setup = function() {
if (window.useAppPanes()) {
app.addPane('plugin-portalsJSON', 'Portals JSON', 'ic_action_paste');
addHook('paneChanged', window.plugin.portalsJSON.onPaneChanged);
window.plugin.portalsJSON.onPaneChanged('plugin-portalsJSON'); // Manually trigger pane changed to display button
} else {
var portalJSONLink = document.createElement('a');
portalJSONLink.setAttribute('title', 'Exports a JSON of portals in the current view [j]');
portalJSONLink.setAttribute('accesskey', 'j');
portalJSONLink.textContent = 'Portals JSON';
portalJSONLink.addEventListener('click', function() {
window.plugin.portalsJSON.displayPL();
});
document.querySelector('#toolbox').appendChild(portalJSONLink);
}
};
// inject code into site context
setup.info = plugin_info; //add the script info data to the function as a property
if (!window.bootPlugins) window.bootPlugins = [];
window.bootPlugins.push(setup);
if (window.iitcLoaded && typeof setup === 'function') setup();
}
// inject code into site context