I'm using a document store that stores files and folders in a database and can output the contents (or part of the contents) as a serie of nested objects, like this:
var a = [
{
id: 0,
children: [
{
id: 1,
parent: 0,
children: [
{
id: 2,
children: []
}
]
}, {
id: 3,
parent: 0,
children: []
}, {
id: 4,
parent: 0,
children: [
{
id: 5,
parent: 4,
children: [
{
id: 6,
parent: 5,
children: []
}, {
id: 7,
parent: 5,
children: []
}, {
id: 8,
parent: 5,
children: []
}
]
}
]
}
]
}
]
I'm displaying this and allowing users to interact with it in the browser using the HTML5 drag and drop API. When a user drags an element and drops it into another I want to change the object's position in the data. All I have available to use is the object to be moved and the destination object.
I've written a function that handles the move. It works by:
- Finding the item to move, the original parent and the new destination.
- Removing the item from the parent's children array.
- Updating the parent on the item to move.
- Pushing the item to the destinations children array.
Here's the code
function findItem (array, id) {
var result
array.some(item => {
if (item.id === id) {
result = item
return true
}
if (item.children.length) {
let subResult = findItem(item.children, id)
if (subResult) {
result = subResult
}
}
})
return result
}
function move (itemId, destinationId) {
let itemToMove, parentItem, destinationItem
itemToMove = findItem(a, itemId)
parentItem = findItem(a, itemToMove.parent)
destinationItem = findItem(a, destinationId)
// Remove the item from the the parents childen
var index
parentItem.children.find((child, idx) => {
if (child.id === itemToMove.id) {
index = idx
return true
}
})
parentItem.children.splice(index, 1)
// Update the parent of the item to move
itemToMove.parent = destinationId
// Push it to the new parent
destinationItem.children.push(itemToMove)
}
move(3, 1)
Is there a better way of doing this?