{"id":94,"date":"2025-08-20T09:10:29","date_gmt":"2025-08-20T09:10:29","guid":{"rendered":"http:\/\/mlc72130.fr\/?page_id=94"},"modified":"2025-09-30T08:00:49","modified_gmt":"2025-09-30T08:00:49","slug":"commerce","status":"publish","type":"page","link":"https:\/\/mlc72130.fr\/index.php\/commerce\/","title":{"rendered":"Annuaire des entreprises, artisans et associations"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Cet espace a pour vocation de <strong>mettre en valeur les acteurs \u00e9conomiques, artisanaux et associatifs du territoire<\/strong>, et de faciliter leur visibilit\u00e9 aupr\u00e8s des habitants, visiteurs et partenaires.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Vous y trouverez des informations utiles sur les entreprises, commerces, artisans, services et associations pr\u00e9sents dans notre commune :<br>\ud83d\udd39 Nom et description de l\u2019activit\u00e9<br>\ud83d\udd39 Coordonn\u00e9es et horaires<br>\ud83d\udd39 Lien vers le site ou les r\u00e9seaux sociaux, le cas \u00e9ch\u00e9ant<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u27a1\ufe0f <strong>Vous \u00eates une entreprise, un artisan ou une association implant\u00e9(e) \u00e0 Moulins-le-Carbonnel et vous souhaitez appara\u00eetre dans cet annuaire ?<\/strong><br>Rien de plus simple : remplissez notre formulaire en ligne \ud83d\udc49 <a href=\"https:\/\/forms.gle\/CKBbtLvSkzED4FFbA\">Lien du formulaire<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cet annuaire est mis \u00e0 jour r\u00e9guli\u00e8rement. Il s\u2019inscrit dans la volont\u00e9 de la commune de <strong>soutenir l\u2019\u00e9conomie locale et la vie associative<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n  <meta charset=\"UTF-8\" \/>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" \/>\n  <style>\n    body {\n      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n      padding: 0;\n      margin: 0;\n      background: transparent;\n      color: #333;\n    }\n\n    h1 {\n      margin-bottom: 15px;\n      font-weight: 700;\n      font-size: 1.6rem;\n    }\n\n    input[type=\"text\"] {\n      width: 100%;\n      padding: 10px 12px;\n      margin-bottom: 20px;\n      font-size: 16px;\n      border-radius: 6px;\n      border: 1px solid #ccc;\n      box-sizing: border-box;\n    }\n\n    .table-container {\n      padding: 0;\n      margin: 0;\n      background: transparent;\n    }\n\n    table {\n      width: 100%;\n      border-collapse: collapse;\n      background: transparent;\n    }\n\n    th, td {\n      padding: 8px 10px;\n      text-align: left;\n      border-bottom: 1px solid #ddd;\n      cursor: pointer;\n      user-select: none;\n      background: transparent;\n    }\n\n    th {\n      background-color: #2c3e50;\n      color: #ecf0f1;\n      cursor: default;\n    }\n\n    tr.detail-row {\n      background: #f9f9f9;\n    }\n\n    tr.detail-row td {\n      cursor: default;\n    }\n\n    .contact a {\n      font-size: 20px;\n      margin-right: 12px;\n      text-decoration: none;\n      color: #0077cc;\n    }\n\n    .contact a:hover {\n      text-decoration: underline;\n    }\n\n    \/* Styles carrousel agrandi *\/\n    .carousel {\n      position: relative;\n      max-width: 600px;\n      max-height: 450px;\n      margin: 10px 0;\n      user-select: none;\n    }\n\n    .carousel img {\n      width: 100%;\n      max-height: 450px;\n      border-radius: 8px;\n      object-fit: contain;\n      box-shadow: 0 2px 5px rgba(0,0,0,0.1);\n      display: block;\n      cursor: pointer; \/* Pour indiquer que c'est cliquable *\/\n    }\n\n    .carousel-button {\n      position: absolute;\n      top: 50%;\n      transform: translateY(-50%);\n      background-color: rgba(0,0,0,0.3);\n      border: none;\n      color: white;\n      font-weight: bold;\n      font-size: 1.5rem;\n      padding: 0 10px;\n      cursor: pointer;\n      border-radius: 4px;\n      user-select: none;\n      transition: background-color 0.3s ease;\n    }\n\n    .carousel-button:hover {\n      background-color: rgba(0,0,0,0.6);\n    }\n\n    .carousel-prev {\n      left: 5px;\n    }\n\n    .carousel-next {\n      right: 5px;\n    }\n\n    .carousel-indicator {\n      text-align: center;\n      margin-top: 5px;\n      font-size: 0.9rem;\n      color: #555;\n      user-select: none;\n    }\n\n    \/* Modal lightbox *\/\n    .modal {\n      display: none;\n      position: fixed;\n      z-index: 9999;\n      left: 0; top: 0;\n      width: 100vw;\n      height: 100vh;\n      background-color: rgba(0,0,0,0.8);\n      align-items: center;\n      justify-content: center;\n      cursor: zoom-out;\n    }\n\n    .modal img {\n      max-width: 90vw;\n      max-height: 90vh;\n      border-radius: 8px;\n      box-shadow: 0 4px 15px rgba(0,0,0,0.7);\n    }\n  <\/style>\n<\/head>\n<body>\n\n<h1>Annuaire des entreprises &#038; associations moulinoises<\/h1>\n\n<input type=\"text\" id=\"search\" placeholder=\"\ud83d\udd0d Rechercher par mot-cl\u00e9...\" \/>\n\n<div class=\"table-container\">\n  <table id=\"annuaire-table\">\n    <thead>\n      <tr><th>Nom<\/th><\/tr>\n    <\/thead>\n    <tbody>\n      <tr><td>Chargement&#8230;<\/td><\/tr>\n    <\/tbody>\n  <\/table>\n<\/div>\n\n<!-- Modal lightbox -->\n<div id=\"modal\" class=\"modal\" tabindex=\"-1\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Image agrandie\">\n  <img decoding=\"async\" src=\"\" alt=\"Image agrandie\" \/>\n<\/div>\n\n<script>\nconst url = \"https:\/\/docs.google.com\/spreadsheets\/d\/15LMjiIzCuE_tl5OoqqooK83z26QyRIIefd7vLC0HXbM\/gviz\/tq?tqx=out:json&sheet=Annuaire%20filtr\u00e9\";\n\nconst colonnesFixes = [\n  \"Nom\",\n  \"Cat\u00e9gorie\",\n  \"Description\",\n  \"Contact\",\n  \"Adresse\",\n  \"Horaires\",\n  \"Itin\u00e9rante\",\n  \"Secteur\",\n  \"Image\"\n];\n\nlet allRows = [];\nlet openedDetailIndex = null;\n\nfetch(url)\n  .then(res => res.text())\n  .then(data => {\n    const json = JSON.parse(data.substr(47).slice(0, -2));\n    const table = json.table;\n\n    allRows = table.rows.map(row => {\n      let cells = row.c.map(cell => (cell ? cell.v : \"\"));\n\n      const itineranteIndex = colonnesFixes.indexOf(\"Itin\u00e9rante\");\n      if (cells[itineranteIndex] && cells[itineranteIndex].toLowerCase() === \"non\") {\n        return null;\n      }\n\n      const hasContent = cells.some((cell, i) => i !== 0 && cell && cell.toString().trim() !== \"\");\n      if (!hasContent) return null;\n\n      \/\/ Supprimer colonne inutile (ex: colonne d'index 3 si besoin)\n      cells.splice(3, 1); \/\/ Adapter selon ta feuille\n\n      \/\/ Recr\u00e9er le champ Contact avec ic\u00f4nes\n      const tel = cells[3] || \"\";\n      const email = cells[4] || \"\";\n      const site = cells[5] || \"\";\n      let contactHtml = \"\";\n\n      if (tel.trim() !== \"\") {\n        contactHtml += `<a href=\"tel:${tel.replace(\/\\s+\/g,'')}\" title=\"Appeler\">\ud83d\udcde<\/a>`;\n      }\n      if (email.includes(\"@\")) {\n        contactHtml += `<a href=\"mailto:${email}\" title=\"Envoyer un mail\">\ud83d\udce7<\/a>`;\n      }\n      if (site.startsWith(\"http\")) {\n        contactHtml += `<a href=\"${site}\" target=\"_blank\" rel=\"noopener\" title=\"Site web\">\ud83c\udf10<\/a>`;\n      }\n\n      cells.splice(3, 3, contactHtml);\n\n      return cells;\n    }).filter(row => row !== null);\n\n    displayTable(allRows);\n  })\n  .catch(err => {\n    console.error(\"Erreur :\", err);\n    const tbody = document.querySelector(\"#annuaire-table tbody\");\n    tbody.innerHTML = \"<tr><td>Erreur lors du chargement des donn\u00e9es.<\/td><\/tr>\";\n  });\n\nfunction createCarousel(images, altBase, uniqueId) {\n  if (images.length === 0) return \"\";\n\n  const idPrefix = \"carousel-\" + uniqueId;\n\n  return `\n  <div class=\"carousel\" id=\"${idPrefix}\">\n    <button class=\"carousel-button carousel-prev\" aria-label=\"Image pr\u00e9c\u00e9dente\">&#10094;<\/button>\n    <img decoding=\"async\" src=\"${images[0]}\" alt=\"${altBase} - Image 1\" data-index=\"0\" \/>\n    <button class=\"carousel-button carousel-next\" aria-label=\"Image suivante\">&#10095;<\/button>\n    <div class=\"carousel-indicator\">1 \/ ${images.length}<\/div>\n  <\/div>\n  `;\n}\n\nfunction displayTable(rows) {\n  const tbody = document.querySelector(\"#annuaire-table tbody\");\n  tbody.innerHTML = \"\";\n\n  if(rows.length === 0) {\n    tbody.innerHTML = \"<tr><td>Aucun r\u00e9sultat trouv\u00e9.<\/td><\/tr>\";\n    return;\n  }\n\n  rows.forEach((row, index) => {\n    const trMain = document.createElement(\"tr\");\n    const tdName = document.createElement(\"td\");\n    tdName.textContent = row[0] || \"(Sans nom)\";\n    tdName.style.fontWeight = \"600\";\n    tdName.style.color = \"#0077cc\";\n    tdName.style.cursor = \"pointer\";\n    tdName.title = \"Cliquer pour voir les d\u00e9tails\";\n\n    trMain.appendChild(tdName);\n    tbody.appendChild(trMain);\n\n    const trDetail = document.createElement(\"tr\");\n    trDetail.classList.add(\"detail-row\");\n    trDetail.style.display = \"none\";\n\n    const tdDetail = document.createElement(\"td\");\n    tdDetail.colSpan = 1;\n\n    let detailHtml = \"\";\n    let images = [];\n\n    colonnesFixes.forEach((col, i) => {\n      if(i === 0) return;\n      const value = row[i];\n      if(value && value.toString().trim() !== \"\") {\n        if(col === \"Contact\") {\n          detailHtml += `<strong>${col} :<\/strong> <span class=\"contact\">${value}<\/span><br\/>`;\n        } else if(col === \"Image\") {\n          images = value.split('|').map(img => img.trim()).filter(img => img !== \"\");\n        } else {\n          detailHtml += `<strong>${col} :<\/strong> ${value}<br\/>`;\n        }\n      }\n    });\n\n    tdDetail.innerHTML = detailHtml || \"<em>Aucune information disponible.<\/em>\";\n    trDetail.appendChild(tdDetail);\n    tbody.appendChild(trDetail);\n\n    if(images.length > 0) {\n      const carouselId = `carousel-${index}`;\n      const carouselHtml = createCarousel(images, `Image de ${row[0]}`, index);\n      const divCarousel = document.createElement(\"div\");\n      divCarousel.innerHTML = carouselHtml;\n      trDetail.querySelector(\"td\").appendChild(divCarousel);\n\n      initCarousel(carouselId, images, `Image de ${row[0]}`);\n    }\n\n    tdName.addEventListener(\"click\", () => {\n      if(openedDetailIndex === index) {\n        trDetail.style.display = \"none\";\n        openedDetailIndex = null;\n      } else {\n        document.querySelectorAll(\".detail-row\").forEach(row => (row.style.display = \"none\"));\n        trDetail.style.display = \"table-row\";\n        openedDetailIndex = index;\n        trMain.scrollIntoView({behavior: \"smooth\", block: \"start\"});\n      }\n    });\n  });\n}\n\nfunction initCarousel(carouselId, images, altBase) {\n  const carousel = document.getElementById(carouselId);\n  if (!carousel) return;\n\n  const imgElement = carousel.querySelector(\"img\");\n  const prevBtn = carousel.querySelector(\".carousel-prev\");\n  const nextBtn = carousel.querySelector(\".carousel-next\");\n  const indicator = carousel.querySelector(\".carousel-indicator\");\n\n  let currentIndex = 0;\n\n  function updateCarousel() {\n    imgElement.src = images[currentIndex];\n    imgElement.alt = `${altBase} - Image ${currentIndex + 1}`;\n    indicator.textContent = `${currentIndex + 1} \/ ${images.length}`;\n  }\n\n  prevBtn.addEventListener(\"click\", (e) => {\n    e.stopPropagation();\n    currentIndex = (currentIndex - 1 + images.length) % images.length;\n    updateCarousel();\n  });\n\n  nextBtn.addEventListener(\"click\", (e) => {\n    e.stopPropagation();\n    currentIndex = (currentIndex + 1) % images.length;\n    updateCarousel();\n  });\n\n  \/\/ Ajout du clic sur l'image pour ouvrir modal\n  imgElement.addEventListener(\"click\", () => {\n    openModal(imgElement.src, imgElement.alt);\n  });\n\n  updateCarousel();\n}\n\n\/\/ Gestion modal lightbox\nconst modal = document.getElementById(\"modal\");\nconst modalImg = modal.querySelector(\"img\");\n\nfunction openModal(src, alt) {\n  modal.style.display = \"flex\";\n  modalImg.src = src;\n  modalImg.alt = alt;\n  document.body.style.overflow = \"hidden\"; \/\/ bloque scroll page\n  modal.focus();\n}\n\nfunction closeModal() {\n  modal.style.display = \"none\";\n  modalImg.src = \"\";\n  modalImg.alt = \"\";\n  document.body.style.overflow = \"\"; \/\/ r\u00e9active scroll page\n}\n\nmodal.addEventListener(\"click\", closeModal);\n\n\/\/ Fermeture au clavier (Escape)\ndocument.addEventListener(\"keydown\", (e) => {\n  if (e.key === \"Escape\" && modal.style.display === \"flex\") {\n    closeModal();\n  }\n});\n\ndocument.getElementById(\"search\").addEventListener(\"input\", function () {\n  const query = this.value.toLowerCase();\n  const filtered = allRows.filter(row =>\n    row.some(cell => String(cell).toLowerCase().includes(query))\n  );\n  openedDetailIndex = null;\n  displayTable(filtered);\n});\n<\/script>\n\n<\/body>\n<\/html>\n\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Cet espace a pour vocation de mettre en valeur les acteurs \u00e9conomiques, artisanaux et associatifs du territoire, et de faciliter leur visibilit\u00e9 aupr\u00e8s des habitants, visiteurs et partenaires. Vous y&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"page-templates\/fullwidth.php","meta":{"footnotes":""},"class_list":["post-94","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/mlc72130.fr\/index.php\/wp-json\/wp\/v2\/pages\/94","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mlc72130.fr\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/mlc72130.fr\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/mlc72130.fr\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mlc72130.fr\/index.php\/wp-json\/wp\/v2\/comments?post=94"}],"version-history":[{"count":63,"href":"https:\/\/mlc72130.fr\/index.php\/wp-json\/wp\/v2\/pages\/94\/revisions"}],"predecessor-version":[{"id":497,"href":"https:\/\/mlc72130.fr\/index.php\/wp-json\/wp\/v2\/pages\/94\/revisions\/497"}],"wp:attachment":[{"href":"https:\/\/mlc72130.fr\/index.php\/wp-json\/wp\/v2\/media?parent=94"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}