templates/Services/Main/service.html.twig line 1

Open in your IDE?
  1. {% extends 'Services/base.html.twig' %}
  2. {% block header_epingles %}
  3.   {{ include('Lenord/Main/parts/epingles.html.twig') }}
  4. {% endblock %}
  5. {% block header_breadcrumb %}
  6.   {% include 'Nordinfo/Main/parts/breadcrumb.html.twig' %}
  7. {% endblock %}
  8. {% block body %}
  9.   <main tabindex="-1" role="main" id="mainContent">
  10.     {% include 'Nordinfo/Main/parts/back_btn.html.twig' with {'back_btn_class':'--nordServices --postDetails'} %}
  11.     <article style="overflow:visible;position:relative;z-index:98;">
  12.       <div class="containerSm containerPostDetails --nordServices mBLg">
  13.         <h1 class="__headingMain mTMd--imp">{{ service.titre }}</h1>
  14.         <ul class="__tags">
  15.           {% if service.sousprofils is not empty %}
  16.             {% if service.sousprofils|length == count_sous_profils %}
  17.               <li class="--profile"><a href="{{ path('services_services', {'slug': 'particulier'}) }}">Particulier</a></li>
  18.             {% else %}
  19.               {% for sp in service.sousprofils %}
  20.                 <li class="--profile">
  21.                   <a href="{{ path('services_services', {'slug': 'particulier'}) }}?sp[]={{ sp.aliasUrl }}">{{ sp.titre }}</a>{% if not loop.last %},{% endif %}
  22.                 </li>
  23.               {% endfor %}
  24.             {% endif %}
  25.           {% endif %}
  26.           {% for grandprofil in service.grandprofils %}
  27.             {% if grandprofil.aliasUrl != 'particulier' %}
  28.               <li class="--profile">
  29.                 <a href="{{ path('services_services', {'slug': grandprofil.aliasUrl}) }}">{{ grandprofil.titre }}</a>{% if not loop.last %},{% endif %}
  30.               </li>
  31.             {% endif %}
  32.           {% endfor %}
  33.           {% for sp in service.themes %}
  34.             <li class="{% if (service.sousprofils is not empty or service.grandprofils is not empty) and loop.first %}--separator{% endif %}">
  35.               {{ sp.titre }}{% if not loop.last %},{% endif %}
  36.             </li>
  37.           {% endfor %}
  38.         </ul>
  39.         <div class="separatorLine --sm"></div>
  40.         <div class="containerContent --nordServices">
  41.           <p class="__intro">{{ service.chapo }}</p>
  42.           {{ content_post|raw }}
  43.         </div>
  44.         {% if id == 45 %}
  45.           <div
  46.             style="background-color:#ecf4f7;padding-bottom:4rem;margin-top:4rem;width:100vw;transform:translateX(-50%);left:50%;position:relative;">
  47.             <div class="containerSm containerPostDetails --nordServices">
  48.               <h2 class="headingSection pTMd mBMd--imp">Mon adresse</h2>
  49.               <form class="formCustom mBMd--imp">
  50.                 <div class="form-group">
  51.                   <div class="__input-wrapper">
  52.                     <div class="__inner" style="position:relative;">
  53.                       <label for="inputAddress" style="margin-bottom:.5em;">
  54.                         <span class="label-text">Adresse</span>
  55.                       </label>
  56.                       <div id="autocomplete" class="autocomplete">
  57.                         <input class="autocomplete-input"
  58.                                placeholder="Entrez le nom de la rue"
  59.                                aria-label="Entrez le nom de la rue"
  60.                                id="inputAddress"
  61.                         >
  62.                         <ul class="autocomplete-result-list"></ul>
  63.                       </div>
  64.                       <div class="d-none">
  65.                         <input type="text"
  66.                                class="form-control"
  67.                                id="rueInput"
  68.                                placeholder="Entrez le nom de la rue"
  69.                                list="rueOptions"
  70.                                aria-autocomplete="list"
  71.                                aria-activedescendant="rueOptions"
  72.                                aria-expanded="false"
  73.                                style="padding:0.25rem 3rem 0.25rem 0.75rem;"
  74.                                onkeyup="handlerOnKeyUp(event)"
  75.                                onkeydown="handlerOnKeyDown(event)"
  76.                                onfocusout="handlerOnFocusOut(event)"
  77.                                autocomplete="one-time-code"
  78.                         >
  79.                         <ul class="address-feedback position-absolute list-group top-0"
  80.                             style="z-index:1100;top:calc(100% + 1px);width:calc(100%);" id="rueOptions"></ul>
  81.                       </div>
  82.                       <button onclick="init(event)" type="button"
  83.                               class="cardCollege__btnBack" id="btn_reinitialisation" style="display:none;">
  84.                         <svg xmlns="http://www.w3.org/2000/svg" height="1em"
  85.                              viewBox="0 0 384 512">
  86.                           <path
  87.                             d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/>
  88.                         </svg>
  89.                         <span class="sr-only">Vider la recherche</span></button>
  90.                       <div style="display:none;" class="cardCollege__containerLoader" id="rueInputLoader"
  91.                            aria-hidden="true">
  92.                         <div class="loader"></div>
  93.                       </div>
  94.                     </div>
  95.                   </div>
  96.                 </div>
  97.               </form>
  98.               <div id="libelle_multiple" class="labelMultipleColleges" style="display:none;">Cette adresse relève de
  99.                 plusieurs secteurs et donc de plusieurs collèges :
  100.               </div>
  101.               <div id="leCollege" class="cardColleges" style="display:none;">
  102.                 <div class="cardColleges__inner">
  103.                   <div>
  104.                     <h3 id="college_nom"></h3>
  105.                     <p id="college_adresse"></p>
  106.                     <ul class="cardColleges__listButtons">
  107.                       <li>
  108.                         <a id="college_telephone_lien" href="">
  109.                           <div class="cardColleges__inner">
  110.                             <span class="cardColleges__icon">
  111.                               <svg aria-hidden="true" id="b502a819-aaf7-4b39-99a9-de8335e974aa"
  112.                                    data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 265.57 265.51">
  113.                                 <defs>
  114.                                   <style>
  115.                                     .a7dd9744-ec09-4c6c-9c16-c23d5f53046b {
  116.                                       fill: #17323f;
  117.                                     }
  118.                                   </style>
  119.                                 </defs>
  120.                                 <path id="aeeccaf6-071a-4ed9-8b98-9c660428bb39"
  121.                                       data-name="e079d0e0-4290-4499-8edc-92635082f6d4"
  122.                                       class="a7dd9744-ec09-4c6c-9c16-c23d5f53046b"
  123.                                       d="M208.1,274.5a125.29,125.29,0,0,1-45.4-11.6C99.1,232.7,49,188.5,21.3,122.2A233.38,233.38,0,0,1,9.8,78.8,51.3,51.3,0,0,1,20,37.9,84.63,84.63,0,0,1,52.1,11.3,21.59,21.59,0,0,1,62.4,9a11.34,11.34,0,0,1,7.8,3.9c11.3,17.7,22.1,35.7,32.9,53.6A9.93,9.93,0,0,1,101.9,80c-6.1,5.9-12.5,11.5-19,16.9-13.7,11.5-15.2,15.8-5.8,31.1a146,146,0,0,0,24,30.7c18.1,16.5,37.3,31.9,56.8,46.7,14.9,11.2,17.4,10.1,28.9-4.4,4.1-5.1,8-10.4,12.3-15.2,7-8,11.1-8.5,20.1-3.3,16.6,9.7,33,19.6,49.7,29.1a9.3,9.3,0,0,1,5.1,11.7,64.5,64.5,0,0,1-46.9,47.5A135.69,135.69,0,0,1,208.1,274.5Z"
  124.                                       transform="translate(-8.99 -8.99)"></path>
  125.                               </svg>
  126.                             </span>
  127.                             <span class="cardColleges__text" id="college_telephone"></span>
  128.                           </div>
  129.                         </a>
  130.                       </li>
  131.                       <li id="bloc_mail">
  132.                         <a id="college_mail_href" href="#">
  133.                           <div class="cardColleges__inner">
  134.                             <span class="cardColleges__icon">
  135.                               <svg aria-hidden="true" id="b5c621d6-1983-4327-9028-3fe9272e594c"
  136.                                    data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 384">
  137.                                 <path
  138.                                   d="M502.3,190.8a6,6,0,0,1,9.7,4.7V400a48,48,0,0,1-48,48H48A48,48,0,0,1,0,400V195.6a6,6,0,0,1,9.7-4.7c22.4,17.4,52.1,39.5,154.1,113.6,21.1,15.4,56.7,47.8,92.2,47.6,35.7.3,72-32.8,92.3-47.6C450.3,230.4,479.9,208.2,502.3,190.8ZM256,320c23.2.4,56.6-29.2,73.4-41.4,132.7-96.3,142.8-104.7,173.4-128.7A23.93,23.93,0,0,0,512,131V112a48,48,0,0,0-48-48H48A48,48,0,0,0,0,112v19a24.08,24.08,0,0,0,9.2,18.9c30.6,23.9,40.7,32.4,173.4,128.7,16.8,12.2,50.2,41.8,73.4,41.4Z"
  139.                                   transform="translate(0 -64)"></path>
  140.                               </svg>
  141.                             </span>
  142.                             <span class="cardColleges__text" id="college_mail">xxxxxxxxx@ac-lille.fr</span>
  143.                           </div>
  144.                         </a>
  145.                       </li>
  146.                       <li>
  147.                         <a target="_blank" class="--icon-external" id="college_site_ent"
  148.                            href="#" title="Site internet">
  149.                           <div class="cardColleges__inner">
  150.                             <span class="cardColleges__icon">
  151.                               <svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 640 512">
  152.                                 <!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
  153.                                 <path
  154.                                   d="M579.8 267.7c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-1.1 1.6C206.5 251.2 213 330 263 380c56.5 56.5 148 56.5 204.5 0L579.8 267.7zM60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5L217.7 177.2c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.9l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6C433.5 260.8 427 182 377 132c-56.5-56.5-148-56.5-204.5 0L60.2 244.3z"/>
  155.                               </svg>
  156.                             </span>
  157.                             <span class="cardColleges__text">
  158.                               Site internet
  159.                               <span class="cardColleges__icon">
  160.                                 <svg aria-hidden="true" id="f0e66a82-9691-4c5a-8636-9953692f0b2f"
  161.                                      data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 232.3 234.74"
  162.                                      fill="currentColor">
  163.                                   <rect y="51.74" height="183"></rect>
  164.                                   <path d="M0,234.74H183v-183H0ZM20.4,72H162.7v142.3H20.4Z" transform="translate(0 0)">
  165.                                   </path>
  166.                                   <polygon
  167.                                     points="113.2 0 113.2 20.3 211.9 20.3 211.9 121.6 232.3 121.6 232.3 0 113.2 0">
  168.                                   </polygon>
  169.                                 </svg>
  170.                               </span>
  171.                             </span>
  172.                           </div>
  173.                         </a>
  174.                       </li>
  175.                     </ul>
  176.                   </div>
  177.                 </div>
  178.                 <p>
  179.                   <span id="college_rne"></span>
  180.                   <span id="college_nb_eleve"></span>
  181.                   <span class="font-weight-bold">Restauration scolaire :</span> <a id="college_menu_link" href="#"
  182.                                                                                    target="_blank"
  183.                                                                                    title="Consulter le menu"
  184.                                                                                    class="link-external">Consulter le
  185.                     menu du restaurant scolaire</a>
  186.                 </p>
  187.               </div>
  188.               <div id="lesImages" class="cardColleges__map mBMd--imp" style="display:none;">
  189.                 <div class="flex-item-left" id="college_image"></div>
  190.                 <div class="flex-item-right no-first-image" id="college_map"></div>
  191.               </div>
  192.               <div id="results"></div>
  193.               <p class="textCenter pBMd" style="display:none;" id="lien_reinitialisation">
  194.                 <button onclick="init();" class="btnResetCollegeSearch" id="btnResetCollegeSearch">Réinitialiser la
  195.                   recherche
  196.                 </button>
  197.               </p>
  198.             </div>
  199.             <script>
  200.               (() => {
  201.                 const loader = document.getElementById('rueInputLoader');
  202.                 const btnReset = document.getElementById('btn_reinitialisation');
  203.                 function filterByNord(results) {
  204.                   return results.filter(function (result) {
  205.                     return result.properties.postcode && result.properties.postcode.startsWith('59');
  206.                   });
  207.                 }
  208.                 new Autocomplete('#autocomplete', {
  209.                   search: input => {
  210.                     const url = `https://api-adresse.data.gouv.fr/search?q=${encodeURI(input)}&limit=4&autocomplete=1`;
  211.                     return new Promise(resolve => {
  212.                       if (input.length < 3) {
  213.                         return resolve([]);
  214.                       }
  215.                       loader.style.display = 'block';
  216.                       fetch(url)
  217.                         .then(response => response.json())
  218.                         .then(data => {
  219.                           const suggestions = filterByNord(data.features);
  220.                           const results = suggestions.map((result, index) => {
  221.                             return {...result, index};
  222.                           })
  223.                           loader.style.display = 'none';
  224.                           resolve(results);
  225.                         })
  226.                     })
  227.                   },
  228.                   debounceTime: 1000,
  229.                   submitOnEnter: true,
  230.                   renderResult: (result, props) => {
  231.                     let address = result.properties.name + " " + result.properties.postcode + " <strong>" + result.properties.city + "</strong>";
  232.                     return `
  233.                               <li ${props}>
  234.                                 ${address}
  235.                               </li>
  236.                             `
  237.                   },
  238.                   getResultValue: result => {
  239.                     return result.properties.name + " " + result.properties.postcode + " " + result.properties.city;
  240.                   },
  241.                   onSubmit: result => {
  242.                     btnReset.style.display = 'none';
  243.                     loader.style.display = 'block';
  244.                     getInfoRue(result.properties.name + " " + result.properties.postcode + " " + result.properties.city);
  245.                   }
  246.                 })
  247.               })();
  248.             </script>
  249.           </div>
  250.         {% elseif id == 500 %}
  251.           <div
  252.             style="background-color:#ecf4f7;padding-bottom:4rem;margin-top:4rem;width:100vw;transform:translateX(-50%);left:50%;position:relative;">
  253.             <div class="containerSm containerPostDetails --nordServices">
  254.               <h2 class="headingSection pTMd mBMd--imp">Mon adresse</h2>
  255.               <form class="formCustom mBMd--imp">
  256.                 <div class="form-group">
  257.                   <div class="__input-wrapper">
  258.                     <div class="__inner" style="position:relative;">
  259.                       <label for="inputAddress" style="margin-bottom:.5em;">
  260.                         <span class="label-text">Adresse</span>
  261.                       </label>
  262.                       <div id="autocomplete" class="autocomplete">
  263.                         <input class="autocomplete-input"
  264.                                placeholder="Entrez le numéro et le nom de la rue"
  265.                                aria-label="Entrez le numéro et le nom de la rue"
  266.                                id="inputAddress"
  267.                         >
  268.                         <ul class="autocomplete-result-list"></ul>
  269.                       </div>
  270.                       <div style="display:none;">
  271.                         <label for="rueInput">
  272.                           <span class="label-text">Adresse</span>
  273.                         </label>
  274.                         <input type="text" class="form-control" id="rueInput"
  275.                                placeholder="Entrez le numéro et le nom de la rue"
  276.                                list="rueOptions" style="padding:0.25rem 3rem 0.25rem 0.75rem;"
  277.                                onkeyup="handlerOnKeyUp(this.value)" onkeydown="handlerOnKeyDown(event)"
  278.                                onfocusout="handlerOnFocusOut()" autocomplete="one-time-code">
  279.                         <ul class="address-feedback position-absolute list-group top-0"
  280.                             style="z-index:1100;top:calc(100% + 1px);width:calc(100%);" id="rueOptions"></ul>
  281.                       </div>
  282.                       <button class="cardCollege__btnBack" id="btn_reinitialisation"
  283.                               style="display: none;" type="button">
  284.                         <svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 384 512">
  285.                           <path
  286.                             d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z">
  287.                           </path>
  288.                         </svg>
  289.                         <span class="sr-only">Vider la recherche</span></button>
  290.                       <div style="display: none;" class="cardCollege__containerLoader" id="rueInputLoader"
  291.                            aria-hidden="true">
  292.                         <div class="loader"></div>
  293.                       </div>
  294.                     </div>
  295.                   </div>
  296.                 </div>
  297.               </form>
  298.               <div id="mnsContainer"></div>
  299.               <p class="textCenter pBMd" style="display: none;" id="lien_reinitialisation">
  300.                 <button onclick="init();" class="btnResetCollegeSearch" id="btnResetMnsSearch">Réinitialiser la
  301.                   recherche
  302.                 </button>
  303.               </p>
  304.               <script>
  305.                 (() => {
  306.                   const loader = document.getElementById('rueInputLoader');
  307.                   const btnReset = document.getElementById('btn_reinitialisation');
  308.                   const inputAddress = document.getElementById('inputAddress');
  309.                   new Autocomplete('#autocomplete', {
  310.                     search: input => {
  311.                       const url = `https://api-adresse.data.gouv.fr/search?q=${encodeURI(input)}&limit=20&autocomplete=1`;
  312.                       return new Promise(resolve => {
  313.                         if (input.length < 3) {
  314.                           return resolve([]);
  315.                         }
  316.                         loader.style.display = 'block';
  317.                         fetch(url)
  318.                           .then(response => response.json())
  319.                           .then(data => {
  320.                             const suggestions = filterByNord(data.features);
  321.                             const results = suggestions.map((result, index) => {
  322.                               return {...result, index};
  323.                             })
  324.                             loader.style.display = 'none';
  325.                             resolve(results);
  326.                           })
  327.                       })
  328.                     },
  329.                     debounceTime: 1000,
  330.                     submitOnEnter: true,
  331.                     renderResult: (result, props) => {
  332.                       let address = result.properties.name + " " + result.properties.postcode + " <strong>" + result.properties.city + "</strong>";
  333.                       return `
  334.                               <li ${props}>
  335.                                 ${address}
  336.                               </li>
  337.                             `
  338.                     },
  339.                     getResultValue: result => {
  340.                       return result.properties.name + " " + result.properties.postcode + " " + result.properties.city;
  341.                     },
  342.                     onSubmit: async result => {
  343.                       btnReset.style.display = 'none';
  344.                       loader.style.display = 'block';
  345.                       await displayMnsInfo(result.properties.name + " " + result.properties.postcode + " " + result.properties.city);
  346.                     }
  347.                   })
  348.                   let currentFocus = -1;
  349.                   let fetchTrigger = 0;
  350.                   document.getElementById('btnResetMnsSearch').addEventListener('click', function (event) {
  351.                     init(event);
  352.                   });
  353.                   document.getElementById('btnResetMnsSearch').addEventListener('keyup', function (event) {
  354.                     if (event.key === 'Enter') {
  355.                       init(event);
  356.                     }
  357.                   });
  358.                   btnReset.addEventListener('click', init.bind(event));
  359.                   function httpRequest(url, callback) {
  360.                     let xhr = new XMLHttpRequest();
  361.                     xhr.onreadystatechange = function () {
  362.                       if (xhr.readyState === 4 && xhr.status === 200) {
  363.                         callback(JSON.parse(xhr.responseText));
  364.                       }
  365.                     };
  366.                     xhr.open('GET', url, false);
  367.                     xhr.send();
  368.                   }
  369.                   function init(e) {
  370.                     e.preventDefault();
  371.                     document.getElementById('rueInput').setAttribute('aria-expanded', 'false');
  372.                     document.getElementById('rueInputLoader').style.display = 'none';
  373.                     document.getElementById("rueInput").focus();
  374.                     document.getElementById('rueInput').value = "";
  375.                     inputAddress.value = "";
  376.                     afficheResultat(false);
  377.                     let datalist = document.getElementById('rueOptions');
  378.                     datalist.innerHTML = '';
  379.                     document.getElementById('lien_reinitialisation').style.display = "none";
  380.                     document.getElementById('btn_reinitialisation').style.display = "none";
  381.                     document.getElementById('rueInput').disabled = false;
  382.                     document.getElementById('rueInput').focus();
  383.                     document.getElementById('mnsContainer').innerHTML = '';
  384.                   }
  385.                   function afficheResultat(bool) {
  386.                     if (bool) {
  387.                       document.getElementById('lien_reinitialisation').style.display = "";
  388.                       document.getElementById('btn_reinitialisation').style.display = "";
  389.                       document.getElementById('rueInput').disabled = true;
  390.                       document.getElementById('rueInput').setAttribute('aria-expanded', 'false');
  391.                     }
  392.                   }
  393.                   function filterByNord(results) {
  394.                     return results.filter(function (result) {
  395.                       return result.properties.postcode && result.properties.postcode.startsWith('59');
  396.                     });
  397.                   }
  398.                   function convertirPremiereLettreMajuscule(chaine) {
  399.                     // Diviser la phrase en mots
  400.                     let mots = chaine.toLowerCase().split(" ");
  401.                     // Convertir la première lettre de chaque mot en majuscule
  402.                     for (let i = 0; i < mots.length; i++) {
  403.                       mots[i] = mots[i].charAt(0).toUpperCase() + mots[i].slice(1);
  404.                     }
  405.                     // Réassembler les mots en une phrase et la retourner
  406.                     return mots.join(" ");
  407.                   }
  408.                   async function getAddress(address) {
  409.                     const addressResponse = await fetch(
  410.                       `https://api-adresse.data.gouv.fr/search/?q=${encodeURIComponent(address)}`);
  411.                     const addressData = await addressResponse.json();
  412.                     return addressData.features[0].geometry.coordinates;
  413.                   }
  414.                   async function getMnsDetails(mns) {
  415.                     let url = '/ajax/get_mns_details?code_utpas=' + mns[0].attributes.code_utpas;
  416.                     let adresse;
  417.                     let type = "MNS";
  418.                     let horaires;
  419.                     let adresseMail;
  420.                     let photoUrl;
  421.                     let photoExists;
  422.                     let formattedTelephone = '';
  423.                     let telephone_lien = "";
  424.                     let nom;
  425.                     let result_array = [];
  426.                     let features;
  427.                     httpRequest(url, function (response) {
  428.                       features = response.features;
  429.                       let i = 0;
  430.                       features.forEach(feature => {
  431.                           const telephone = feature.attributes.telephone;
  432.                           if (telephone && telephone.length > 0) {
  433.                             // Supprimer tous les espaces du numéro de téléphone
  434.                             const cleanedTelephone = telephone.replace(/\s/g, '');
  435.                             // Formater le numéro de téléphone avec des espaces en utilisant une expression régulière
  436.                             formattedTelephone = cleanedTelephone.replace(/^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/, '$1 $2 $3 $4 $5');
  437.                             // Remplacer "03" par "+33"
  438.                             formattedTelephone = formattedTelephone.replace("03", "+33 3");
  439.                             // Formater le lien de téléphone avec le format tel:
  440.                             telephone_lien = 'tel:' + cleanedTelephone.replace(/^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/, '$1 $2 $3 $4 $5').replace("03", "+333").replace(/\s/g, '');
  441.                           }
  442.                           adresseMail = feature.attributes.adressemail;
  443.                           horaires = feature.attributes.horaires;
  444.                           adresse = feature.attributes.adresse + " " + feature.attributes.cp + " " + convertirPremiereLettreMajuscule(feature.attributes.commune);
  445.                           nom = "Maison Nord Solidarités (ex Unité Territoriale de Prévention et d'Action Sociale) " + mns[0].attributes.nomutpas;
  446.                           if (feature.attributes.adresse2 != null && feature.attributes.adresse2 == "ANTENNE") {
  447.                             nom = "Antenne Maison Nord Solidarités " + mns[0].attributes.nomutpas;
  448.                             type = "ANTENNE";
  449.                           }
  450.                           photoUrl =
  451.                             `https://datasig.lenord.fr/applications/mns/${feature.attributes.code_mns_txt}.jpg`;
  452.                           photoExists = checkPhotoExist(feature.attributes.code_mns_txt);
  453.                           tmp_array = [];
  454.                           tmp_array['id'] = feature.attributes.code_utpas;
  455.                           tmp_array['type'] = type;
  456.                           tmp_array['code_mns'] = feature.attributes.code_mns_txt;
  457.                           tmp_array['nom'] = convertirPremiereLettreMajuscule(nom);
  458.                           tmp_array['adresse'] = adresse;
  459.                           tmp_array['horaires'] = horaires;
  460.                           tmp_array['picto_access'] = feature.attributes.picto_access;
  461.                           tmp_array['longitude'] = feature.attributes.x_wgs84;
  462.                           tmp_array['latitude'] = feature.attributes.y_wgs84;
  463.                           tmp_array['telephone'] = formattedTelephone;
  464.                           tmp_array['telephone_lien'] = telephone_lien;
  465.                           tmp_array['adresseMail'] = adresseMail;
  466.                           tmp_array['photoUrl'] = photoUrl;
  467.                           tmp_array['photoExists'] = photoExists;
  468.                           result_array[i] = tmp_array;
  469.                           i++;
  470.                         }
  471.                       );
  472.                     });
  473.                     return result_array;
  474.                   }
  475.                   async function getMnsInfo(address) {
  476.                     const coordinates = await getAddress(address);
  477.                     let url = '/ajax/get_mns_info?lat=' + coordinates[0] + '&lng=' + coordinates[1];
  478.                     let mnsList;
  479.                     httpRequest(url, function (response) {
  480.                       mnsList = response.features;
  481.                     });
  482.                     return await getMnsDetails(mnsList);
  483.                   }
  484.                   function checkPhotoExist(photo) {
  485.                     let url = '/ajax/check_photo_exists?photo=' + photo;
  486.                     httpRequest(url, function (response) {
  487.                       return response;
  488.                       //}
  489.                     });
  490.                     /*try {
  491.                       const response = await fetch(url, {
  492.                         method: 'HEAD'
  493.                       });
  494.                       return response.ok;
  495.                     } catch (error) {
  496.                       return false;
  497.                     }*/
  498.                   }
  499.                   async function displayMnsInfo(address) {
  500.                     document.getElementById('mnsContainer').innerHTML = '';
  501.                     const mnsInfosArray = await getMnsInfo(address);
  502.                     const googleMapsStaticApiKey = 'AIzaSyCmvIOcgfl_y9l40sGBnqOo-6KypVacBP8';
  503.                     mnsInfosArray.forEach(mnsInfo => {
  504.                       const staticMapUrl = `https://maps.googleapis.com/maps/api/staticmap?center=${encodeURIComponent(mnsInfo.adresse)}&markers=color:red%7C${mnsInfo.latitude},${mnsInfo.longitude}&zoom=16&size=600x400&maptype=roadmap&key=${googleMapsStaticApiKey}`;
  505.                       const googleMapsLink =
  506.                         `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(mnsInfo.adresse)}`;
  507.                       const mnsElement = document.createElement('div');
  508.                       mnsElement.innerHTML = `
  509.                         <div  class="cardColleges" style="">
  510.                         <div class="cardColleges__inner">
  511.                           <div>
  512.                             <h3>${mnsInfo.nom}</h3>
  513.                             <p> ${mnsInfo.adresse}</p>
  514.                             <ul class="cardColleges__listButtons">
  515.                               ${mnsInfo.telephone ? ` <li>
  516.                                 <a href="${mnsInfo.telephone_lien}">
  517.                                   <div class="cardColleges__inner">
  518.                                     <span class="cardColleges__icon">
  519.                                       <svg aria-hidden="true" id="b502a819-aaf7-4b39-99a9-de8335e974aa"
  520.                                         data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 265.57 265.51">
  521.                                         <defs>
  522.                                           <style>
  523.                                             .a7dd9744-ec09-4c6c-9c16-c23d5f53046b {
  524.                                               fill: #17323f;
  525.                                             }
  526.                                           </style>
  527.                                         </defs>
  528.                                         <path id="aeeccaf6-071a-4ed9-8b98-9c660428bb39"
  529.                                           data-name="e079d0e0-4290-4499-8edc-92635082f6d4"
  530.                                           class="a7dd9744-ec09-4c6c-9c16-c23d5f53046b"
  531.                                           d="M208.1,274.5a125.29,125.29,0,0,1-45.4-11.6C99.1,232.7,49,188.5,21.3,122.2A233.38,233.38,0,0,1,9.8,78.8,51.3,51.3,0,0,1,20,37.9,84.63,84.63,0,0,1,52.1,11.3,21.59,21.59,0,0,1,62.4,9a11.34,11.34,0,0,1,7.8,3.9c11.3,17.7,22.1,35.7,32.9,53.6A9.93,9.93,0,0,1,101.9,80c-6.1,5.9-12.5,11.5-19,16.9-13.7,11.5-15.2,15.8-5.8,31.1a146,146,0,0,0,24,30.7c18.1,16.5,37.3,31.9,56.8,46.7,14.9,11.2,17.4,10.1,28.9-4.4,4.1-5.1,8-10.4,12.3-15.2,7-8,11.1-8.5,20.1-3.3,16.6,9.7,33,19.6,49.7,29.1a9.3,9.3,0,0,1,5.1,11.7,64.5,64.5,0,0,1-46.9,47.5A135.69,135.69,0,0,1,208.1,274.5Z"
  532.                                           transform="translate(-8.99 -8.99)"></path>
  533.                                       </svg>
  534.                                     </span>
  535.                                     <span class="cardColleges__text">${mnsInfo.telephone}</span>
  536.                                   </div>
  537.                                 </a>
  538.                               </li> ` : ''}
  539.                               ${mnsInfo.adresseMail ? `<li>
  540.                                 <a href="mailto:${mnsInfo.adresseMail}">
  541.                                   <div class="cardColleges__inner">
  542.                                     <span class="cardColleges__icon">
  543.                                       <svg aria-hidden="true" id="b5c621d6-1983-4327-9028-3fe9272e594c"
  544.                                         data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 384">
  545.                                         <path
  546.                                           d="M502.3,190.8a6,6,0,0,1,9.7,4.7V400a48,48,0,0,1-48,48H48A48,48,0,0,1,0,400V195.6a6,6,0,0,1,9.7-4.7c22.4,17.4,52.1,39.5,154.1,113.6,21.1,15.4,56.7,47.8,92.2,47.6,35.7.3,72-32.8,92.3-47.6C450.3,230.4,479.9,208.2,502.3,190.8ZM256,320c23.2.4,56.6-29.2,73.4-41.4,132.7-96.3,142.8-104.7,173.4-128.7A23.93,23.93,0,0,0,512,131V112a48,48,0,0,0-48-48H48A48,48,0,0,0,0,112v19a24.08,24.08,0,0,0,9.2,18.9c30.6,23.9,40.7,32.4,173.4,128.7,16.8,12.2,50.2,41.8,73.4,41.4Z"
  547.                                           transform="translate(0 -64)"></path>
  548.                                       </svg>
  549.                                     </span>
  550.                                     <span class="cardColleges__text" >${mnsInfo.adresseMail}</span>
  551.                                   </div>
  552.                                 </a>
  553.                               </li>` : ''}
  554.                             </ul>
  555.                           </div>
  556.                         </div>
  557.                         ${mnsInfo.horaires ? `<p >
  558.                           <b>Horaires : </b><span>${mnsInfo.horaires}</span>
  559.                         </p>` : ''}
  560.                         ${mnsInfo.picto_access ? `<p >
  561.                           <b>Accessibilité des lieux :</b><br /><iframe  title="Détail de l'accessibilité de ${mnsInfo.nom}"
  562.                             src="${mnsInfo.picto_access}"
  563.                             height="150"
  564.                             width="330"
  565.                             loading="lazy"
  566.                             style="border: none;"
  567.                           > 
  568.                           </iframe>
  569.                         </p>` : ''}
  570.                       </div>
  571.                     </section>
  572.                       <div  class="cardColleges__map mBMd--imp" style="">
  573.                         <div class="flex-item-left">
  574.                           <img src="${mnsInfo.photoUrl}" alt="">
  575.                         </div>
  576.                         <div class="flex-item-right">
  577.                           <a target="_blank" href="${googleMapsLink}" title="Itinéraire vers ${mnsInfo.nom}" style="position:relative;">
  578.                             <img src="${staticMapUrl}" alt="Itinéraire vers ${mnsInfo.nom}" style="width:100%;height:100%;position:absolute;left:0;top:0;object-fit:cover;border:0">
  579.                           </a>
  580.                         </div>
  581.                       </div>
  582.                         `;
  583.                       if (mnsInfo.type === "MNS") {
  584.                         document.getElementById('mnsContainer').appendChild(mnsElement);
  585.                       }
  586.                     });
  587.                     afficheResultat(true);
  588.                     btnReset.focus();
  589.                     loader.style.display = 'none';
  590.                   }
  591.                   async function onRueSelection(inputValue) {
  592.                     const address = inputValue.trim();
  593.                     if (address.length > 0) {
  594.                       await displayMnsInfo(address);
  595.                       document.getElementById('lien_reinitialisation').style.display = "";
  596.                       document.getElementById('btn_reinitialisation').style.display = "";
  597.                       document.getElementById('rueInput').disabled = true;
  598.                     }
  599.                   }
  600.                   function setActive() {
  601.                     let nbVal = $("div.address-feedback a").length;
  602.                     if (!nbVal)
  603.                       return false;
  604.                     $('div.address-feedback a').removeClass("active");
  605.                     currentFocus = ((currentFocus + nbVal - 1) % nbVal) + 1;
  606.                     $('div.address-feedback a:nth-child(' + currentFocus + ')').addClass("active");
  607.                   }
  608.                   function handlerOnKeyUp() {
  609.                     event.preventDefault();
  610.                     event.stopPropagation();
  611.                     if (event.keyCode === 38) {
  612.                       currentFocus--;
  613.                       setActive();
  614.                       return false;
  615.                     } else if (event.keyCode === 40) {
  616.                       currentFocus++;
  617.                       setActive();
  618.                       return false;
  619.                     } else if (event.keyCode === 13) {
  620.                       if (currentFocus > 0) {
  621.                         if ($("div.address-feedback a:nth-child(" + currentFocus + ")").attr("data-name")) {
  622.                           $("#rueInput").val($("div.address-feedback a:nth-child(" + currentFocus + ")").attr("data-name") + ' ' + $(
  623.                             "div.address-feedback a:nth-child(" + currentFocus + ")").attr("data-postcode") + ' ' + $(
  624.                             "div.address-feedback a:nth-child(" + currentFocus + ")").attr("data-city"));
  625.                         } else {
  626.                           $("#rueInput").val('');
  627.                         }
  628.                         $('.address-feedback').empty();
  629.                         onRueSelection($("#rueInput").val()).then(r => null);
  630.                       }
  631.                       return false;
  632.                     }
  633.                     $('div.address-feedback a').removeClass("active");
  634.                     currentFocus = 0;
  635.                     clearTimeout(fetchTrigger);
  636.                     let rue = $("#rueInput").val();
  637.                     if (rue.length === 0) {
  638.                       $('.address-feedback').empty();
  639.                       return false;
  640.                     }
  641.                     if (rue.length > 2) {
  642.                       document.getElementById('rueInputLoader').style.display = 'block';
  643.                       fetchTrigger = setTimeout(function () {
  644.                         $.get('https://api-adresse.data.gouv.fr/search/', {
  645.                           q: rue,
  646.                           limit: 20,
  647.                           autocomplete: 1
  648.                         }, function (data, status, xhr) {
  649.                           let liste = "";
  650.                           let suggestions = filterByNord(data.features);
  651.                           $.each(suggestions, function (i, obj) {
  652.                             let cooladdress = obj.properties.name + " " + obj.properties.postcode + " <strong>" + obj
  653.                               .properties.city + "</strong>";
  654.                             if (obj.properties.type && obj.properties.type.trim() !== 'municipality') {
  655.                               liste +=
  656.                                 '<a class="list-group-item list-group-item-action py-1" href="javascript:void(0)" name="' +
  657.                                 obj.properties.label + '" data-name="' + obj.properties.name + '" data-postcode="' + obj
  658.                                   .properties.postcode + '" data-city="' + obj.properties.city + '">' + cooladdress + '</a>';
  659.                             }
  660.                           });
  661.                           $('.address-feedback').html(liste);
  662.                           const elems = document.querySelectorAll('.list-group-item');
  663.                           for (let i = 0; i < elems.length; i++) {
  664.                             elems[i].addEventListener('mousedown', function (event) {
  665.                               handlerOnMouseDown(event, i, elems[i]);
  666.                             });
  667.                           }
  668.                           document.getElementById('rueInputLoader').style.display = 'none';
  669.                           document.getElementById('rueInput').setAttribute('aria-expanded', 'true');
  670.                         }, 'json');
  671.                       }, 500);
  672.                     }
  673.                   }
  674.                   function handlerOnKeyDown(e) {
  675.                     if ($("div.address-feedback a").length > 0 && (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 13)) {
  676.                       e.preventDefault();
  677.                     }
  678.                   }
  679.                   function handlerOnFocusOut() {
  680.                     $('.address-feedback').empty();
  681.                     document.getElementById('rueInput').setAttribute('aria-expanded', 'false');
  682.                   }
  683.                   function handlerOnMouseDown(event, index, element) {
  684.                     event.preventDefault();
  685.                     event.stopPropagation();
  686.                     $("#rueInput").val($(element).attr("data-name") + ' ' + $(element).attr("data-postcode") + ' ' + $(element).attr(
  687.                       "data-city"));
  688.                     $('.address-feedback').empty();
  689.                     onRueSelection($("#rueInput").val()).then(r => null);
  690.                   }
  691.                 })();
  692.               </script>
  693.             </div>
  694.           </div>
  695.         {% endif %}
  696.       </div>
  697.     </article>
  698.     {% if is_preview != 1 %}
  699.       <div class="container pT pB">
  700.         {% include 'Nordinfo/Main/parts/article-actions.html.twig' with {'post_title': title, 'post_id':'test', 'is_le_nord':true} %}
  701.       </div>
  702.     {% endif %}
  703.     {% if is_pdf|default and is_pdf == 1 %}{% else %}
  704.       <div class="containerVoting">
  705.         <div class="containerSm" aria-live="polite">
  706.           {% if hasVoted == 1 %}
  707.             <p id="labelSuccess" class="__result" style="margin-bottom:0;display:block!important;">Vous avez déja donné
  708.               votre avis sur ce
  709.               service.</p>
  710.           {% else %}
  711.             <fieldset class="__fieldset" id="fieldset">
  712.               <legend>Ce contenu vous a-t-il été utile ?</legend>
  713.               <div>
  714.                 <div>
  715.                   <input type="radio" id="vote_yes" name="vote" value="positif" aria-labelledby="label_yes"
  716.                          class="sr-only">
  717.                   <label id="label_yes" for="vote_yes">
  718.                   <span aria-hidden="true">
  719.                     <img src="{{ asset('img/brandmaster/icon-yes.svg') }}" alt="">
  720.                   </span>
  721.                     <span>Oui</span>
  722.                   </label>
  723.                 </div>
  724.                 <div>
  725.                   <input
  726.                     type="radio" id="vote_no" name="vote" value="negatif" aria-labelledby="label_no" class="sr-only">
  727.                   <label id="label_no" for="vote_no">
  728.                   <span aria-hidden="true">
  729.                     <img src="{{ asset('img/brandmaster/icon-no.svg') }}" alt="">
  730.                   </span>
  731.                     <span>Non</span>
  732.                   </label>
  733.                 </div>
  734.               </div>
  735.             </fieldset>
  736.             <div class="containerBtnSubmitVote"
  737.                  id="containerBtnSubmitVote"
  738.                  style="display:none;"
  739.             >
  740.               <button
  741.                 id="btnSubmitVote"
  742.                 class="btn btnFormSubmit --nordServices"
  743.                 aria-disabled="false"
  744.                 aria-busy="false"
  745.               >
  746.                 <span>Valider</span>
  747.                 <span class="loader"></span>
  748.               </button>
  749.             </div>
  750.             <p id="labelSuccess" class="__result" role="status">Merci d'avoir donné votre avis</p>
  751.             <p id="labelSuccessMessage" class="__result" role="status">Merci de votre message</p>
  752.             <div class="__containerForm" id="containerForm" style="display:none;">
  753.               <p class="__subtitle">Comment améliorer cette page ?</p>
  754.               <form
  755.                 action="#"
  756.                 method="post"
  757.                 class="needs-validation formCustom"
  758.                 id="formComment"
  759.               >
  760.                 <div class="form-group">
  761.                   <div class="__input-wrapper">
  762.                     <div class="__inner">
  763.                       <label for="inputComment">
  764.                         <span class="label-text">Votre commentaire <span class="colorRed">*</span></span>
  765.                       </label>
  766.                       <input
  767.                         type="text"
  768.                         class="form-control"
  769.                         id="inputComment"
  770.                         name="comment"
  771.                         placeholder=""
  772.                         required
  773.                       >
  774.                     </div>
  775.                   </div>
  776.                 </div>
  777.                 <div class="__buttons-wrapper containerBtnSubmitComment">
  778.                   <button
  779.                     class="btn btnFormSubmit --nordServices"
  780.                     id="btnSubmitFormComment"
  781.                     type="submit"
  782.                     aria-disabled="false"
  783.                     aria-busy="false"
  784.                   >
  785.                     <span>Valider</span>
  786.                     <span class="loader"></span>
  787.                   </button>
  788.                 </div>
  789.               </form>
  790.             </div>
  791.           {% endif %}
  792.         </div>
  793.       </div>
  794.     {% endif %}
  795.   </main>
  796. {% endblock %}
  797. {% block include_js %}
  798.   <script type="text/javascript">
  799.     const id = "{{ id }}";
  800.     const btnSubmitFormComment = document.getElementById('btnSubmitFormComment');
  801.     const formComment = document.getElementById('formComment');
  802.     const containerBtnSubmitVote = document.getElementById('containerBtnSubmitVote');
  803.     const btnSubmitVote = document.getElementById('btnSubmitVote');
  804.     const voteYes = document.getElementById('vote_yes');
  805.     const voteNo = document.getElementById('vote_no');
  806.     const containerForm = document.getElementById('containerForm');
  807.     const fieldset = document.getElementById('fieldset');
  808.     const labelSuccess = document.getElementById('labelSuccess');
  809.     const inputComment = document.getElementById('inputComment');
  810.     const labelSuccessMessage = document.getElementById('labelSuccessMessage');
  811.     function toggleSubmitButtonVisibility() {
  812.       if (voteYes.checked || voteNo.checked) {
  813.         containerBtnSubmitVote.style.display = 'block';
  814.       } else {
  815.         containerBtnSubmitVote.style.display = 'none';
  816.       }
  817.     }
  818.     voteYes.addEventListener('change', toggleSubmitButtonVisibility);
  819.     voteNo.addEventListener('change', toggleSubmitButtonVisibility);
  820.     btnSubmitVote.addEventListener('click', function (e) {
  821.       e.preventDefault();
  822.       if (voteYes.checked) {
  823.         btnSubmitVote.classList.add('--loading');
  824.         btnSubmitVote.setAttribute('aria-disabled', 'true');
  825.         btnSubmitVote.setAttribute('aria-busy', 'true');
  826.         btnSubmitVote.setAttribute('disabled', 'disabled');
  827.         $.ajax({
  828.           url: "{{ path('services_save_avis') }}",
  829.           data: {
  830.             'id': id,
  831.             'valeur': 'positif'
  832.           },
  833.           type: "POST",
  834.           success: function () {
  835.             setTimeout(() => {
  836.               containerBtnSubmitVote.style.display = 'none';
  837.               fieldset.style.display = 'none';
  838.               labelSuccess.style.display = 'block';
  839.             }, 1500);
  840.           }
  841.         });
  842.       } else if (voteNo.checked) {
  843.         btnSubmitVote.classList.add('--loading');
  844.         btnSubmitVote.setAttribute('aria-disabled', 'true');
  845.         btnSubmitVote.setAttribute('aria-busy', 'true');
  846.         btnSubmitVote.setAttribute('disabled', 'disabled');
  847.         setTimeout(() => {
  848.           containerForm.style.display = 'block';
  849.           containerBtnSubmitVote.style.display = 'none';
  850.           fieldset.style.display = 'none';
  851.         }, 1000);
  852.       }
  853.     });
  854.     formComment.addEventListener('submit', function (e) {
  855.       e.preventDefault();
  856.       btnSubmitFormComment.classList.add('--loading');
  857.       btnSubmitFormComment.setAttribute('aria-disabled', 'true');
  858.       btnSubmitFormComment.setAttribute('aria-busy', 'true');
  859.       btnSubmitFormComment.setAttribute('disabled', 'disabled');
  860.       $.ajax({
  861.         url: "{{ path('services_save_avis') }}",
  862.         data: {
  863.           'id': id,
  864.           'valeur': 'negatif',
  865.           'comment': inputComment.value
  866.         },
  867.         type: "POST",
  868.         success: function () {
  869.           setTimeout(() => {
  870.             containerForm.style.display = 'none';
  871.             labelSuccessMessage.style.display = 'block';
  872.           }, 1500);
  873.         }
  874.       });
  875.     });
  876.     if (id === "45") {
  877.       {% include 'Services/js/college.js' %}
  878.     }
  879.   </script>
  880. {% endblock %}