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

This commit is contained in:
Bachir Soussi Chiadmi 2023-02-01 22:15:20 +01:00
parent 71776320fe
commit 1410059001
4 changed files with 237 additions and 29 deletions

View File

@ -133,47 +133,47 @@
/* BOUSSOLE FORM */ /* BOUSSOLE FORM */
.boussole-layout{ #boussole-layout{
display: flex; display: flex;
flex-direction: row; flex-direction: row;
gap: 1em; 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; flex:0 0 31em;
} }
.boussole-layout .boussole-wrapper{ #boussole-layout .boussole-wrapper{
flex:1 1 auto; flex:1 1 auto;
} }
/* drupal form optimisation */ /* 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; 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; padding:0.5em;
border: 1px solid #bbb; border: 1px solid #bbb;
border-radius: 5px; 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; 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; border: none;
margin:0; margin:0;
padding: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; 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; 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; border:none;
} }
@ -206,12 +206,12 @@
flex:0 1 auto; 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; font-size: 0.9em;
} }
/* boussole */ /* boussole */
.boussole-layout .boussole-wrapper .boussole{ #boussole-layout .boussole-wrapper .boussole{
background-image: url(../images/boussole.svg); background-image: url(../images/boussole.svg);
background-clip: padding-box; background-clip: padding-box;
background-size: contain; background-size: contain;
@ -219,4 +219,16 @@
background-position: center; background-position: center;
aspect-ratio: 1 / 1; aspect-ratio: 1 / 1;
width:100%; 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;
} }

View File

@ -1,15 +1,209 @@
(function ($, Drupal, once) {
var _boussole;
Drupal.behaviors.boussole = { Drupal.behaviors.boussole = {
attach: function (context, settings) { attach: function (context, settings) {
console.log("Hello boussole", context); console.log("Drupal Boussole behavior", context);
// Use context to filter the DOM to only the elements of interest, once('boussole-class-behaviour', '#boussole-layout', context).forEach(element => {
// and use once() to guarantee that our callback function processes _boussole = new Boussole();
// 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). let $form = document.querySelector('#boussole-layout>.form-item');
// once('boussoleForm', 'input.myCustomBehavior', context).forEach( console.log($form);
// function (element) { let $tabledrag = $form.querySelector('table.field-multiple-table');
// element.classList.add('processed'); 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);

View File

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

View File

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