custom dynamic sites svg map
This commit is contained in:
		@@ -16,6 +16,7 @@
 | 
			
		||||
    ],
 | 
			
		||||
    "require": {
 | 
			
		||||
        "composer/installers": "^2.0",
 | 
			
		||||
        "drupal/block_field": "^1.0@RC",
 | 
			
		||||
        "drupal/config_pages": "^2.15",
 | 
			
		||||
        "drupal/core-composer-scaffold": "^10.2",
 | 
			
		||||
        "drupal/core-project-message": "^10.2",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										67
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										67
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
 | 
			
		||||
        "This file is @generated automatically"
 | 
			
		||||
    ],
 | 
			
		||||
    "content-hash": "365559febcbdf4e52ca276eed5a58fe5",
 | 
			
		||||
    "content-hash": "d9c788ae880184300ad1f5beb62e85a1",
 | 
			
		||||
    "packages": [
 | 
			
		||||
        {
 | 
			
		||||
            "name": "asm89/stack-cors",
 | 
			
		||||
@@ -2271,6 +2271,70 @@
 | 
			
		||||
                "irc": "irc://irc.freenode.org/drupal-contribute"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "drupal/block_field",
 | 
			
		||||
            "version": "1.0.0-rc5",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://git.drupalcode.org/project/block_field.git",
 | 
			
		||||
                "reference": "8.x-1.0-rc5"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://ftp.drupal.org/files/projects/block_field-8.x-1.0-rc5.zip",
 | 
			
		||||
                "reference": "8.x-1.0-rc5",
 | 
			
		||||
                "shasum": "b87e43e9bbaaf6cff6d8946d5e45db492978cbb6"
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "drupal/core": "^9 || ^10 || ^11"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "drupal-module",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "drupal": {
 | 
			
		||||
                    "version": "8.x-1.0-rc5",
 | 
			
		||||
                    "datestamp": "1723550576",
 | 
			
		||||
                    "security-coverage": {
 | 
			
		||||
                        "status": "not-covered",
 | 
			
		||||
                        "message": "RC releases are not covered by Drupal security advisories."
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packages.drupal.org/8/downloads",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "GPL-2.0-or-later"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "acbramley",
 | 
			
		||||
                    "homepage": "https://www.drupal.org/user/1036766"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "berdir",
 | 
			
		||||
                    "homepage": "https://www.drupal.org/user/214652"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "fenstrat",
 | 
			
		||||
                    "homepage": "https://www.drupal.org/user/362649"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "jrockowitz",
 | 
			
		||||
                    "homepage": "https://www.drupal.org/user/371407"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "michaellander",
 | 
			
		||||
                    "homepage": "https://www.drupal.org/user/636494"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "paulocs",
 | 
			
		||||
                    "homepage": "https://www.drupal.org/user/3640109"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Provides a field that allows a content entity to create and configure custom block instances.",
 | 
			
		||||
            "homepage": "https://www.drupal.org/project/block_field",
 | 
			
		||||
            "support": {
 | 
			
		||||
                "source": "https://git.drupalcode.org/project/block_field"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "drupal/bulkdelete",
 | 
			
		||||
            "version": "dev-1.x",
 | 
			
		||||
@@ -12825,6 +12889,7 @@
 | 
			
		||||
    "aliases": [],
 | 
			
		||||
    "minimum-stability": "stable",
 | 
			
		||||
    "stability-flags": {
 | 
			
		||||
        "drupal/block_field": 5,
 | 
			
		||||
        "drupal/page_manager": 5,
 | 
			
		||||
        "drupal/viewsreference": 10,
 | 
			
		||||
        "drupal/advanced_text_formatter": 5,
 | 
			
		||||
 
 | 
			
		||||
@@ -5,16 +5,17 @@ dependencies:
 | 
			
		||||
  config:
 | 
			
		||||
    - field.field.node.static.body
 | 
			
		||||
    - field.field.node.static.field_map
 | 
			
		||||
    - field.field.node.static.field_map_block
 | 
			
		||||
    - field.field.node.static.field_pieces_jointes
 | 
			
		||||
    - field.field.node.static.field_textes
 | 
			
		||||
    - node.type.static
 | 
			
		||||
  module:
 | 
			
		||||
    - block_field
 | 
			
		||||
    - field_group
 | 
			
		||||
    - file
 | 
			
		||||
    - paragraphs
 | 
			
		||||
    - path
 | 
			
		||||
    - text
 | 
			
		||||
    - viewsreference
 | 
			
		||||
third_party_settings:
 | 
			
		||||
  field_group:
 | 
			
		||||
    group_details:
 | 
			
		||||
@@ -57,15 +58,14 @@ content:
 | 
			
		||||
    region: content
 | 
			
		||||
    settings: {  }
 | 
			
		||||
    third_party_settings: {  }
 | 
			
		||||
  field_map:
 | 
			
		||||
    type: viewsreference_autocomplete
 | 
			
		||||
  field_map_block:
 | 
			
		||||
    type: block_field_default
 | 
			
		||||
    weight: 2
 | 
			
		||||
    region: content
 | 
			
		||||
    settings:
 | 
			
		||||
      match_operator: CONTAINS
 | 
			
		||||
      match_limit: 10
 | 
			
		||||
      size: 60
 | 
			
		||||
      placeholder: ''
 | 
			
		||||
      plugin_id: ''
 | 
			
		||||
      settings: {  }
 | 
			
		||||
      configuration_form: full
 | 
			
		||||
    third_party_settings: {  }
 | 
			
		||||
  field_pieces_jointes:
 | 
			
		||||
    type: file_generic
 | 
			
		||||
@@ -159,4 +159,5 @@ content:
 | 
			
		||||
      size: 60
 | 
			
		||||
      placeholder: ''
 | 
			
		||||
    third_party_settings: {  }
 | 
			
		||||
hidden: {  }
 | 
			
		||||
hidden:
 | 
			
		||||
  field_map: true
 | 
			
		||||
 
 | 
			
		||||
@@ -5,14 +5,15 @@ dependencies:
 | 
			
		||||
  config:
 | 
			
		||||
    - field.field.node.static.body
 | 
			
		||||
    - field.field.node.static.field_map
 | 
			
		||||
    - field.field.node.static.field_map_block
 | 
			
		||||
    - field.field.node.static.field_pieces_jointes
 | 
			
		||||
    - field.field.node.static.field_textes
 | 
			
		||||
    - node.type.static
 | 
			
		||||
  module:
 | 
			
		||||
    - block_field
 | 
			
		||||
    - entity_reference_revisions
 | 
			
		||||
    - manage_display
 | 
			
		||||
    - text
 | 
			
		||||
    - viewsreference
 | 
			
		||||
_core:
 | 
			
		||||
  default_config_hash: 9mgezio6-8HiMYhQHSfouZjKyY4BFKR71Yh4kbSmAYU
 | 
			
		||||
id: node.static.default
 | 
			
		||||
@@ -27,12 +28,10 @@ content:
 | 
			
		||||
    third_party_settings: {  }
 | 
			
		||||
    weight: 1
 | 
			
		||||
    region: content
 | 
			
		||||
  field_map:
 | 
			
		||||
    type: viewsreference_formatter
 | 
			
		||||
    label: visually_hidden
 | 
			
		||||
    settings:
 | 
			
		||||
      plugin_types:
 | 
			
		||||
        - block
 | 
			
		||||
  field_map_block:
 | 
			
		||||
    type: block_field
 | 
			
		||||
    label: above
 | 
			
		||||
    settings: {  }
 | 
			
		||||
    third_party_settings: {  }
 | 
			
		||||
    weight: 2
 | 
			
		||||
    region: content
 | 
			
		||||
@@ -61,6 +60,7 @@ content:
 | 
			
		||||
    region: content
 | 
			
		||||
hidden:
 | 
			
		||||
  created: true
 | 
			
		||||
  field_map: true
 | 
			
		||||
  field_pieces_jointes: true
 | 
			
		||||
  langcode: true
 | 
			
		||||
  search_api_excerpt: true
 | 
			
		||||
 
 | 
			
		||||
@@ -6,14 +6,15 @@ dependencies:
 | 
			
		||||
    - core.entity_view_mode.node.full
 | 
			
		||||
    - field.field.node.static.body
 | 
			
		||||
    - field.field.node.static.field_map
 | 
			
		||||
    - field.field.node.static.field_map_block
 | 
			
		||||
    - field.field.node.static.field_pieces_jointes
 | 
			
		||||
    - field.field.node.static.field_textes
 | 
			
		||||
    - node.type.static
 | 
			
		||||
  module:
 | 
			
		||||
    - block_field
 | 
			
		||||
    - entity_reference_revisions
 | 
			
		||||
    - manage_display
 | 
			
		||||
    - text
 | 
			
		||||
    - viewsreference
 | 
			
		||||
_core:
 | 
			
		||||
  default_config_hash: 9mgezio6-8HiMYhQHSfouZjKyY4BFKR71Yh4kbSmAYU
 | 
			
		||||
id: node.static.full
 | 
			
		||||
@@ -28,15 +29,10 @@ content:
 | 
			
		||||
    third_party_settings: {  }
 | 
			
		||||
    weight: 1
 | 
			
		||||
    region: content
 | 
			
		||||
  field_map:
 | 
			
		||||
    type: viewsreference_formatter
 | 
			
		||||
  field_map_block:
 | 
			
		||||
    type: block_field
 | 
			
		||||
    label: hidden
 | 
			
		||||
    settings:
 | 
			
		||||
      plugin_types:
 | 
			
		||||
        block: block
 | 
			
		||||
        default: '0'
 | 
			
		||||
        page: '0'
 | 
			
		||||
        feed: '0'
 | 
			
		||||
    settings: {  }
 | 
			
		||||
    third_party_settings: {  }
 | 
			
		||||
    weight: 2
 | 
			
		||||
    region: content
 | 
			
		||||
@@ -65,6 +61,7 @@ content:
 | 
			
		||||
    region: content
 | 
			
		||||
hidden:
 | 
			
		||||
  created: true
 | 
			
		||||
  field_map: true
 | 
			
		||||
  field_pieces_jointes: true
 | 
			
		||||
  langcode: true
 | 
			
		||||
  search_api_excerpt: true
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ dependencies:
 | 
			
		||||
    - core.entity_view_mode.node.teaser
 | 
			
		||||
    - field.field.node.static.body
 | 
			
		||||
    - field.field.node.static.field_map
 | 
			
		||||
    - field.field.node.static.field_map_block
 | 
			
		||||
    - field.field.node.static.field_pieces_jointes
 | 
			
		||||
    - field.field.node.static.field_textes
 | 
			
		||||
    - node.type.static
 | 
			
		||||
@@ -35,6 +36,7 @@ content:
 | 
			
		||||
hidden:
 | 
			
		||||
  created: true
 | 
			
		||||
  field_map: true
 | 
			
		||||
  field_map_block: true
 | 
			
		||||
  field_pieces_jointes: true
 | 
			
		||||
  field_textes: true
 | 
			
		||||
  langcode: true
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ module:
 | 
			
		||||
  block: 0
 | 
			
		||||
  block_class: 0
 | 
			
		||||
  block_content: 0
 | 
			
		||||
  block_field: 0
 | 
			
		||||
  breakpoint: 0
 | 
			
		||||
  bulkdelete: 0
 | 
			
		||||
  ckeditor5: 0
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								config/sync/field.field.node.static.field_map_block.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								config/sync/field.field.node.static.field_map_block.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
uuid: f1d706d7-b94c-4070-a98d-e00418611b82
 | 
			
		||||
langcode: fr
 | 
			
		||||
status: true
 | 
			
		||||
dependencies:
 | 
			
		||||
  config:
 | 
			
		||||
    - field.storage.node.field_map_block
 | 
			
		||||
    - node.type.static
 | 
			
		||||
  module:
 | 
			
		||||
    - block_field
 | 
			
		||||
id: node.static.field_map_block
 | 
			
		||||
field_name: field_map_block
 | 
			
		||||
entity_type: node
 | 
			
		||||
bundle: static
 | 
			
		||||
label: 'map block'
 | 
			
		||||
description: ''
 | 
			
		||||
required: false
 | 
			
		||||
translatable: false
 | 
			
		||||
default_value: {  }
 | 
			
		||||
default_value_callback: ''
 | 
			
		||||
settings:
 | 
			
		||||
  selection: blocks
 | 
			
		||||
  selection_settings:
 | 
			
		||||
    plugin_ids:
 | 
			
		||||
      sitesmap_block: sitesmap_block
 | 
			
		||||
field_type: block_field
 | 
			
		||||
							
								
								
									
										19
									
								
								config/sync/field.storage.node.field_map_block.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								config/sync/field.storage.node.field_map_block.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
uuid: fe870b67-228b-460b-848b-b696a91b740c
 | 
			
		||||
langcode: fr
 | 
			
		||||
status: true
 | 
			
		||||
dependencies:
 | 
			
		||||
  module:
 | 
			
		||||
    - block_field
 | 
			
		||||
    - node
 | 
			
		||||
id: node.field_map_block
 | 
			
		||||
field_name: field_map_block
 | 
			
		||||
entity_type: node
 | 
			
		||||
type: block_field
 | 
			
		||||
settings: {  }
 | 
			
		||||
module: block_field
 | 
			
		||||
locked: false
 | 
			
		||||
cardinality: 1
 | 
			
		||||
translatable: true
 | 
			
		||||
indexes: {  }
 | 
			
		||||
persist_with_no_fields: false
 | 
			
		||||
custom_storage: false
 | 
			
		||||
@@ -202,18 +202,15 @@ variant_settings:
 | 
			
		||||
        - ''
 | 
			
		||||
      html_id: ''
 | 
			
		||||
      css_styles: ''
 | 
			
		||||
    9c0f77a5-efea-4e81-99c4-2199c1d0d07d:
 | 
			
		||||
      id: 'views_block:site-block_2'
 | 
			
		||||
      label: ''
 | 
			
		||||
    f3919785-5a3a-4926-9de5-e63613bcba52:
 | 
			
		||||
      id: sitesmap_block
 | 
			
		||||
      label: 'Sites map Block'
 | 
			
		||||
      label_display: '0'
 | 
			
		||||
      provider: views
 | 
			
		||||
      provider: q2d_mod
 | 
			
		||||
      context_mapping: {  }
 | 
			
		||||
      views_label: ''
 | 
			
		||||
      items_per_page: none
 | 
			
		||||
      exposed: {  }
 | 
			
		||||
      region: first
 | 
			
		||||
      weight: -4
 | 
			
		||||
      uuid: 9c0f77a5-efea-4e81-99c4-2199c1d0d07d
 | 
			
		||||
      uuid: f3919785-5a3a-4926-9de5-e63613bcba52
 | 
			
		||||
      css_classes:
 | 
			
		||||
        - ''
 | 
			
		||||
      html_id: ''
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ display:
 | 
			
		||||
            alter_text: false
 | 
			
		||||
            text: ''
 | 
			
		||||
            make_link: false
 | 
			
		||||
            path: ''
 | 
			
		||||
            path: '{{ field_pieces_jointes }}'
 | 
			
		||||
            absolute: false
 | 
			
		||||
            external: false
 | 
			
		||||
            replace_spaces: false
 | 
			
		||||
@@ -50,7 +50,7 @@ display:
 | 
			
		||||
            link_class: ''
 | 
			
		||||
            prefix: ''
 | 
			
		||||
            suffix: ''
 | 
			
		||||
            target: ''
 | 
			
		||||
            target: _blank
 | 
			
		||||
            nl2br: false
 | 
			
		||||
            max_length: 0
 | 
			
		||||
            word_boundary: true
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,57 @@
 | 
			
		||||
@font-face {
 | 
			
		||||
  font-family: 'gilroy-semibold';
 | 
			
		||||
  src: url('fonts/Gilroy/gilroy-semibold-webfont.woff') format('woff');
 | 
			
		||||
}
 | 
			
		||||
#sites-map-container {
 | 
			
		||||
  background-color: #c3cef2;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
/* #sites-map-container .circle {
 | 
			
		||||
  fill: black;
 | 
			
		||||
  stroke: white;
 | 
			
		||||
  stroke-width: 0.7;
 | 
			
		||||
} */
 | 
			
		||||
 | 
			
		||||
/* Changer la couleur au survol (hover) */
 | 
			
		||||
#sites-map-container .site-link:hover{
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#sites-map-container .site-link:hover circle.circle {
 | 
			
		||||
  fill: #f7002b!important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Styles du popup (caché par défaut) */
 | 
			
		||||
#sites-map-container #popup {
 | 
			
		||||
  font-family: 'gilroy-semibold';
 | 
			
		||||
  display: none;
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  left: 50%;
 | 
			
		||||
  top: 50%;
 | 
			
		||||
  transform: translate(-50%, -50%);
 | 
			
		||||
  z-index: 1000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#sites-map-container strong{
 | 
			
		||||
  color: #f7002b;
 | 
			
		||||
  font-family: 'gilroy-semibold';
 | 
			
		||||
}
 | 
			
		||||
#sites-map-container a{
 | 
			
		||||
  display: inline-flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  color: white;
 | 
			
		||||
  background: black;
 | 
			
		||||
  text-transform: uppercase;
 | 
			
		||||
  font-size: 0.8rem;
 | 
			
		||||
  padding-left: 0.5rem;
 | 
			
		||||
  text-decoration: none;
 | 
			
		||||
  margin-top: 0.7rem;
 | 
			
		||||
  height: 1.3rem;
 | 
			
		||||
}
 | 
			
		||||
#sites-map-container a:after{
 | 
			
		||||
        display: inline-flex;
 | 
			
		||||
        content: url("../img/noun-arrow-to-right.svg");
 | 
			
		||||
        padding-right: 0.2rem;
 | 
			
		||||
        padding-left: 0.2rem;
 | 
			
		||||
        
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										0
									
								
								web/modules/custom/q2d_mod/assets/css/fontface.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								web/modules/custom/q2d_mod/assets/css/fontface.css
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
// Sélection des éléments au préalable pour éviter de les rechercher plusieurs fois
 | 
			
		||||
const svgElement = document.querySelector('#sites-map-container svg');
 | 
			
		||||
const popup = document.querySelector('#sites-map-container #popup');
 | 
			
		||||
const popupContent = document.querySelector('#sites-map-container #popup-content');
 | 
			
		||||
const modalBackground = document.querySelector('#sites-map-container #modal-background');
 | 
			
		||||
console.log('svgElement', svgElement);
 | 
			
		||||
 | 
			
		||||
// Fonction pour afficher le popup
 | 
			
		||||
function showPopup(content, x, y) {
 | 
			
		||||
    console.log('showPopup', content, x, y);
 | 
			
		||||
    
 | 
			
		||||
    popupContent.innerHTML = content;
 | 
			
		||||
 | 
			
		||||
    // Récupérer la position de l'élément SVG seulement une fois
 | 
			
		||||
    const rect = svgElement.getBoundingClientRect();
 | 
			
		||||
 | 
			
		||||
    // Calculer la position du popup par rapport à l'élément SVG
 | 
			
		||||
    const popupX = rect.left + x + 120; // Décalage de 120px à droite
 | 
			
		||||
    const popupY = rect.top + y + 20;  // Décalage de 20px en dessous
 | 
			
		||||
 | 
			
		||||
    // Dimensions de la fenêtre et du popup
 | 
			
		||||
    const viewportWidth = window.innerWidth;
 | 
			
		||||
    const viewportHeight = window.innerHeight;
 | 
			
		||||
    const popupWidth = popup.offsetWidth;
 | 
			
		||||
    const popupHeight = popup.offsetHeight;
 | 
			
		||||
 | 
			
		||||
    // Vérification des bordures droite et gauche
 | 
			
		||||
    if (popupX + popupWidth > viewportWidth) {
 | 
			
		||||
        popupX = viewportWidth - popupWidth - 10; // Ajuster pour qu'il ne dépasse pas à droite
 | 
			
		||||
    }
 | 
			
		||||
    if (popupX < 0) {
 | 
			
		||||
        popupX = 10; // S'assurer que le popup ne dépasse pas à gauche
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Vérification des bordures inférieure et supérieure
 | 
			
		||||
    if (popupY + popupHeight > viewportHeight) {
 | 
			
		||||
        popupY = viewportHeight - popupHeight - 10; // Ajuster pour qu'il ne dépasse pas en bas
 | 
			
		||||
    }
 | 
			
		||||
    if (popupY < 0) {
 | 
			
		||||
        popupY = 10; // S'assurer que le popup ne dépasse pas en haut
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    popup.style.left = `${popupX}px`;
 | 
			
		||||
    popup.style.top = `${popupY}px`;
 | 
			
		||||
    popup.style.display = 'block';
 | 
			
		||||
    modalBackground.style.display = 'block'; // Activer le fond modal si nécessaire
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Recalculer la position du popup lors du redimensionnement de la fenêtre
 | 
			
		||||
window.addEventListener('resize', function() {
 | 
			
		||||
    if (popup.style.display === 'block') {
 | 
			
		||||
        // Recalculer les coordonnées et ajuster la position
 | 
			
		||||
        const currentPopupRect = popup.getBoundingClientRect();
 | 
			
		||||
        showPopup(popupContent.innerHTML, currentPopupRect.left, currentPopupRect.top);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Fonction pour fermer le popup
 | 
			
		||||
function closePopup() {
 | 
			
		||||
    popup.style.display = 'none';
 | 
			
		||||
    modalBackground.style.display = 'none'; // Désactiver le fond modal
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Ajout d'un écouteur d'événement sur l'élément SVG pour tous les cercles
 | 
			
		||||
svgElement.addEventListener('click', function(event) {
 | 
			
		||||
    console.log('svgElement click', event.target);
 | 
			
		||||
    
 | 
			
		||||
    if (event.target.classList.contains('site-link')) {
 | 
			
		||||
        // Récupérer le contenu personnalisé de l'attribut data-content
 | 
			
		||||
        const content = event.target.getAttribute('data-content');
 | 
			
		||||
 | 
			
		||||
        // Récupérer la position du cercle cliqué par rapport à l'élément SVG
 | 
			
		||||
        const rect = svgElement.getBoundingClientRect();
 | 
			
		||||
        const circleX = event.clientX - rect.left;
 | 
			
		||||
        const circleY = event.clientY - rect.top;
 | 
			
		||||
 | 
			
		||||
        // Afficher le popup avec le contenu spécifique
 | 
			
		||||
        showPopup(content, circleX, circleY);
 | 
			
		||||
 | 
			
		||||
        // Empêcher la propagation de l'événement pour éviter la fermeture immédiate
 | 
			
		||||
        event.stopPropagation();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Ferme le popup quand on clique n'importe où sur la page, sauf sur le popup
 | 
			
		||||
document.addEventListener('click', function(event) {
 | 
			
		||||
    // Vérifier si le clic s'est produit en dehors du popup
 | 
			
		||||
    if (popup.style.display === 'block' && !popup.contains(event.target)) {
 | 
			
		||||
        closePopup();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										7
									
								
								web/modules/custom/q2d_mod/q2d_mod.libraries.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								web/modules/custom/q2d_mod/q2d_mod.libraries.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
sites_map_block:
 | 
			
		||||
  css:
 | 
			
		||||
    theme:
 | 
			
		||||
      assets/css/fontface.css: {}
 | 
			
		||||
      assets/css/carte-interactive-qdd.css: {}
 | 
			
		||||
  js:
 | 
			
		||||
    assets/js/carte-interactive-qdd.js: {}
 | 
			
		||||
@@ -5,3 +5,13 @@
 | 
			
		||||
 * Primary module hooks for reha module.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Implements hook_theme().
 | 
			
		||||
 */
 | 
			
		||||
function q2d_mod_theme() {
 | 
			
		||||
  return array(
 | 
			
		||||
    'svg_mapsites' => array(
 | 
			
		||||
      'variables' => array('vpw' => null, 'vph' => null, 'sites' => []),
 | 
			
		||||
    ),
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										113
									
								
								web/modules/custom/q2d_mod/src/Plugin/Block/SitesMap.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								web/modules/custom/q2d_mod/src/Plugin/Block/SitesMap.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Drupal\q2d_mod\Plugin\Block;
 | 
			
		||||
 | 
			
		||||
use Drupal\Core\Block\BlockBase;
 | 
			
		||||
use Drupal\Core\Block\Attribute\Block;
 | 
			
		||||
// use Drupal\Core\StringTranslation\TranslatableMarkup;
 | 
			
		||||
use Drupal\Core\Link;
 | 
			
		||||
use Drupal\Core\Render\Markup;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides a 'Sites Map' Block.
 | 
			
		||||
 * @Block(
 | 
			
		||||
 *   id = "sitesmap_block",
 | 
			
		||||
 *   admin_label = @Translation("Sites map Block"),
 | 
			
		||||
 * )
 | 
			
		||||
 */
 | 
			
		||||
class SitesMap extends BlockBase {
 | 
			
		||||
 
 | 
			
		||||
  /**
 | 
			
		||||
   * {@inheritdoc}
 | 
			
		||||
   */
 | 
			
		||||
  public function build() {
 | 
			
		||||
    $return = null;
 | 
			
		||||
 | 
			
		||||
    $allSites = \Drupal::entityTypeManager()->getStorage('node')
 | 
			
		||||
          ->loadByProperties(['type' => 'site', 'status' => 1]);
 | 
			
		||||
  
 | 
			
		||||
    $sites_paths = "";
 | 
			
		||||
 | 
			
		||||
    $vp_w = 400;
 | 
			
		||||
    $vp_h = 400;
 | 
			
		||||
 | 
			
		||||
    // Coordonnées géographiques des coins de la carte (France)
 | 
			
		||||
    $latTop = 52.0; // Nord-Ouest (coin supérieur gauche)
 | 
			
		||||
    $lonLeft = -6.0;
 | 
			
		||||
    $latBottom = 40.0; // Sud-Est (coin inférieur droit)
 | 
			
		||||
    $lonRight = 11.0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    foreach($allSites as $index => $site){
 | 
			
		||||
      $title = $site->get('title')->getString();
 | 
			
		||||
      $subtitle = $site->get('field_sous_titre')->getString();
 | 
			
		||||
 | 
			
		||||
      $link_options = ['absolute' => FALSE, 'attributes' => ['class' => 'site-link']];
 | 
			
		||||
      $site_link_object = Link::createFromRoute("voir le site", 'entity.node.canonical', ['node' => $site->id()], $link_options);
 | 
			
		||||
      $link = $site_link_object->toString()->getGeneratedLink();
 | 
			
		||||
 | 
			
		||||
      $datacontent = htmlspecialchars("<strong>$title</strong><br>$subtitle<br>$link");
 | 
			
		||||
 | 
			
		||||
      $geofield = $site->get('field_geofield')->get(0);
 | 
			
		||||
      $lon = $geofield->lon;
 | 
			
		||||
      $lat = $geofield->lat;
 | 
			
		||||
 | 
			
		||||
      $x = round(($lon - $lonLeft) / ($lonRight - $lonLeft) * $vp_w);
 | 
			
		||||
      $y = round(($latTop - $lat) / ($latTop - $latBottom) * $vp_h);
 | 
			
		||||
 | 
			
		||||
      $r = 10;
 | 
			
		||||
      $m = -$r+2;
 | 
			
		||||
      $l = $r*2-4;
 | 
			
		||||
      $sites_paths .= <<<SVGSITEPATH
 | 
			
		||||
      <g 
 | 
			
		||||
        id="site-$index"
 | 
			
		||||
        transform="
 | 
			
		||||
          translate($x,$y)">
 | 
			
		||||
        <circle
 | 
			
		||||
          id="path83" class="circle"
 | 
			
		||||
          cx="0" cy="0" r="$r"
 | 
			
		||||
          style="fill:#000000;fill-opacity:1;fill-rule:nonzero;" />
 | 
			
		||||
        <path
 | 
			
		||||
          id="path84"
 | 
			
		||||
          d="m 0,$m v $l"
 | 
			
		||||
          style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" />
 | 
			
		||||
        <path
 | 
			
		||||
          id="path85"
 | 
			
		||||
          d="m $m,0 h $l"
 | 
			
		||||
          style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" />
 | 
			
		||||
        <circle
 | 
			
		||||
          class="site-link"
 | 
			
		||||
          data-content="$datacontent"
 | 
			
		||||
          cx="0" cy="0" r="$r"
 | 
			
		||||
          style="fill:#000000;fill-opacity:0;fill-rule:nonzero;" />
 | 
			
		||||
      </g>
 | 
			
		||||
      SVGSITEPATH;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    $return = [
 | 
			
		||||
      '#cache' => [
 | 
			
		||||
        'max-age' => 0,
 | 
			
		||||
      ],
 | 
			
		||||
      'svg_mapsites' => [
 | 
			
		||||
        '#theme' => 'svg_mapsites',
 | 
			
		||||
        '#sites' => $sites_paths,
 | 
			
		||||
        '#vpw' => $vp_w,
 | 
			
		||||
        '#vph' => $vp_h,
 | 
			
		||||
        '#attached' => [
 | 
			
		||||
          'library' => [
 | 
			
		||||
            'q2d_mod/sites_map_block',
 | 
			
		||||
          ],
 | 
			
		||||
        ],
 | 
			
		||||
      ]
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    return $return;
 | 
			
		||||
    // return [
 | 
			
		||||
    //   '#markup' => $this->t('Hello, Sites Map!'),
 | 
			
		||||
    // ];
 | 
			
		||||
  }
 | 
			
		||||
  public function getCacheMaxAge() {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								web/modules/custom/q2d_mod/templates/svg-mapsites.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								web/modules/custom/q2d_mod/templates/svg-mapsites.html.twig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
<div id="sites-map-container">
 | 
			
		||||
  {# <svg {{ svg_attributes }}>
 | 
			
		||||
    <path {{ path_attributes }}></path>
 | 
			
		||||
  </svg> #}
 | 
			
		||||
  <svg
 | 
			
		||||
      width="{{ vpw }}"
 | 
			
		||||
      height="{{ vph }}"
 | 
			
		||||
      viewBox="0 0 100% 400px"
 | 
			
		||||
      version="1.1"
 | 
			
		||||
      id="svg1"
 | 
			
		||||
      xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
      xmlns:svg="http://www.w3.org/2000/svg">
 | 
			
		||||
 | 
			
		||||
      <g
 | 
			
		||||
        id="layer1"
 | 
			
		||||
        transform="
 | 
			
		||||
          translate(-25.237685,-27.066503)
 | 
			
		||||
          scale(2 2)"
 | 
			
		||||
        > 
 | 
			
		||||
        <g
 | 
			
		||||
          id="g87"
 | 
			
		||||
          transform="matrix(0.26458333,0,0,0.26458333,-117.12499,-462.76799)"
 | 
			
		||||
          >
 | 
			
		||||
          <path
 | 
			
		||||
            d="M 22.94948,0 24.34889,-18.0149 0,-25.72302 5.65439,-72.56693 20.36713,-85.65977 31.67962,-51.59929 30.80613,-4.91625 Z"
 | 
			
		||||
            style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
 | 
			
		||||
            transform="matrix(1.3333333,0,0,-1.3333333,1086.6494,2370.4282)"
 | 
			
		||||
            id="path86" />
 | 
			
		||||
          <path
 | 
			
		||||
            d="M 213.91022,-8.56159 245.88833,0 c 0,0 58.73522,-78.05274 188.63529,-102.77609 0,0 -13.72994,-23.9062 -20.7684,-68.77233 l -46.76509,-59.13289 22.59883,4.10628 9.98215,-59.15478 -15.22238,-6.69194 c 0,0 21.10627,-42.02694 33.11738,-51.15904 l -49.61728,-51.89156 c 0,0 -54.37257,40.3184 -83.08495,23.05862 -26.13166,-16.38332 -20.26669,-47.73592 -20.26669,-47.73592 l -84.48157,7.5286 -73.42912,23.87167 c 0,0 13.68285,68.86637 13.5616,120.85908 l 13.70164,-16.03089 -8.31311,25.90453 c -7.71795,24.04996 -30.44003,42.76792 -30.59939,44.58536 -3.6948,42.13802 -38.37183,51.8082 -82.82932,56.0101 L 0,-120.94655 l 48.38804,11.38921 63.90371,-13.15789 c 0,0 -1.62874,19.5427 -17.78042,51.54499 l 20.25382,7.61331 c 0,0 16.51357,-27.83033 25.80184,-26.51089 4.8781,0.69253 23.95695,21.70897 32.12568,26.76126 7.32295,4.5292 35.79484,10.58956 36.55389,13.534 2.94469,10.87069 4.66366,41.21097 4.66366,41.21097 z"
 | 
			
		||||
            style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
 | 
			
		||||
            transform="matrix(1.3333333,0,0,-1.3333333,543.93475,1857.6088)"
 | 
			
		||||
            id="path87" />
 | 
			
		||||
        </g>
 | 
			
		||||
      </g>
 | 
			
		||||
      <g
 | 
			
		||||
        id="layer2">
 | 
			
		||||
          {{ sites|raw }}
 | 
			
		||||
      </g>
 | 
			
		||||
    </svg>
 | 
			
		||||
 | 
			
		||||
    <!-- Fond du modal -->
 | 
			
		||||
    <div id="modal-background" class="modal-background"></div>
 | 
			
		||||
 | 
			
		||||
    <!-- Popup -->
 | 
			
		||||
    <div id="popup" class="popup">
 | 
			
		||||
      <p id="popup-content">Hello! I am a popup!</p>
 | 
			
		||||
      <!--<button onclick="closePopup()">Close</button>-->
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
		Reference in New Issue
	
	Block a user