{"id":989,"date":"2020-03-15T13:34:00","date_gmt":"2020-03-15T12:34:00","guid":{"rendered":"http:\/\/wollef.org\/?p=989"},"modified":"2020-03-15T13:34:00","modified_gmt":"2020-03-15T12:34:00","slug":"evolution-du-jeu-salesforce-3-4-la-page-son-affichage","status":"publish","type":"post","link":"https:\/\/wollef.org\/blog\/evolution-du-jeu-salesforce-3-4-la-page-son-affichage\/","title":{"rendered":"\u00c9volution du jeu Salesforce (3-4) &#8211; La page, son affichage"},"content":{"rendered":"\n<p>La page utilise le contr\u00f4leur<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;apex:page controller=\"CarRacerStatisticsCtrl\" showHeader=\"false\" sidebar=\"false\" cache=\"false\"><\/code><\/pre>\n\n\n\n<p>Ce panneau s\u2019affiche s\u2019il y a une erreur&nbsp;: pas de racer<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;apex:outputPanel id=\"ErrorPage\" rendered=\"{! !HasRacer}\">\nNO RACER FOUND\n&lt;\/apex:outputPanel><\/code><\/pre>\n\n\n\n<p>Toute la suite s\u2019affiche s\u2019il y a bien un racer<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;apex:outputPanel id=\"FullPage\" rendered=\"{! HasRacer}\"><\/code><\/pre>\n\n\n\n<p>Styles graphique<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;style>\n.chart-container {\n    width: {!PageWidth}px;\n    height:250px\n}\n&lt;\/style>\n<\/code><\/pre>\n\n\n\n<p>La librairie qui permet d\u2019afficher un graphe<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;apex:includeScript value=\"{!$Resource.ChartJS}\"\/><\/code><\/pre>\n\n\n\n<p>Les infos qui permettent de suivre l\u2019\u00e9tat de la carte Google<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;script type=\"text\/javascript\">\n\/\/&lt;![CDATA[\n    \/\/ gloabal page vars\n    var pageGoogleMap;\n    var pageGoogleMapCreated = false;\n    var pageGoogleMapMarkers = new Map();\n    var pageGoogleMapMarkersInfoWindows = new Map();\n    \/\/]]>\n&lt;\/script> <\/code><\/pre>\n\n\n\n<p>Le code qui va redemander toutes les 5 secondes de rafraichir des parties de la page<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;apex:form >\n    &lt;apex:actionPoller action=\"{!reloadPageData}\" rerender=\"rawdata,carchart,maprefresh\" interval=\"5\"\/>\n&lt;\/apex:form>\n<\/code><\/pre>\n\n\n\n<p>La table qui affiche les donn\u00e9es de la voiture (cela appelle les fonctions de renvoi d\u2019information du contr\u00f4leur \u2013 d\u00e9crites \u00e0 la fin de la partie pr\u00e9c\u00e9dente)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;apex:outputPanel id=\"rawdata\">\n&lt;br\/>\n&lt;table border=\"1\" style=\"width: {!PageWidth}px;\">\n&lt;tr>\n&lt;td >\n&lt;font size=\"5\">\n    &lt;b>Race : {!raceName}&lt;\/b>&lt;br\/>\nRacer : {!racerName}&lt;br\/>\n&lt;i>Racer Car : {!racerCarName}&lt;\/i>&lt;br\/>\n    &lt;\/font>\n&lt;\/td>\n&lt;td >\n    &lt;font size=\"4\">\n        Now : &lt;apex:outputText value=\"{0,date,MM\/dd\/yy HH:mm a}\" rendered=\"{!CurrentDisplayTime !=null}\">\n&lt;apex:param value=\"{!CurrentDisplayTime}\"\/>\n&lt;\/apex:outputText> ( {!elapsedTime} s. )\n    &lt;\/font>\n    &lt;font size=\"4\">\n        &lt;br\/>Request : &lt;apex:outputText value=\"{0,date,MM\/dd\/yy HH:mm a}\"  style=\"{!if(LastRequestTooOld , 'color:red' , 'color:blue') };\" rendered=\"{!LastRequestDate !=null}\" >\n            &lt;apex:param value=\"{!LastRequestDate}\"\/>\n&lt;\/apex:outputText>\n    &lt;\/font>\n&lt;\/td>\n&lt;\/tr>\n&lt;\/table>\n&lt;table border=\"1\" style=\"width: {!PageWidth}px;\">\n&lt;tr>\n&lt;td>\n&lt;b>OBD&lt;\/b>\n&lt;br\/>\nMeasure : &lt;apex:outputText value=\"{0,date,MM\/dd\/yy HH:mm a}\"  style=\"{!if(ObdDataTooOld , 'color:red' , 'color:blue') };\" rendered=\"{!LastOBDMeasure !=null}\">\n    &lt;apex:param value=\"{!LastOBDMeasure}\"\/>\n&lt;\/apex:outputText>\n&lt;br\/>\n&lt;font size=\"8\">Speed: {! OBDSpeed }&lt;\/font>\n&lt;br\/>\nRPM :{! OBDRPM }&lt;br\/>\nFuel Level: {! OBDFuelLevel }&lt;br\/>\n&lt;\/td>\n&lt;td>\n&lt;b>GPS&lt;\/b>&lt;br\/>\nMeasure : &lt;apex:outputText value=\"{0,date,MM\/dd\/yy HH:mm a}\"  style=\"{!if(GpsDataTooOld , 'color:red' , 'color:blue') };\" rendered=\"{!LastGPSMeasure !=null}\">\n&lt;apex:param value=\"{!LastGPSMeasure}\"\/>\n&lt;\/apex:outputText>&lt;br\/>\n&lt;font size=\"8\">Speed:{! GPSSpeed }&lt;\/font>&lt;br\/>\nElevation:{! GPSElevation }&lt;br\/>\nTime:&lt;apex:outputText value=\"{0,date,MM\/dd\/yy HH:mm a}\"  style=\"{!if(TimeOutOfSync , 'color:red' , 'color:blue') };\"  rendered=\"{!GPSTime !=null}\">\n&lt;apex:param value=\"{!GPSTime}\"\/>\n&lt;\/apex:outputText>\n\n&lt;\/td>\n&lt;td>\n    &lt;font size=\"6\">\n        Req:&amp;nbsp;&lt;apex:outputText value=\"{!LastRequestAge} s.\"  style=\"{!if(LastRequestAge > 350 , 'color:red' , 'color:blue') };\" \/>&lt;br\/>\n        GPS:&amp;nbsp;&lt;apex:outputText value=\"{!LastGPSMeasureAge-LastRequestAge} s.\"  style=\"{!if( (LastGPSMeasureAge-LastRequestAge) > 30 , 'color:red' , 'color:blue') };\" \/>&lt;br\/>\n        OBD:&amp;nbsp;&lt;apex:outputText value=\"{!LastOBDMeasureAge-LastRequestAge} s.\"  style=\"{!if( (LastOBDMeasureAge-LastRequestAge) > 30 , 'color:red' , 'color:blue') };\" \/>\n    &lt;\/font>\n&lt;\/td>\n&lt;\/tr>\n&lt;\/table>\n&lt;br\/>\n&lt;\/apex:outputPanel>\n<\/code><\/pre>\n\n\n\n<p>La zone pour afficher le graphe des vitesses<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;div class=\"chart-container\">\n&lt;canvas id=\"myChartSpeed\" width=\"{!PageWidth}\" height=\"250\">&lt;\/canvas>\n&lt;\/div>\n<\/code><\/pre>\n\n\n\n<p>Le script qui va mettre les donn\u00e9es du graphe vitesse dans le chartSpeed<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;apex:outputPanel id=\"carchart\">\n    &lt;script>\n    var theSpeedJsonContent = '{!SpeedChartData}';\n    var speedJSON = JSON.parse(theSpeedJsonContent);\n    var ctx = document.getElementById('myChartSpeed').getContext('2d');\n    var myChartSpeed = new Chart(ctx, speedJSON );\n    &lt;\/script>\n&lt;\/apex:outputPanel>\n\n<\/code><\/pre>\n\n\n\n<p>La zone pour afficher la carte<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;apex:outputPanel >\n&lt;div id=\"map\" style=\"width: {!PageWidth}px; height: {!MapHeight}px;\" >&lt;\/div>\n&lt;\/apex:outputPanel>\n<\/code><\/pre>\n\n\n\n<p>Le script qui va mettre les marqueurs sur la carte commence ici<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;script type=\"text\/javascript\">\n\/\/&lt;![CDATA[<\/code><\/pre>\n\n\n\n<p>On r\u00e9cup\u00e8re les infos depuis le contr\u00f4leur<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var theJsonContent = '{!mapMarkersJSON}';\nvar mapCenterLatitude = '{!mapCenterLatitude}';\nvar mapCenterLongitude = '{!mapCenterLongitude}';\nvar mapCenterZoom = '{!mapCenterZoom}';\n<\/code><\/pre>\n\n\n\n<p>Ici c\u2019est le code qui remplit la page&nbsp;:<br \/>Nota : on ne cr\u00e9e qu\u2019une fois la carte <em>(if (pageGoogleMapCreated == false))<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var firstInitialisationDone = false;\nfunction initMap() {\n\n    if (pageGoogleMapCreated == false) {\n        var mapDiv = document.getElementById('map');\n        pageGoogleMap = new google.maps.Map(mapDiv, {\n            center : {\n                lat : mapCenterLatitude ,\n                lng :  mapCenterLongitude\n            },\n            zoom : mapCenterZoom\n        });\n        pageGoogleMapCreated = true;\n    }\n\n    try {\n        var geoJSON = JSON.parse(theJsonContent);\n        var markerBounds = new google.maps.LatLngBounds();\n<\/code><\/pre>\n\n\n\n<p><em>On boucle sur les participants, on r\u00e9cup\u00e9re les infos, et on cr\u00e9e les marqueur (la premi\u00e8re fois, ou on les d\u00e9place, s\u2019ils existent d\u00e9j\u00e0)&nbsp;&nbsp;&nbsp; <\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for (var i = 0; i &lt; geoJSON.features.length; i++) {\n\n            var coords = geoJSON.features[i].geometry.coordinates;\n            var theName = geoJSON.features[i].properties.name;\n            var theRacerId = geoJSON.features[i].properties.racerId;\n            var theCarName = geoJSON.features[i].properties.carName;\n            var theStoredTime = geoJSON.features[i].properties.storedTime;\n            var theMeasureTime = geoJSON.features[i].properties.measureTime;\n            var theElapsedTime = geoJSON.features[i].properties.elapsedTime;\n            var theMeasureAge = geoJSON.features[i].properties.measureAge\n\n            var theMarkerPosition = new google.maps.LatLng(\ncoords[1],\ncoords[0]\n    );\n\n            \/\/ \u00e9tend la carte pour afficher le marqueur ajout\u00e9.\n            markerBounds.extend(theMarkerPosition);\n\n\t\t   \/\/ nom du marqueur\n           var theTitle = \"Name : \"+theCarName+\" \"+theMeasureTime;\n\n\t\t   \/\/ popup d\u2019information si on clique sur le marqueur de la voiture\n           var theContentText =\n               \"&lt;b>\"+theCarName+\"&lt;\/b>&lt;br\/>\"+\n               \"\"+theMeasureTime+\" (\"+theElapsedTime+\" sec after start)&lt;br\/>\"+\n                \"&lt;i>\"+theMeasureAge+\" sec old measure&lt;\/i>&lt;br\/>\"+\n                \"&lt;i>Read at \"+theStoredTime+\"&lt;\/i>&lt;br\/>\"\n           ;\n\t\t   \/\/ modification de l\u2019icone en fonction du statut des infos sur la voiture\n           theMarkerIcon = \"http:\/\/maps.google.com\/mapfiles\/ms\/icons\/blue-dot.png\";\n                if (geoJSON.features[i].properties.currentRacer) {\n                    if (geoJSON.features[i].properties.finished) {\n                            theMarkerIcon = \"http:\/\/maps.google.com\/mapfiles\/ms\/icons\/purple-dot.png\";\n                    } else {\n                        if (theMeasureAge > 60) {\n                            theMarkerIcon = \"http:\/\/maps.google.com\/mapfiles\/ms\/icons\/orange-dot.png\";\n                        } else {\n                            theMarkerIcon = \"http:\/\/maps.google.com\/mapfiles\/ms\/icons\/red-dot.png\";\n                        }\n                    }\n                } else {\n                    if (geoJSON.features[i].properties.finished) {\n                            theMarkerIcon = \"http:\/\/maps.google.com\/mapfiles\/ms\/icons\/green-dot.png\";\n                    } else {\n                        if (theMeasureAge > 60) {\n                            theMarkerIcon = \"http:\/\/maps.google.com\/mapfiles\/ms\/icons\/yellow-dot.png\";\n                        } else {\n                            theMarkerIcon = \"http:\/\/maps.google.com\/mapfiles\/ms\/icons\/blue-dot.png\";\n                        }\n                    }\n                }\n\n            \/\/ si le marqueur existait de la fois pr\u00e9cedente, on l\u2019utilise, en mettant \u00e0 jour la position, changeant la couleur si n\u00e9cessaire, et mettant \u00e0 jour l\u2019info window)\n\n            if (pageGoogleMapMarkers.has(theRacerId) ) {\n                \/\/ get existing marker\n                var existingMarker = pageGoogleMapMarkers.get(theRacerId);\n                \/\/ move it\n                existingMarker.setPosition( theMarkerPosition );\n                existingMarker.setIcon(theMarkerIcon);\n\n                var existingInfoWindow = pageGoogleMapMarkersInfoWindows.get(theRacerId);\n                existingInfoWindow.setContent(theContentText);\n            } else {\n                \/\/ cr\u00e9e le marqueur\n                var theNewMarker = new google.maps.Marker({\n                    position: theMarkerPosition,\n                    map: pageGoogleMap,\n                    title: theTitle,\n                    icon: {\n                          url: theMarkerIcon\n                    }\n                });\n                \/\/ memorise le nouveau marqueur pour pouvoir le r\u00e9utiliser\n                pageGoogleMapMarkers.set(theRacerId,theNewMarker);\n                \/\/ cr\u00e9e la fenetre d\u2019info si on clique sur le marqueur\n                var theNewInfoWindow = new google.maps.InfoWindow({\n                    content: theContentText\n                });\n                pageGoogleMapMarkersInfoWindows.set(theRacerId, theNewInfoWindow);\n                google.maps.event.addListener(\n                    theNewMarker,\n                    'click',\n                    (function(marker,contentText,infowindow){\n                        return function() {\n                            infowindow.setContent(contentText);\n                            infowindow.open(pageGoogleMap,marker);\n                            windows.push(infowindow)\n                            google.maps.event.addListener(pageGoogleMap,'click', function(){\n                                infowindow.close();\n                            });\n                        };\n                    })(theNewMarker,theContentText,theNewInfoWindow));\n                }\n            }\n        } catch(error) {\n            console.error(error);\n        }\n        pageGoogleMap.fitBounds(markerBounds);\n        firstInitialisationDone = true;\n    }\n\/\/]]>\n&lt;\/script>\n<\/code><\/pre>\n\n\n\n<p>Le panneau qui va demander le rafraichissement p\u00e9riodique en redemandant les infos au contr\u00f4leur&nbsp;et redemander \u00e0 remplir la carte (initMap)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;apex:outputPanel id=\"maprefresh\">\n        &lt;script type=\"text\/javascript\">\n        \/\/&lt;![CDATA[\n        if (firstInitialisationDone) {\n            theJsonContent      = '{!mapMarkersJSON}';\n            mapCenterLatitude   = '{!mapCenterLatitude}';\n            mapCenterLongitude  = '{!mapCenterLongitude}';\n            mapCenterZoom       = '{!mapCenterZoom}';\n            initMap();\n        }\n        \/\/]]>\n        &lt;\/script>\n&lt;\/apex:outputPanel>\n<\/code><\/pre>\n\n\n\n<p>Le code \u00e0 ajouter pour pouvoir afficher une map google<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;script src=\"https:\/\/maps.googleapis.com\/maps\/api\/js?key=AIz...ktO0ANQ&amp;callback=initMap\">\n&lt;\/script>\n<\/code><\/pre>\n\n\n\n<p>On referme la page<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;\/apex:outputPanel>\n&lt;\/apex:page>\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>La page utilise le contr\u00f4leur Ce panneau s\u2019affiche s\u2019il y a une erreur&nbsp;: pas de racer Toute la suite s\u2019affiche s\u2019il y a bien un racer Styles graphique La librairie qui permet d\u2019afficher un graphe Les infos qui permettent de suivre l\u2019\u00e9tat de la carte Google Le code qui va redemander toutes les 5 secondes <a class=\"read-more\" href=\"https:\/\/wollef.org\/blog\/evolution-du-jeu-salesforce-3-4-la-page-son-affichage\/\">Continue Reading<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[31,1],"tags":[53],"class_list":["post-989","post","type-post","status-publish","format-standard","hentry","category-raspberry-cars","category-non-classe","tag-2020-raspberry-cars"],"_links":{"self":[{"href":"https:\/\/wollef.org\/blog\/wp-json\/wp\/v2\/posts\/989","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wollef.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wollef.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wollef.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wollef.org\/blog\/wp-json\/wp\/v2\/comments?post=989"}],"version-history":[{"count":0,"href":"https:\/\/wollef.org\/blog\/wp-json\/wp\/v2\/posts\/989\/revisions"}],"wp:attachment":[{"href":"https:\/\/wollef.org\/blog\/wp-json\/wp\/v2\/media?parent=989"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wollef.org\/blog\/wp-json\/wp\/v2\/categories?post=989"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wollef.org\/blog\/wp-json\/wp\/v2\/tags?post=989"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}