There is a way to set the initial position of nodes in a force graph in echarts. But is there a way to have this node stay at this position?
Of course,there is an attribute named fixed decide a node fix or not.So you can set an event listener on echarts.For example,I set a click event listener like:
myChart.on('click', function (params) {
fixNode(params.data);
});
The params.data is the object that you click on echarts.Then you should write a fixNode method like:
function fixNode(currentNode){
_nodes.forEach(function (node) {
if(node.name==currentNode.name) node.fixed = true;
});
refresh();
}
This method is to traverse the node array named _nodes and find the same node as currentNode in _nodes.when we find it,we can set its attribute fixed true.Finally, we have to rebind data to echarts,so we write a method to refresh echarts:
function refresh(){
option={
series:[
{
data:_nodes
}
]
};
mycharts.setOption(option);
}
Now,the node that you click will fixed in a position.
Related
Is there any way to determine whether an event was triggered programmatically or by a user?
We want to reload marker listings when the map moves or zooms, but we are initially setting the bounds of the map with setBounds() (http://leafletjs.com/reference.html#rectangle-setbounds) which is also triggering the moveend (http://leafletjs.com/reference.html#map-moveend) and zoomend (http://leafletjs.com/reference.html#map-zoomend) events which is causing the markers to reload twice.
There seems to be a (undocumented) property on the event object called hard that gets set when the map is moved by setBounds and doesn't get set when the user drags the map or uses the cursors:
map.on('moveend', function (e) {
if (e.hard) {
// moved by bounds
} else {
// moved by drag/keyboard
}
});
Testcase here on Plunker: http://plnkr.co/edit/SloKuB?p=preview
As another option you could bind to event after you've set the bounds so it won't fire when you set the bounds and when you do want to set the bounds afterwards you could first unbind using .off and rebind again after setting with .on. Something like (untested/hacky):
function moveEndHandler () {
....
}
map.on('moveend', moveEndHandler);
function mySetBounds (bounds) {
map.off('moveEnd', moveEndHandler);
map.setBounds(bounds);
map.on('moveend', moveEndHandler);
}
Using Google Earth I have a loaded kml layer that displays polygons of every county in the US. On click a balloon pop's up with some relevant info about the state (name, which state, area, etc) When a user clicks the polygon I want the information to also pop up on a DIV element somewhere else.
This is my code so far.
var ge;
google.load("earth", "1");
function init() {
google.earth.createInstance('map3d', initCB, failureCB);
}
function initCB(instance) {
ge = instance;
ge.getWindow().setVisibility(true);
ge.getNavigationControl().setVisibility(ge.VISIBILITY_AUTO);
ge.getNavigationControl().setStreetViewEnabled(true);
ge.getLayerRoot().enableLayerById(ge.LAYER_ROADS, true);
//here is where im loading the kml file
google.earth.fetchKml(ge, href, function (kmlObject) {
if (kmlObject) {
// show it on Earth
ge.getFeatures().appendChild(kmlObject);
} else {
setTimeout(function () {
alert('Bad or null KML.');
}, 0);
}
});
function recordEvent(event) {
alert("click");
}
// Listen to the mousemove event on the globe.
google.earth.addEventListener(ge.getGlobe(), 'click', recordEvent);
}
function failureCB(errorCode) {}
google.setOnLoadCallback(init);
My problem is that when I change ge.getGlobe() to kmlObject or ge.getFeatures() it doesn't work.
My first question is what should I change ge.getGlobe() to to be able to get a click listener when a user clicks on a kml layer's polygon?
After that I was planning on using getDescription() or getBalloonHtml() to get the polygons balloons information. Am I even on the right track?
...what should I change ge.getGlobe() to...
You don't need to change the event object from GEGlobe. Indeed it is the best option as you can use it to capture all the events and then check the target object in the handler. This means you only have to set up a single event listener in the API.
The other option would be to somehow parse the KML and attach specific event handlers to specific objects. This means you have to create an event listener for each object.
Am I even on the right track?
So, yes you are on the right track. I would keep the generic GEGlobe event listener but extend your recordEvent method to check for the types of KML object you are interested in. You don't show your KML so it is hard to know how you have structured it (are your <Polygon>s nested in <Placemarks> or ` elements for example).
In the simple case if your Polygons are in Placemarks then you could just do the following. Essentially listening for clicks on all objects, then filtering for all Placmark's (either created via the API or loaded in via KML).
function recordEvent(event) {
var target = event.getTarget();
var type = target.getType();
if(type == "KmlPolygon") {
} else if(type == "KmlPlacemark") {
// get the data you want from the target.
var description = target.getDescription();
var balloon = target.getBalloonHtml();
} else if(type == "KmlLineString") {
//etc...
}
};
google.earth.addEventListener(ge.getGlobe(), 'click', recordEvent);
If you wanted to go for the other option you would iterate over the KML Dom once it has loaded and then add events to specific objects. You can do this using something like kmldomwalk.js. Although I wouldn't really recommend this approach here as you will create a large number of event listeners in the api (one for each Placemark in this case). The up side is that the events are attached to each specific object from the kml file, so if you have other Plaemarks, etc, that shouldn't have the same 'click' behaviour then it can be useful.
function placeMarkClick(event) {
var target = event.getTarget();
// get the data you want from the target.
var description = target.getDescription();
var balloon = target.getBalloonHtml();
}
google.earth.fetchKml(ge, href, function (kml) {
if (kml) {
parseKml(kml);
} else {
setTimeout(function () {
alert('Bad or null KML.');
}, 0);
}
});
function parseKml(kml) {
ge.getFeatures().appendChild(kml);
walkKmlDom(kml, function () {
var type = this.getType();
if (type == 'KmlPlacemark') {
// add event listener to `this`
google.earth.addEventListener(this, 'click', placeMarkClick);
}
});
};
Long time since i have worked with this.. but i can try to help you or to give you some tracks...
About your question on "google.earth.addEventListener(ge.getGlobe(), 'click', recordEvent);"
ge.getGlobe can not be replaced with ge.getFeatures() : if you look in the documentation ( https://developers.google.com/earth/documentation/reference/interface_g_e_feature_container-members) for GEFeatureContainer ( which is the output type of getFeatures() , the click Event is not defined!
ge.getGlobe replaced with kmlObject: waht is kmlObject here??
About using getDescription, can you have a look on the getTarget, getCurrentTarget ...
(https://developers.google.com/earth/documentation/reference/interface_kml_event)
As I told you, i haven't work with this since a long time.. so I'm not sure this can help you but at least, it's a first track on which you can look!
Please keep me informed! :-)
I am having difficulties by selecting child nodes when parent is also selected , also would like to open subfolders and select all childs (not sure if im making it clear) so I have know how to get all the child nodes by:
selected_nodes = $("#demo").jstree("get_selected", null, true);
var tree = jQuery.jstree._reference('#demo');
var children = tree._get_children(selected_nodes);
but doest really select or open child folder and nodes
This might not be what OP wanted but on JSTree 3.3. I used this to open all nodes under a selected parent.
$(treeContainer).bind("select_node.jstree", function (e, data) {
return data.instance.open_all(data.node);
});
I gave up on this Idea.. now im just doing ajax requests to load the childs and receive a json object, and from there i can see if its a file or directory, if its a directory again another request and like this i have the whole structure
You have to turn on two_state checkboxes to allow parent and child nodes to be selected indepentently. Below I've configured the "two_state" parameter for the checkbox plugin:
$("#docTree").jstree({
"themes": {
"theme": "classic",
"url": "jstree/themes/classic/style.css"
},
"plugins": ["themes", "ui", "checkbox", "json_data"],
"checkbox": { "two_state" : true }
})
Check documentation here: http://www.jstree.com/documentation/checkbox
If I understand this correctly you want to select all of the lowest descendants in a jsTree (the files) when one of their parents (the folders) have been selected.
Unfortunately I haven't found a more direct approach than the one below. I'm using jsTree 3.1.1 and managed to solve this problem using the following:
var $demo = $("#demo");
var nodes = $demo.jstree("get_top_selected", true);
//Selects all of the children of each selected node including folders
if(nodes.length > 0){
nodes.forEach(function(node, i){
$demo.jstree("select_node", node.children_d, true, false);
});
}
var fileNodes = $demo.jstree("get_bottom_selected", false);
//We now need to deselect everything and only select the file nodes
$demo.jstree("deselect_all", true);
$demo.jstree("select_node", fileNodes, true, false);
The above code allows the user to "select" multiple folders and have those files selected.
The parameter with the value true for the "get_top_selected" function returns the full node instead of just ID's. This lets you get access to the node's children.
Function "select_node" takes three parameters. The first is the nodes to select (in this case the descendants of the current parent node). If the second parameter is set to true it prevents the changed.jstree event from firing for each selected node. The third parameter is set to false as setting to true prevents the children folders from opening.
The function "get_bottom_selected" only returns a node if it has both been selected and it itself does not have any children. As we are now only interested in the node ID's we can pass the parameter false (or omit it completely).
Passing a parameter of true to the function "deselect_all" again prevents the changed.jstree event from firing.
If you want to check out the jsTree API docs you can find them here. That list is filtered to only include the select functions and events. A full list of the API can be found here.
I hope this helps but let me know if you require further clarification on any of the code ^_^
select all child nodes when parent selected ,
$(data.rslt.obj).find("li").each( function( idx, listItem ) {
var child = $(listItem); // child object
$.jstree._reference("#associateRightHandTree").check_node(child);
});
unselect all child nodes when parent unselected ,
$(data.rslt.obj).find("li").each( function( idx, listItem ) {
var child = $(listItem); // child object
$.jstree._reference("#associateRightHandTree").uncheck_node(child);
});
I want to implement the move functionality for a node in jstree. Is it the move that needs to be implemented or the drag and drop? Also, it would be nice to have working code for binding the container to event and the event code.
You only need to use the dnd plugin if you don't need to enforce any move rules(don't allow certain nodes to be moved to other nodes etc)
If you need to enforce move rules, you can add the crrm plugin.
See the Reorder only demo of the dnd pluign documentation for an example of this. The documentation is very poor, so you will have to use the developer tool on your browser to see what the properties of the parameter for the check_move callback are. For the example in the documentation, m.o refers to your dragged node and m.r refers to your destination node.
You will also likely need to be notified when a node is moved, so bind to the move_node.jstree event when you initialize the tree:
$("#treeHost").jstree({
// ...
}).bind("move_node.jstree", function (e, data) {
// data.rslt.o is a list of objects that were moved
// Inspect data using your fav dev tools to see what the properties are
});
$("#demo1").jstree({
....
.bind("move_node.jstree", function (e, data) {
/*
requires crrm plugin
.o - the node being moved
.r - the reference node in the move
.ot - the origin tree instance
.rt - the reference tree instance
.p - the position to move to (may be a string - "last", "first", etc)
.cp - the calculated position to move to (always a number)
.np - the new parent
.oc - the original node (if there was a copy)
.cy - boolen indicating if the move was a copy
.cr - same as np, but if a root node is created this is -1
.op - the former parent
.or - the node that was previously in the position of the moved node */
var nodeType = $(data.rslt.o).attr("rel");
var parentType = $(data.rslt.np).attr("rel");
if (nodeType && parentType) {
// TODO!
}
})
});
The above approaches do not work with the latest versions of jstree (3.3.7 as of today).
The first line of Bojin's answer still holds true. To implement rules, you can use core.check_callback or possibly, the types plugin; the crrm plugin doesn't exist anymore. Bind to move_node.jstree to perform some action on completion of move (drop). By default, the dnd plugin allows re-ordering (dropping between two nodes) and copying (Ctrl + drag), in addition to moving a node. The code snippet below shows how to disable these additional behaviors.
$('#treeElement').jstree({
'core': {
'check_callback': CheckOperation,
...
},
'plugins': ['dnd']
})
.bind("move_node.jstree", function(e, data) {
//data.node was dragged and dropped on data.parent
});
function CheckOperation(operation, node, parent, position, more) {
if (operation == "move_node") {
if (more && more.dnd && more.pos !== "i") { // disallow re-ordering
return false;
}
... more rules if needed ...
else {
return true;
}
}
else if (operation == "copy_node") {
return false;
}
return true;
}
I try to use good lib jstree but i have some strange problem with dblclick binding.
Here is my code
$("#basic_html").jstree({
themes: {
url: "http://mywork/shinframework/shinfw/themes/redmond/css/jstree/default/style.css"
},
"plugins" : ["themes","html_data","ui","crrm","hotkeys", "core"],
});
$("#basic_html").bind("dblclick.jstree", function (e, data) {
alert(e);
alert(data);
});
When this code runs and i make dblclick for some node i can see 2 alerts. The first is object -right, the second is undefined - BUT i want receive data information.
Please, if some specialist solve this problem give me right way for correct use dblclick and receive "data" information about node who is i clicked.
Thanks
I recommend this approach . . .
$("#basic_html li").live("dblclick", function (data) {
//this object is jsTree node that was double clicked
...
});
First, you usually only need to know if the li was clicked so monitoring the event on the li will give you everything you need. Secondly, use live or delegate for the event binding so you can manipulate the tree without breaking the event.
Once you have the node that was double clicked (the this object) you can then use the built-in functions like this . . .
if (!jsAll.is_selected(this)) { return false; } //cancel operation if dbl-clicked node not selected
Where . . .
jsAll = $.jstree._reference("basic_html")
$("#basic_html").bind("dblclick.jstree", function (event) {
var node = $(event.target).closest("li");//that was the node you double click
});
that's the code you want.