//treeview source
function populateTreeView(search) {
debugger;
var tree = $("#tvwResults").kendoTreeView({
dataTextField: [{
text: search.columnName,
items: [{
text: "activemeters"
}]
}],
select: function (e) {
console.log("Selecting ", e.node)
},
animation: {
expand: {
effects: "fadeIn expandVertical",
duration: 600
}
}
}).data("kendoTreeView");
$.getJSON("http://127.0.0.2:6080/arcgis/rest/services/WW/WW2/MapServer/exts/RestSOE/Search%20Query?columnName=" + search.columnName + "&operand=" + search.operand + "&searchVal=" + search.searchVal + "&f=", function (data) {
tree.dataSource.data(data);
});
};
I'm really missing something here. I can see the results in the root node, showing two records, however, the "activemeters" child node isn't showing up. I'm stumbling and thankful for help. Quite a setback hoping to push these results into a pivot grid using KendoUI but the control is non-existent. I just need two columns, first listing the table column names and the second showing the details. SO grateful for your help, learning alot here.
The JSON you showed isn't quite enough to tell how your hierarchy works, since that is just 1 node at 1 level, but the dataTextField that you have defined is incorrect. When it is specified as an array, it is supposed to be an array of strings that tells the treeview what field to use at each level of depth as the display name for the node.
I think you want something like this:
var tree = $("#tvwResults").kendoTreeView({
dataTextField: ["Account Num", "activemeters"],
select: function (e) {
console.log("Selecting ", e.node)
},
animation: {
expand: {
effects: "fadeIn expandVertical",
duration: 600
}
}
}).data("kendoTreeView");
tree.dataSource.data([
{
"Account Num": "210663845",
"Address": "9 COUNTRY RD",
"City": "HAMDENEE",
"Name_1": "ANDREW SMITH",
"Name_2": "",
"Street": "GREEN ST",
"Street Num": "25",
"items": [
{"activemeters": "T30619-00T|30078309"}
]
}
]);
Related
In my survey in SurveyJs, I'm attempting to implement a question with the type 'paneldynamic', which has the following structure:
{
type: "paneldynamic",
name: "9.2",
visible: false,
visibleIf: "{9.a.n} > 0",
title: "When did you give birth?",
enableIf: "{9.a.n} > 0",
requiredIf: "{9.a.n} > 0",
templateTitle: "Date of birth:",
templateElements: [
{
type: "text",
name: "9.2.1",
inputType: "date",
maxValueExpression: "today()",
titleLocation: 'hidden'
},
],
panelCount: "{9.a.n}"
}
where Question 9a is a number entry. I want the number of panels on this question to vary depending on the answer given to Q9a, but with this question structure the survey does not appear to bind the value of 9a to the actual panel count.
I've been unable to find anything in the documentation, and have tried variants such as "bindings: { "panelCount": "9.a.n" } which also don't seem to work.
How can I correctly set the variable panelCount property?
You may wish to create a custom function and calculate the number of panels based on another question answer. For example: https://plnkr.co/edit/iYNMt7JRPOh2dTOy.
Survey.Serializer.addProperty("paneldynamic", {
name: "panelCountExpression:expression",
onExecuteExpression: (obj, res) => {
if(res !== undefined) {
obj.panelCount = res;
}
}
});
var json = {
"pages": [
{
"name": "page1",
"elements": [
{
"type": "text",
"name": "question1",
"inputType":"number",
"min": 0,
"max": 5,
"defaultValue":"2"
},
{
"type": "paneldynamic",
"name": "question2",
"panelCountExpression":"{question1}",
"templateElements": [
{
"type": "text",
"name": "question3"
}]
}
]
}
],
};
I also recommend that you review the following:
Blogpost (the example was taken from it): SurveyJS Library — Calculate Properties and Hide Elements With Expressions and Functions.
Documentation: Conditional Logic and Dynamic Texts.
Thanks
My goal here is to have the childless nodes contain hyperlinks. This is the D3 plugin I'm basing things off of: https://github.com/deltoss/d3-mitch-tree
Image Example
I'm newer to JS and JSON so I'm having difficulties on figuring out how to proceed, especially since there's little to refer to in regard to hyperlinks & JSON. If there's a better way to go about this, I'm certainly open to new ideas.
Thank you in advance
<script src="https://cdn.jsdelivr.net/gh/deltoss/d3-mitch-tree#1.0.2/dist/js/d3-mitch-tree.min.js"></script>
<script>
var data = {
"id": 1,
"name": "Animals",
"type": "Root",
"description": "A living that feeds on organic matter",
"children": [
{
"id": 6,
"name": "Herbivores",
"type": "Type",
"description": "Diet consists solely of plant matter",
"children": [
{
"id": 7,
"name": "Angus Cattle",
"type": "Organism",
"description": "Scottish breed of black cattle",
"children": []
},
{
"id": 8,
"name": "Barb Horse",
"type": "Organism",
"description": "A breed of Northern African horses with high stamina and hardiness. Their generally hot temperament makes it harder to tame.",
"children": []
}
]
}
]
};
var treePlugin = new d3.mitchTree.boxedTree()
.setData(data)
.setElement(document.getElementById("visualisation"))
.setMinScale(0.5)
.setAllowZoom(false)
.setIdAccessor(function(data) {
return data.id;
})
.setChildrenAccessor(function(data) {
return data.children;
})
.setBodyDisplayTextAccessor(function(data) {
return data.description;
})
.setTitleDisplayTextAccessor(function(data) {
return data.name;
})
.initialize();
</script>
Chain this method before .initialize():
.on("nodeClick", function(event, index, arr) {
if (!event.data.children.length) {
console.log('you clicked a child-less item', event.data);
}
})
Inside the condition, event.data is the clicked childless item. Feel free to place URLs inside those objects and use those URLs to navigate away.
Taken from the repo's /examples folder, where I found one named Advanced example with Node Click Event.
According to the comment on the same page, you can also achieve this using the options syntax:
/* const tree = [
place your data here...
]; // */
new d3.mitchTree.boxedTree({
events: {
nodeClick({ data }) {
if (!data.children.length) {
console.log('You clicked a childless item', data);
}
}
}
})
.setData(tree)
// ...rest of chain
.initialize();
So I've generated a JSON file with four tiers and I used D3.js's collapsing boxes format (https://bl.ocks.org/swayvil/b86f8d4941bdfcbfff8f69619cd2f460) to create a visualization.
The problem I am encountering is that because the JSON file is so large, the visualization won't even load into the HTML and even when it does, the boxes in the visualization lag and don't collapse as they should.
Therefore, I want to create a search form using Select2's dropdown box in HTML, so that users can enter a node/tier 1 value and the visualization will appear with only that specific sector shown. Since I am not good with Javascript I am finding quite hard to create such search functionality. I have assigned ID numbers to each value in the JSON but I'm not sure how to approach it further (and if this is even the correct direction to go in).
Below is a sample of my JSON code. So for example, if a user enters Lawyer and McDonald's, I want the visualization show only that node and it's children. I apologize if I'm unclear but any help would be great. Thanks so much!
{
"tree": {
"name": "Top Level",
"children": [
{
"name": "[('Lawyer', 'McDonald's')]",
"children": [
{
"name": "[('Doctor', 'Wendy's')]",
"percentage": "10%",
"duration": 5,
"children": [
{
"name": "[('Nurse', 'NYU')]",
"percentage": "1%",
"duration": 5,
"children": [
{
"name": "[('Pharmacist', 'LIU')]",
"percentage": "4%",
"duration": 5,
"id": "1.1.1.1"
},
{
"name": "[('PA', 'Wagner')]",
"percentage": "4%",
"duration": 5,
"id": "1.1.1.2"
}
],
"id": "1.1.1"
},
{
"name": "[('Surgeon', 'Harvard')]",
"percentage": "1%",
"duration": 3,
"children": [
{
"name": "[('Dentist', 'Buffalo')]",
"percentage": "1%",
"duration": 4,
"id": "1.1.2.1"
}
],
"id": "1.1.2"
}
],
"id": "1.1"
}
],
"id": "1"
},
{
There are a few things to change before you can actually make the D3 visualization work properly. Here are they.
(1) The data structure of the json doesn't match with the D3 code for displaying it. If you'd like to show the json data in the collapsing boxes properly adjust the below part of the code. d here corresponds with your children object and has properties; name, percentage, and duration
.append('xhtml').html(function(d) {
return '<div style="width: '
+ (rectNode.width - rectNode.textMargin * 2) + 'px; height: '
+ (rectNode.height - rectNode.textMargin * 2) + 'px;" class="node-text wordwrap">'
+ '<b>' + d.name + '</b><br><br>'
+ '<b>Percentage: </b>' + d.percentage + '<br>'
+ '<b>Duration: </b>' + d.duration + '<br>'
+ '</div>';
});
(2) Your data doesn't contain the following which is responsible for displaying the arrows properly when collapsing items into a parent box. This might be the case why the animation is not as it should.
"link" : {
"name" : "Link node 1 to 2.3",
"nodeName" : "NODE NAME 2.3",
"direction" : "ASYN"
},
(3) Here's the addition needed to implement the select2 drop-down box with all main branches.
HTML
<select class="js-example-basic-single" name="state">
JavaScript
$(document).ready(function() {
// map over all children in the main json branch
var dropdownData = json.tree.children.map(function(branch, i) {
return {
id: i,
text: branch.name,
}
});
// Add all branches to select2.
$('.js-example-basic-single').select2({
data: dropdownData
});
// Add change event listener. When an option is selected, clear the SVG and run treeBoxes function again.
$('.js-example-basic-single').change(function(e) {
$("#tree-container").empty();
var selectedBranch = e.target.value;
treeBoxes(null, json.tree.children[selectedBranch]);
});
});
Here's a live working example on JSFiddle that still needs some tweaking but it'll help you in the right direction.
NOTE: To make this example work, I've added the json in the html document instead of loading data from a file.
I have JSON data and that JSON data has parent child relation . I Want to create tree structure from it. i found many plugins and libraries but i can't found my requirement . I am getting this JSON data using PHP script.
Here is image that has tree structure that i want to create . i'm stuck at it.I know JSON is not as displayed in image but i only want to show you what a tree should look like .How to create tree like in image.All i want is javascript code to handle and create this type of structure of tree . Working example is must & much appreciated.
You can use JSON format as you like and tree should be collapsible.Also provide required JSON format for it.
and my JSON data as follows :
{
"2":
{
"5": "Wrist Watch"
},
"5":
{
"9": "Men's"
},
"18":
{
"3": "Clothing"
},
"28":
{
"1": "Perfumes"
},
"29":
{
"7": "Laptop",
"10": "Tablets"
},
"30":
{
"8": "Mobile"
},
"31":
{
"2": "Books"
},
"33":
{
"6": "Electronics"
},
"34":
{
"4": "Home & Kitchen\n"
}
}
If you want to roll your own, the keyword in "trees" is recursion. It needs to support any depth of data and the code and data should both support recursion.
This means your JSON data should be a recursive structure, where each node looks the same (and looks something like this):
{
id: 1, // data id
title: "title", // display title
children: [ // list of children, each with this same structure
// list of child nodes
]
}
Note: I have changed the sample data to contain more depth as 2 levels never shows up recursion problems.
e.g.:
{
id: 0,
title: "root - not displayed",
children: [{
id: 1,
title: "Option 1",
children: [{
id: 11,
title: "Option 11",
children: [{
id: 111,
title: "Option 111"
}, {
id: 112,
title: "Option 112"
}]
}, {
id: 12,
title: "Option 12"
}]
}, {
id: 2,
title: "Option 2",
children: [{
id: 21,
title: "Option 21"
}, {
id: 22,
title: "Option 22"
}]
}, {
id: 3,
title: "Option 3",
children: [{
id: 31,
title: "Option 31"
}, {
id: 32,
title: "Option 32"
}]
}]
}
The recursive function looks like this:
function addItem(parentUL, branch) {
for (var key in branch.children) {
var item = branch.children[key];
$item = $('<li>', {
id: "item" + item.id
});
$item.append($('<input>', {
type: "checkbox",
name: "item" + item.id
}));
$item.append($('<label>', {
for: "item" + item.id,
text: item.title
}));
parentUL.append($item);
if (item.children) {
var $ul = $('<ul>').appendTo($item);
addItem($ul, item);
}
}
}
JSFiddle: http://jsfiddle.net/0s0p3716/188/
The code recurses the structure, adding new ULs and LIs (with checkbox etc ) as it goes. The top level call just provides the initial root starting points of both the display and the data.
addItem($('#root'), data);
The end result looks like this:
If you want to toggle visibility, based on the checked state, use this:
$(':checkbox').change(function () {
$(this).closest('li').children('ul').slideToggle();
});
If you also want the labels to toggle the checkboxes, use this:
$('label').click(function(){
$(this).closest('li').find(':checkbox').trigger('click');
});
Note: I have only provided the most basic of styling as that will typically be "to taste". Examples in links were shown in another answer.
-- updated:
amended: possible wrong ids for items 31 & 32?
function for better selection and deselection(for parents cascading into child nodes):
$(function () {
addItem($('#root'), data);
$(':checkbox').click(function () {
$(this).find(':checkbox').trigger('click');
var matchingId = $(this).attr('id');
if ($(this).attr('checked'))
{
$('input[id*=' + matchingId +']').each(function() {
$(this).removeAttr('checked');
$(this).prop('checked', $(this).attr('checked'));
});
}
else {
$('input[id*=' + matchingId +']').each(function() {
$(this).attr('checked', 'checked');
$(this).prop('checked', $(this).attr('checked'));
});
}
});
$('label').click(function(){
$(this).closest('li').children('ul').slideToggle();
});
-- Update the fiddle with this as shown here(JsFiddle) and it will work better and also will allow you to click the text to expand without selecting at the same time - I know I find this far more useful. It will help (and this is personal preference) you to see what values and options are available without having to select the first.
The thing with programming is: existing libraries and tools rarely do exactly what you need. It's always up to you to convert the input data into exactly the format they expect and then the output data into the format you need. Occasionally this conversion requires more effort than writing your own code instead of a library function - this seems to be one of those occasions.
As #philosophocat already noted, the best way to present such a tree in HTML markup would be nested lists. All you need is iterate through the JSON data recursively and create the corresponding elements:
function createList(data)
{
var result = document.createElement("ul");
for (var key in data)
{
if (!data.hasOwnProperty(key) || key == "_title")
continue;
var value = data[key];
var item = createItem(key, typeof value == "string" ? value : value._title);
if (typeof value == "object")
item.appendChild(createList(value));
result.appendChild(item);
}
return result;
}
function createItem(value, title)
{
var result = document.createElement("li");
var checkbox = document.createElement("input");
checkbox.setAttribute("type", "checkbox");
checkbox.setAttribute("name", "selection");
checkbox.setAttribute("value", value);
result.appendChild(checkbox);
result.appendChild(document.createTextNode(title));
return result;
}
document.body.appendChild(createList(jsonData));
Note that the order in which the items appear is "random" here, as object keys are generally unordered. You can change the code above to sort the keys somehow, or you can change the data to use arrays and define an order. I also added a "_title" property to the data to make sure the categories are labeled - your data doesn't have any labels at all for the categories.
Now you need to style the lists in such a way that they look like a tree. The obvious solution is using the list-style-image CSS property to replace the usual bullet points by a grid lines image. However, that doesn't work for nested lists - there you need to show multiple images, vertical lines from the higher-level lists as well as the image actually belonging to the current list item.
This can be solved by using background images for the list items instead, these background images will be shown next to sublists as well then. Here are the example styles I've got:
ul
{
padding: 0;
list-style-type: none;
font-size: 14px;
}
li
{
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAABkCAYAAABdELruAAAAP0lEQVR42u3PQQoAIAgEQP3/o6t7JAhdolkQD4sMZuwZazKKlGXniHRDOu6HfyKRSCQSiUQikUgkEolEIv0rTc/fNmQ78+lPAAAAAElFTkSuQmCC);
background-repeat: no-repeat;
padding-left: 13px;
}
li:last-child
{
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAJCAYAAADpeqZqAAAAHUlEQVR42mNkwAT/gZiRAQ/AK0mKplGbqGETThoACFgJCVdBEqAAAAAASUVORK5CYII=);
}
li > ul
{
margin-left: 5px;
}
Note that this will still get ugly if the sublist is too high - the height of the background image I used is merely 100px. This can be solved by using a larger background image of course. A cleaner alternative would be using border-image-slice CSS property but that one is currently only supported in Firefox.
Fiddle for this code
Edit: This article goes into more detail on styling nested lists like a tree. While the approach is similar, it manages to avoid the image size issues I mentioned above by using a separate image for the vertical line which can be repeated vertically. On the downside, that approach looks like it might only work with solid lines and produce artifacts if applied to dotted lines.
Use http://www.jstree.com/. This library provides each function I ever need when working with trees and javascript.
You simple have to change your json-response according to the given format (http://www.jstree.com/docs/json/):
{
id : "string" // will be autogenerated if omitted
text : "string" // node text
icon : "string" // string for custom
state : {
opened : boolean // is the node open
disabled : boolean // is the node disabled
selected : boolean // is the node selected
},
children : [] // array of strings or objects
li_attr : {} // attributes for the generated LI node
a_attr : {} // attributes for the generated A node
}
Set up the javascript and include all required files and there you go.
I just skip repeating the documentation by referring to it: http://www.jstree.com/
I'm using DynaTree for an internal site at work and it works fantastic.
Download DynaTree
Format your JSON as such (taking your screenshot as an example):
{
"title": "Sports & Outdoors",
"isFolder": true,
"key": "0",
"children": [
{
"title": "Fitness Accessories",
"key": "1",
"isFolder": true,
"children": [
{
"title": "Fitness Accessories",
"key": "2",
"isFolder": true,
"children": [
{
"title": "Pedometer & Watches",
"key": "3"
}
]
}
]
}
]
}
Run this JS on page load:
$("#buildTree").dynatree({
onActivate: function (node) {
// A DynaTreeNode object is passed to the activation handler
// Note: we also get this event, if persistence is on, and the page is reloaded.
leftActiveNodeKey = node.data.key;
},
persist: false,
checkbox: true,
selectMode: 3,
children: $.parseJSON(response.d)
});
To get the selected nodes you can use:
var selectedNodes = $("#buildTree").dynatree("getTree").getSelectedNodes();
Dynatree is pretty customization, both in look and function. Read through the documentation for the settings you need.
Check these sites.Hope this helps.
http://www.jstree.com/docs/json/
http://www.jeasyui.com/documentation/tree.php
http://jqwidgets.com/jquery-widgets-demo/demos/jqxtree/index.htm#demos/jqxtree/checkboxes.htm
#Gone Coding's example is excellent, but the child check boxes will not show as 'uncheked' even though the checked attribute is removed, as rendered in Chrome.
If you add,
$(this).prop('checked', false);
to the code, so it reads as
$(function () {
addItem($('#root'), data);
$(':checkbox').click(function () {
var matchingId = $(this).attr('id');
if ($(this).attr('checked'))
{
$('input[id*=' + matchingId +']').each(function() {
$(this).removeAttr('checked');
$(this).prop('checked', false);
$(this).prop('checked', $(this).attr('checked'));
return;
});
}
else {
$('input[id*=' + matchingId +']').each(function() {
$(this).attr('checked', 'checked');
$(this).prop('checked', $(this).attr('checked'));
});
}
});
$('label').click(function(){
$(this).closest('li').children('ul').slideToggle();
});
});
the child check boxes will fill or clear when the user makes a change.
I'm having a radial graph showing two levels of nodes. On clicking a node it is possible to add a sub graph with calling the sum() function. Everything works fine except setting individual color for the newly added edges.
Does anybody have ever tried to load sub graphs with individual edge colors or have a hint what I'm doing wrong?
Here I'm getting and adding the sub graph:
subtree = getSubtree(node.id);
//perform animation.
subtree.success(function(data){
rg.op.sum(data, {
type: 'fade:seq',
fps: 40,
duration: 1000,
hideLabels: false,
});
});
I've checked also the loaded data but for me it seems to be totally equal. I've also loaded the same data into the initial graph instead of the sub graph and then it was colored correct. Nevertheless here is some test data which is the result of the function getSubtree (the id "placeholder" matches the id of the existing where the sub graph should be added):
{
"id": "placeholder1",
"name": "country",
"children": [{
"id": "2_3mSV~_scat_1",
"name": "hyponym",
"children": [{
"children": [],
"adjacencies": {
"nodeTo": "2_3mSV~_scat_1",
"data": {
"$color": "#29A22D"
}
},
"data": {
"$color": "#29A22D"
},
"id": "3_58z3q_sc_174_6",
"name": "location"
}],
"data": {
"$type": "star",
"$color": "#666666"
},
"adjacencies": [{
"nodeTo": "3_58z3q_sc_174_6",
"data": {
"$color": "#29A22D"
}
}]
}]
}
I finally found the problem in the framework itself...
When calling the construct function inside the call of sum() which is actually adding the subtree then the data object containing information about the adjacence's individual visualization is not used for adding the new adjacence. Therefore I changed the code manually (this for loop is the new version of the existing for loop inside the construct() function):
for(var i=0, ch = json.children; i<ch.length; i++) {
//CUSTOM CODE: GET DATA OF THIS ADJACENCE
data = null;
if(ch[i].adjacencies[0]==undefined){
data = ch[i].adjacencies.data;
}
else{
data = ch[i].adjacencies.data;
}
ans.addAdjacence(json, ch[i], data);
arguments.callee(ans, ch[i]);
//CUSTOM CODE END
}