how to call ajax function to update the Highcharts graph dynamically? - json

I am using Highcharts to plot the graph of temperature vs time. I am having a JSON file wherein data from the backend keep updates the JSON file. I want to call ajax function such that the graphs automatically generates with respect to time. How to do that? I am new to high charts, please help me.

You can use Series.addPoint method.
http://api.highcharts.com/highcharts/Series.addPoint
Here is a example of using Highcharts with live data with GET HTTP requests.
const options = {
chart: {
type: 'spline'
},
title: {
text: 'Live Bitcoin Price'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: 'Price (USD)'
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Live Bitcoint Price [USD]',
data: []
}]
}
const chart = Highcharts.chart('container', options)
// Data
const getData = () => {
setInterval(() => {
window.fetch('https://api.cryptonator.com/api/ticker/btc-usd').then((response) => {
return response.json()
}).then((data) => {
chart.series[0].addPoint({ x: data.timestamp * 1000, y: Number(data.ticker.price) })
})
}, 3000)
}
getData()
#import 'https://code.highcharts.com/css/highcharts.css';
.highcharts-background {
fill: #222;
}
.highcharts-title,
.highcharts-axis-title {
fill: #DDD;
}
.highcharts-credits,
.highcharts-credits:hover {
fill: #222;
}
body {
background-color: #222;
margin 0 !important;
}
#container {
margin: 0;
padding: 0;
border: 0;
background-color: #222;
min-height: 400px;
height:95%;
width:95%;
position:absolute;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>
Live example:
https://jsfiddle.net/xpfkx91w/

Related

CSS Show div, detect if end of screen

I am implementing a customized dropdown becuase of the requirements we have, using Vue 2 and typescript (jquery is not an option).
It is working fine, when you click on the main box, it opens the options list downwards.
An improvement I am looking for is that, when at the end of the screen, the options list adds to the page height and thus causing the scrollbar to appear or increase scroll height.
What I am looking for is that, when popping up the div, if there's not enough space at the bottom of the screen, open it upwards instead. How do I achieve this?
(classes are using bootstrat 5)
Opened dropdown &
Closed dropdown
My code:
import Vue, {
PropType
} from 'vue';
import {
Validation
} from 'vuelidate';
let uidc = 0;
export default Vue.extend({
name: 'BaseDropdown',
props: {
value: {
type: [Number, String, Object],
default: () => ''
as string,
},
target: {
type: String,
default: '',
},
label: {
type: String,
default: '',
},
valueIsNumber: {
type: Boolean,
default: false,
},
options: {
type: Array,
default: null,
},
placeholder: {
type: String,
default: '',
},
required: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
validations: {
type: Object as PropType < Validation > ,
default: () => ({
$error: false,
$touch: () => undefined,
$params: {},
}) as Validation,
},
error: {
type: Boolean,
default: false,
},
trackEvent: {
type: String,
default: '',
},
trackField: {
type: String,
default: '',
},
trackPublic: {
type: Boolean,
default: false,
},
padLeft: {
type: Boolean,
default: false,
},
enforceBlackColour: {
type: Boolean,
default: false,
},
customStyled: {
type: Boolean,
default: false,
},
borderBottomWarning: {
type: Boolean,
default: false,
},
},
data(): {
selectedItem: any | null;
menuOpen: boolean;
searchText: string | null;
} {
return {
selectedItem: null,
menuOpen: false,
searchText: null,
};
},
mounted() {
const appElement = document.getElementById('app_home');
(appElement as any).addEventListener('click', this.handleDropdownClickOutside);
this.$nextTick(() => {
if (this.value) {
if (this.valueIsNumber) {
this.selectedItem = this.options.find((x: any) => x.value === Number(this.value)) || null;
} else {
this.selectedItem = this.options.find((x: any) => x.value.toString().toLowerCase() === this.value.toString().toLowerCase()) || null;
}
}
});
},
computed: {
v(): Validation | {} {
return this.validations;
},
errorMessage(): string {
// Validation must be cast to any to access validators
return Object.entries((this.v as Validation).$params).find(([k]) => !(this.v as any)[k]) ? .[1].message;
},
optgroups(): any {
return this.options.reduce((acc: any, o: any) => ({ ...acc,
[o.optgroup]: [...(acc[o.optgroup] || []), o]
}), {});
},
isRequired(): boolean {
return this.required !== false;
},
getSelectedItemText(): string | null {
return this.selectedItem ? this.selectedItem.text : this.placeholder || 'Please select an item';
},
filteredItems(): any[] {
const list: any[] = [];
for (let c = 0; c < 10; c += 1) {
list.push({
text: c,
value: c
});
}
// return this.searchText && this.searchText.length > 0 ? this.options.filter((x: any) => x.text.toLowerCase().indexOf(this.searchText!.toLowerCase()) > -1) : this.options;
return list;
},
},
methods: {
openMenu() {
this.menuOpen = !this.menuOpen;
if (this.menuOpen) {
this.searchText = null;
}
},
selectItem(item: any) {
this.selectedItem = item;
this.$emit('input', item.value);
this.menuOpen = false;
},
setSuppliedSelectedItem() {
this.$nextTick(() => {
if (this.value) {
this.selectedItem = this.options.find((x: any) => x.value === this.value) || null;
}
});
},
handleDropdownClickOutside(event: any): void {
const parent = document.getElementById(`select-${(this as any).uid}`);
const isParent = parent !== event.target && parent ? .contains(event.target);
if (!isParent) {
this.menuOpen = false;
// this.closeOpenendMenu();
// this.searchText = '';
}
},
},
beforeCreate() {
// eslint-disable-next-line no-plusplus
(this as any).uid = uidc++;
},
});
.dropdown {
font-size: 0.7rem;
img {
// float: right;
// padding-right: 10px;
// padding-top: 5px;
position: absolute;
top: 40%;
right: 10px;
}
.fade {
opacity: 0.5;
}
.search-box {
.form-control {
font-size: 12px !important;
height: 30px !important;
margin: 0 10px 5px 10px !important;
width: 95% !important;
}
}
.selected-item {
border-radius: 3px;
border: 1px solid #ced4da;
padding: 10px;
.selected-item-text {
text-overflow: ellipsis;
overflow: hidden;
width: 93%;
/* height: 1.2em; */
white-space: nowrap;
}
}
.items {
border: 1px solid rgb(236, 236, 236);
width: 100%;
z-index: 15;
max-height: 300px;
overflow-y: auto;
overflow-x: hidden;
background-color: white;
}
.item {
padding: 10px;
background-color: rgb(240, 240, 240);
cursor: pointer;
&:hover {
background-color: rgb(216, 216, 216);
}
}
}
.hidden {
opacity: 0.2;
}
.disabled {
background-color: #e9ecef;
opacity: 1;
pointer-events: none;
}
<template>
<div class="mt-2" :id="`select-${uid}`">
<label v-show="label" class="mb-2 label-grey" :class="{ 'required': isRequired }" :for="`select-${uid}`">{{ label }}</label>
<div class="dropdown noselect position-relative" :class="{'disabled': disabled}">
<div class="selected-item cursor-pointer" #click="openMenu">
<div class="selected-item-text" :class="{'fade': !selectedItem}">{{getSelectedItemText}}</div>
<img v-if="menuOpen" :src="constants.icons.arrowTop" />
<img v-else :src="constants.icons.arrowDown" />
</div>
<div class="items position-absolute" v-show="menuOpen">
<div v-if="filteredItems && filteredItems.length > 5 || searchText" class="search-box">
<input :size="'sm'" v-model="searchText" />
</div>
<div v-for="item in filteredItems" :key="item.value" #click="selectItem(item)">
<div class="item">
{{item.text}}
</div>
</div>
</div>
</div>
<span v-if="v.$error" class="text-error text-xs font-light">{{ errorMessage }}</span>
</div>
</template>
Suggest to use Floating-ui (well known as Poper)
Floating UI is a low-level library for positioning "floating" elements...intelligently keeping them in view
It's been using widely and cover a lot of edge cases you might encounter when try to create dropdown yourself
You can try with references here
creating-vue-component-dropdown-with-popper-js
floating-vue/dropdown

Replace cell's editor of ag-grid with tinymce editor

How can we add tinymce editor in the place of editor present in the cell of ag-grid?
In order to customize ag-grid's cell's you need to create a custom Cell Renderer component.
You can pretty much put anything you want in that custom component, including tinyMCE.
More info: https://www.ag-grid.com/javascript-grid-cell-rendering-components/
Please see Cell Renderer
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script>var __basePath = './';</script>
<style media="only screen">
html, body {
height: 100%;
width: 100%;
margin: 0;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
}
html {
position: absolute;
top: 0;
left: 0;
padding: 0;
overflow: auto;
}
body {
padding: 1rem;
overflow: auto;
}
</style>
<script src="https://unpkg.com/#ag-grid-community/all-modules#24.1.0/dist/ag-grid-community.min.js"></script>
</head>
<body>
<div id="myGrid" style="height: 100%;width: 100%" class="ag-theme-alpine"></div>
<script src="main.js"></script>
</body>
</html>
main.js
var columnDefs = [
{ field: 'athlete' },
{ field: 'country' },
{ field: 'year', width: 100 },
{ field: 'gold', width: 100, cellRenderer: 'medalCellRenderer' },
{ field: 'silver', width: 100, cellRenderer: 'medalCellRenderer' },
{ field: 'bronze', width: 100, cellRenderer: 'medalCellRenderer' },
{ field: 'total', width: 100 }
];
var gridOptions = {
columnDefs: columnDefs,
components: {
'medalCellRenderer': MedalCellRenderer
},
defaultColDef: {
editable: true,
sortable: true,
flex: 1,
minWidth: 100,
filter: true,
resizable: true
}
};
// cell renderer class
function MedalCellRenderer() {
}
// init method gets the details of the cell to be renderer
MedalCellRenderer.prototype.init = function(params) {
this.eGui = document.createElement('span');
var text = '';
// one star for each medal
for (var i = 0; i < params.value; i++) {
text += '#';
}
this.eGui.innerHTML = text;
};
MedalCellRenderer.prototype.getGui = function() {
return this.eGui;
};
// setup the grid after the page has finished loading
document.addEventListener('DOMContentLoaded', function() {
var gridDiv = document.querySelector('#myGrid');
new agGrid.Grid(gridDiv, gridOptions);
agGrid.simpleHttpRequest({ url: 'https://raw.githubusercontent.com/ag-grid/ag-grid/master/grid-packages/ag-grid-docs/src/olympicWinnersSmall.json' })
.then(function(data) {
gridOptions.api.setRowData(data);
});
});

angular ag-grid how to style the header

I am using ag-grid in my angular application and trying to export to excel. I want to style the header row in the excel. Can anyone help me how to achieve this? I tried the below but doesnt seems to be working.
this.excelStyles = [
{
id: 'smallFont',
font: {
fontName:'Calibri',
size: 9
}
},
{
id:'blueBackground',
interior: {
color: 'blue',
pattern: 'solid'
}
}
]
defaultColDef: {
cellClassRules: {
smallFont: (params) => true,
blueBackground: (params) => params.rowIndex == 0
}
}
Thanks
Seting the excelstyle with id 'header' as shown below will set style for the excel headers.
{
id:'header',
interior: {
color: '#002776',
pattern: 'solid'
},
font: {
color: '#ffffff',
fontName: 'Calibri',
size: 9,
bold: true
}
}

Adding a Y Axis to a google stacked column chart

I have been creating column charts using the google chart tool, but am struggling to add a Y axis to my charts. I just need a standard series of values to appear on the axis on the left hand side of the chart.
I am able to create and manipulate the X axis but the Y axis will not appear for some reason. I'm sure there is something simple I am missing here.
Also apologies if the following code is messy, I am pretty new to this.
<head>
<script type = "text/javascript" src = "https://www.gstatic.com/charts/loader.js">
</script>
<script type = "text/javascript">
google.charts.load('current', {packages: ['corechart']});
</script>
<script language = "JavaScript">
function drawChart() {
// Define the chart to be drawn.
var data = google.visualization.arrayToDataTable([
['Year','Orange','Orange2','Blue','Blue2','Green','Green2','Purple','Purple2','Brown','Brown2','Grey', 'Grey2', {role: 'annotation'}],
['2007',0,2,0,0,0,0,0,0,0,0,0,0,''],
['2008',0,0,0,1,0,0,0,0,0,0,1,0,''],
['2009',0,0,0,0,0,0,0,0,0,0,0,0,''],
['2010',0,0,0,1,0,0,1,0,0,0,0,1,''],
['2011',0,0,0,0,0,0,0,0,0,0,0,0,''],
['2012',0,0,0,0,0,0,0,0,1,0,5,0,''],
['2013',0,0,2,0,0,0,0,0,3,0,0,0,''],
['2014',0,0,0,0,0,0,0,0,0,0,0,0,''],
['2015',0,0,0,2,0,0,0,0,1,0,1,0,''],
['2016',0,2,0,0,0,1,0,0,4,0,0,0,''],
['2017',1,0,0,1,0,0,0,2,0,0,0,0,'']
]);
var colors = [
{ color: 'ff884d' },
{ color: 'ffddcc' },
{ color: '3366ff' },
{ color: '99b3ff' },
{ color: '33ff77' },
{ color: 'b3ffcc' },
{ color: 'd633ff' },
{ color: 'f0b3ff' },
{ color: 'e6ccb3' },
{ color: 'ac7339' },
{ color: 'c0c0c0' },
{ color: 'e6e6e6' },
];
var options = {
isStacked:true,
series: colors,
bar: {groupWidth: "90%"},
legend: {position:'top', textStyle: {fontSize: 9}},
chartArea: { width: "100%"},
axes: {
y: {
0: { side: 'left', label: 'Count'}
}}
};
// Instantiate and draw the chart.
var chart = new google.visualization.ColumnChart(document.getElementById('publicbarchart'));
chart.draw(data, options);
}
google.charts.setOnLoadCallback(drawChart);
</script>
</head>
<body>
<div id="publicbarchart" style="width: 900px; height: 300px;"></div>
</body>
Thanks in Advance,
the y-axis is being hidden by chart option --> chartArea: {width: "100%"}
chartArea controls the size of the center section where the bars are,
and does not include the labels on either axis or at the top
use height & width outside of chartArea for the entire chart
if you want to maximize the chart area, then set limits on left, bottom, top, and / or right,
recommend replacing with the following...
height: '100%',
width: '100%',
chartArea: {
top: 32,
left: 32,
bottom: 32,
right: 12,
height: '100%',
width: '100%'
}
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Year','Orange','Orange2','Blue','Blue2','Green','Green2','Purple','Purple2','Brown','Brown2','Grey', 'Grey2', {role: 'annotation'}],
['2007',0,2,0,0,0,0,0,0,0,0,0,0,''],
['2008',0,0,0,1,0,0,0,0,0,0,1,0,''],
['2009',0,0,0,0,0,0,0,0,0,0,0,0,''],
['2010',0,0,0,1,0,0,1,0,0,0,0,1,''],
['2011',0,0,0,0,0,0,0,0,0,0,0,0,''],
['2012',0,0,0,0,0,0,0,0,1,0,5,0,''],
['2013',0,0,2,0,0,0,0,0,3,0,0,0,''],
['2014',0,0,0,0,0,0,0,0,0,0,0,0,''],
['2015',0,0,0,2,0,0,0,0,1,0,1,0,''],
['2016',0,2,0,0,0,1,0,0,4,0,0,0,''],
['2017',1,0,0,1,0,0,0,2,0,0,0,0,'']
]);
var colors = [
{ color: 'ff884d' },
{ color: 'ffddcc' },
{ color: '3366ff' },
{ color: '99b3ff' },
{ color: '33ff77' },
{ color: 'b3ffcc' },
{ color: 'd633ff' },
{ color: 'f0b3ff' },
{ color: 'e6ccb3' },
{ color: 'ac7339' },
{ color: 'c0c0c0' },
{ color: 'e6e6e6' },
];
var options = {
isStacked:true,
series: colors,
bar: {groupWidth: "90%"},
legend: {position:'top', textStyle: {fontSize: 9}},
axes: {
y: {
0: { side: 'left', label: 'Count'}
}
},
height: '100%',
width: '100%',
chartArea: {
top: 32,
left: 32,
bottom: 32,
right: 12,
height: '100%',
width: '100%'
}
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

kendo treeview change datasource on the fly

I have a kendoTreeView connected to OData source as given in the demo on official site. I need to change the dataSource of the kendoTreeView to something else. Here is the html with the script.
When I click on the change button the tree changes but shows all the nodes as undefined. It is not able to show the new dataTextField values. When I revert it back it works even without setting the dataTextField.
I need to either change the dataSource of the tree or destroy the tree, remove it from DOM and then add a new one. Any help or pointers?
<body>
<input type="button" id="expandAllNodes" value="expandAllNodes" />
<input type="button" id="changedatasource" value="changedatasource" />
<input type="button" id="revert" value="revert" />
<span>First Tree</span>
<div id="treeview"></div>
<br/>
<span>Second Tree</span>
<div id="treeview2"></div>
<!--<div id="example" class="k-content">
<div id="treeview" class="demo-section"></div>-->
<script>
</script>
<style scoped>
#example {
text-align: center;
}
.demo-section {
display: inline-block;
vertical-align: top;
width: 320px;
height: 300px;
text-align: left;
margin: 0 2em;
}
</style>
<!--</div>-->
</body>
$(document).ready(function () {
// TreeView bound to Categories > Products > OrderDetails
var viewModel = {
self: this,
OrderDetails: {
type: "odata",
transport: {
read: {
url: function (options) {
return kendo.format("http://demos.telerik.com/kendo-ui/service/Northwind.svc/Products({0})/Order_Details", options.ProductID);
}
}
},
schema: {
model: {
hasChildren: function () {
return false;
}
}
}
},
Products: new kendo.data.HierarchicalDataSource({
type: "odata",
transport: {
read: {
url: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Products"
}
},
schema: {
model: {
id: "ProductID",
hasChildren: "Order_Details",
children: {
type: "odata",
transport: {
read: {
url: function (options) {
return kendo.format("http://demos.telerik.com/kendo-ui/service/Northwind.svc/Products({0})/Order_Details", options.ProductID);
}
}
},
schema: {
model: {
hasChildren: function () {
return false;
}
}
}
}
}
}
}),
Categories: new kendo.data.HierarchicalDataSource({
type: "odata",
transport: {
read: {
url: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Categories"
}
},
schema: {
model: {
hasChildren: "Products",
id: "CategoryID",
children: {
type: "odata",
schema: {
model: {
id: "ProductID",
hasChildren: "Order_Details",
children: {
type: "odata",
transport: {
read: {
url: function (options) {
return kendo.format("http://demos.telerik.com/kendo-ui/service/Northwind.svc/Products({0})/Order_Details", options.ProductID);
}
}
},
schema: {
model: {
hasChildren: function () {
return false;
}
}
}
}
}
},
transport: {
read: {
url: function (options) {
return kendo.format("http://demos.telerik.com/kendo-ui/service/Northwind.svc/Categories({0})/Products", options.CategoryID);
}
}
}
}
}
}
})
}
$("#treeview").kendoTreeView({
dataSource: viewModel.Categories,
dataTextField: ["CategoryName", "ProductName", "OrderID"],
checkboxes: {
checkChildren: true
}
});
$("#treeview2").kendoTreeView({
dataSource: viewModel.Products,
dataTextField: ["ProductName", "OrderID"],
checkboxes: {
checkChildren: true
}
});
ko.applyBindings(viewModel);
$("#expandAllNodes").click(function () {
var treeView = $("#kendoTreeView").data("kendoTreeView");
treeView.expand(".k-item");
});
$("#changedatasource").click(function () {
var treeview: kendo.ui.TreeView = $("#treeview").data("kendoTreeView");
//treeview.destroy();
treeview.setOptions({ dataTextField: ["ProductName", "OrderID"] });
treeview.setDataSource(viewModel.Products);
});
$("#revert").click(function () {
var treeview: kendo.ui.TreeView = $("#treeview").data("kendoTreeView");
//treeview.setOptions({ dataTextField: ["CategoryName", "ProductName", "OrderID"] });
treeview.setDataSource(viewModel.Categories);
});
});
Set the datasource to a new instance of a HierarchicalDataSource, see here: http://d585tldpucybw.cloudfront.net/forums/datasource-property-update-and-refresh. Direct link to Dojo by Alex Gyoshev: http://dojo.telerik.com/#gyoshev/iJIhI.