Does anyone know which is the most optimal free JS library for a dynamic organisational chart where you can add and delete nodes like this:
please check below html code
<!DOCTYPE html>
<html>
<link rel="stylesheet" href="https://fperucic.github.io/treant-js/Treant.css">
<script src="https://fperucic.github.io/treant-js/vendor/raphael.js"></script>
<script src="https://fperucic.github.io/treant-js/Treant.js"></script>
<script>
var simple_chart_config = {
chart: {
container: "#OrganiseChart-simple"
},
nodeStructure: {
text: { name: "Parent node" },
children: [
{
text: { name: "First child" }
},
{
text: { name: "Second child" }
}
]
}
};
var config = {
container: "#OrganiseChart-simple"
};
var parent_node = {
text: { name: "Parent node" }
};
var first_child = {
parent: parent_node,
text: { name: "First child" }
};
var second_child = {
parent: parent_node,
text: { name: "Second child" }
};
var simple_chart_config = [
config, parent_node,
first_child, second_child
];
</script>
<style>
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td { margin:0; padding:0; }
body { background: #fff; }
/* optional Container STYLES */
.chart { height: 159px; width: 332px; margin: 5px; margin: 5px auto; border: 3px solid #DDD; border-radius: 3px; }
.node { color: #9CB5ED; border: 2px solid #C8C8C8; border-radius: 3px; }
.node p { font-size: 20px; line-height: 20px; height: 20px; font-weight: bold; padding: 3px; margin: 0; }
</style>
<body>
<div class="chart" id="OrganiseChart-simple">
</body>
<script>
new Treant( simple_chart_config );
</script>
</html>
Reference URL : https://fperucic.github.io/treant-js/
you could try OrgChart
It is opensource and you can checkout a live demo
Related
trying to replace customer js with
export default[
{ id: 0, name: 'some one', title: 'zero' },
{ id: 1, name: 'test last', title:'one'},
{ id: 2, name: 'test first', title:'two'},
{ id: 3, name: 'test second', title:'three'},
{ id: 4, name: 'test third', title:'four'},
{ id: 5, name: 'test fourth', title:'five'},
{ id: 6, name: 'test fifth', title:'six'}
];
My app is fine while using the above raw json.
since i am trying to get the date using axios in same file as per below code
Something i am missing to get the data into app.
import axios from 'axios';
export default {
data () {
return {
info: []
}
},
mounted () {
axios
.get('http://localhost/json/test.json')
.then(response => (this.info = response))
}
}
for getting data from url into customer.js
not working in case.
while my app.vue is
<template>
<div id="app">
<Autocomplete :items="customers"
filterby="name"
#change="onChange"
title="Look for a customer"
#selected="customerSelected"/>
</div>
</template>
<script>
import customers from './assets/customers';
import Autocomplete from './components/Autocomplete'
export default {
name: 'App',
mounted() {
this.customers = customers;
},
data() {
return {
customers: []
};
},
methods: {
customerSelected(customer) {
console.log(`Customer Selected:\nid: ${customer.id}\nname: ${customer.name}\ntitle:${customer.title}`);
},
onChange(value) {
// do something with the current value
}
},
components: {
Autocomplete
}
}
</script>
<style>
#app {
margin: 0px auto;
margin-top: 60px;
width: 400px;
}
</style>
and Autocomplete.vue is
<template>
<div class="autocomplete">
<div class="input" #click="toggleVisible" v-text="selectedItem ? selectedItem[filterby] : ''"></div>
<div class="placeholder" v-if="selectedItem == null" v-text="title"></div>
<button class="close" #click="selectedItem = null" v-if="selectedItem">x</button>
<div class="popover" v-show="visible">
<input type="text"
ref="input"
v-model="query"
#keydown.up="up"
#keydown.down="down"
#keydown.enter="selectItem"
placeholder="Start Typing...">
<div class="options" ref="optionsList">
<ul>
<li v-for="(match, index) in matches"
:key="index"
:class="{ 'selected': (selected == index)}"
#click="itemClicked(index)"
v-text="match[filterby]"></li>
</ul>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
items: {
default: [],
type: Array
},
filterby: {
type: String
},
title: {
default: 'Select One...',
type: String
},
shouldReset: {
type: Boolean,
default: true
}
},
data() {
return {
itemHeight: 39,
selectedItem: null,
selected: 0,
query: '',
visible: false
};
},
methods: {
toggleVisible() {
this.visible = !this.visible;
setTimeout(() => {
this.$refs.input.focus();
}, 50);
},
itemClicked(index) {
this.selected = index;
this.selectItem();
},
selectItem() {
if (!this.matches.length) {
return;
}
this.selectedItem = this.matches[this.selected];
this.visible = false;
if (this.shouldReset) {
this.query = '';
this.selected = 0;
}
this.$emit('selected', JSON.parse(JSON.stringify(this.selectedItem)));
},
up() {
if (this.selected == 0) {
return;
}
this.selected -= 1;
this.scrollToItem();
},
down() {
if (this.selected >= this.matches.length - 1) {
return;
}
this.selected += 1;
this.scrollToItem();
},
scrollToItem() {
this.$refs.optionsList.scrollTop = this.selected * this.itemHeight;
}
},
computed: {
matches() {
this.$emit('change', this.query);
if (this.query == '') {
return [];
}
return this.items.filter((item) => item[this.filterby].toLowerCase().includes(this.query.toLowerCase()))
}
}
}
</script>
<style scoped>
.autocomplete {
width: 100%;
position: relative;
}
.input {
height: 40px;
border-radius: 3px;
border: 2px solid lightgray;
box-shadow: 0 0 10px #eceaea;
font-size: 25px;
padding-left: 10px;
padding-top: 10px;
cursor: text;
}
.close {
position: absolute;
right: 2px;
top: 4px;
background: none;
border: none;
font-size: 30px;
color: lightgrey;
cursor: pointer;
}
.placeholder {
position: absolute;
top: 11px;
left: 11px;
font-size: 25px;
color: #d0d0d0;
pointer-events: none;
}
.popover {
min-height: 50px;
border: 2px solid lightgray;
position: absolute;
top: 46px;
left: 0;
right: 0;
background: #fff;
border-radius: 3px;
text-align: center;
}
.popover input {
width: 95%;
margin-top: 5px;
height: 40px;
font-size: 16px;
border-radius: 3px;
border: 1px solid lightgray;
padding-left: 8px;
}
.options {
max-height: 150px;
overflow-y: scroll;
margin-top: 5px;
}
.options ul {
list-style-type: none;
text-align: left;
padding-left: 0;
}
.options ul li {
border-bottom: 1px solid lightgray;
padding: 10px;
cursor: pointer;
background: #f1f1f1;
}
.options ul li:first-child {
border-top: 2px solid #d6d6d6;
}
.options ul li:not(.selected):hover {
background: #8c8c8c;
color: #fff;
}
.options ul li.selected {
background: orange;
color: #fff;
font-weight: 600;
}
</style>
In most of the cases, response consists of several properties and you will need response.data.
if this didn't work then print the response, using console.log(response) and inspect it such that which key holds the JSON data.
I took an example of Paged grid from jsfiddle.net ( http://jsfiddle.net/rniemeyer/QSRBR/ ) and put it into one *.html file
But it does not work - I got an error in the browser console:
Uncaught TypeError: Cannot read property 'viewModel' of undefined
at new PagedGridModel (knockout pagination.html:72)
at knockout pagination.html:83
Here is the html file content:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<style>
body { font-family: arial; font-size: 14px; }
.liveExample { padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 655px; }
.liveExample input { font-family: Arial; }
.liveExample b { font-weight: bold; }
.liveExample p { margin-top: 0.9em; margin-bottom: 0.9em; }
.liveExample select[multiple] { width: 100%; height: 8em; }
.liveExample h2 { margin-top: 0.4em; }
.ko-grid { margin-bottom: 1em; width: 25em; border: 1px solid silver; background-color:White; }
.ko-grid th { text-align:left; background-color: Black; color:White; }
.ko-grid td, th { padding: 0.4em; }
.ko-grid tr:nth-child(odd) { background-color: #DDD; }
.ko-grid-pageLinks { margin-bottom: 1em; }
.ko-grid-pageLinks a { padding: 0.5em; }
.ko-grid-pageLinks a.selected { background-color: Black; color: White; }
.liveExample { height:20em; overflow:auto } /* Mobile Safari reflows pages slowly, so fix the height to avoid the need for reflows */
li { list-style-type: disc; margin-left: 20px; }
</style>
</head>
<body>
<div class='liveExample'>
<div data-bind='simpleGrid: gridViewModel'> </div>
<button data-bind='click: addItem'>
Add item
</button>
<button data-bind='click: sortByName'>
Sort by name
</button>
<button data-bind='click: jumpToFirstPage, enable: gridViewModel.currentPageIndex'>
Jump to first page
</button>
</div>
<script type="text/javascript">
var initialData = [
{ name: "Well-Travelled Kitten", sales: 352, price: 75.95 },
{ name: "Speedy Coyote", sales: 89, price: 190.00 },
{ name: "Furious Lizard", sales: 152, price: 25.00 },
{ name: "Indifferent Monkey", sales: 1, price: 99.95 },
{ name: "Brooding Dragon", sales: 0, price: 6350 },
{ name: "Ingenious Tadpole", sales: 39450, price: 0.35 },
{ name: "Optimistic Snail", sales: 420, price: 1.50 }
];
var PagedGridModel = function(items) {
this.items = ko.observableArray(items);
this.addItem = function() {
this.items.push({ name: "New item", sales: 0, price: 100 });
};
this.sortByName = function() {
this.items.sort(function(a, b) {
return a.name < b.name ? -1 : 1;
});
};
this.jumpToFirstPage = function() {
this.gridViewModel.currentPageIndex(0);
};
this.gridViewModel = new ko.simpleGrid.viewModel({
data: this.items,
columns: [
{ headerText: "Item Name", rowText: "name" },
{ headerText: "Sales Count", rowText: "sales" },
{ headerText: "Price", rowText: function (item) { return "$" + item.price.toFixed(2) } }
],
pageSize: 4
});
};
ko.applyBindings(new PagedGridModel(initialData));
</script>
</body>
</html>
This code works fine at jsfiddle but why doesn't it work when I put it all together an a single file?
So, this is a model of tree diagram. Click run on jsfiddel to see it (no right to more than 2 links)
And it is perfect, but my real diagram will be bigger, so I wrote a function that toggle the title and description on click, so I could have the information on something only if it interests me. My problem is that the links won't update too.
when hided
My code is looking like
Jsfiddle link
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equi="X-UA-Compatible" content="IE=edge, chrome=1">
<meta name="viewport" content="width=device-width">
<title>My Try</title>
<link rel="stylesheet" href="../treant-js-master/Treant.css">
<link rel="stylesheet" href="myTry.css">
</head>
<body>
<div class="chart Treant loaded" id="myTry"></div>
<script src="../treant-js-master/vendor/raphael.js"></script>
<script src="../treant-js-master/Treant.js"></script>
<script src="../treant-js-master/vendor/jquery.min.js"></script>
<script src="myTry.js"></script>
<script>
new Treant( chart_config );
</script>
<script>
$(".node1").click(function(e){
if (e.target.classList.value !== "collapse-switch"){
$(this).children(".node-title").toggle();
$(this).children(".node-desc").toggle();
}
})
</script>
</body>
</html>
Javascript
var config = {
container: "#myTry",
levelSeparation: 45,
rootOrientation: "WEST",
siblingSeparation: 10,
connectors: {
type: "curve",
style: {
fill: "#e6b8ff"
}
},
node: {
HTMLclass: 'node1',
collapsable: true,
collapsed: true
}
},
group = {
text: {
name: "Group",
title: "Group",
desc: "complicated group"
}
},
group1 = {
parent: group,
text: {
name: "Grou",
title: "Grou",
desc: "complicated grou"
}
},
group2 = {
parent: group,
text: {
name: "Gro",
title: "Gro",
desc: "complicated gro"
}
},
group11 = {
parent: group1,
text: {
name: "Gr",
title: "Gr",
desc: "complicated gr"
}
},
group12 = {
parent: group1,
text: {
name: "G",
title: "G",
desc: "complicated g"
}
},
chart_config = [
config,
group,
group1,
group2,
group11,
group12
];
CSS
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td
{ margin:0; padding:0; }
table { border-collapse:collapse; border-spacing:0; }
fieldset,img { border:0; }
address,caption,cite,code,dfn,em,strong,th,var { font-style:normal; font-weight:normal; }
caption,th { text-align:left; }
h1,h2,h3,h4,h5,h6 { font-size:100%; font-weight:normal; }
q:before,q:after { content:''; }
abbr,acronym { border:0; }
body { background: #fff; }
/* optional Container STYLES */
.chart { height: 600px; margin: 5px; width: 900px; }
.Treant > .node { }
.Treant > p { font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; font-weight: bold; font-size: 12px; }
.node-name { font-weight: bold;}
.node1 {
padding: 2px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
background-color: #ffe4e1;
border: 3px solid #ffc0cb;
width: 200px;
font-family: Arial;
font-size: 14px;
}
.collapse-switch {
width: 16px !important;
height: 16px !important;
}
I am using ag-grid for Angular 2. In that i have multiple headers like token number. It is not displaying completely. It is just like Token N...
Below is my component.ts
import { Component, OnInit } from '#angular/core';
import{ GridOptions } from 'ag-grid';
import { FlightProcessGridStatusComponent } from '../flight-process-grid-status/flight-process-grid-status.component';
import { FetchedFlightInfoBean } from '../../_model/FetchedFlightInfoBean';
#Component({
selector: 'app-user-home-child',
templateUrl: './user-home-child.component.html',
styleUrls: ['./user-home-child.component.css'],
//providers: [FetchedFlightInfoBean]
})
export class UserHomeChildComponent {
private gridOptions: GridOptions;
private refreshFlag: boolean;
fetchedFltBean: FetchedFlightInfoBean [] = [
{tokenNbr:1, flightNbr:"AY01", flightDate: "12-aug-17", flightBrPoint:"DEL", flightoffPoint:"LKO", nbrPax:2, okEmail:"Y", nonOkEmail:"N", okphn:"Y", nonOkPhn:"N", status:"WAIT"},
{tokenNbr:2, flightNbr:"AY02", flightDate: "6-aug-17", flightBrPoint:"BAN", flightoffPoint:"MUM", nbrPax:4, okEmail:"N", nonOkEmail:"Y", okphn:"Y", nonOkPhn:"N", status:"MISSED-CONNECTION"},
{tokenNbr:3, flightNbr:"AY013", flightDate: "22-aug-17", flightBrPoint:"HEL", flightoffPoint:"PAR", nbrPax:1, okEmail:"N", nonOkEmail:"Y", okphn:"Y", nonOkPhn:"N", status:"FLOWN"}
];
constructor() {
this.gridOptions = <GridOptions>{headerHeight: 48,
rowHeight: 35,
rowSelection: 'single',
enableColResize: true,
onGridReady: (params) => {
params.api.sizeColumnsToFit();
}
};
this.gridOptions.columnDefs = [
{headerName: 'Token Number', field: 'tokenNbr'},
{headerName: "Flight Number", field: "flightNbr"},
{headerName: "Flight Date", field: "flightDate"},
{headerName: "Flight Boarding Point", field: "flightBrPoint"},
{headerName: "Flight Off Point", field: "flightoffPoint"},
{headerName: "NBR of Pax", field: "nbrPax"},
{headerName: "Ok Email", field: "okEmail"},
{headerName: "NonOk Email", field: "nonOkEmail"},
{headerName: "Ok Phone", field: "okphn"},
{headerName: "NonOk Phone", field: "nonOkPhn"},
{
headerName: "Status",
field: "status",
cellRendererFramework: FlightProcessGridStatusComponent,
}
];
this.gridOptions.rowData = this.createRowData();
}
public refreshRowData()
{
this.refreshFlag = true;
alert(`inside refreshRowData`);
let rowData = this.createRowData();
this.gridOptions.api.setRowData(rowData);
}
private createRowData() {
if(this.refreshFlag)
{
alert(`refresh call`);
}
let rowData:FetchedFlightInfoBean[] = this.fetchedFltBean;
/* let rowDataLength = rowData.length;
alert(`${rowDataLength}`)
for (var i = 0; i < rowDataLength; i++) {
rowData.push({
tokenNbr: 1,
flightNbr: "",
flightDate: "",
flightBrPoint: "",
flightoffPoint: "",
nbrPax: 3,
okEmail: "",
nonOkEmail: "",
okphn: "",
nonOkPhn: "",
status: "",
});
}
*/
return rowData;
}
}
next is my html part....
<div style="width: 800px; padding-left: 100px" class="ag-fresh ag-header-cell-label">
<button (click)="refreshRowData()">Refresh Data</button>
<button (click)="autoFit()">AutoFit</button>
<ag-grid-angular style="width: 1000px; height: 1000px;"
[gridOptions]="gridOptions"
enableSorting
enableFilter >
</ag-grid-angular>
</div>
my CSS-
#import url("https://fonts.googleapis.com/css?family=Raleway:400,700");
.ag-fresh {
font-family: "Raleway", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
}
.ag-fresh .ag-root {
border: none;
}
.ag-fresh .ag-header-container {
background: #fff;
}
.ag-fresh .ag-header {
border-bottom: 2px solid #000;
}
.ag-fresh .ag-header-row {
font-weight: bold;
font-size: 13px;
line-height: 1em;
color: #000;
background: #fff;
border: none;
}
.ag-fresh .ag-ltr .ag-header-cell {
padding: 10px;
border: none
}
.ag-fresh .ag-row {
border-bottom: 1px solid #ddd;
}
.ag-fresh .ag-row:nth-child(odd){
border-top: 1px solid #ddd;
background-color: #f9f9f9;
}
.ag-fresh .ag-row:last-child {
border-bottom: none;
}
.ag-fresh .ag-row:hover {
background-color: #d9edf7;
border-top: 1px solid #aaa;
border-color: #aaa;
}
.ag-fresh .ag-row .ag-cell {
color: #333;
padding: 10px 15px;
}
.ag-fresh .ag-row .ag-cell:focus,
.ag-fresh .ag-row .ag-cell:hover {
font-weight: bold;
background-color: #d0edf3 ;
color:#000;
}
.ag-header-cell-label {
text-overflow: clip;
overflow: visible;
white-space: normal;
}
In my component you can see I have fixed the size of the column using params.api.sizeColumnsToFit(). This allow my columns to display without a horizontal scroll bar. So i am getting complete data in one view.
But now my column-headers are not wraaping up there name. I am not getting the complete name displayed.
For example, If the column-header is Token Number then only "token n..." this part is displayed.
Please help.
I am newbe in knowkout js and i am trying Paged grid example of knowkout from
http://knockoutjs.com/examples/gridEditor.html
Here is my code :
Its giving error TypeError: ko.simpleGrid is undefined
Please help me in this thanx in adv.
<html>
<head>
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" type="text/javascript"></script>
<script src='http://knockoutjs.com/examples/resources/knockout.simpleGrid.js'></script>
<script src="http://knockoutjs.com/downloads/knockout-3.0.0.debug.js" type="text/javascript"></script>
<script>
var initialData = [
{name: "Well-Travelled Kitten", sales: 352, price: 75.95},
{name: "Speedy Coyote", sales: 89, price: 190.00},
{name: "Furious Lizard", sales: 152, price: 25.00},
{name: "Indifferent Monkey", sales: 1, price: 99.95},
{name: "Brooding Dragon", sales: 0, price: 6350},
{name: "Ingenious Tadpole", sales: 39450, price: 0.35},
{name: "Optimistic Snail", sales: 420, price: 1.50}
];
var PagedGridModel = function (items) {
this.items = ko.observableArray(items);
this.addItem = function () {
this.items.push({name: "New item", sales: 0, price: 100});
};
this.sortByName = function () {
this.items.sort(function (a, b) {
return a.name < b.name ? -1 : 1;
});
};
this.jumpToFirstPage = function () {
this.gridViewModel.currentPageIndex(0);
};
this.gridViewModel = new ko.simpleGrid.viewModel({
data: this.items,
columns: [
{headerText: "Item Name", rowText: "name"},
{headerText: "Sales Count", rowText: "sales"},
{headerText: "Price", rowText: function (item) {
return "$" + item.price.toFixed(2)
}}
],
pageSize: 4
});
};
ko.applyBindings(new PagedGridModel(initialData));
</script>
<style>
body { font-family: arial; font-size: 14px; }
.liveExample { padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 655px; }
.liveExample input { font-family: Arial; }
.liveExample b { font-weight: bold; }
.liveExample p { margin-top: 0.9em; margin-bottom: 0.9em; }
.liveExample select[multiple] { width: 100%; height: 8em; }
.liveExample h2 { margin-top: 0.4em; }
.ko-grid { margin-bottom: 1em; width: 25em; border: 1px solid silver; background-color:White; }
.ko-grid th { text-align:left; background-color: Black; color:White; }
.ko-grid td, th { padding: 0.4em; }
.ko-grid tr:nth-child(odd) { background-color: #DDD; }
.ko-grid-pageLinks { margin-bottom: 1em; }
.ko-grid-pageLinks a { padding: 0.5em; }
.ko-grid-pageLinks a.selected { background-color: Black; color: White; }
.liveExample { height:20em; overflow:auto } /* Mobile Safari reflows pages slowly, so fix the height to avoid the need for reflows */
li { list-style-type: disc; margin-left: 20px; }
</style>
</head>
<body>
<div data-bind='simpleGrid: gridViewModel'> </div>
<button data-bind='click: addItem'>
Add item
</button>
<button data-bind='click: sortByName'>
Sort by name
</button>
<button data-bind='click: jumpToFirstPage, enable: gridViewModel.currentPageIndex'>
Jump to first page
</button>
</body>
</html>