JavaScript implements draggable tree

WBOY
Release: 2023-05-12 10:17:37
Original
582 people have browsed it

As Web applications are increasingly used, we increasingly need to design more efficient methods for interaction with web pages. One of them is to use JavaScript to implement a draggable tree (Drag & Drop Tree). This article will introduce how to use JavaScript to create a draggable tree, detailing the implementation process and related technical details.

1. Goals to be achieved

The draggable tree described in this article refers to a structure on the web page, which contains nodes of the tree structure, and we can drag and drop them. Reorganize their hierarchical relationships. To implement such a tree, the following two key aspects need to be completed.

  1. Implementing the tree structure

First we need to create nodes for the tree structure in the page and determine the levels and associations between the nodes. These contents can be represented using JSON. For example, we can store the structure of the tree in the following JSON format:

{
    name: "节点A",
    children: [{
        name: "子节点A1",
        children: []
    }, {
        name: "子节点A2",
        children: [{
            name: "子节点A2-1",
            children: []
        }]
    }]
}
Copy after login

When rendered as a tree structure, it should look like this:

- 节点A
  |- 子节点A1
  |- 子节点A2
     |- 子节点A2-1
Copy after login
  1. Implementing drag and drop functionality

Making nodes drag-and-drop requires the use of some JavaScript techniques. Regarding the drag and drop API, generally speaking, it involves three categories:

  • Dragable elements
  • Place target elements
  • Drag data

Using these APIs, we can easily implement the drag-and-drop function of nodes.

2. Technical details

After understanding our goals, let’s now discuss the implementation details in detail. The following are the steps to implement:

  1. Build a tree structure

We need to create node elements first and add them to HTML, usually using ul and li element levels. accomplish. For each node, a li element is required, and more li elements must be nested in the child node ul. In order to associate the tree structure with JSON data, you can use the data-* attributes to store the JSON data in the corresponding li element.

<ul id="tree">
    <li data-name="节点A">
        <div class="node">节点A</div>
        <ul>
            <li data-name="子节点A1">
                <div class="node">子节点A1</div>
            </li>
            <li data-name="子节点A2">
                <div class="node">子节点A2</div>
                <ul>
                    <li data-name="子节点A2-1">
                        <div class="node">子节点A2-1</div>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>
Copy after login
  1. Add drag events to nodes

We need to add drag events for each node, including mousedown, dragstart, dragover, dragleave, drop and dragend. Among them, mousedown and dragstart events need to be processed before dragging starts, and subsequent processing is dragover, dragleave, drop and dragend respectively. The handling functions of these drag and drop events can be completed through event listeners.

// 获取所有节点并添加事件监听器
const nodes = document.querySelectorAll('.node');
nodes.forEach((node) => {
    node.addEventListener('mousedown', onMouseDown);
    node.addEventListener('dragstart', onDragStart);
    node.addEventListener('dragover', onDragOver);
    node.addEventListener('dragleave', onDragLeave);
    node.addEventListener('drop', onDrop);
    node.addEventListener('dragend', onDragEnd);
});
Copy after login
  1. Implementing the processing function of the drag event

The processing function of the drag event is somewhat complicated, and each step of the operation needs to be carefully designed. The following are instructions for each step:

  • mousedown: Record the element where the drag starts and set isDragged to true.
  • dragstart: Set the data transmission type and the data to be transmitted. In addition, it is necessary to determine whether the drag operation can be performed based on the status of isDragged. To set the data transmission type, you can use the setData() method.
function onDragStart(event) {
    if (!isDragged) {
        draggedItem = event.currentTarget.parentNode;
        event.dataTransfer.setData('text/plain', event.currentTarget.dataset.name);
        isDragged = true;
    }
}
Copy after login
  • dragover: Prevent the default event and add the isOver attribute to the current element. This attribute indicates that the current element is placed above other elements and can be placed. Default events can be prevented through the event.preventDefault() method.
function onDragOver(event) {
    event.preventDefault();
    if (!event.currentTarget.dataset.isOver) {
        event.currentTarget.parentNode.classList.add('over');
        event.currentTarget.dataset.isOver = true;
    }
}
Copy after login
  • dragleave: Remove the over attribute of the current element, indicating that there is no mouse hovering over the element.
function onDragLeave(event) {
    if (event.currentTarget.dataset.isOver) {
        event.currentTarget.parentNode.classList.remove('over');
        event.currentTarget.dataset.isOver = false;
    }
}
Copy after login
  • drop: Determine whether the placement operation can be performed based on whether the current element has the over attribute. If it doesn't work, exit directly; if it works, perform a placement operation and adjust the tree structure.
function onDrop(event) {
    event.preventDefault();
    if (event.currentTarget.dataset.isOver) {
        const droppedItem = event.currentTarget.parentNode;
        const parent = draggedItem.parentNode;
        parent.removeChild(draggedItem);
        event.currentTarget.parentNode.insertBefore(draggedItem, droppedItem.nextSibling);
    }
}
Copy after login
  • dragend: implements the termination event of drag operation. In this event, reset the value of isDragged and remove all over attributes.
function onDragEnd(event) {
    event.currentTarget.parentNode.classList.remove('over');
    event.currentTarget.dataset.isOver = false;
    isDragged = false;
}
Copy after login

3. Complete code

Finally, we integrate the above Javascript code to display a complete draggable tree. You can use this code directly, copy it into a text editor, save it as an html file and run it in the browser.




    
    可拖动的树
    


<ul id="tree">
    <li data-name="节点A">
        <div class="node">节点A</div>
        <ul>
            <li data-name="子节点A1">
                <div class="node">子节点A1</div>
            </li>
            <li data-name="子节点A2">
                <div class="node">子节点A2</div>
                <ul>
                    <li data-name="子节点A2-1">
                        <div class="node">子节点A2-1</div>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>
<script>
    let draggedItem = null;
    let isDragged = false;

    const nodes = document.querySelectorAll('.node');
    nodes.forEach((node) => {
        node.addEventListener('mousedown', onMouseDown);
        node.addEventListener('dragstart', onDragStart);
        node.addEventListener('dragover', onDragOver);
        node.addEventListener('dragleave', onDragLeave);
        node.addEventListener('drop', onDrop);
        node.addEventListener('dragend', onDragEnd);
    });

    function onMouseDown(event) {
        event.preventDefault();
    }

    function onDragStart(event) {
        if (!isDragged) {
            draggedItem = event.currentTarget.parentNode;
            event.dataTransfer.setData('text/plain', event.currentTarget.dataset.name);
            isDragged = true;
        }
    }

    function onDragOver(event) {
        event.preventDefault();
        if (!event.currentTarget.dataset.isOver) {
            event.currentTarget.parentNode.classList.add('over');
            event.currentTarget.dataset.isOver = true;
        }
    }

    function onDragLeave(event) {
        if (event.currentTarget.dataset.isOver) {
            event.currentTarget.parentNode.classList.remove('over');
            event.currentTarget.dataset.isOver = false;
        }
    }

    function onDrop(event) {
        event.preventDefault();
        if (event.currentTarget.dataset.isOver) {
            const droppedItem = event.currentTarget.parentNode;
            const parent = draggedItem.parentNode;
            parent.removeChild(draggedItem);
            event.currentTarget.parentNode.insertBefore(draggedItem, droppedItem.nextSibling);
        }
    }

    function onDragEnd(event) {
        event.currentTarget.parentNode.classList.remove('over');
        event.currentTarget.dataset.isOver = false;
        isDragged = false;
    }
</script>

Copy after login

Through the above code implementation, we successfully created a draggable tree structure. In the web page, users can easily adjust the tree structure by dragging and dropping. At the same time, we also introduced in detail various technical details during the implementation process. This is undoubtedly a very useful practical case for developers who are learning JavaScript.

The above is the detailed content of JavaScript implements draggable tree. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!