From 1410059001a53813472ddf65d7d812d7f7fa318b Mon Sep 17 00:00:00 2001 From: bach Date: Wed, 1 Feb 2023 22:15:20 +0100 Subject: [PATCH] =?UTF-8?q?displaying=20entities=20in=20boussole=20=C3=A0?= =?UTF-8?q?=20the=20right=20place,=20updating=20position=20when=20form=20i?= =?UTF-8?q?s=20modified,=20remains=20the=20inverse=20to=20do=20:=20drag&dr?= =?UTF-8?q?op=20which=20updates=20the=20form?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ouatminimal_theme/css/ouatminimal.css | 38 ++- .../custom/ouatminimal_theme/js/boussole.js | 222 ++++++++++++++++-- .../ouatminimal.libraries.yml | 4 +- ...-field-entite--node-concernement.html.twig | 2 +- 4 files changed, 237 insertions(+), 29 deletions(-) diff --git a/src/web/themes/custom/ouatminimal_theme/css/ouatminimal.css b/src/web/themes/custom/ouatminimal_theme/css/ouatminimal.css index ca562d5..d1db20d 100644 --- a/src/web/themes/custom/ouatminimal_theme/css/ouatminimal.css +++ b/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; } \ No newline at end of file diff --git a/src/web/themes/custom/ouatminimal_theme/js/boussole.js b/src/web/themes/custom/ouatminimal_theme/js/boussole.js index fd7a731..dd00572 100644 --- a/src/web/themes/custom/ouatminimal_theme/js/boussole.js +++ b/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); + } + } + } } -}; \ No newline at end of file + + 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); \ No newline at end of file diff --git a/src/web/themes/custom/ouatminimal_theme/ouatminimal.libraries.yml b/src/web/themes/custom/ouatminimal_theme/ouatminimal.libraries.yml index dae064e..adacce5 100644 --- a/src/web/themes/custom/ouatminimal_theme/ouatminimal.libraries.yml +++ b/src/web/themes/custom/ouatminimal_theme/ouatminimal.libraries.yml @@ -8,4 +8,6 @@ boussole: js: js/boussole.js: {} dependencies: - - core/jquery \ No newline at end of file + - core/drupal + - core/jquery + - core/once \ No newline at end of file diff --git a/src/web/themes/custom/ouatminimal_theme/templates/form/field-multiple-value-form--field-entite--node-concernement.html.twig b/src/web/themes/custom/ouatminimal_theme/templates/form/field-multiple-value-form--field-entite--node-concernement.html.twig index 65988f9..d850ef7 100644 --- a/src/web/themes/custom/ouatminimal_theme/templates/form/field-multiple-value-form--field-entite--node-concernement.html.twig +++ b/src/web/themes/custom/ouatminimal_theme/templates/form/field-multiple-value-form--field-entite--node-concernement.html.twig @@ -28,7 +28,7 @@ 'form-item' ] %} -
+
{{ table }} {% if description.content %}