Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 04.02.2021, 16:33
Аспирант
Отправить личное сообщение для jabbascript Посмотреть профиль Найти все сообщения от jabbascript
 
Регистрация: 27.11.2017
Сообщений: 31

Обмен узлов между двумя деревьями
Здравствуйте!!!
Хочу разобраться как можно осуществить смену узлов 2х деревьев с n вложенностью(узел получаем по клику, по факту это будет драг энд дроп). Корневой узел перетаскивает всех дочерних, любой дочерний может стать корневым и дочерним для любого другого узла в своем дереве или соседнем. Учитывается позиция.

1. Какие нужно учесть условия чтобы это стало возможо?
2. Задачка конечно ппц, хочется както понять с чего начать)

Допустим есть входящие данные такие:
const tree1 = [
	{
		id: 1, 
		title: 'node1', 
		children: [
			{
				id: 3, 
				title: 'sub node1' ,
			}, 
			{ 
				id: 4, 
				title: 'sub node1' , 
				children: [ { id: 5, title: 'sub sub node1'}]
			}
		] ,
	},
	{
		id: 2, 
		title: 'node2', 
		children: [
			{
				id: 6, 
				title: 'sub node2' ,
			}, 
			{ 
				id: 7, title: 'sub node2' , 
				children: [ { id: 8, title: 'sub sub node2'}]
			}
		] ,
	}
];

const tree2 = [
	{
		id: 9, 
		title: 'node1', 
		children: [
			{
				id: 10, 
				title: 'sub node1' ,
			}, 
			{ 
				id: 11, title: 'sub node1' , 
				children: []
			}
		] ,
	},
	{
		id: 12, 
		title: 'node2', 
		children: [
			{
				id: 13, 
				title: 'sub node2' ,
			}, 
			{ 
				id: 14, 
				title: 'sub node2' , 
				children: [ { id: 15, title: 'sub sub node2'}]
			}
		] ,
	}
];

const treeToTreeNodes = (tree1, tree2) => {

}

Последний раз редактировалось jabbascript, 04.02.2021 в 16:39.
Ответить с цитированием
  #2 (permalink)  
Старый 04.02.2021, 17:16
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 1,101

По моему у ваших деревьев не хватает полноценного корня.
Должно быть как то так
const tree1 = {
id: 0,
title: 'root',
children: [
		{
			id: 1,
			title: 'node1',
			children: [
				{
					id: 3,
					title: 'sub node1' ,
				},
				{
					id: 4,
					title: 'sub node1' ,
					children: [ { id: 5, title: 'sub sub node1'}]
				}
			] ,
		},
		{
			id: 2,
			title: 'node2',
			children: [
				{
					id: 6,
					title: 'sub node2' ,
				},
				{
					id: 7, title: 'sub node2' ,
					children: [ { id: 8, title: 'sub sub node2'}]
				}
			] ,
		}
	]
};


const treeToTreeNodes = (tree1, tree2) => {}

И какая конкретно операция должна быть выполнена? Что вставить и куда?
Ответить с цитированием
  #3 (permalink)  
Старый 05.02.2021, 07:54
Аспирант
Отправить личное сообщение для jabbascript Посмотреть профиль Найти все сообщения от jabbascript
 
Регистрация: 27.11.2017
Сообщений: 31

Допустим я беру и удаляю ноду из tree2:
{
		id: 12, 
		title: 'node2', 
		children: [
			{
				id: 13, 
				title: 'sub node2' ,
			}, 
			{ 
				id: 14, 
				title: 'sub node2' , 
				children: [ { id: 15, title: 'sub sub node2'}]
			}
		] ,
	}

и ее вставляю в tree1 между:
{
				id: 6, 
				title: 'sub node2' ,
			},

и
{ 
				id: 7, title: 'sub node2' , 
				children: [ { id: 8, title: 'sub sub node2'}]
			}

и так далее все возможные комбинации.
Ответить с цитированием
  #4 (permalink)  
Старый 05.02.2021, 10:05
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 1,101

Если такие операции требуются часто, я бы сделал класс, хотя бы с минимально необходимыми функциями работы с деревом.
Ну как то так
class Node {
// Создает узел дерева.
// fields - объект с полями определяемыми пользователем
// childs - массив дочерних узлов (необязат)
	constructor (fields, childs) {
		this.parent = null;
		this.childs = [];
		for (const f in fields) {
			this[f] = fields[f];
		}
		if (childs) {
			for (const ch of childs) {
				this.append(ch);
			}
		}
	}

// Добавить узел nd, как последний дочерний к текущему	
	append (nd) {
		nd.remove();
		nd.parent = this;
		this.childs.push(nd)
		return this
	}
	
// Найти в текущем и среди всех его потомков узел, удовлетворяющий условию,
// задаваемому функцией  fcmp	
	find (fcmp) {
		if (fcmp(this)) return this;
		for (const ch of this.childs) {
			const rf = ch.find (fcmp)
			if (rf) return rf;
		}
		return null;
	}
	
// Удалить узел
// nd.remove () удаляет узел  nd из его родителя.
// par.remove (nd) удаляет из дочерних par узел nd
	remove (nd) {
		let par = this;
		if (nd === undefined) {
			par = this.parent;
			nd = this;
		}
		if (!par || !nd) return
		const ind = par.childs.indexOf(nd);
		if (ind < 0) return;
		par.childs.splice(ind, 1);
		nd.parent = null;
		return nd;
	}
	
// Вставляет узел nd перед текущим, в его родительский узел, если он есть
	before (nd) {
		const par = this.parent;
		if (!par) return;
		nd.remove();
		const ind = par.childs.indexOf(nd);
		par.childs.splice(ind, 0, nd)
		nd.parent = this;
		return this;
	}
	
	toString () {
		let s = '{'
		for (const f in this) {
			if (f == 'childs') continue;
			if (f == 'parent') continue;
			s += `${f}: ${this[f].toString()}, `
		}
		s+='childs: ['
		for (const ch of this.childs) {
			s+=ch.toString() + ','
		}
		s+=']}'
		return s
	}
}

const tree1 = new Node ({},
	[
		new Node ({id: 1, title: 'node1'},
			[
				new Node ({id: 3, title: 'sub node1'}),
				new Node ({id: 4, title: 'sub node1'}, [new Node ({ id: 5, title: 'sub sub node1'})]),
			]),
		new Node ({id: 2, title: 'node2'}, 
			[
				new Node ({id: 6, title: 'sub node2'}),
				new Node ({id: 7, title: 'sub node2'}, [new Node ({ id: 8, title: 'sub sub node2'})]),
			])
		
	]);
	
const tree2 = new Node ({},
	[
		new Node ({id: 9, title: 'node1'},
			[
				new Node ({id: 10, title: 'sub node1'}),
				new Node ({id: 11, title: 'sub node1'}),
			]),
		new Node ({id: 12, title: 'node2'}, 
			[
				new Node ({id: 13, title: 'sub node2'}),
				new Node ({id: 14, title: 'sub node2'}, [new Node ({ id: 15, title: 'sub sub node2'})]),
			])
		
	]);
	
console.log(tree1.toString());
console.log(tree2.toString());
// Допустим я беру и удаляю ноду из tree2:
// и ее вставляю в tree1 между:
const nd12 = tree2.find (nd => nd.id == 12)
const nd7 = tree1.find (nd => nd.id == 7)
nd7.before(nd12)

console.log(tree1.toString());
console.log(tree2.toString());
Ответить с цитированием
  #5 (permalink)  
Старый 05.02.2021, 12:07
Аватар для Vlasenko Fedor
Профессор
Отправить личное сообщение для Vlasenko Fedor Посмотреть профиль Найти все сообщения от Vlasenko Fedor
 
Регистрация: 13.03.2013
Сообщений: 1,452

https://www.jstree.com/demo/
https://dbushell.github.io/Nestable/
и много других
тут вопрос целесообразности своего велосипеда или изспользованя готовых либ
как не крути если хочешь свое, то нужно смотреть, что есть хорошее у других
пример с учебника и здесь на сайте где то в учебнике было примитивное дерево
https://learn.javascript.ru/drag-and-drop-plus
Ответить с цитированием
  #6 (permalink)  
Старый 05.02.2021, 13:29
Аспирант
Отправить личное сообщение для jabbascript Посмотреть профиль Найти все сообщения от jabbascript
 
Регистрация: 27.11.2017
Сообщений: 31

Сообщение от Vlasenko Fedor Посмотреть сообщение
https://www.jstree.com/demo/
https://dbushell.github.io/Nestable/
и много других
тут вопрос целесообразности своего велосипеда или изспользованя готовых либ
как не крути если хочешь свое, то нужно смотреть, что есть хорошее у других
пример с учебника и здесь на сайте где то в учебнике было примитивное дерево
https://learn.javascript.ru/drag-and-drop-plus
https://dbushell.github.io/Nestable/ Это круто и я бы взял, но мне такое надо на React)
Ответить с цитированием
  #7 (permalink)  
Старый 05.02.2021, 13:30
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 1,101

Сообщение от Vlasenko Fedor
тут вопрос целесообразности своего велосипеда или изспользованя готовых либ
Эти готовые либы работают с DOM.
А оно надо?
Зачем в простом случае тащить готовую либу, где 90% не требуется?
Сообщение от Vlasenko Fedor
https://learn.javascript.ru/drag-and-drop-plus
Где дерево то?
Ответить с цитированием
  #8 (permalink)  
Старый 05.02.2021, 13:37
Аспирант
Отправить личное сообщение для jabbascript Посмотреть профиль Найти все сообщения от jabbascript
 
Регистрация: 27.11.2017
Сообщений: 31

Проблема сейчас в том что мне нужно подобие этого https://frontend-collective.github.i...-tree-dragging, но то что есть у них не работает, выдает ошибку.
Ответить с цитированием
  #9 (permalink)  
Старый 05.02.2021, 17:13
Аватар для Vlasenko Fedor
Профессор
Отправить личное сообщение для Vlasenko Fedor Посмотреть профиль Найти все сообщения от Vlasenko Fedor
 
Регистрация: 13.03.2013
Сообщений: 1,452

Сообщение от voraa
Зачем в простом случае тащить готовую либу, где 90% не требуется?
чтоб не тратить время на свой велосипед, взять готовое,чтоб не тестить и не ловить баги во всех браузерах, потратить время на другое
в нынешнее время плевать на 10k на вебе можно
в конце ТС ответил про react
avesome react tree
https://reactscript.com/best-tree-view/
с React не подскажу, у меня к нему особое мнение
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
На каком протоколе реализовать обмен между двумя серверами. jtag Node.JS 7 18.08.2018 05:48
Обмен сообщениями между вкладками Nikolay37 Events/DOM/Window 2 05.07.2017 14:43
Обмен событиями между видами khusamov ExtJS 4 26.03.2017 23:09
Количество отмеченный дней недели между двумя датами freenick jQuery 7 18.01.2016 23:25
Центрирование среднего блока между двумя float Siend (X)HTML/CSS 3 14.09.2015 14:08