소스 검색

displaying entities in boussole à the right place, updating position when form is modified, remains the inverse to do : drag&drop which updates the form

bach 2 년 전
부모
커밋
1410059001

+ 25 - 13
src/web/themes/custom/ouatminimal_theme/css/ouatminimal.css

@@ -133,47 +133,47 @@
 
 /* BOUSSOLE FORM */
 
-.boussole-layout{
+#boussole-layout{
   display: flex;
   flex-direction: row;
   gap: 1em;
 }
 
-.boussole-layout .form-item[data-drupal-selector="edit-field-entite"]{
+#boussole-layout .form-item[data-drupal-selector="edit-field-entite"]{
   flex:0 0 31em;
 }
-.boussole-layout .boussole-wrapper{
+#boussole-layout .boussole-wrapper{
   flex:1 1 auto;
 }
 
 /* drupal form optimisation */
-.boussole-layout .form-item[data-drupal-selector="edit-field-entite"] table.field-multiple-table>tbody>tr{
+#boussole-layout .form-item[data-drupal-selector="edit-field-entite"] table.field-multiple-table>tbody>tr{
   border: none;
 }
-.boussole-layout .form-item[data-drupal-selector="edit-field-entite"] table.field-multiple-table>tbody>tr>td.field-multiple-drag{
+#boussole-layout .form-item[data-drupal-selector="edit-field-entite"] table.field-multiple-table>tbody>tr>td.field-multiple-drag{
   
 }
-.boussole-layout .form-item[data-drupal-selector="edit-field-entite"] table.field-multiple-table>tbody>tr>td:not(.field-multiple-drag)>div{
+#boussole-layout .form-item[data-drupal-selector="edit-field-entite"] table.field-multiple-table>tbody>tr>td:not(.field-multiple-drag)>div{
   padding:0.5em;
   border: 1px solid #bbb;
   border-radius: 5px;
 }
 
-.boussole-layout .form-item[data-drupal-selector="edit-field-entite"] table.field-multiple-table>tbody>tr>td:not(.field-multiple-drag) > div .horizontal-tabs-panes>details>.seven-details__wrapper{
+#boussole-layout .form-item[data-drupal-selector="edit-field-entite"] table.field-multiple-table>tbody>tr>td:not(.field-multiple-drag) > div .horizontal-tabs-panes>details>.seven-details__wrapper{
   padding:0;
 }
-.boussole-layout .form-item[data-drupal-selector="edit-field-entite"] .field--type-entity-reference.field--name-field-entite.field--widget-inline-entity-form-complex>div>fieldset{
+#boussole-layout .form-item[data-drupal-selector="edit-field-entite"] .field--type-entity-reference.field--name-field-entite.field--widget-inline-entity-form-complex>div>fieldset{
   border: none;
   margin:0;
   padding:0;
 }
-.boussole-layout .form-item[data-drupal-selector="edit-field-entite"] .field--type-entity-reference.field--name-field-entite.field--widget-inline-entity-form-complex>div>fieldset>legend{
+#boussole-layout .form-item[data-drupal-selector="edit-field-entite"] .field--type-entity-reference.field--name-field-entite.field--widget-inline-entity-form-complex>div>fieldset>legend{
   display:none;
 }
-.boussole-layout .form-item[data-drupal-selector="edit-field-entite"] .field--type-entity-reference.field--name-field-entite.field--widget-inline-entity-form-complex>div>fieldset>.fieldset-wrapper>table>thead{
+#boussole-layout .form-item[data-drupal-selector="edit-field-entite"] .field--type-entity-reference.field--name-field-entite.field--widget-inline-entity-form-complex>div>fieldset>.fieldset-wrapper>table>thead{
   display:none;
 }
-.boussole-layout .form-item[data-drupal-selector="edit-field-entite"] .field--type-entity-reference.field--name-field-entite.field--widget-inline-entity-form-complex>div>fieldset>.fieldset-wrapper>table>tbody>tr{
+#boussole-layout .form-item[data-drupal-selector="edit-field-entite"] .field--type-entity-reference.field--name-field-entite.field--widget-inline-entity-form-complex>div>fieldset>.fieldset-wrapper>table>tbody>tr{
   border:none;
 }
 
@@ -206,12 +206,12 @@
   flex:0 1 auto; 
 }
 
-.boussole-layout .form-item[data-drupal-selector="edit-field-entite"] .button{
+#boussole-layout .form-item[data-drupal-selector="edit-field-entite"] .button{
   font-size: 0.9em;
 }
 
 /* boussole */
-.boussole-layout .boussole-wrapper .boussole{
+#boussole-layout .boussole-wrapper .boussole{
   background-image: url(../images/boussole.svg);
   background-clip: padding-box;
   background-size: contain;
@@ -219,4 +219,16 @@
   background-position: center;
   aspect-ratio: 1 / 1;
   width:100%;
+  position: relative;
+}
+#boussole-layout .boussole-wrapper .boussole .entity{
+  position: absolute;
+  width:10px; height:10px;
+  border-radius: 5px;
+  background-color: black;
+  transform: translate(-5px, -5px);
+  cursor:move;
+}
+#boussole-layout .boussole-wrapper .boussole .entity.hide{
+  display: none;
 }

+ 208 - 14
src/web/themes/custom/ouatminimal_theme/js/boussole.js

@@ -1,15 +1,209 @@
-Drupal.behaviors.boussole = {
-  attach: function (context, settings) {
-    console.log("Hello boussole", context);
-    // Use context to filter the DOM to only the elements of interest,
-    // and use once() to guarantee that our callback function processes
-    // any given element one time at most, regardless of how many times
-    // the behaviour itself is called (it is not sufficient in general
-    // to assume an element will only ever appear in a single context).
-    // once('boussoleForm', 'input.myCustomBehavior', context).forEach(
-    //   function (element) {
-    //     element.classList.add('processed');
-    //   }
-    // );
+(function ($, Drupal, once) {
+  var _boussole;
+  Drupal.behaviors.boussole = {
+    attach: function (context, settings) {
+      console.log("Drupal Boussole behavior", context);
+      once('boussole-class-behaviour', '#boussole-layout', context).forEach(element => {
+        _boussole = new Boussole();
+      });
+      
+      let $form = document.querySelector('#boussole-layout>.form-item');
+      console.log($form);
+      let $tabledrag = $form.querySelector('table.field-multiple-table');
+      console.log($tabledrag);
+      let $form_entities = $tabledrag.querySelectorAll(':scope>tbody>tr>td:not(.field-multiple-drag):not(.delta-order)>div');
+      console.log($form_entities);
+
+      let entities = {};
+      [...$form_entities].forEach($entity => {
+        console.log($entity);
+        let id = $entity.getAttribute('id');
+        let $title = $entity.querySelector('.paragraphs-subform>.field--type-entity-reference.field--name-field-entite td.inline-entity-form-node-label');
+        let $af = $entity.querySelector('.paragraphs-subform .field--name-field-actuel-future');
+        let $p = $entity.querySelector('.paragraphs-subform .field--name-field-prise input');
+        let $mm = $entity.querySelector('.paragraphs-subform .field--name-field-menace-maintien-degres input');
+        let e = {
+          wrapper:{
+            $dom: $entity,
+            id: id
+          },
+          title: {
+            $dom: $title,
+            value: $title.textContent
+          },
+          af: {
+            $dom: $af,
+            value: parseInt($af.querySelector('input:checked').value)
+          },
+          p: {
+            $dom: $p,
+            value: parseFloat($p.value)
+          },
+          mm: {
+            $dom: $mm,
+            value: parseFloat($mm.value)
+          }
+        }
+        entities[id] = e;
+      });
+      console.log(entities);
+      _boussole.updateEntities(entities);
+    }
+  };
+
+  class Boussole {
+    constructor() {
+      this.$boussole = document.querySelector('#boussole-layout>.boussole-wrapper>.boussole');
+      
+      this.entities = {}
+    }
+
+    updateEntities(entities){
+      console.log('Class Boussole update entities', entities);
+      for (const [id, values] of Object.entries(entities)) {
+        // console.log(id, typeof this.entities[id], values);
+        if (typeof this.entities[id] === 'undefined') {
+          this.entities[id] = new Entity(this.$boussole, id, values);
+        }else{
+          this.entities[id].updateValues(values);
+        }
+      }
+    }
   }
-};
+
+  class Entity {
+    constructor($container, id, values){
+      console.log('Entity constructor', $container, id, values);
+      this.$container = $container;
+      this.updateSceneSize();
+      this.id = id;
+      this.values = values;
+      this.listenToFormValue();
+      this.createDomElemt();
+    }
+
+    updateSceneSize(){
+      this.sceneSize = {
+        w: this.$container.clientWidth,
+        h: this.$container.clientHeight
+      };
+    }
+
+    createDomElemt(){
+      this.$e = document.createElement('div');
+      this.$e.classList.add('entity');
+      this.$e.setAttribute('title', this.values.title.value);
+      this.$container.append(this.$e);
+      console.log(this.$e);
+      this.updatePos();
+      this.initDraggable()
+    }
+
+    initDraggable(){
+      // // this is working but to slow, we loose the item
+      // this.$e.addEventListener('mousedown', function(event){
+      //   this.mousedown = true;
+      //   this.moving_x = this.$e.offsetLeft - event.clientX;
+      //   this.moving_y = this.$e.offsetTop - event.clientY;
+      // }.bind(this));
+      // this.$e.addEventListener('mouseup', function(event){
+      //   this.mousedown = false;
+      // }.bind(this));
+      // this.$e.addEventListener('mousemove', function(event){
+      //   if (this.mousedown) {
+      //     this.$e.style.left = event.clientX + this.moving_x + 'px';
+      //     this.$e.style.top = event.clientY + this.moving_y + 'px';
+      //   }
+      // }.bind(this));
+      this.$e.setAttribute('draggable', true);
+      this.$e.addEventListener('dragstart', function(event){
+        event.dataTransfer.setData('text/plain', event.target.id);
+        setTimeout(() => {
+          event.target.classList.add('hide');  
+        }, 0);
+      }.bind(this));
+      this.$e.addEventListener('drag', function(event){
+        console.log('drag', event);
+      }.bind(this));
+      this.$e.addEventListener('dragend', function(event){
+        console.log('dragend', event);
+        event.target.style.top = event.clientY + 'px';
+        event.target.style.left = event.clientX + 'px';
+        event.target.classList.remove('hide');
+      }.bind(this))
+    }
+
+    listenToFormValue(){
+      ['af','p','mm'].forEach(v =>{
+        this.values[v].$dom.addEventListener('change', function(v, event) {
+          switch (v) {
+            case 'af':
+              this.values[v].value = parseInt(this.values[v].$dom.querySelector('input:checked').value);
+              break;
+            default:
+              this.values[v].value = parseInt(this.values[v].$dom.value);
+              break;
+          }
+          
+          console.log(`new ${v}`, this.values[v].value);
+          this.updatePos();
+        }.bind(this, v));
+      })
+      // this.values.af.$dom.addEventListener('change', function(event) {
+      //   console.log('af changed', event);
+      //   let af = event.target.parent('.fieldset-wrapper').querySelector('input:checked').value;
+      //   this.values.af.value = parseInt(af);
+      //   console.log(`new af`, this.values.af.value);
+      //   this.updatePos();
+      // }.bind(this));
+    }
+
+    updateValuesFromForm(values){
+
+    }
+
+    updatePos(){
+      console.log('update pos');
+      // converte degres to radian, inverse it and rotate it
+      let a = parseInt((this.values.mm.value) * -1 + 90) * (Math.PI/180);
+      // https://stackoverflow.com/questions/5731863/mapping-a-numeric-range-onto-another
+      // from range 0 -> 100 to range 0 -> diagonale de la scene
+      // let diagonale = Math.sqrt(Math.pow(this.sceneSize.w, 2) + Math.pow(this.sceneSize.h, 2))/2;
+      // let r_max = diagonale;
+      let r_max = this.sceneSize.w/2; 
+      let r_slope = (r_max - 0) / (100 - 0)
+      let r = parseInt(0 + r_slope * (this.values.p.value - 0));
+
+      let x = r * Math.cos(a);
+      let y = r * Math.sin(a);
+      // console.log('x:', x, 'r:', r, 'a:', a, "y:", y);
+
+      let af = this.values.af.value;
+
+      let left = this.sceneSize.w / 2 + x;
+      let top = this.sceneSize.h / 2 - (af ? -y : y);
+      // console.log('left:', left, "top:", top);
+
+      this.$e.style.left = left+'px';
+      this.$e.style.top = top+'px';
+    }
+
+    
+  }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+})(jQuery, Drupal, once);

+ 3 - 1
src/web/themes/custom/ouatminimal_theme/ouatminimal.libraries.yml

@@ -8,4 +8,6 @@ boussole:
   js:
     js/boussole.js: {}
   dependencies:
-    - core/jquery
+    - core/drupal
+    - core/jquery
+    - core/once

+ 1 - 1
src/web/themes/custom/ouatminimal_theme/templates/form/field-multiple-value-form--field-entite--node-concernement.html.twig

@@ -28,7 +28,7 @@
       'form-item'
     ]
   %}
-  <div class="boussole-layout">
+  <div id="boussole-layout">
     <div{{ attributes.addClass(classes) }}>
       {{ table }}
       {% if description.content %}