Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple parents, how to #102

Open
fcnyp opened this issue Aug 25, 2020 · 10 comments
Open

Multiple parents, how to #102

fcnyp opened this issue Aug 25, 2020 · 10 comments
Labels
question Further information is requested

Comments

@fcnyp
Copy link

fcnyp commented Aug 25, 2020

Seen that several people have requested the ability to add multiple parents. I understand this is outside the scope of the library and why alyssaxuu has made that choice.

I am looking to add this feature locally and am querying for information on how to.

Outside the scope of the ask:

  1. How to select a parent. This is a UX decision and something people should handle on their own.
  2. How to remove parent relationships. Again this is UX.
  3. How to store the relationships.

My thought would be to expose a function with the following inputs: block (original child), second parent id. I have the arrow being drawn, the shape is right but the height is off. I am also concerned that it may not draw right under all circumstances.

const snapParent = function(drag, i) {
	let blocko = blocks.map(a => a.id);

	let arrowhelp = blocks.filter(a => a.id == parseInt(drag.querySelector(".blockid").value))[0];
	let arrowx = arrowhelp.x - blocks.filter(a => a.id == blocko[i])[0].x + 20;

	let arrowy = parseFloat(arrowhelp.y - (arrowhelp.height / 2) - (blocks.filter(block => block.id == blocko[i])[0].y + (blocks.filter(block => block.id == blocko[i])[0].height / 2)) + canvas_div.scrollTop);
	canvas_div.innerHTML += `<div class="arrowblock"><input type="hidden" class="arrowid" value="${drag.querySelector(".blockid").value}.${i}">
		<svg preserveaspectratio="none" fill="none" xmlns="http://www.w3.org/2000/svg">
			<path d="M${(blocks.filter(a => a.id == blocko[i])[0].x - arrowhelp.x + 5)} 0L${(blocks.filter(a => a.id == blocko[i])[0].x - arrowhelp.x + 5)} ${(paddingy / 2)}L5 ${(paddingy / 2)}L5 ${arrowy}" stroke="#C5CCD0" stroke-width="2px"/>
			<path d="M0 ${(arrowy - 5)}H10L5 ${arrowy}L0 ${(arrowy - 5)}Z" fill="#C5CCD0"/>
		</svg>
	</div>`;

	//El horizontal position
	flowyScope.querySelector(`.arrowid[value="${drag.querySelector(".blockid").value}.${i}"]`).parentNode.style.left = (arrowhelp.x - 5) - (canvas_div.getBoundingClientRect().left + window.scrollX) + canvas_div.scrollLeft + "px";

	//El virtical position
	flowyScope.querySelector(`.arrowid[value="${parseInt(drag.querySelector(".blockid").value)}.${i}"]`).parentNode.style.top = 
		blocks.filter(a => a.id == blocko[i])[0].y + "px";
}
@fcnyp
Copy link
Author

fcnyp commented Aug 26, 2020

Updated.

@fcnyp
Copy link
Author

fcnyp commented Aug 26, 2020

@alyssaxuu Any assistance you can provide would be great! The above seems to work but it doesn't account for two things.

  1. The arrow placement doesn't account for canvas scroll position. If your scrolled down its off.
  2. Arrows are not routed correctly around child blocks are multiple levels down (would assume this would be the same in reverse). (e.g., I have 4 rows. Root, row 2 with 2 nodes, row 3 with 1 node and row 4 with 1 node. I try to connect row 4 node to row 2 node and the arrow goes straight through row 3 node).

@queenie0708
Copy link

also need multi parents or at least 2 parents

@fcnyp
Copy link
Author

fcnyp commented Aug 26, 2020

See update. Scroll position addressed. Only one issue left - Arrows are not routed around blocks if the arrow must pass through multiple levels between the parent and child. Not sure how to solve this one, looking for any suggestions/direction.

snapParent = function(drag, i) {
	let blocko = blocks.map(a => a.id);

	let arrowhelp = blocks.filter(a => a.id == parseInt(drag.querySelector(".blockid").value))[0];

	let arrowy = parseFloat(arrowhelp.y - (arrowhelp.height / 2) - (blocks.filter(block => block.id == blocko[i])[0].y + (blocks.filter(block => block.id == blocko[i])[0].height / 2)));

	canvas_div.innerHTML += `<div class="arrowblock"><input type="hidden" class="arrowid" value="${drag.querySelector(".blockid").value}.${i}">
		<svg preserveaspectratio="none" fill="none" xmlns="http://www.w3.org/2000/svg">
			<path d="M${(blocks.filter(a => a.id == blocko[i])[0].x - arrowhelp.x + 5)} 0L${(blocks.filter(a => a.id == blocko[i])[0].x - arrowhelp.x + 5)} ${(paddingy / 2)}L5 ${(paddingy / 2)}L5 ${arrowy}" stroke="#C5CCD0" stroke-width="2px"/>
			<path d="M0 ${(arrowy - 5)}H10L5 ${arrowy}L0 ${(arrowy - 5)}Z" fill="#C5CCD0"/>
		</svg>
	</div>`;

	let arrowParent = flowyScope.querySelector(`.arrowid[value="${parseInt(drag.querySelector(".blockid").value)}.${i}"]`).parentNode;
	arrowParent.style.left = (arrowhelp.x - 5) - (canvas_div.getBoundingClientRect().left + window.scrollX) + canvas_div.scrollLeft + "px";

	arrowParent.style.top = (blocks.filter(a => a.id == blocko[i])[0].y + 12) + "px";
};

@alyssaxuu Maybe we can make this a method (and a modification that deletes any parent/children if delete) people can call? They would be responsible for their own UX/UI implementation.

@ebihimself
Copy link

ebihimself commented Sep 8, 2020

How this method is getting called?
By the way for better user experience, I assume if the indicator becomes active on the time of mouse hover and lets the client grab the line and drop it on the children would be more intuitive. But need to decide how we want to centralize and align the children below their parent.

@Divyahb
Copy link

Divyahb commented Sep 24, 2020

@fcnyp A good solution! Did you manage to solve this issue? And how and where is this snapParent supposed to be called. Thanks in advance

@alyssaxuu alyssaxuu added the question Further information is requested label Oct 6, 2020
@alyssaxuu
Copy link
Owner

See update. Scroll position addressed. Only one issue left - Arrows are not routed around blocks if the arrow must pass through multiple levels between the parent and child. Not sure how to solve this one, looking for any suggestions/direction.

snapParent = function(drag, i) {
	let blocko = blocks.map(a => a.id);

	let arrowhelp = blocks.filter(a => a.id == parseInt(drag.querySelector(".blockid").value))[0];

	let arrowy = parseFloat(arrowhelp.y - (arrowhelp.height / 2) - (blocks.filter(block => block.id == blocko[i])[0].y + (blocks.filter(block => block.id == blocko[i])[0].height / 2)));

	canvas_div.innerHTML += `<div class="arrowblock"><input type="hidden" class="arrowid" value="${drag.querySelector(".blockid").value}.${i}">
		<svg preserveaspectratio="none" fill="none" xmlns="http://www.w3.org/2000/svg">
			<path d="M${(blocks.filter(a => a.id == blocko[i])[0].x - arrowhelp.x + 5)} 0L${(blocks.filter(a => a.id == blocko[i])[0].x - arrowhelp.x + 5)} ${(paddingy / 2)}L5 ${(paddingy / 2)}L5 ${arrowy}" stroke="#C5CCD0" stroke-width="2px"/>
			<path d="M0 ${(arrowy - 5)}H10L5 ${arrowy}L0 ${(arrowy - 5)}Z" fill="#C5CCD0"/>
		</svg>
	</div>`;

	let arrowParent = flowyScope.querySelector(`.arrowid[value="${parseInt(drag.querySelector(".blockid").value)}.${i}"]`).parentNode;
	arrowParent.style.left = (arrowhelp.x - 5) - (canvas_div.getBoundingClientRect().left + window.scrollX) + canvas_div.scrollLeft + "px";

	arrowParent.style.top = (blocks.filter(a => a.id == blocko[i])[0].y + 12) + "px";
};

@alyssaxuu Maybe we can make this a method (and a modification that deletes any parent/children if delete) people can call? They would be responsible for their own UX/UI implementation.

I see - so basically this function draws an arrow between the blocks then? As per the arrows not being routed to avoid blocks, I assume that is happening because you want to allow for blocks to be attached in different levels? Seems interesting, although with the multiple level functionality it would be very convoluted from a UX/UX perspective, don't really know how it could work while looking clean. Same level though would be something I might consider adding into the library, that said.

@cmoussalli
Copy link

As per my understanding, we still don't have a solution for fork's join -multiple parent-, Am I correct?

@douglasrono
Copy link

Hello. I also thought that this needs some improvement

@simkimsia
Copy link

@fcnyp

They would be responsible for their own UX/UI implementation.

Do you have an eventual choice on how to set the UX/UI for selecting 2nd parent, storing relations, delete the connection? I like to emulate your example

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

8 participants