How to use selector :removed in cytoscape.js? - cytoscape.js

How can I get removed eles from the graph?
cy.filter(":removed") doesn't work and cy.elements() doesn't have removed eles.
Thanks!

Cytoscape.js does not keep removed elements in the graph. That would contradict that they're removed. So, of course if you ask the graph for all removed elements, it will return to you an empty collection -- i.e. there are no removed elements in the graph.
The :removed selector exists for completeness and so you can use it on your own collections. If you have a collection for which you've held onto a reference, some elements may be removed later on but they'll still be in the referenced collection.

You need to remember which nodes you removed and then call restore on them:
var removed = [];
function remove(elements)
{
removed.push(elements);
selected.remove();
}
function restore()
{
cy.startBatch();
for (var i = 0; i < removed.length; i++)
{
removed[i].restore();
}
removed = [];
cy.endBatch();
}
For some reason, removing takes a long time on a large graph. And if you only remove and restore nodes, their connected edges are gone.

Related

Add value at the beginning of an array in react-native hook

I am functional component I am using hooks to update the state of the array locationData
const c = {
title: inputValue,
}
setLocationData([...locationData, c]);
This is working fine, but now I want to add the value at the beginning of the array, and not at the end.
Edit:
I also have a problem to delete an item from the array. I want to delete one item, but more are deleted
const deleteItem = (index) => {
console.log(index)
var temp = locationData;
var temp = locationData.splice(index, 1);
setLocationData(temp);
}
You are almost there, just switch the position in the array.
setLocationData([c, ...locationData]);
You should also be aware of other methods like splice, slice, push, pop etc...
Update: Using Splice
This relates to part 2 of your question with regards to removing from specific index.
The splice() method changes the contents of an array by removing or
replacing existing elements and/or adding new elements in place. To
access part of an array without modifying it, see slice().
So your codes should be similar to the following
var temp = [...locationData];
temp.splice(index, 1);
setLocationData(temp);

How to make an instance itself removed from an array using for ...of?

Now i have an array "enermies" including several instances of class Enermy, i want to make an iterator that if an enermy is killed, it will be removed from array.
I know how to write in traditional JS
for(let i= enermies.length-1;i>=0;i--){
if(enermies[i].iskilled){
enermies.splice(i,1)
}
}
but as to ES6, is there a better way using "for...of"?
for (enermy of enermies){
if(enermy.iskilled){
??????
}
}
Your code won't work because slice is not a mutative function, so it does nothing. Even if you use the correct splice, deleting elements inside loop is dangerous and you need to avoid it. Instead, one of the simplest ways is filter:
enemies = enemies.filter(enemy => !enemy.iskilled);
If you're dealing with only one element, you can also do this:
const index = enemies.findIndex(enemy => enemy.iskilled);
if (index >= 0) enemies.splice(index, 1):
This way you keep the array in place and don't have to re-assign a new array, though you'll need to do a proper loop if you want to delete more than one elements.

Why does data in list1 changed automatically when I change the data in the other list2 which is cloned from the list1? Using Vue.Draggable

I am using Vue.Draggable in my Vue project and trying to drag(clone) a button from sider into a draggable component.
I want to modify the data when I clone the button into the component. But I find that when I modify the data in the list which is binded with the component, the original list that sider used got changed automatically.
Is there some kind of synchronization mechanism in Vue.Draggable or something? I want to change the object data in the component only.
I tried to modify the object in the list2 manually by using a vue extension in Chrome browser. And it still happens. So I think maybe it's not bug in my code.
addEntity (conditionID, entity) {
if (!entity.forChoose) {
}
else {
let variable = 0;
for (let i = 0, len = this.whens.length; i < len; i++) {
if (this.whens[i].entity[0].id == entity.id) {
variable++;
}
}
this.whens[conditionID].entity[0].forChoose = false;
this.whens[conditionID].entity[0].variable = variable;
this.whens[conditionID].entity[0].name = entity.name + '-fake';
}
},
The code above is the event when I drag the data into the component, and changed some variable.
Although I did nothing to the original data in the Sider where I cloned the data from, it still got changed as well.
Is there a way to change the dragged data but do not affect the original data?
Please help me, thank you!
I think this is happening because of the immutability.
so can you try using spread operator to create new shallow copy of your list before you change it.
how to use spread operator (triple dot)
let newArrayOfWhens = [...this.whens]
then use the "newArrayOfWhens" array in your code
You can create a deep clone as well if you want, but try to avoid it if it is not necessary.
you can use a library call "lodash" to do it very easily
deepClone

How to create an empty collection in cytoscape.js?

I want users to hide nodes in a cytoscape.js graph but also have a reset function. How should I initialize hiddenNodes in the following code? I looked at http://js.cytoscape.org/#collection/building--filtering which tells me how to add and remove nodes from a collection but not how to create an empty one.
var hiddenNodes = ?
function hide(nodes)
{
nodes.hide();
hiddenNodes = hiddenNodes.union(nodes);
}
function reset()
{
hiddenNodes.show();
}
P.S.: The hidden nodes are just a MWE, I know I could do this with selectors also.
P.P.S.: Are there alternative functions for union and difference that change the collection directly or are there only those who return new objects?
From the documentation for collection:
cy.collection() - Get an empty collection

Dojo DnD Move Node Programmatically

I would like to know if there is a way to move the node programmatically in dojo Dnd? The reason is I would like to revert the changes to the drag and drop when the web service call triggered a failed save on the database. Here is what I have so far.
In my code, the node Id seems to be unrecognized by the dojo.dnd.Container.DelItem. I cannot just use the selected item on the target because this is a asynchronous webservice function callback. So the user may be selecting another node on the container when this is called.
function OnMoveWSComplete(strResult) {
var resultObj = eval('(' + strResult + ')');
var sourceContainer = eval('(' + objResult.sourceContainerId + ')');
var targetContainer = eval('(' + objResult.targetContainerId + ')');
var targetNodes = targetContainer.getAllNodes();
for (var iNode = 0; iNode < targetNodes.length; iNode++) {
var currId = getLastIdFromStr(targetNodes[iNode].id);
if (currId == resultObj.Id) {
var targetN = targetNodes[iNode];
var Name = targetNodes[iNode].childNodes[0].nodeValue;
targetContainer.delItem(targetNodes[iNode].id);
var origData = { Id: resultObj.Id, Name: Name };
sourceContainer.insertNodes(true, origData);
break;
}
}
}
EDIT: Solution (Thanks Eugene Lazutkin) [2009/11/30]:
/**
* Move one node from one container to the other
*/
function moveNode(nodeId, sourceContainer, targetContainer) {
var node = dojo.byId(nodeId);
// Save the data
var saveData = sourceContainer.map[nodeId].data;
// Do the move
sourceContainer.parent.removeChild(node);
targetContainer.parent.appendChild(node);
// Sync the DOM object → map
sourceContainer.sync();
targetContainer.sync();
// Restore data for recreation of data
targetContainer.map[nodeId].data = saveData;
}
It looks like you assume that delItem removes physical nodes. Take a look at the documentation — probably you want to move nodes between containers instead of deleting them from the map. One simple way to do that just to move DOM nodes between containers, and call sync() on both containers.
Addition: Here is a super-simple pseudocode-like example:
function move(node, source, target){
// normalize node and/or node id
node = dojo.byId(node);
// move it physically from one parent to another
// (from target to source) adding to the end
target.parent.appenChild(node);
// now it is moved from source to target
// let's synchronize both dojo.dnd.Source's
source.sync();
target.sync();
}
Or something along these lines should work. The important pieces:
Move node from one parent to another using any DOM operations you deem appropriate. I used appendChild(), but you can use insertBefore(), or anything else.
Synchronize both sources involved after the move.
Obviously it works if both sources use nodes of the same type and structure. If not, you should do something more complex, e.g., move everything you need emulating a real DnD move by publishing topics described in the documentation.
I have this function which moves selected nodes by button click:
source.forInItems(dojo.hitch(this, function(item, id, map) {
if (dojo.hasClass(id, "dojoDndItemAnchor")) {
target.onDrop(source, [ dojo.byId(id) ], false);
dojo.removeClass(id, "dojoDndItemAnchor");
}
}));
onDrop() is an overridable method, which is called upon item drop, and by default calls to method onDropExternal(source, nodes, copy).
I am doing the same thing right now. I was able to solve by doing the following.
Set the dnd/Source autoSync property to true
<div data-dojo-type="dojo.dnd.Source" accept="widget" class="source" data-dojo-props="autoSync: true">
After dragging it looses the dndtype so I had to re-add it using client side code. Also I remove the dojoDndItemAnchor class after drop.
$(node).removeClass('dojoDndItemAnchor').attr('dndtype', 'widget');