first update of sidebar for new data format: show the info available from the brief portal data
TODO: retrieve the full portal data and update to include that
This commit is contained in:
parent
c197f74945
commit
7a19d30173
41
code/portal_data.js
Normal file
41
code/portal_data.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/// PORTAL DATA TOOLS ///////////////////////////////////////////////////
|
||||||
|
// misc functions to get portal info
|
||||||
|
|
||||||
|
// search through the links data for all that link from or to a portal. returns an object with separate lists of in
|
||||||
|
// and out links. may or may not be as accurate as the portal details, depending on how much data the API returns
|
||||||
|
window.getPortalLinks = function(guid) {
|
||||||
|
|
||||||
|
var links = { in: [], out: [] };
|
||||||
|
|
||||||
|
$.each(window.links, function(g,l) {
|
||||||
|
var d = l.options.data;
|
||||||
|
|
||||||
|
if (d.oGuid == guid) {
|
||||||
|
links.out.push(g);
|
||||||
|
}
|
||||||
|
if (d.dGuid == guid) {
|
||||||
|
links.in.push(g);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return links;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// search through the fields for all that reference a portal
|
||||||
|
window.getPortalFields = function(guid) {
|
||||||
|
var fields = [];
|
||||||
|
|
||||||
|
$.each(window.fields, function(g,f) {
|
||||||
|
var d = f.options.data;
|
||||||
|
|
||||||
|
if ( d.points[0].guid == guid
|
||||||
|
|| d.points[1].guid == guid
|
||||||
|
|| d.points[2].guid == guid ) {
|
||||||
|
|
||||||
|
fields.push(g);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
@ -3,81 +3,42 @@
|
|||||||
// methods that highlight the portal in the map view.
|
// methods that highlight the portal in the map view.
|
||||||
|
|
||||||
window.renderPortalDetails = function(guid) {
|
window.renderPortalDetails = function(guid) {
|
||||||
|
// TODO: start a request for the selected portal detailed data
|
||||||
|
// (do this even if not in window.portals?)
|
||||||
|
|
||||||
selectPortal(window.portals[guid] ? guid : null);
|
selectPortal(window.portals[guid] ? guid : null);
|
||||||
|
|
||||||
|
|
||||||
if(!window.portals[guid]) {
|
if(!window.portals[guid]) {
|
||||||
urlPortal = guid;
|
urlPortal = guid;
|
||||||
$('#portaldetails').html('');
|
$('#portaldetails').html('');
|
||||||
if(isSmartphone()) {
|
if(isSmartphone()) {
|
||||||
$('.fullimg').remove();
|
$('.fullimg').remove();
|
||||||
$('#mobileinfo').html('');
|
$('#mobileinfo').html('<div style="text-align: center"><b>tap here for info screen</b></div>');
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var d = window.portals[guid].options.details;
|
var portal = window.portals[guid];
|
||||||
|
var data = portal.options.data;
|
||||||
// collect some random data that’s not worth to put in an own method
|
var details = undefined; //TODO: get the details
|
||||||
var links = {incoming: 0, outgoing: 0};
|
|
||||||
if(d.portalV2.linkedEdges) $.each(d.portalV2.linkedEdges, function(ind, link) {
|
|
||||||
links[link.isOrigin ? 'outgoing' : 'incoming']++;
|
|
||||||
});
|
|
||||||
function linkExpl(t) { return '<tt title="↳ incoming links\n↴ outgoing links\n• is the portal">'+t+'</tt>'; }
|
|
||||||
var linksText = [linkExpl('links'), linkExpl(' ↳ ' + links.incoming+' • '+links.outgoing+' ↴')];
|
|
||||||
|
|
||||||
var player = d.captured && d.captured.capturingPlayerId
|
|
||||||
? '<span class="nickname">' + getPlayerName(d.captured.capturingPlayerId) + '</span>'
|
|
||||||
: null;
|
|
||||||
var playerText = player ? ['owner', player] : null;
|
|
||||||
|
|
||||||
var time = d.captured
|
|
||||||
? '<span title="' + unixTimeToDateTimeString(d.captured.capturedTime, false) + '\n'
|
|
||||||
+ formatInterval(Math.floor((Date.now()-d.captured.capturedTime)/1000), 2) + ' ago">'
|
|
||||||
+ unixTimeToString(d.captured.capturedTime) + '</span>'
|
|
||||||
: null;
|
|
||||||
var sinceText = time ? ['since', time] : null;
|
|
||||||
|
|
||||||
var linkedFields = ['fields', d.portalV2.linkedFields ? d.portalV2.linkedFields.length : 0];
|
|
||||||
|
|
||||||
// collect and html-ify random data
|
|
||||||
var randDetails = [
|
|
||||||
playerText, sinceText,
|
|
||||||
getRangeText(d), getEnergyText(d),
|
|
||||||
linksText, getAvgResoDistText(d),
|
|
||||||
linkedFields, getAttackApGainText(d),
|
|
||||||
getHackDetailsText(d), getMitigationText(d)
|
|
||||||
];
|
|
||||||
|
|
||||||
// artifact details
|
|
||||||
|
|
||||||
//niantic hard-code the fact it's just jarvis shards/targets - so until more examples exist, we'll do the same
|
|
||||||
//(at some future point we can iterate through all the artifact types and add rows as needed)
|
|
||||||
var jarvisArtifact = artifact.getPortalData (guid, 'jarvis');
|
|
||||||
if (jarvisArtifact) {
|
|
||||||
// the genFourColumnTable function below doesn't handle cases where one column is null and the other isn't - so default to *something* in both columns
|
|
||||||
var target = ['',''], shards = ['shards','(none)'];
|
|
||||||
if (jarvisArtifact.target) {
|
|
||||||
target = ['target', '<span class="'+TEAM_TO_CSS[jarvisArtifact.target]+'">'+(jarvisArtifact.target==TEAM_RES?'Resistance':'Enlightened')+'</span>'];
|
|
||||||
}
|
|
||||||
if (jarvisArtifact.fragments) {
|
|
||||||
shards = [jarvisArtifact.fragments.length>1?'shards':'shard', '#'+jarvisArtifact.fragments.join(', #')];
|
|
||||||
}
|
|
||||||
|
|
||||||
randDetails.push (target, shards);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
randDetails = '<table id="randdetails">' + genFourColumnTable(randDetails) + '</table>';
|
var modDetails = details ? '<div class="mods">'+getModDetails(details)+'</div>' : '';
|
||||||
|
var randDetails = details ? getPortalRandDetails(details) : '';
|
||||||
|
var resoDetails = details ? getResonatorDetails(details) : '';
|
||||||
|
|
||||||
var resoDetails = '<table id="resodetails">' + getResonatorDetails(d) + '</table>';
|
|
||||||
|
|
||||||
var img = getPortalImageUrl(d);
|
|
||||||
var lat = d.locationE6.latE6/1E6;
|
|
||||||
var lng = d.locationE6.lngE6/1E6;
|
var img = fixPortalImageUrl(details ? details.imageByUrl && details.imageByUrl.imageUrl : data.image);
|
||||||
var perma = '/intel?ll='+lat+','+lng+'&z=17&pll='+lat+','+lng;
|
var title = details ? details.portalV2.descriptiveText.TITLE : data.title;
|
||||||
var imgTitle = 'title="'+getPortalDescriptionFromDetails(d)+'\n\nClick to show full image."';
|
|
||||||
var poslinks = 'window.showPortalPosLinks('+lat+','+lng+',\''+escapeJavascriptString(d.portalV2.descriptiveText.TITLE)+'\')';
|
var lat = data.latE6/1E6;
|
||||||
var portalDetailObj = window.getPortalDescriptionFromDetailsExtended(d);
|
var lng = data.lngE6/1E6;
|
||||||
|
|
||||||
|
var imgTitle = ''; //'title="'+getPortalDescriptionFromDetails(details)+'\n\nClick to show full image."';
|
||||||
|
var portalDetailObj = undefined; //window.getPortalDescriptionFromDetailsExtended(details);
|
||||||
|
|
||||||
var portalDetailedDescription = '';
|
var portalDetailedDescription = '';
|
||||||
|
|
||||||
@ -111,71 +72,182 @@ window.renderPortalDetails = function(guid) {
|
|||||||
portalDetailedDescription += '</table>';
|
portalDetailedDescription += '</table>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var levelDetails = getPortalLevel(d);
|
// portal level. start with basic data - then extend with fractional info in tooltip if available
|
||||||
if(levelDetails != 8) {
|
var levelInt = data ? data.level : getPortalLevel(details);
|
||||||
if(levelDetails==Math.ceil(levelDetails))
|
var levelDetails = data.level;
|
||||||
levelDetails += "\n8";
|
if (details) {
|
||||||
else
|
levelDetails = getPortalLevel(details);
|
||||||
levelDetails += "\n" + (Math.ceil(levelDetails) - levelDetails)*8;
|
if(levelDetails != 8) {
|
||||||
levelDetails += " resonator level(s) needed for next portal level";
|
if(levelDetails==Math.ceil(levelDetails))
|
||||||
} else {
|
levelDetails += "\n8";
|
||||||
levelDetails += "\nfully upgraded";
|
else
|
||||||
|
levelDetails += "\n" + (Math.ceil(levelDetails) - levelDetails)*8;
|
||||||
|
levelDetails += " resonator level(s) needed for next portal level";
|
||||||
|
} else {
|
||||||
|
levelDetails += "\nfully upgraded";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
levelDetails = "Level " + levelDetails;
|
levelDetails = "Level " + levelDetails;
|
||||||
|
|
||||||
|
|
||||||
|
var linkDetails = [];
|
||||||
|
|
||||||
|
var posOnClick = 'window.showPortalPosLinks('+lat+','+lng+',\''+escapeJavascriptString(title)+'\')';
|
||||||
|
var permalinkUrl = '/intel?ll='+lat+','+lng+'&z=17&pll='+lat+','+lng;
|
||||||
|
|
||||||
|
if (typeof android !== 'undefined' && android && android.intentPosLink) {
|
||||||
|
// android devices. one share link option - and the android app provides an interface to share the URL,
|
||||||
|
// share as a geo: intent (navigation via google maps), etc
|
||||||
|
|
||||||
|
var shareLink = $('<div>').html( $('<a>').attr({onclick:posOnClick}).text('Share portal') ).html();
|
||||||
|
linkDetails.push('<aside>'+shareLink+'</aside>');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// non-android - a permalink for the portal
|
||||||
|
var permaHtml = $('<div>').html( $('<a>').attr({href:permalinkUrl, target:'_blank', title:'Create a URL link to this portal'}).text('Portal link') ).html();
|
||||||
|
linkDetails.push ( '<aside>'+permaHtml+'</aside>' );
|
||||||
|
|
||||||
|
// and a map link popup dialog
|
||||||
|
var mapHtml = $('<div>').html( $('<a>').attr({onclick:posOnClick, title:'Link to alternative maps (Google, etc)'}).text('Map links') ).html();
|
||||||
|
linkDetails.push('<aside>'+mapHtml+'</aside>');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
$('#portaldetails')
|
$('#portaldetails')
|
||||||
.attr('class', TEAM_TO_CSS[getTeam(d)])
|
.html('') //to ensure it's clear
|
||||||
.html(''
|
.attr('class', TEAM_TO_CSS[portal.options.team])
|
||||||
+ '<h3 class="title">'+escapeHtmlSpecialChars(d.portalV2.descriptiveText.TITLE)+'</h3>'
|
.append(
|
||||||
+ '<span class="close" onclick="renderPortalDetails(null); if(isSmartphone()) show(\'map\');" title="Close">X</span>'
|
$('<h3>').attr({class:'title'}).text(data.title),
|
||||||
|
|
||||||
|
$('<span>').attr({class:'close', onclick:'renderPortalDetails(null); if(isSmartphone()) show("map");',title:'Close'}).text('X'),
|
||||||
|
|
||||||
// help cursor via ".imgpreview img"
|
// help cursor via ".imgpreview img"
|
||||||
+ '<div class="imgpreview" '+imgTitle+' style="background-image: url('+img+')">'
|
$('<div>')
|
||||||
+ '<span id="level" title="'+levelDetails+'">'+Math.floor(getPortalLevel(d))+'</span>'
|
.attr({class:'imgpreview', title:imgTitle, style:"background-image: url('"+img+"')"})
|
||||||
+ '<div class="portalDetails">'+ portalDetailedDescription + '</div>'
|
.append(
|
||||||
+ '<img class="hide" src="'+img+'"/></div>'
|
$('<span>').attr({id:'level', title: levelDetails}).text(levelInt),
|
||||||
+ '</div>'
|
$('<div>').attr({class:'portalDetails'}).html(portalDetailedDescription),
|
||||||
+ '<div class="mods">'+getModDetails(d)+'</div>'
|
$('<img>').attr({class:'hide', src:img})
|
||||||
+ randDetails
|
),
|
||||||
+ resoDetails
|
|
||||||
+ '<div class="linkdetails">'
|
modDetails,
|
||||||
+ (
|
|
||||||
typeof android !== 'undefined' && android && android.intentPosLink // Android handles both links via a dialog
|
randDetails,
|
||||||
? '<aside><a onclick="'+poslinks+'" title="Create a URL link to this portal" >Portal link</a></aside>'
|
|
||||||
: '<aside><a href="'+perma+'" onclick="return androidCopy(this.href)" title="Create a URL link to this portal" >Portal link</a></aside>'
|
resoDetails,
|
||||||
+ '<aside><a onclick="'+poslinks+'" title="Link to alternative maps (Google, etc)">Map links</a></aside>'
|
|
||||||
)
|
'<div class="linkdetails">' + linkDetails.join('') + '</div>'
|
||||||
+ '</div>'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
runHooks('portalDetailsUpdated', {portalDetails: d});
|
runHooks('portalDetailsUpdated', {guid: guid, portal: portal, portalDetails: details, portalData: data});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
window.getRandPortalDetails = function(d) {
|
||||||
|
|
||||||
|
var randDetails;
|
||||||
|
|
||||||
|
if (d) {
|
||||||
|
|
||||||
|
// collect some random data that’s not worth to put in an own method
|
||||||
|
var links = {incoming: 0, outgoing: 0};
|
||||||
|
$.each(d.portalV2.linkedEdges||[], function(ind, link) {
|
||||||
|
links[link.isOrigin ? 'outgoing' : 'incoming']++;
|
||||||
|
});
|
||||||
|
|
||||||
|
function linkExpl(t) { return '<tt title="↳ incoming links\n↴ outgoing links\n• is the portal">'+t+'</tt>'; }
|
||||||
|
var linksText = [linkExpl('links'), linkExpl(' ↳ ' + links.incoming+' • '+links.outgoing+' ↴')];
|
||||||
|
|
||||||
|
var player = d.captured && d.captured.capturingPlayerId
|
||||||
|
? '<span class="nickname">' + getPlayerName(d.captured.capturingPlayerId) + '</span>'
|
||||||
|
: null;
|
||||||
|
var playerText = player ? ['owner', player] : null;
|
||||||
|
|
||||||
|
var time = d.captured
|
||||||
|
? '<span title="' + unixTimeToDateTimeString(d.captured.capturedTime, false) + '\n'
|
||||||
|
+ formatInterval(Math.floor((Date.now()-d.captured.capturedTime)/1000), 2) + ' ago">'
|
||||||
|
+ unixTimeToString(d.captured.capturedTime) + '</span>'
|
||||||
|
: null;
|
||||||
|
var sinceText = time ? ['since', time] : null;
|
||||||
|
|
||||||
|
var linkedFields = ['fields', d.portalV2.linkedFields ? d.portalV2.linkedFields.length : 0];
|
||||||
|
|
||||||
|
// collect and html-ify random data
|
||||||
|
var randDetailsData = [];
|
||||||
|
if (playerText && sinceText) {
|
||||||
|
randDetailsData.push (playerText, sinceText);
|
||||||
|
}
|
||||||
|
|
||||||
|
randDetailsData.push (
|
||||||
|
getRangeText(d), getEnergyText(d),
|
||||||
|
linksText, getAvgResoDistText(d),
|
||||||
|
linkedFields, getAttackApGainText(d),
|
||||||
|
getHackDetailsText(d), getMitigationText(d)
|
||||||
|
);
|
||||||
|
|
||||||
|
// artifact details
|
||||||
|
|
||||||
|
//niantic hard-code the fact it's just jarvis shards/targets - so until more examples exist, we'll do the same
|
||||||
|
//(at some future point we can iterate through all the artifact types and add rows as needed)
|
||||||
|
var jarvisArtifact = artifact.getPortalData (guid, 'jarvis');
|
||||||
|
if (jarvisArtifact) {
|
||||||
|
// the genFourColumnTable function below doesn't handle cases where one column is null and the other isn't - so default to *something* in both columns
|
||||||
|
var target = ['',''], shards = ['shards','(none)'];
|
||||||
|
if (jarvisArtifact.target) {
|
||||||
|
target = ['target', '<span class="'+TEAM_TO_CSS[jarvisArtifact.target]+'">'+(jarvisArtifact.target==TEAM_RES?'Resistance':'Enlightened')+'</span>'];
|
||||||
|
}
|
||||||
|
if (jarvisArtifact.fragments) {
|
||||||
|
shards = [jarvisArtifact.fragments.length>1?'shards':'shard', '#'+jarvisArtifact.fragments.join(', #')];
|
||||||
|
}
|
||||||
|
|
||||||
|
randDetailsData.push (target, shards);
|
||||||
|
}
|
||||||
|
|
||||||
|
randDetails = '<table id="randdetails">' + genFourColumnTable(randDetailsData) + '</table>';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return randDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// draws link-range and hack-range circles around the portal with the
|
// draws link-range and hack-range circles around the portal with the
|
||||||
// given details. Clear them if parameter 'd' is null.
|
// given details. Clear them if parameter 'd' is null.
|
||||||
window.setPortalIndicators = function(d) {
|
window.setPortalIndicators = function(p) {
|
||||||
if(portalRangeIndicator) map.removeLayer(portalRangeIndicator);
|
if(portalRangeIndicator) map.removeLayer(portalRangeIndicator);
|
||||||
portalRangeIndicator = null;
|
portalRangeIndicator = null;
|
||||||
if(portalAccessIndicator) map.removeLayer(portalAccessIndicator);
|
if(portalAccessIndicator) map.removeLayer(portalAccessIndicator);
|
||||||
portalAccessIndicator = null;
|
portalAccessIndicator = null;
|
||||||
|
|
||||||
if(d === null) return;
|
// if we have a portal...
|
||||||
|
|
||||||
var range = getPortalRange(d);
|
if(p) {
|
||||||
var coord = [d.locationE6.latE6/1E6, d.locationE6.lngE6/1E6];
|
var coord = p.getLatLng();
|
||||||
portalRangeIndicator = (range.range > 0
|
|
||||||
? L.geodesicCircle(coord, range.range, {
|
// range is only known for sure if we have portal details
|
||||||
fill: false,
|
// TODO? render a min range guess until details are loaded..?
|
||||||
color: RANGE_INDICATOR_COLOR,
|
|
||||||
weight: 3,
|
var d = p.options.details;
|
||||||
dashArray: range.isLinkable ? undefined : "10,10",
|
if (d) {
|
||||||
clickable: false })
|
var range = getPortalRange(d);
|
||||||
: L.circle(coord, range.range, { fill: false, stroke: false, clickable: false })
|
portalRangeIndicator = (range.range > 0
|
||||||
|
? L.geodesicCircle(coord, range.range, {
|
||||||
|
fill: false,
|
||||||
|
color: RANGE_INDICATOR_COLOR,
|
||||||
|
weight: 3,
|
||||||
|
dashArray: range.isLinkable ? undefined : "10,10",
|
||||||
|
clickable: false })
|
||||||
|
: L.circle(coord, range.range, { fill: false, stroke: false, clickable: false })
|
||||||
|
).addTo(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
portalAccessIndicator = L.circle(coord, HACK_RANGE,
|
||||||
|
{ fill: false, color: ACCESS_INDICATOR_COLOR, weight: 2, clickable: false }
|
||||||
).addTo(map);
|
).addTo(map);
|
||||||
|
}
|
||||||
|
|
||||||
portalAccessIndicator = L.circle(coord, HACK_RANGE,
|
|
||||||
{ fill: false, color: ACCESS_INDICATOR_COLOR, weight: 2, clickable: false }
|
|
||||||
).addTo(map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// highlights portal with given GUID. Automatically clears highlights
|
// highlights portal with given GUID. Automatically clears highlights
|
||||||
|
@ -184,7 +184,8 @@ window.getResonatorDetails = function(d) {
|
|||||||
|
|
||||||
resoDetails.push(renderResonatorDetails(slot, l, v, dist, nick));
|
resoDetails.push(renderResonatorDetails(slot, l, v, dist, nick));
|
||||||
});
|
});
|
||||||
return genFourColumnTable(resoDetails);
|
return '<table id="resodetails">' + genFourColumnTable(resoDetails) + '</table>';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper function that renders the HTML for a given resonator. Does
|
// helper function that renders the HTML for a given resonator. Does
|
||||||
|
@ -194,10 +194,8 @@ window.potentialPortalLevel = function(d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
window.getPortalImageUrl = function(d) {
|
window.fixPortalImageUrl = function(url) {
|
||||||
if (d.imageByUrl && d.imageByUrl.imageUrl) {
|
if (url) {
|
||||||
url = d.imageByUrl.imageUrl;
|
|
||||||
|
|
||||||
if (window.location.protocol === 'https:') {
|
if (window.location.protocol === 'https:') {
|
||||||
url = url.indexOf('www.panoramio.com') !== -1
|
url = url.indexOf('www.panoramio.com') !== -1
|
||||||
? url.replace(/^http:\/\/www/, 'https://ssl').replace('small', 'medium')
|
? url.replace(/^http:\/\/www/, 'https://ssl').replace('small', 'medium')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user