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:
Jon Atkins 2013-11-30 22:26:40 +00:00
parent c197f74945
commit 7a19d30173
4 changed files with 222 additions and 110 deletions

41
code/portal_data.js Normal file
View 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;
}

View File

@ -3,81 +3,42 @@
// methods that highlight the portal in the map view.
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);
if(!window.portals[guid]) {
urlPortal = guid;
$('#portaldetails').html('');
if(isSmartphone()) {
$('.fullimg').remove();
$('#mobileinfo').html('');
$('#mobileinfo').html('<div style="text-align: center"><b>tap here for info screen</b></div>');
}
return;
}
var d = window.portals[guid].options.details;
// collect some random data thats not worth to put in an own method
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+'&nbsp;&nbsp;•&nbsp;&nbsp;'+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);
}
var portal = window.portals[guid];
var data = portal.options.data;
var details = undefined; //TODO: get the details
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 perma = '/intel?ll='+lat+','+lng+'&z=17&pll='+lat+','+lng;
var imgTitle = 'title="'+getPortalDescriptionFromDetails(d)+'\n\nClick to show full image."';
var poslinks = 'window.showPortalPosLinks('+lat+','+lng+',\''+escapeJavascriptString(d.portalV2.descriptiveText.TITLE)+'\')';
var portalDetailObj = window.getPortalDescriptionFromDetailsExtended(d);
var img = fixPortalImageUrl(details ? details.imageByUrl && details.imageByUrl.imageUrl : data.image);
var title = details ? details.portalV2.descriptiveText.TITLE : data.title;
var lat = data.latE6/1E6;
var lng = data.lngE6/1E6;
var imgTitle = ''; //'title="'+getPortalDescriptionFromDetails(details)+'\n\nClick to show full image."';
var portalDetailObj = undefined; //window.getPortalDescriptionFromDetailsExtended(details);
var portalDetailedDescription = '';
@ -111,7 +72,11 @@ window.renderPortalDetails = function(guid) {
portalDetailedDescription += '</table>';
}
var levelDetails = getPortalLevel(d);
// portal level. start with basic data - then extend with fractional info in tooltip if available
var levelInt = data ? data.level : getPortalLevel(details);
var levelDetails = data.level;
if (details) {
levelDetails = getPortalLevel(details);
if(levelDetails != 8) {
if(levelDetails==Math.ceil(levelDetails))
levelDetails += "\n8";
@ -121,48 +86,152 @@ window.renderPortalDetails = function(guid) {
} else {
levelDetails += "\nfully upgraded";
}
}
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')
.attr('class', TEAM_TO_CSS[getTeam(d)])
.html(''
+ '<h3 class="title">'+escapeHtmlSpecialChars(d.portalV2.descriptiveText.TITLE)+'</h3>'
+ '<span class="close" onclick="renderPortalDetails(null); if(isSmartphone()) show(\'map\');" title="Close">X</span>'
.html('') //to ensure it's clear
.attr('class', TEAM_TO_CSS[portal.options.team])
.append(
$('<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"
+ '<div class="imgpreview" '+imgTitle+' style="background-image: url('+img+')">'
+ '<span id="level" title="'+levelDetails+'">'+Math.floor(getPortalLevel(d))+'</span>'
+ '<div class="portalDetails">'+ portalDetailedDescription + '</div>'
+ '<img class="hide" src="'+img+'"/></div>'
+ '</div>'
+ '<div class="mods">'+getModDetails(d)+'</div>'
+ randDetails
+ resoDetails
+ '<div class="linkdetails">'
+ (
typeof android !== 'undefined' && android && android.intentPosLink // Android handles both links via a dialog
? '<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>'
+ '<aside><a onclick="'+poslinks+'" title="Link to alternative maps (Google, etc)">Map links</a></aside>'
)
+ '</div>'
$('<div>')
.attr({class:'imgpreview', title:imgTitle, style:"background-image: url('"+img+"')"})
.append(
$('<span>').attr({id:'level', title: levelDetails}).text(levelInt),
$('<div>').attr({class:'portalDetails'}).html(portalDetailedDescription),
$('<img>').attr({class:'hide', src:img})
),
modDetails,
randDetails,
resoDetails,
'<div class="linkdetails">' + linkDetails.join('') + '</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 thats 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+'&nbsp;&nbsp;•&nbsp;&nbsp;'+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
// given details. Clear them if parameter 'd' is null.
window.setPortalIndicators = function(d) {
window.setPortalIndicators = function(p) {
if(portalRangeIndicator) map.removeLayer(portalRangeIndicator);
portalRangeIndicator = null;
if(portalAccessIndicator) map.removeLayer(portalAccessIndicator);
portalAccessIndicator = null;
if(d === null) return;
// if we have a portal...
if(p) {
var coord = p.getLatLng();
// range is only known for sure if we have portal details
// TODO? render a min range guess until details are loaded..?
var d = p.options.details;
if (d) {
var range = getPortalRange(d);
var coord = [d.locationE6.latE6/1E6, d.locationE6.lngE6/1E6];
portalRangeIndicator = (range.range > 0
? L.geodesicCircle(coord, range.range, {
fill: false,
@ -172,12 +241,15 @@ window.setPortalIndicators = function(d) {
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);
}
}
// highlights portal with given GUID. Automatically clears highlights
// on old selection. Returns false if the selected portal changed.
// Returns true if it's still the same portal that just needs an

View File

@ -184,7 +184,8 @@ window.getResonatorDetails = function(d) {
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

View File

@ -194,10 +194,8 @@ window.potentialPortalLevel = function(d) {
}
window.getPortalImageUrl = function(d) {
if (d.imageByUrl && d.imageByUrl.imageUrl) {
url = d.imageByUrl.imageUrl;
window.fixPortalImageUrl = function(url) {
if (url) {
if (window.location.protocol === 'https:') {
url = url.indexOf('www.panoramio.com') !== -1
? url.replace(/^http:\/\/www/, 'https://ssl').replace('small', 'medium')