fixed chicked&egg&connectedCB issue between graflow & editor + fixed no Flow issue in graflow + Fixed nodesMove issue on displaced graflow + graflowEditor: DND ok
This commit is contained in:
@@ -60,7 +60,8 @@ class Buildoz extends HTMLElement {
|
|||||||
fireEvent(eventName, detail){
|
fireEvent(eventName, detail){
|
||||||
let myname = this.tagName.toLocaleLowerCase()
|
let myname = this.tagName.toLocaleLowerCase()
|
||||||
myname = myname.substring(myname.indexOf('-')+1)
|
myname = myname.substring(myname.indexOf('-')+1)
|
||||||
this.dispatchEvent(new CustomEvent(`bz:${myname}:${eventName}`, {
|
const eventFullName = `bz:${myname}:${eventName}`
|
||||||
|
this.dispatchEvent(new CustomEvent(eventFullName, {
|
||||||
detail,
|
detail,
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
composed: true,
|
composed: true,
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ class BZgrafloweditor extends Buildoz{
|
|||||||
this.defaultAttrs = { }
|
this.defaultAttrs = { }
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
async connectedCallback() {
|
||||||
|
await customElements.whenDefined('bz-graflow')
|
||||||
super.connectedCallback()
|
super.connectedCallback()
|
||||||
const nodesUrl = this.getBZAttribute('nodes')
|
const nodesUrl = this.getBZAttribute('nodes')
|
||||||
this.mainContainer = document.createElement('div')
|
this.mainContainer = document.createElement('div')
|
||||||
@@ -26,20 +27,64 @@ class BZgrafloweditor extends Buildoz{
|
|||||||
this.mainContainer.append(this.nodesContainer)
|
this.mainContainer.append(this.nodesContainer)
|
||||||
this.graflow = document.createElement('bz-graflow')
|
this.graflow = document.createElement('bz-graflow')
|
||||||
this.graflow.setAttribute('nodes', nodesUrl)
|
this.graflow.setAttribute('nodes', nodesUrl)
|
||||||
|
this.graflow.setAttribute('edit', "nodesmove,editwires,dropnodes")
|
||||||
|
this.graflow.addEventListener('bz:graflow:domConnected', this.setupDropZone.bind(this))
|
||||||
this.mainContainer.append(this.graflow)
|
this.mainContainer.append(this.graflow)
|
||||||
this.append(this.mainContainer)
|
this.append(this.mainContainer)
|
||||||
|
|
||||||
this.graflow.addEventListener('bz:graflow:nodesLoaded', this.refreshNodes.bind(this))
|
this.graflow.addEventListener('bz:graflow:nodesLoaded', this.refreshNodes.bind(this))
|
||||||
this.graflow.loadNodes(nodesUrl)
|
this.graflow.loadNodes(nodesUrl)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshNodes(e){
|
refreshNodes(e){
|
||||||
for(const nodeType in this.graflow.nodesRegistry){
|
for(const nodeType in this.graflow.nodesRegistry){
|
||||||
const nodeDef = this.graflow.nodesRegistry[nodeType]
|
const nodeDef = this.graflow.nodesRegistry[nodeType]
|
||||||
this.nodesContainer.append(nodeDef.cloneNode(true))
|
if(nodeDef.dataset.editor=='exclude') continue
|
||||||
|
const node = nodeDef.cloneNode(true)
|
||||||
|
this.makeNodeDraggable(node)
|
||||||
|
this.nodesContainer.append(node)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeNodeDraggable(node){
|
||||||
|
node.draggable = true
|
||||||
|
node.style.cursor = 'pointer'
|
||||||
|
node.addEventListener('dragstart', (evt) => {
|
||||||
|
evt.dataTransfer.setData('text/plain', node.dataset.nodetype)
|
||||||
|
evt.dataTransfer.effectAllowed = 'copy'
|
||||||
|
evt.dataTransfer.setDragImage(node, evt.offsetX, evt.offsetY)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onNodeDragEnd(evt){
|
||||||
|
console.log('drag end', evt)
|
||||||
|
evt.dataTransfer.clearData()
|
||||||
|
}
|
||||||
|
|
||||||
|
setupDropZone(){
|
||||||
|
const dropZone = this.graflow.wiresContainer
|
||||||
|
const nodesContainer = this.graflow.nodesContainer
|
||||||
|
dropZone.addEventListener('dragover', (evt) => {
|
||||||
|
evt.preventDefault()
|
||||||
|
evt.dataTransfer.dropEffect = 'copy'
|
||||||
|
})
|
||||||
|
dropZone.addEventListener('drop', (evt) => {
|
||||||
|
evt.preventDefault()
|
||||||
|
const nodeType = evt.dataTransfer.getData('text/plain')
|
||||||
|
if(!nodeType || !(nodeType in this.graflow.nodesRegistry)) return
|
||||||
|
const rect = nodesContainer.getBoundingClientRect()
|
||||||
|
const x = evt.clientX - rect.left + nodesContainer.scrollLeft
|
||||||
|
const y = evt.clientY - rect.top + nodesContainer.scrollTop
|
||||||
|
const id = 'n' + crypto.randomUUID().replace(/-/g, '').slice(0, 8)
|
||||||
|
this.graflow.addNode({ id, nodeType, coords: { x, y } })
|
||||||
|
for(const node of this.graflow.flow.nodes){
|
||||||
|
if(node.id == id){
|
||||||
|
node.coords.x = x
|
||||||
|
node.coords.y = y
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.graflow.refresh()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Buildoz.define('grafloweditor', BZgrafloweditor)
|
Buildoz.define('grafloweditor', BZgrafloweditor)
|
||||||
40
bzGraflow.js
40
bzGraflow.js
@@ -66,10 +66,6 @@ class BZgraflow extends Buildoz{
|
|||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
super.connectedCallback()
|
super.connectedCallback()
|
||||||
const flowUrl = this.getBZAttribute('flow')
|
|
||||||
if(!flowUrl) return // Be tolerant: maybe injected later from JS above
|
|
||||||
// If attribute "isolated" is present, render inside a shadow root.
|
|
||||||
// Otherwise, render in light DOM (no shadow DOM).
|
|
||||||
this.hostContainer = document.createElement('div')
|
this.hostContainer = document.createElement('div')
|
||||||
this.hostContainer.classList.add('bzgf-main-container')
|
this.hostContainer.classList.add('bzgf-main-container')
|
||||||
this.mainContainer = this.hasAttribute('isolated')
|
this.mainContainer = this.hasAttribute('isolated')
|
||||||
@@ -96,7 +92,10 @@ class BZgraflow extends Buildoz{
|
|||||||
this.NodesReceiver = new DroppingNodes(this, '.bzgf-node')
|
this.NodesReceiver = new DroppingNodes(this, '.bzgf-node')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.loadFlow(flowUrl)
|
this.fireEvent('domConnected', { graflow: this })
|
||||||
|
const flowUrl = this.getBZAttribute('flow')
|
||||||
|
if(flowUrl) this.loadFlow(flowUrl)
|
||||||
|
else this.initFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
error(msg, err){
|
error(msg, err){
|
||||||
@@ -126,6 +125,10 @@ class BZgraflow extends Buildoz{
|
|||||||
this.fireEvent('flowLoaded', { url: url })
|
this.fireEvent('flowLoaded', { url: url })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initFlow(){
|
||||||
|
this.flow = { nodes: [], links: [] }
|
||||||
|
}
|
||||||
|
|
||||||
async loadNodes(url) {
|
async loadNodes(url) {
|
||||||
const res = await fetch(url+'?'+crypto.randomUUID())
|
const res = await fetch(url+'?'+crypto.randomUUID())
|
||||||
const html = await res.text()
|
const html = await res.text()
|
||||||
@@ -1217,17 +1220,17 @@ class MovingNodes{
|
|||||||
if(e.target != handle) return
|
if(e.target != handle) return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const rect = node.getBoundingClientRect()
|
const rect = node.getBoundingClientRect()
|
||||||
|
const parentBB = this.nodesContainer.getBoundingClientRect()
|
||||||
|
const offsetX = rect.left - parentBB.left + this.nodesContainer.scrollLeft
|
||||||
|
const offsetY = rect.top - parentBB.top + this.nodesContainer.scrollTop
|
||||||
this.state = {
|
this.state = {
|
||||||
node,
|
node,
|
||||||
handle,
|
handle,
|
||||||
startX: e.clientX,
|
startX: e.clientX,
|
||||||
startY: e.clientY,
|
startY: e.clientY,
|
||||||
offsetX: rect.left,
|
offsetX,
|
||||||
offsetY: rect.top
|
offsetY
|
||||||
}
|
}
|
||||||
const x = e.clientX - this.state.startX + this.state.offsetX
|
const x = e.clientX - this.state.startX + this.state.offsetX
|
||||||
const y = e.clientY - this.state.startY + this.state.offsetY
|
const y = e.clientY - this.state.startY + this.state.offsetY
|
||||||
@@ -1252,11 +1255,20 @@ class MovingNodes{
|
|||||||
|
|
||||||
pointerUp(e){
|
pointerUp(e){
|
||||||
if(!this.state) return
|
if(!this.state) return
|
||||||
this.state.node.releasePointerCapture(e.pointerId)
|
const { node, startX, startY, offsetX, offsetY } = this.state
|
||||||
this.state.node.style.pointerEvents = ''
|
const x = e.clientX - startX + offsetX
|
||||||
|
const y = e.clientY - startY + offsetY
|
||||||
|
node.releasePointerCapture(e.pointerId)
|
||||||
|
node.style.pointerEvents = ''
|
||||||
|
for(const n of this.graflow.flow.nodes){
|
||||||
|
if(n.id == node.dataset.id){
|
||||||
|
n.coords.x = x
|
||||||
|
n.coords.y = y
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.graflow.fireEvent('nodeMoved', { nodeId: node.dataset.id, x, y })
|
||||||
this.state = null
|
this.state = null
|
||||||
|
|
||||||
this.graflow.fireEvent('nodeMoved', { nodeId: this.state.node.dataset.id, x: this.state.x, y: this.state.y })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,7 @@
|
|||||||
width:3em;
|
width:3em;
|
||||||
height:3em;
|
height:3em;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
|
border: none;
|
||||||
}
|
}
|
||||||
.bzgf-node[data-nodetype="refnodein"] .body, .bzgf-node[data-nodetype="refnodeout"] .body{
|
.bzgf-node[data-nodetype="refnodein"] .body, .bzgf-node[data-nodetype="refnodeout"] .body{
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
@@ -118,6 +119,10 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
margin:0;
|
||||||
|
}
|
||||||
|
.bzgf-node[data-nodetype="refnodein"] .port, .bzgf-node[data-nodetype="refnodeout"] .port{
|
||||||
|
top: 50%;
|
||||||
}
|
}
|
||||||
.bzgf-node[data-nodetype="refnodein"] .body{ background: #0F0; }
|
.bzgf-node[data-nodetype="refnodein"] .body{ background: #0F0; }
|
||||||
.bzgf-node[data-nodetype="refnodeout"] .body{ background: #FF0; }
|
.bzgf-node[data-nodetype="refnodeout"] .body{ background: #FF0; }
|
||||||
@@ -209,16 +214,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="bzgf-node" data-nodetype="refnodein">
|
<div class="bzgf-node" data-nodetype="refnodein" data-editor="exclude">
|
||||||
<div class="body">{parentport}</div>
|
<div class="body">{parentport}</div>
|
||||||
<div class="port" data-type="out" data-id="out1" data-direction="e"></div>
|
<div class="port" data-type="out" data-id="out1" data-direction="e"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="bzgf-node" data-nodetype="refnodeout">
|
<div class="bzgf-node" data-nodetype="refnodeout" data-editor="exclude">
|
||||||
<div class="body">{parentport}</div>
|
<div class="body">{parentport}</div>
|
||||||
<div class="port" data-type="in" data-id="in1" data-direction="w"></div>
|
<div class="port" data-type="in" data-id="in1" data-direction="w"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user