Paper.js has a clear way to add an Item to a Group using addChild(item). However, there does not seem to be a clear way to remove an Item from a Group without also removing that item itself from the view.
Groups have a children property, but according to the documentation, it should not be mutated:
The children array should not be modified directly using array functions. To remove single items from the children list, use item.remove(), to remove all items from the children list, use item.removeChildren(). To add items to the children list, use item.addChild(item) or item.insertChild(index, item).
So each item has a remove() method, but this not only removes it from the Group but also from the display.
How can I remove an Item from a Group, only dissociating it with the Group and not removing it from the display? Is there a cleaner way to do it than this?
item.remove();
paper.project.activeLayer.addChild(item);
Your approach
item.remove();
paper.project.activeLayer.addChild(item);
is how it should be done. Unless you call paper.view.update() it's not going to re-render the canvas in between the two calls, so there is little cost in making the extra function call.
Related
I am using Vuedraggable (Sortable JS) to try and accomplish grouping of items. The items themselves shouldn't have children (as the demos for Sortable JS use), but instead should be grouped in a parent "group" type object. I'm having issues stopping groups from being dragged inside of other groups, as at the first level, both the Group Objects and Form Objects are in the same "sortable group".
There are Form Objects and Group Objects at the same 1st level Form
Objects and Group Objects should be sortable at the first level Form
Objects should be draggable into and out of groups
Groups should NOT be able to be dragged inside of other groups
#4 is the current issue. Its currently possible to drag one group inside another group. Its not easy to do... if you first drag an object from one group into another group, this seems to make it easier to subsequently grab the fist group and drag it into the 2nd group.
Here is a codesandbox illustrating the issue:
https://codesandbox.io/s/vuedraggable-nested-simplified-wc-tr6mx?file=/src/components/NestedDraggable.vue
Looks like the answer is to use a function in the pull/put configuration of the group
Working CodeSandbox
References:
https://github.com/SortableJS/Vue.Draggable#props
https://github.com/SortableJS/Sortable#options
I am using vue draggable component to drag and drop objects from one div to another. I am also using filterBy filtering the v-model. The problem is when I filter(and for example get 1 result) and try to drag and drop the item the very first from all items is dropped and not the dragged item.
Dragging from:
<draggable :list="available" class="draggable" :options=" group:'stuff'}">
<div v-for="people in filterBy(available, filter_available, 'name')" class="list-item">
<img :src="image" height="20"> {{ name }}
</div>
</draggable>
Dropping to:
<draggable :list="drop" class="draggable" :options="{group:'stuff'}">
<div v-for="people in filterBy(drop, filter_doppred, 'name')" class="list-item">
<img :src=image" height="20"> {{ name }}
</div>
</draggable>
On it's own both features are working fine. However, when filtering the results, it changes the index of the elements and when moving from one list to another - I move a different item, not the one dragged.
Any Ideas?
Well, you have to pass the same list to the draggable component that you use for the v-for - both need the filtered result.
You currently use a method to do the filter operation. You would have t call this method twice to get the same result to both places.
You should instead use a computed property to avoid doing the same operation twice.
Edit: the draggable component will mutate the provided list, which will not affect your source data when you use a computed property.
After looking at the docs for vue-draggable, you should probably use the changeevent provided by the component (https://github.com/SortableJS/Vue.Draggable#events) to update your source data.
I can't give you a concrete example because I don't know what your logic is to determine the new position of the moved element in the unfiltered source list.
Mostly I agree with #LinusBorg, with some minor differences:
1) draggable list props and v-for must use a collection
2) Create a different array for the filtered array. A computed property won´t work as draggable will try to change it. You can use a data field and use watch if the master array may change.
3) Listen the change event to propagate change on the master array.
I think that's happening because SortableJS uses indexes to get the currently dragged element.
// Sortable.js:341
// Get the index of the dragged element within its parent
startIndex = _index(target, options.draggable);
I have a similar case:
several sets of drag'n'drop groups should share the same list of items, and the items cannot repeat across sets.
I think I'll end up with adding/removing the elements manually.
I added a property(visible) to my object, when the filter change I set the property to true if is still visible, to false if not. Based on the property i hide or show the element to avoid create a new array with filterBy, filterBy is the reason the index changes and does not match with the original array (cause it creates a new one).
I have an array of JSON objects that are used to render a list of elements:
mydata.map(thing => {
return <SomeComponent key={thing._id} />
});
Each rendered item has up/down arrows, and if the user clicks the up arrow, for example, the item will be moved up the list. On the back end, the items in the array are simply swapped.
How can I make this process animate so it's easier for the user to see what the result of their action was? I was looking into react-motion, but it seems to work based on modifying CSS/styles. I was hoping there would be something that uses React's key property to determine unique elements and handle movement based on that.
Any suggestions?
React-flip-move is a wonderful component which allows you to animate children components. There is an example animation flipping values on a list too.
I am working with knockout.js. I have a situation where I have a collection of items which each have a observable boolean isleader. Where one of them can be active at a time. If people swap an item in the collection with one from another collection then I check if the old one isleader is true and if so I set it on the new one. This works fine. Now I need to add a second input mechanism which is a dropdown which is bound to the collection to show all the items from the collection. I want the one item in the collection with the isleader set to true to be the selected item and if the selected item is changed I would like the isleader to be updated to reflect this.
How can I do this without creating an infinite loop between the dropdown and the collection constantly updating the selected item.
You can do a peek.
this.selectedItem.peek()
as opposed to
this.selectedItem()
as you are propably doing.
Both will return the fields value, but the first will do it without creating a dependency. In other words, peek will get the value, but it won't subscribe to it.
I have two <select>s with the same <option>s, and I need - using prototype - that when selecting an option in one of them, the same option is removed from the other select and additionally the latter must mantain its previously selected option.
Any clues ? Is there a better way than remembering the last item selected, recreate the options array, an reselecting the item ?
Thanks!
You can 'remove' the item from the other select, but you need to specify it by its index, and you'll still need to remember the selected item, and recalculate its index after the removal. So it's slightly better than recreating the array, but not much better.