From 7e4e6dca1110d4f6651dfde7a287eafac327b12c Mon Sep 17 00:00:00 2001 From: bach Date: Thu, 2 Feb 2023 16:17:52 +0100 Subject: [PATCH] boussole: moving entity points is ok, and it records the new values on the form, so it can be recorded --- .../custom/ouatminimal_theme/js/boussole.js | 182 +++++++++++++----- 1 file changed, 133 insertions(+), 49 deletions(-) diff --git a/src/web/themes/custom/ouatminimal_theme/js/boussole.js b/src/web/themes/custom/ouatminimal_theme/js/boussole.js index dd00572..2615ed3 100644 --- a/src/web/themes/custom/ouatminimal_theme/js/boussole.js +++ b/src/web/themes/custom/ouatminimal_theme/js/boussole.js @@ -3,11 +3,15 @@ Drupal.behaviors.boussole = { attach: function (context, settings) { console.log("Drupal Boussole behavior", context); + let $boussole_wrapper = document.querySelector('#boussole-layout'); once('boussole-class-behaviour', '#boussole-layout', context).forEach(element => { - _boussole = new Boussole(); + let tabs = + // div.field-group-tabs-wrapper + // input.horizontal-tabs-active-tab + _boussole = new Boussole($boussole_wrapper); }); - let $form = document.querySelector('#boussole-layout>.form-item'); + let $form = $boussole_wrapper.querySelector(':scope>.form-item'); console.log($form); let $tabledrag = $form.querySelector('table.field-multiple-table'); console.log($tabledrag); @@ -47,19 +51,74 @@ entities[id] = e; }); console.log(entities); - _boussole.updateEntities(entities); + _boussole.updateCreateEntities(entities); } }; class Boussole { - constructor() { + constructor($boussole_wrapper) { + this.$boussole_wrapper = $boussole_wrapper; this.$boussole = document.querySelector('#boussole-layout>.boussole-wrapper>.boussole'); - this.entities = {} + + this.initTabChecking(); + this.enableDragArea() } - updateEntities(entities){ - console.log('Class Boussole update entities', entities); + initTabChecking(){ + // debugger + this.$field_group_tab = this.$boussole_wrapper.closest('details.field-group-tab'); + // watch for tabs opening and closing + // hidden input do not triggers events + // so we have to use mutationObserver tomake it trigger the change event + this.$tabInput = this.$field_group_tab.parentElement.querySelector(':scope>input[type="hidden"]'); + let observer = new MutationObserver(function(mutations, observer) { + if(mutations[0].attributeName == "value") { + // console.log('mutation observed', mutations, observer); + let event = new Event('change'); + mutations[0].target.dispatchEvent(event); + } + }); + observer.observe(this.$tabInput, {attributes: true}); + // then we listen to the event + this.$tabInput.addEventListener('change', event => { + // console.log('tab input changed', event, this); + this.wrapperTabChanged(event); + }); + this.checkTabIsOpen(); + } + + checkTabIsOpen(){ + this.tabisopen = this.$field_group_tab.getAttribute('id') === this.$tabInput.value; + } + + wrapperTabChanged(event){ + this.checkTabIsOpen(); + if(this.tabisopen){ + this.updateEntities(); + } + } + + enableDragArea(){ + this.$boussole.addEventListener("dragenter", (event) => { + event.preventDefault(); + }); + this.$boussole.addEventListener("dragover", (event) => { + event.preventDefault(); + }); + this.$boussole.addEventListener("drop", (event) => { + event.preventDefault(); + let data = JSON.parse(event.dataTransfer.getData('text/plain')); + console.log('boussole drop', event, data); + data.clientX = event.clientX; + data.clientY = event.clientY; + // return on the entity class + this.entities[data.entity_id].dropedOnBoussole(data); + }); + } + + updateCreateEntities(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') { @@ -69,6 +128,12 @@ } } } + + updateEntities(){ + for (const [id, entity] of Object.entries(this.entities)) { + entity.update(); + } + } } class Entity { @@ -92,6 +157,7 @@ createDomElemt(){ this.$e = document.createElement('div'); this.$e.classList.add('entity'); + this.$e.setAttribute('id', `${this.id}-boussole-point`); this.$e.setAttribute('title', this.values.title.value); this.$container.append(this.$e); console.log(this.$e); @@ -100,37 +166,60 @@ } 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'; + this.$e.addEventListener('dragstart', event => { + // console.log('dragstart', event); + let data = { + entity_id : this.id, + dragging_start_x : event.target.offsetLeft - event.clientX, + dragging_start_y : event.target.offsetTop - event.clientY + }; + event.dataTransfer.setData('text/plain', JSON.stringify(data)); + // event.dataTransfer.effectAllowed = "move"; + setTimeout(() => {event.target.classList.add('hide');}, 0); + }); + this.$e.addEventListener('dragend', event => { + // console.log('dragend', event); event.target.classList.remove('hide'); - }.bind(this)) + }); + // CAN'T DO THAT, EVENT IS FIRED FOR EACH ENTITIES + // TAKING CARE OF THE DROP IN THE BOUSSOLE CLASS + // this.$container.addEventListener('drop', event =>{ + // event.preventDefault(); + // console.log('drop', event); + // }) + } + + dropedOnBoussole(data){ + this.$e.style.left = data.clientX + data.dragging_start_x + 'px'; + this.$e.style.top = data.clientY + data.dragging_start_y + 'px'; + this.updateValuesFromBoussole(); + } + + updateValuesFromBoussole(){ + let compstyle = window.getComputedStyle(this.$e); + // AF + let top = parseInt(compstyle.top); + let af = top >= this.sceneSize.h/2 ? 0 : 1; + this.values.af.value = af; + this.values.af.$dom.querySelector(`input[value="${af}"]`).checked = true; + + // (x, y) + let x = parseInt(compstyle.left) - this.sceneSize.h/2; + let y = Math.abs(this.sceneSize.h/2 - top); + let a = parseFloat(Math.atan(x/y) * (180/Math.PI)).toFixed(2); + let r = Math.sqrt(Math.pow(x,2)+Math.pow(y,2)); + + this.values.mm.value = this.values.mm.$dom.value = a; + + // https://stackoverflow.com/questions/5731863/mapping-a-numeric-range-onto-another + // from range 0 -> rayon_de_la_boussole to range 0 -> 100 + let r_max = this.sceneSize.w/2; + let r_slope = (100 - 0) / (r_max - 0); + this.values.p.value = this.values.p.$dom.value = parseFloat(0 + r_slope * (r - 0)).toFixed(2); + // this.values.p.$dom.value = this.values.p.value; + + console.log('x:', x, 'r:', r, 'a:', a, "y:", y); } listenToFormValue(){ @@ -149,17 +238,6 @@ 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(){ @@ -170,6 +248,7 @@ // 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; + // actualy we don't use diagonale, we stay on the circle 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)); @@ -181,14 +260,19 @@ let af = this.values.af.value; let left = this.sceneSize.w / 2 + x; - let top = this.sceneSize.h / 2 - (af ? -y : y); + 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'; } - + update(){ + console.log('Entity update'); + this.updateSceneSize() + this.updatePos() + } + }