Évolution du jeu Salesforce (3-4) – La page, son affichage
La page utilise le contrôleur
<apex:page controller="CarRacerStatisticsCtrl" showHeader="false" sidebar="false" cache="false">
Ce panneau s’affiche s’il y a une erreur : pas de racer
<apex:outputPanel id="ErrorPage" rendered="{! !HasRacer}">
NO RACER FOUND
</apex:outputPanel>
Toute la suite s’affiche s’il y a bien un racer
<apex:outputPanel id="FullPage" rendered="{! HasRacer}">
Styles graphique
<style>
.chart-container {
width: {!PageWidth}px;
height:250px
}
</style>
La librairie qui permet d’afficher un graphe
<apex:includeScript value="{!$Resource.ChartJS}"/>
Les infos qui permettent de suivre l’état de la carte Google
<script type="text/javascript">
//<![CDATA[
// gloabal page vars
var pageGoogleMap;
var pageGoogleMapCreated = false;
var pageGoogleMapMarkers = new Map();
var pageGoogleMapMarkersInfoWindows = new Map();
//]]>
</script>
Le code qui va redemander toutes les 5 secondes de rafraichir des parties de la page
<apex:form >
<apex:actionPoller action="{!reloadPageData}" rerender="rawdata,carchart,maprefresh" interval="5"/>
</apex:form>
La table qui affiche les données de la voiture (cela appelle les fonctions de renvoi d’information du contrôleur – décrites à la fin de la partie précédente)
<apex:outputPanel id="rawdata">
<br/>
<table border="1" style="width: {!PageWidth}px;">
<tr>
<td >
<font size="5">
<b>Race : {!raceName}</b><br/>
Racer : {!racerName}<br/>
<i>Racer Car : {!racerCarName}</i><br/>
</font>
</td>
<td >
<font size="4">
Now : <apex:outputText value="{0,date,MM/dd/yy HH:mm a}" rendered="{!CurrentDisplayTime !=null}">
<apex:param value="{!CurrentDisplayTime}"/>
</apex:outputText> ( {!elapsedTime} s. )
</font>
<font size="4">
<br/>Request : <apex:outputText value="{0,date,MM/dd/yy HH:mm a}" style="{!if(LastRequestTooOld , 'color:red' , 'color:blue') };" rendered="{!LastRequestDate !=null}" >
<apex:param value="{!LastRequestDate}"/>
</apex:outputText>
</font>
</td>
</tr>
</table>
<table border="1" style="width: {!PageWidth}px;">
<tr>
<td>
<b>OBD</b>
<br/>
Measure : <apex:outputText value="{0,date,MM/dd/yy HH:mm a}" style="{!if(ObdDataTooOld , 'color:red' , 'color:blue') };" rendered="{!LastOBDMeasure !=null}">
<apex:param value="{!LastOBDMeasure}"/>
</apex:outputText>
<br/>
<font size="8">Speed: {! OBDSpeed }</font>
<br/>
RPM :{! OBDRPM }<br/>
Fuel Level: {! OBDFuelLevel }<br/>
</td>
<td>
<b>GPS</b><br/>
Measure : <apex:outputText value="{0,date,MM/dd/yy HH:mm a}" style="{!if(GpsDataTooOld , 'color:red' , 'color:blue') };" rendered="{!LastGPSMeasure !=null}">
<apex:param value="{!LastGPSMeasure}"/>
</apex:outputText><br/>
<font size="8">Speed:{! GPSSpeed }</font><br/>
Elevation:{! GPSElevation }<br/>
Time:<apex:outputText value="{0,date,MM/dd/yy HH:mm a}" style="{!if(TimeOutOfSync , 'color:red' , 'color:blue') };" rendered="{!GPSTime !=null}">
<apex:param value="{!GPSTime}"/>
</apex:outputText>
</td>
<td>
<font size="6">
Req: <apex:outputText value="{!LastRequestAge} s." style="{!if(LastRequestAge > 350 , 'color:red' , 'color:blue') };" /><br/>
GPS: <apex:outputText value="{!LastGPSMeasureAge-LastRequestAge} s." style="{!if( (LastGPSMeasureAge-LastRequestAge) > 30 , 'color:red' , 'color:blue') };" /><br/>
OBD: <apex:outputText value="{!LastOBDMeasureAge-LastRequestAge} s." style="{!if( (LastOBDMeasureAge-LastRequestAge) > 30 , 'color:red' , 'color:blue') };" />
</font>
</td>
</tr>
</table>
<br/>
</apex:outputPanel>
La zone pour afficher le graphe des vitesses
<div class="chart-container">
<canvas id="myChartSpeed" width="{!PageWidth}" height="250"></canvas>
</div>
Le script qui va mettre les données du graphe vitesse dans le chartSpeed
<apex:outputPanel id="carchart">
<script>
var theSpeedJsonContent = '{!SpeedChartData}';
var speedJSON = JSON.parse(theSpeedJsonContent);
var ctx = document.getElementById('myChartSpeed').getContext('2d');
var myChartSpeed = new Chart(ctx, speedJSON );
</script>
</apex:outputPanel>
La zone pour afficher la carte
<apex:outputPanel >
<div id="map" style="width: {!PageWidth}px; height: {!MapHeight}px;" ></div>
</apex:outputPanel>
Le script qui va mettre les marqueurs sur la carte commence ici
<script type="text/javascript">
//<![CDATA[
On récupère les infos depuis le contrôleur
var theJsonContent = '{!mapMarkersJSON}';
var mapCenterLatitude = '{!mapCenterLatitude}';
var mapCenterLongitude = '{!mapCenterLongitude}';
var mapCenterZoom = '{!mapCenterZoom}';
Ici c’est le code qui remplit la page :
Nota : on ne crée qu’une fois la carte (if (pageGoogleMapCreated == false))
var firstInitialisationDone = false;
function initMap() {
if (pageGoogleMapCreated == false) {
var mapDiv = document.getElementById('map');
pageGoogleMap = new google.maps.Map(mapDiv, {
center : {
lat : mapCenterLatitude ,
lng : mapCenterLongitude
},
zoom : mapCenterZoom
});
pageGoogleMapCreated = true;
}
try {
var geoJSON = JSON.parse(theJsonContent);
var markerBounds = new google.maps.LatLngBounds();
On boucle sur les participants, on récupére les infos, et on crée les marqueur (la première fois, ou on les déplace, s’ils existent déjà)
for (var i = 0; i < geoJSON.features.length; i++) {
var coords = geoJSON.features[i].geometry.coordinates;
var theName = geoJSON.features[i].properties.name;
var theRacerId = geoJSON.features[i].properties.racerId;
var theCarName = geoJSON.features[i].properties.carName;
var theStoredTime = geoJSON.features[i].properties.storedTime;
var theMeasureTime = geoJSON.features[i].properties.measureTime;
var theElapsedTime = geoJSON.features[i].properties.elapsedTime;
var theMeasureAge = geoJSON.features[i].properties.measureAge
var theMarkerPosition = new google.maps.LatLng(
coords[1],
coords[0]
);
// étend la carte pour afficher le marqueur ajouté.
markerBounds.extend(theMarkerPosition);
// nom du marqueur
var theTitle = "Name : "+theCarName+" "+theMeasureTime;
// popup d’information si on clique sur le marqueur de la voiture
var theContentText =
"<b>"+theCarName+"</b><br/>"+
""+theMeasureTime+" ("+theElapsedTime+" sec after start)<br/>"+
"<i>"+theMeasureAge+" sec old measure</i><br/>"+
"<i>Read at "+theStoredTime+"</i><br/>"
;
// modification de l’icone en fonction du statut des infos sur la voiture
theMarkerIcon = "http://maps.google.com/mapfiles/ms/icons/blue-dot.png";
if (geoJSON.features[i].properties.currentRacer) {
if (geoJSON.features[i].properties.finished) {
theMarkerIcon = "http://maps.google.com/mapfiles/ms/icons/purple-dot.png";
} else {
if (theMeasureAge > 60) {
theMarkerIcon = "http://maps.google.com/mapfiles/ms/icons/orange-dot.png";
} else {
theMarkerIcon = "http://maps.google.com/mapfiles/ms/icons/red-dot.png";
}
}
} else {
if (geoJSON.features[i].properties.finished) {
theMarkerIcon = "http://maps.google.com/mapfiles/ms/icons/green-dot.png";
} else {
if (theMeasureAge > 60) {
theMarkerIcon = "http://maps.google.com/mapfiles/ms/icons/yellow-dot.png";
} else {
theMarkerIcon = "http://maps.google.com/mapfiles/ms/icons/blue-dot.png";
}
}
}
// si le marqueur existait de la fois précedente, on l’utilise, en mettant à jour la position, changeant la couleur si nécessaire, et mettant à jour l’info window)
if (pageGoogleMapMarkers.has(theRacerId) ) {
// get existing marker
var existingMarker = pageGoogleMapMarkers.get(theRacerId);
// move it
existingMarker.setPosition( theMarkerPosition );
existingMarker.setIcon(theMarkerIcon);
var existingInfoWindow = pageGoogleMapMarkersInfoWindows.get(theRacerId);
existingInfoWindow.setContent(theContentText);
} else {
// crée le marqueur
var theNewMarker = new google.maps.Marker({
position: theMarkerPosition,
map: pageGoogleMap,
title: theTitle,
icon: {
url: theMarkerIcon
}
});
// memorise le nouveau marqueur pour pouvoir le réutiliser
pageGoogleMapMarkers.set(theRacerId,theNewMarker);
// crée la fenetre d’info si on clique sur le marqueur
var theNewInfoWindow = new google.maps.InfoWindow({
content: theContentText
});
pageGoogleMapMarkersInfoWindows.set(theRacerId, theNewInfoWindow);
google.maps.event.addListener(
theNewMarker,
'click',
(function(marker,contentText,infowindow){
return function() {
infowindow.setContent(contentText);
infowindow.open(pageGoogleMap,marker);
windows.push(infowindow)
google.maps.event.addListener(pageGoogleMap,'click', function(){
infowindow.close();
});
};
})(theNewMarker,theContentText,theNewInfoWindow));
}
}
} catch(error) {
console.error(error);
}
pageGoogleMap.fitBounds(markerBounds);
firstInitialisationDone = true;
}
//]]>
</script>
Le panneau qui va demander le rafraichissement périodique en redemandant les infos au contrôleur et redemander à remplir la carte (initMap)
<apex:outputPanel id="maprefresh">
<script type="text/javascript">
//<![CDATA[
if (firstInitialisationDone) {
theJsonContent = '{!mapMarkersJSON}';
mapCenterLatitude = '{!mapCenterLatitude}';
mapCenterLongitude = '{!mapCenterLongitude}';
mapCenterZoom = '{!mapCenterZoom}';
initMap();
}
//]]>
</script>
</apex:outputPanel>
Le code à ajouter pour pouvoir afficher une map google
<script src="https://maps.googleapis.com/maps/api/js?key=AIz...ktO0ANQ&callback=initMap">
</script>
On referme la page
</apex:outputPanel>
</apex:page>