Grab compound nodes when a child node is grabbed - cytoscape.js

I'm currently trying to implement the developp the following behavior in my application embedding Cytoscape.js : I would like that when a particular child node of a compound node is grabbed, the whole compound node is grabbed.
If tried using this code but it does not work as I expect :
cy.$(mySubNodeSelector)
.on('grab', function(){
this.ungrabify();
this.parent().select();
this.parent().grabify();
});
Does anybody has an advice about how to implement this behavior ?
Thanks a lot.

Disable events on the child: http://js.cytoscape.org/#style/events
Your code doesn't do anything because (1) you're mutating grabbability after elements have been grabbed and (2) you conflate grabifying (allowing grabbing) with grabbing (a user gesture).

Related

Vue components hierarchy and passing data

I'm writing an app in Vue and I have a really hard time understanding the component hierarchy, namely the parent-child relationships and how to pass data around.
I have a view that contains a map which in turn has some navigation controls and options that are overlayed on top of the map. Now, I want these controls to manipulate the map WITHOUT having to nest the buttons inside the actual maps as it will cause severe display issues (for example, clicking on a zoom button falls through the button and also clicks the next element under it).
My app looks like this:
Mapview
Map
Controls
Options
Optionpanel1
Optionpanel2
...
Now, a HTML input element in Optionpanel1 needs to control something in the Map, which is not actually it's parent component. Also, some data from Map needs to be passed down to Optionpanel1 so it would know what to control. To make matters worse, something in Options also needs to pass something down to Optionpanel1, so, even though event bus would allow communication upwards, it would not solve that I need to pass data from parents to indirect children and also components that are not it's children.
I can actually pass the required property down the line if I nest the Options inside Map and pass it down with :myProp="prop" and then in Options, declare it in props and bind to Optionpanel1, where it is again declared as a prop. But as I mentioned earlier, nesting elements that I do not want to be nested in a visual sense causes massive issues like mouse click falling through. Do elements even need to be nested inside eachother in order to define parent-child relationship?
I would want components to exchange read-only data without Y being a child of X in the DOM. Also, even if nesting components like this would not cause visual issues, does it not seem very annoying to have to register and bind it in every component along the way?
I don't understand why is it so difficult to simply read something from another component. It's starting to seem that Vue is causing a problem that it's supposed to solve? Am I missing something here or am I looking at this in a completely wrong way?
Thanks in advance.
Basically you have 2 options to control complex components:
Handle the actions in your so-called "smart component" (in terms of React), which is the common ancestor for the controlling and controlled components. It's a pretty good solution for small components, but that's not the case.
To separate common logic and data in a Vuex store. I'd recommend you doing this.

Default-expand-all doesn't work for q-tree? Vue.Js

I have to code a web application and the most important element is the q-tree. I'm already able to load and show data (passing an array called list), but I want that all nodes are expanded.
The vue.js examples of the official documentation show that you're be able to do this with the 'default-expand-all' attribute but this isn't working for me.
It only shows me the root node with an arrow, where I have to expand the children nodes manually.
<q-tree
:nodes="list"
:selected.sync="selected"
#update:selected="onSelectionChangedNode"
node-key="NodeNr"
label-key="NodeTxt"
default-expand-all
></q-tree>
Taking a cue from the accepted answer, I realised that the dom has already been created with the tree component on first render.
In my use case, I want to update the Tree when data comes back from the server.
So, I had to force it to re-render with the expanded functionality using:
this.$nextTick(function () {
this.$refs.nodes.expandAll();
})
The nextTick function will update the dom in the next window of execution, by which time the nodes will get expanded by calling the expandAll function.
And NB: For those confused by the astericks on the ref attribute or how to add it to the component, here goes:
<q-tree :nodes="list"
:selected.sync="selected"
#update:selected="onSelectionChangedNode"
node-key="NodeNr"
label-key="NodeTxt"
ref="nodes"
>
Solved my problem as following:
I have added a ref attribute to the QTree DOM Element which makes it possible to access predefined methods of QTree API.
<q-tree
:nodes="list"
:selected.sync="selected"
#update:selected="onSelectionChangedNode"
node-key="NodeNr"
label-key="NodeTxt"
**ref="nodes"**
>
The function I have been using is expandAll().
updated() {
this.$refs.nodes.expandAll();
}
The most important thing for me was, I had to find out which lifecycle hook was the right one for me. The update() hook was the one I was looking for.
The reason:
Called after a data change causes the virtual DOM to be re-rendered and
patched.
The component’s DOM will have been updated when this hook is called, so you
can perform DOM-dependent operations here.
The default-expand-all is only applied on the first rendering of that Component.
So if your Component renders when the nodes aren't assigned they wont expand if assigned afterwards.
https://v1.quasar-framework.org/vue-components/tree
You have to work with scoped slots and an expanded attribute if you dont have the nodes on first rendering.

DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node

I am having an issue with a third party library.
I wrote a component to watch the position property and call the reload method to refresh the overlays on the map.
It performed normal when there is only one v-for.
But failed when there is two v-for.
How do I fix this?
Just wrap every v-for directive in it's own, dedicated parent div.
Each v-for directive expands into multiple elements. If there are multiple lists with the same parent element which need to be updated at the same time, Vue is having a hard time updating the virtual dom.
This issue does not only happen with multiple v-fors in one component; I also came across it when using multiple root elements in nuxt3. I fixed the issue by using old-style vue2 syntax: Every template contains only one child element (or v-for-directive), which contains all the content.
TL;DR: Wrapping complex contents (v-for, content of a page > 1 element, ...) in another surrounding div might solve the issue.

How to use z-index in cytoscape.js?

I'm using cytoscape.js. I have some nodes that are superposed and I’m trying to fix their z-index so I can bring to the front the nodes that are in the back. I don’t see to get it right. I did two examples:
1) http://jsfiddle.net/VzCZm/2/ In these one I used the parent attribute of the library, I fixed the z-index of the node “n2” to 10 and when you move the nodes “n1” and “n2” inside the node “father3”, you can see that these one is darker than “n1” but still it is behind the “father3” node. How can I bring it to the front?
ready: function(){
window.cy = this;
cy.nodes("[id='n2']").css('z-index', 10);
}
2) http://jsfiddle.net/6tKdD/ In these example I didn’t use the parent attribute because I thought that might be the problem, instead I used normal nodes and I superposed them manually. In this case you can manipulate the z-indexes and they work well, the only problem now is that the edges are drawn behind the nodes so you can’t see them, even if you change their z-index you still can’t see them. If you move either “George” or “Elaine” node outside “Jerry” node, you can see there’s an edge between those two nodes. How can make the edge visible?
ready: function(){
window.cy = this;
cy.nodes("[id='j']").css("z-index", 1);
cy.nodes("[id='g']").css("z-index", 3);
cy.nodes("[id='e']").css("z-index", 3);
cy.edges("[source='g']").css("z-index", 2);
cy.nodes("[id='k']").css("z-index", 0);
}
Thank you very much for your help!
Andreina
Amendment: There are properties for fine-grained control of z-ordering. You can set any order, if you like. The default is as specified in the OP that follows.
Properties:
z-index
z-index-compare
z-compound-depth
Docs: http://js.cytoscape.org/#style/visibility
—
OP:
Like HTML, setting the z-index is not global: It's relative to the parent node. Edges are drawn behind nodes for accessibility reasons. If you want to show the edges, don't put nodes in front of them. Please note that edges between compound nodes are an exception.

Can a node in dynatree have several parents?

Using this http://wwwendt.de/tech/dynatree/
I know the answer is probably no, but I want to verify this: can a node have several parents in this component?
That would mean, that nodes with identical properties (title, icon, and other attributes) appear at different locations in the tree.
This is possible, of course.
The only restriction is: It's not allowed to have two nodes with the same key property in one tree.
I think that the behaviour would be hard to define, if nodes where really 'identical'. For example, when you activate one node that has multiple parents, would you expect all instances to be highlighted? And then, when you press [Cursor-Left]: which parent should be navigated to?
But you could add a new property like myBackendKey whith the same value for all node instances.
Yes, a node in DynaTree can have multiple parents. That is: one identical node can be assigned to more than one parent node in the same tree. I am using jQuery Dynatree Plugin v1.2.2.
I've just now encountered a situation where I've had to deal with duplicate nodes in conjunction with navigating from current node to its next/prev sibling.
Since I had dublicate nodes in the tree, the navigation was broken. When querying the tree for a node with key "abc", dynatree will give you only the first occourance of the node with that key (and not care about the remaining nodes with the same key).
Solution: To prevent this from happening, I've simply prefixed the key for duplicate nodes with a unique string.