Le blog francophone consacré
aux technologies Esri

Conseils & Astuces ArcGIS Online - N°184

N° 184 - Afficher des horaires d'ouverture (sur deux périodes) dans des fenêtres contextuelles avec Arcade 

Dans mon précédent article (Conseils & Astuces ArcGIS Online n°183), je vous ai montré comment présenter dans une fenêtre contextuelle, à l'aide d'une expression Arcade, des informations concernant les heures d'ouverture et de fermeture associés à vos points d'intérêts. En commentaire de l'article, vous m'avez demandé comment prendre en charge le cas où l'on dispose de deux plages d'ouverture par jour (généralement le matin et l'après-midi). Dans cet article je vous propose une adaptation de l'expression Arcade pour ce cas de figure.


Reprenons l'exemple d'une couche de points contenant les déchèteries sur la région Ile-de-France. Cette dernière contient les horaires d'ouverture et de fermeture, pour chaque matinée et chaque après-midi des différents jours de la semaine, stockés dans 28 champs de type "Heure uniquement" (Time only). Par exemple, pour la journée du lundi, les horaires se trouveront dans les champs Ouverture_Lundi_AM et Fermeture_Lundi_AM pour le matin et dans les champs Ouverture_Lundi_PM et Fermeture_Lundi_PM pour l'après-midi. 


Dans mon cas, l'absence de valeur sur l'heure d'ouverture le matin ou l'après-midi indique une fermeture le matin ou l'après-midi.

Voici comment vous pouvez préparer les déchèteries ouvertes ou fermées en fonction du jour et de l'heure actuels.
  1. Après avoir ajouté la couche des déchèteries dans la carte, vous afficherez l'interface de définition des fenêtres contextuelles. Vous supprimerez la liste des champs proposée par défaut et vous ajouterez une expression Arcade.


  2. Vous donnerez tout d'abord un nom à votre expression, par exemple ici : "Table des horaires d'ouverture".



  3. Vous saisirez ensuite l'expression Arcade suivante :
    Expects($feature,"*")
    
    // Fonction permettant de construire la partie horaire du calendrier
    function  GenererPlagesHoraires(HeureMinCalendrier,HeureMaxCalendrier,HeureOuvertureAM,
                                    HeureFermetureAM,HeureOuverturePM,HeureFermeturePM){
      // Récupération du nombre minutes de la plage horaire du calendrier
      var MinutesDansLaPlage = DateDiff(HeureMaxCalendrier,HeureMinCalendrier,"minutes")
      // On initialise la variable du bloc HTML de la cellule du tableau
      var strTD = ""
    
      // Si les heures d'ouverture AM et d'ouverture PM sont bien défines
      if(!IsEmpty(HeureOuvertureAM) && !IsEmpty(HeureOuverturePM)){
        // Position des heures d'ouverture dans la journée
        var MinutesOuvertureAM = DateDiff(HeureOuvertureAM,HeureMinCalendrier,"minutes")
        var MinutesFermetureAM = DateDiff(HeureFermetureAM,HeureMinCalendrier,"minutes")
        var MinutesOuverturePM = DateDiff(HeureOuverturePM,HeureMinCalendrier,"minutes")
        var MinutesFermeturePM = DateDiff(HeureFermeturePM,HeureMinCalendrier,"minutes")
        // Calcul du nombre de pixels pour séparer bloc vert pour l'ouverture du matin
        var pixels_ouvertureAM = Floor((MinutesOuvertureAM/MinutesDansLaPlage)*350)
        var pixels_fermetureAM = Floor((MinutesFermetureAM/MinutesDansLaPlage)*350)
        // Calcul du nombre de pixels pour séparer bloc vert pour l'ouverture de l'après-midi
        var pixels_ouverturePM = Floor((MinutesOuverturePM/MinutesDansLaPlage)*350)
        var pixels_fermeturePM = Floor((MinutesFermeturePM/MinutesDansLaPlage)*350)
    
        // Bloc gris (fermé)
        strTD += "<td style='width: "+pixels_ouvertureAM+"px;background-color: #cccccc'></td>"
        // 1er Bloc vert (ouvert le matin)
        strTD += "<td style='width: "+(pixels_fermetureAM - pixels_ouvertureAM)+
                 "px;background-color: #00cc00;color: #FFFFFF;font-size: 7pt;text-align: center'>"
                 +Text(HeureOuvertureAM,"H:mm")+" - " + Text(HeureFermetureAM,"H:mm") +"</td>"
        // Bloc gris (fermé entre matin et après-midi)
        strTD += "<td style='width: "+(pixels_ouverturePM - pixels_fermetureAM)+
                 "px;background-color: #cccccc;color: #FFFFFF;font-size: 7pt;text-align: center'></td>"
        // 2ème Bloc vert (ouvert l'après-midi)
        strTD += "<td style='width: "+(pixels_fermeturePM - pixels_ouverturePM)+
                 "px;background-color: #00cc00;color: #FFFFFF;font-size: 7pt;text-align: center'>"
                 +Text(HeureOuverturePM,"H:mm")+" - " + Text(HeureFermeturePM,"H:mm") +"</td>"
        strTD += "<td style='width: "+ (350 - pixels_fermeturePM) +
                 "px;background-color: #cccccc;font-size: 7pt;'></td>"
      }
    
      // Si l'entité a une plage d'ouverture uniquement le matin
      else if(!IsEmpty(HeureOuvertureAM) && IsEmpty(HeureOuverturePM)){
        // Position des heures d'ouverture dans la journée
        var MinutesOuvertureAM = DateDiff(HeureOuvertureAM,HeureMinCalendrier,"minutes")
        var MinutesFermetureAM = DateDiff(HeureFermetureAM,HeureMinCalendrier,"minutes")
        // Calcul du nombre de pixels pour séparer bloc vert pour l'ouverture du matin
        var pixels_ouvertureAM = Floor((MinutesOuvertureAM/MinutesDansLaPlage)*350)
        var pixels_fermetureAM = Floor((MinutesFermetureAM/MinutesDansLaPlage)*350)
        // Bloc gris (fermé)
        strTD += "<td style='width: "+pixels_ouvertureAM+"px;background-color: #cccccc'></td>"
        // Bloc vert (ouvert le matin)
        strTD += "<td style='width: "+(pixels_fermetureAM - pixels_ouvertureAM)+
                 "px;background-color: #00cc00;color: #FFFFFF;font-size: 7pt;text-align: center'>"
                 +Text(HeureOuvertureAM,"H:mm")+" - " + Text(HeureFermetureAM,"H:mm") +"</td>"
        strTD += "<td style='width: "+ (350 - pixels_fermetureAM) +
                 "px;background-color: #cccccc;font-size: 7pt;'></td>"
      }
    
      // Si l'entité a une plage d'ouverture uniquement l'après-midi
      else if(IsEmpty(HeureOuvertureAM) && !IsEmpty(HeureOuverturePM)){
        // Position des heures d'ouverture dans la journée
        var MinutesOuverturePM = DateDiff(HeureOuverturePM,HeureMinCalendrier,"minutes")
        var MinutesFermeturePM = DateDiff(HeureFermeturePM,HeureMinCalendrier,"minutes")
        // Calcul du nombre de pixels pour séparer bloc vert pour l'ouverture de l'après-midi
        var pixels_ouverturePM = Floor((MinutesOuverturePM/MinutesDansLaPlage)*350)
        var pixels_fermeturePM = Floor((MinutesFermeturePM/MinutesDansLaPlage)*350)
        // Bloc gris (fermé)
        strTD += "<td style='width: "+pixels_ouverturePM+"px;background-color: #cccccc'></td>"
        // Bloc vert (ouvert l'après-midi)
        strTD += "<td style='width: "+(pixels_fermeturePM - pixels_ouverturePM)+
                 "px;background-color: #00cc00;color: #FFFFFF;font-size: 7pt;text-align: center'>"
                 +Text(HeureOuverturePM,"H:mm")+" - " + Text(HeureFermeturePM,"H:mm") +"</td>"
        strTD += "<td style='width: "+ (350 - pixels_fermeturePM) +
                 "px;background-color: #cccccc;font-size: 7pt;'></td>"
      }
    
      // Si aucune heure d'ouverture ou de fermeture n'est défninie alors c'est fermé toute la journée !
      else{
        // On créé 2 blocs gris cote à cote pour une largeur totale de 350px
        strTD += "<td style='width: 175px;background-color: #CCCCCC'></td>"
        strTD += "<td style='width: 175px;background-color: #CCCCCC'></td>"
      }
      return strTD
    }
    
    var ListeJourSemaine=["Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche"]
    // 2 variables pour définir les heures min et max des journées dans le calendrier
    var HeureMinCalendrier = Time("07:00")
    var HeureMaxCalendrier = Time("19:00")
    
    // On initialise la variable contenant le bloc HTML de la fenêtre contextuelle
    var strHTML = ""
    // On commence à construire le paragraphe de texte
    strHTML += "<p style='font-family: Arial; font-size: 10pt;'>Horaires d'ouverture<br/>"
    
    // Varaible pour gérer la bordure supérieure du premier tableau
    var border_top = ""
    
    strHTML += "<table style='border-collapse: collapse;font-family: Arial; font-size: 10pt;'>"
    strHTML += "<tr style='border: Opx solid;'><td  style='width: 80px;'> </td>"
    strHTML += "<td  style='width: 175px;text-align: left;font-size: 7pt;'>"+
               Text(HeureMinCalendrier,"H:mm")+"</td>"
    strHTML += "<td  style='width: 175px;text-align: right;font-size: 7pt;'>"+
               Text(HeureMaxCalendrier,"H:mm")+"</td>"
    // Fin du tableau 
    strHTML += "</tr></table>"
    
    // On boucle sur chaque jour de la semaine
    for(var i in ListeJourSemaine)
    {
      var NomDuJour = ListeJourSemaine[i]
      // On démarre un nouveau tableau
      strHTML += "<table style='border-collapse: collapse;font-family: Arial; font-size: 9pt;'>"
    
      // Si la ligne courante (i va de 0 à 6) est égal au jour courant (ISOWeekday de 1 à 7)
      // alors on met la ligne en gras et su fond gris clair
      if(i == ISOWeekday(Today())-1){
        strHTML += "<tr style='border: 1px solid;" + border_top + ";"
        strHTML += "background-color: #EEEEEE;font-weight: bold'>"
      }else{
        strHTML += "<tr style='border: 1px solid;" + border_top + ";'>"
      }
    
      // La première cellule contient le nom du jour
      strHTML += "<td  style='width: 80px;padding-left: 5px;'>" +  NomDuJour+"</td>"
    
      // On récupère les heures d'ouverture et de fermeture correspondant à ce
      // jour de la semaine
      var HeureOuvertureAM = $feature["Ouverture_"+NomDuJour+"_AM"]
      var HeureFermetureAM = $feature["Fermeture_"+NomDuJour+"_AM"]
      var HeureOuverturePM = $feature["Ouverture_"+NomDuJour+"_PM"]
      var HeureFermeturePM = $feature["Fermeture_"+NomDuJour+"_PM"]
    
      // Appel de la fonction remplissant la partie horaire du calendrier
      strHTML += GenererPlagesHoraires(HeureMinCalendrier,HeureMaxCalendrier,HeureOuvertureAM,
                                       HeureFermetureAM,HeureOuverturePM,HeureFermeturePM)
      // Fin du tableau 
      strHTML += "</tr></table>"
      // Pour les autres jours/tableaux, la bordure supérieure sera invisible
      border_top = "border-top: 0px;"
    }
    
    strHTML += "</p>"
    
    // On renvoie le bloc de code HTML de la fenêtre contextuelle
    return { 
    	type : 'text', 
    	text : strHTML
    }
    
  4. Votre carte affiche désormais les déchèteries avec des fenêtres contextuelles présentant le tableau des horaires d'ouverture pour le matin et l'après-midi. 



Bonne route sur ArcGIS Online !
   
Pour retrouver l'ensemble des Conseils & Astuces ArcGIS Online, cliquez sur ce lien.

  

Partager cet article:

Rejoindre la discussion

    Les commentaires à propos de cet article:

6 comments :

ElectroPlankton a dit…

Bonjour,

Merci beaucoup pour cet excellent travail.

Outre une logique jour de semaine, peut-on imaginer un code similaire mais qui représenterait des établissements qui ont ouvert puis fermé au fil des années ?

Bonne journée.

Gaëtan Lavenu a dit…

Bonjour,

Oui, de manière similaire vous pouvez afficher avec différents symboles (ou même marquer) des établissements ouverts ou fermé depuis une certaine date. Toutes les fonctions Arcade sur les données de type date et heure vous permettrons d'imaginer un peu ce que vous voulez aussi bien pour le rendu de la couche que pour les fenêtres contextuelles.

ElectroPlankton a dit…

Bonjour, y a-t-il de la documentation qui permet d'approfondir toutes les fonctions existantes et exploitables dans Arcade pour les solutions ESRI ?

Gaëtan Lavenu a dit…

Oui, une documentation très complète du langage Arcade (référence, exemples, playground, ... ) et des différents profils d'utilisation se trouve ici : https://developers.arcgis.com/arcade/

Gilles Grisard a dit…

Bonjour Gaëtan,

Merci pour cette présentation.
Pas de possibilité d'interpréter en arcade le format opening hours d'OSM ?

Bonne journée,

Gaëtan Lavenu a dit…

Bonjour,

Merci pour votre retour, la question est intéressante. Le format Open Hours OSM semble simple mais avec pas de syntaxes potentielles et un certain nombre de cas particuliers. Je regarde que l'on peut faire mais il y a clairement des possibilités avec Arcade pour représenter ces données.