Updating highcharts dynamically with json response - angularjs

I am trying to draw highcharts with the json response, however I can able to draw for the first time, but unable to update the series with new data
function get_chart(data) {
//alert('hello..' + data);
return {
xAxis: {
type: 'datetime',
labels: {
formatter: function() {
var monthStr = Highcharts.dateFormat('%b', this.value);
var firstLetter = monthStr.substring(0, 1);
return firstLetter;
}
}
},
title: {
text: data.measurementName
},
chart: {
height: 300,
width: 500,
type: 'column',
zoomType: 'x'
},
credits: {
enabled: false
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function() {
console.log ('Category: '+ this.category +', value: '+ this.y);
}
}
}
}
},
series: [{
name: 'Hours',
data: (function() {
var chart = [{key:data.measurementName, values:[]}];
var i = 0;
if(typeof(data) == 'string')return chart;
for(n in data.values){
data.values[n].snapshot = new Date(data.values[n].snapshot);
data.values[n].value = parseInt(data.values[n].value);
}
chart[0].values = data.values.map(function(arrayObj){
return [arrayObj.value]
});
return chart[0].values;
})()
}]
};
}
and I am calling this function like
$scope.renderChart = function(measurement){
$scope.showChart = false;
restApp.getMeasurementForCompID(comp.id, measurement.id).then(function(data){
console.log(data);
$scope.example_chart = get_chart(data);
console.log($scope.example_chart);
$scope.showChart = true;
});
}
Here getMeasurementForCompID is another function which gets the data from database.
What is the problem here? any help..

I used https://github.com/pablojim/highcharts-ng
I just alter the data object and the highcharts reflects the change.

Related

Date range picker for extjs?

Is there a good date-range picker for ExtJs?
Something like this: http://www.daterangepicker.com/?
I whipped this up in about 2 hours, so I'm sure there are some lingering bugs and things left to be desired, but it at least gets you started with a custom date range component. Here's my Fiddle. And the code:
Ext.define('DatePickerEnhanced', {
extend: 'Ext.picker.Date',
alias: 'widget.datePickerEnhanced',
config: {
startDate: null,
endDate: null
},
isDateRange: true,
isDragging: false,
initComponent: function () {
this.callParent()
this.on({
mouseover: {
element: 'el',
fn: 'onMouseOverEnhanced',
delegate: 'td.x-datepicker-cell',
scope: this
}
});
},
handleDateClick: function (e, t) {
this.callParent(arguments)
if (this.isDateRange) {
if (this.isDragging) {
this.isDragging = false;
var startCell = this.getCellByValue(this.startCell)
if (startCell) {
Ext.get(startCell).addCls(this.selectedCls)
}
this.setEndDate(new Date(this.getCellDateValue(this.activeCell)))
this.updateDateRange(this.startCell, this.endCell);
} else {
this.setStartDate(new Date(this.getCellDateValue(this.activeCell)))
this.isDragging = true;
this.updateDateRange(this.getCellDateValue(), -1);
}
}
},
getCellByValue: function (value) {
var cells = this.cells.elements;
for (var i = 0; i < cells.length; i++) {
var cell = cells[i]
if (cell.firstChild.dateValue === value) {
return cell;
}
}
},
onMouseOverEnhanced: function (e, target, eOpts) {
if (this.isDragging) {
this.updateDateRange(this.getCellDateValue(), this.getCellDateValue(target));
}
},
updateDateRange: function (startValue, endValue) {
var cells = this.cells.elements;
var selectedCls = this.selectedCls;
for (var i = 0; i < cells.length; i++) {
var cell = Ext.fly(cells[i])
var dateValue = this.getCellDateValue(cells[i]);
if (dateValue !== startValue && (dateValue < startValue || dateValue > endValue)) {
cell.removeCls(selectedCls)
} else {
cell.addCls(selectedCls)
}
}
},
getCellDateValue: function (cell) {
return cell && cell.firstChild.dateValue || this.startCell;
},
getDateRange: function () {
return {
start: this.getStartDate(),
end: this.getEndDate()
}
},
/**
* Update the contents of the picker for a new month
* #private
* #param {Date} date The new date
*/
fullUpdate: function (date) {
var me = this;
me.callParent(arguments);
Ext.asap(function () {
if (me.isDateRange && me.endCell) {
me.updateDateRange(me.startCell, me.endCell)
}
})
},
updateStartDate: function (value) {
this.startCell = value.getTime()
this.publishState('startDate', value);
},
updateEndDate: function (value) {
this.endCell = value.getTime()
this.publishState('endDate', value);
}
});
Ext.create('Ext.container.Viewport', {
viewModel: {
data: {
theStart: Ext.Date.add(new Date(), Ext.Date.DAY, 2),
theEnd: Ext.Date.add(new Date(), Ext.Date.DAY, 5)
}
},
items: [{
xtype: 'datePickerEnhanced',
minDate: new Date(),
bind: {
startDate: '{theStart}',
endDate: '{theEnd}'
}
}, {
xtype: 'displayfield',
fieldLabel: 'Start',
bind: {
value: '{theStart:date("m/d/Y")}'
}
}, {
xtype: 'displayfield',
fieldLabel: 'End',
bind: {
value: '{theEnd:date("m/d/Y")}'
}
}]
});

ExtJS5: Custom component(ticker) increasing CPU cycles 10 times

I am using a ticker component in my application. When the text is rolling, the CPU cycles hit 10+. As soon as I hover cursor over it, the scrolling stops and the CPU cycles comes down to 0
Can someone tell if this is normal? If not, how can I make this component use less CPU cycles?
Here is the code for ticker:
Ext.define('MyApp.ux.Ticker', {
extend: 'Ext.Component',
xtype: 'ticker',
baseCls: 'x-ticker',
autoEl: {
tag: 'div',
cls: 'x-ticker-wrap',
children: {
tag: 'div',
cls: 'x-ticker-body'
}
},
body: null,
constructor: function (config) {
Ext.applyIf(config, {
direction: 'left',
speed: 10,
pauseOnHover: true
});
if (config.speed < 1) config.speed = 1;
else if (config.speed > 20) config.speed = 20;
Ext.applyIf(config, {
refreshInterval: parseInt(10 / config.speed * 15)
});
config.unitIncrement = 1;
this.callParent([config]);
},
afterRender: function () {
this.body = this.el.first('.x-ticker-body');
this.body.addCls(this.direction);
this.taskCfg = {
interval: this.refreshInterval,
scope: this
};
var posInfo, body = this.body;
switch (this.direction) {
case "left":
case "right":
posInfo = { left: body.getWidth() };
this.taskCfg.run = this.scroll.horz;
break;
case "up":
case "down":
posInfo = { top: body.getHeight() };
this.taskCfg.run = this.scroll.vert;
break;
}
posInfo.position = 'relative';
body.setPositioning(posInfo);
DHT.ux.Ticker.superclass.afterRender.call(this);
if (this.pauseOnHover) {
this.el.on('mouseover', this.onMouseOver, this);
this.el.on('mouseout', this.onMouseOut, this);
this.el.on('click', this.onMouseClick, this);
}
this.task = Ext.apply({}, this.taskCfg);
Ext.util.TaskManager.start(this.task);
},
add: function (o) {
var dom = Ext.DomHelper.createDom(o);
this.body.appendChild(Ext.fly(dom).addCls('x-ticker-item').addCls(this.direction));
},
onDestroy: function () {
if (this.task) {
Ext.util.TaskManager.stop(this.task);
}
DHT.ux.Ticker.superclass.onDestroy.call(this);
},
onMouseOver: function () {
if (this.task) {
Ext.util.TaskManager.stop(this.task);
delete this.task;
}
},
onMouseClick: function (e, t, o) {
var item = Ext.fly(t).up('.x-ticker-item');
if (item) {
this.fireEvent('itemclick', item, e, t, o);
}
},
onMouseOut: function () {
if (!this.task) {
this.task = Ext.apply({}, this.taskCfg);
Ext.util.TaskManager.start(this.task);
}
},
scroll: {
horz: function () {
var body = this.body;
var bodyLeft = body.getLeft(true);
if (this.direction == 'left') {
var bodyWidth = body.getWidth();
if (bodyLeft <= -bodyWidth) {
bodyLeft = this.el.getWidth(true);
} else {
bodyLeft -= this.unitIncrement;
}
} else {
var elWidth = this.el.getWidth(true);
if (bodyLeft >= elWidth) {
bodyLeft = -body.getWidth(true);
} else {
bodyLeft += this.unitIncrement;
}
}
body.setLeft(bodyLeft);
},
vert: function () {
var body = this.body;
var bodyTop = body.getTop(true);
if (this.direction == 'up') {
var bodyHeight = body.getHeight(true);
if (bodyTop <= -bodyHeight) {
bodyTop = this.el.getHeight(true);
} else {
bodyTop -= this.unitIncrement;
}
} else {
var elHeight = this.el.getHeight(true);
if (bodyTop >= elHeight) {
bodyTop = -body.getHeight(true);
} else {
bodyTop += this.unitIncrement;
}
}
body.setTop(bodyTop);
}
}
});
And this is how I am using it:
{
xtype: 'panel',
border: false,
height: 40,
width: 256,
layout: {
type: 'hbox',
align: 'stretch'
},
items: [{
width: 200,
direction: 'left',
xtype: 'ticker',
itemId: 'rollerPanel'
}],
listeners: {
afterrender: function (panel) {
var ticker = panel.down('ticker');
ticker.add({
tag: 'div',
cls: 'title',
html: "Ticker content."
});
}
}
}
What's wrong with the above code? What may be the reason for higher CPU usage?
The Chrome developer tools will help you profile this but it wouldn't hurt to cache some of the things like the width/height of the body and elements so that you're only reading it when you start up and not on every tick.

Using buffered store + infinite grid with dynamic data

The goal is to use buffered store for the dynamic data set.
The workflow is below:
Some data is already present on server.
Clients uses buffered store & infinite grid to handle the data.
When the application runs the store is loading
and 'load' event scrolls the grid to the last message.
Some records are added to server.
Client gets a push notification and runs store reload.
topic.store.load({addRecords: true});
The load event runs and tries to scroll to the last message again but failes:
TypeError: offsetsTo is null
e = Ext.fly(offsetsTo.el || offsetsTo, '_internal').getXY();
Seems that the grid view doesn't refreshes and doesn't show the added records, only the white spaces on their places.
Any ideas how can I make the grid view refresh correctly?
The store initialization:
Ext.define('orm.data.Store', {
extend: 'Ext.data.Store',
requires: ['orm.data.writer.Writer'],
constructor: function (config) {
Ext.apply(this, config);
this.proxy = Ext.merge(this.proxy, {
type: 'rest',
batchActions: true,
reader: {
type: 'json',
root: 'rows'
},
writer: {
type: 'orm'
}
});
this.callParent(arguments);
}
});
Ext.define('akma.chat.model.ChatMessage', {
extend:'Ext.data.Model',
fields:[
{ name:'id', type:'int', defaultValue : undefined },
{ name:'createDate', type:'date', dateFormat:'Y-m-d\\TH:i:s', defaultValue : undefined },
{ name:'creator', type:'User', isManyToOne : true, defaultValue : undefined },
{ name:'message', type:'string', defaultValue : undefined },
{ name:'nameFrom', type:'string', defaultValue : undefined },
{ name:'topic', type:'Topic', isManyToOne : true, defaultValue : undefined }
],
idProperty: 'id'
});
Ext.define('akma.chat.store.ChatMessages', {
extend: 'orm.data.Store',
requires: ['orm.data.Store'],
alias: 'store.akma.chat.store.ChatMessages',
storeId: 'ChatMessages',
model: 'akma.chat.model.ChatMessage',
proxy: {
url: 'http://localhost:8080/chat/services/entities/chatmessage'
}
});
var store = Ext.create('akma.chat.store.ChatMessages', {
buffered: true,
pageSize: 10,
trailingBufferZone: 5,
leadingBufferZone: 5,
purgePageCount: 0,
scrollToLoadBuffer: 10,
autoLoad: false,
sorters: [
{
property: 'id',
direction: 'ASC'
}
]
});
Grid initialization:
Ext.define('akma.chat.view.TopicGrid', {
alias: 'widget.akma.chat.view.TopicGrid',
extend: 'akma.chat.view.grid.DefaultChatMessageGrid',
requires: ['akma.chat.Chat', 'akma.UIUtils', 'Ext.grid.plugin.BufferedRenderer'],
features: [],
hasPagingBar: false,
height: 500,
loadedMsg: 0,
currentPage: 0,
oldId: undefined,
forceFit: true,
itemId: 'topicGrid',
selModel: {
pruneRemoved: false
},
multiSelect: true,
viewConfig: {
trackOver: false
},
plugins: [{
ptype: 'bufferedrenderer',
pluginId: 'bufferedrenderer',
variableRowHeight: true,
trailingBufferZone: 5,
leadingBufferZone: 5,
scrollToLoadBuffer: 10
}],
tbar: [{
text: 'unmask',
handler: function(){
this.up('#topicGrid').getView().loadMask.hide();
}
}],
constructor: function (config) {
this.topicId = config.topicId;
this.store = akma.chat.Chat.getMessageStoreInstance(this.topicId);
this.topic = akma.chat.Chat.getTopic(this.topicId);
var topicPanel = this;
this.store.on('load', function (store, records) {
var loadedMsg = store.getTotalCount();
var pageSize = store.pageSize;
store.currentPage = Math.ceil(loadedMsg/pageSize);
if (records && records.length > 0) {
var newId = records[0].data.id;
if (topicPanel.oldId) {
var element;
for (var i = topicPanel.oldId; i < newId; i++) {
element = Ext.get(i + '');
topicPanel.blinkMessage(element);
}
}
topicPanel.oldId = records[records.length-1].data.id;
var view = topicPanel.getView();
view.refresh();
topicPanel.getPlugin('bufferedrenderer').scrollTo(store.getTotalCount()-1);
}
});
this.callParent(arguments);
this.on('afterrender', function (grid) {
grid.getStore().load();
});
var me = this;
akma.UIUtils.onPasteArray.push(function (e, it) {
if(e.clipboardData){
var items = e.clipboardData.items;
for (var i = 0; i < items.length; ++i) {
if (items[i].kind == 'file' && items[i].type.indexOf('image/') !== -1) {
var blob = items[i].getAsFile();
akma.chat.Chat.upload(blob, function (event) {
var response = Ext.JSON.decode(event.target.responseText);
var fileId = response.rows[0].id;
me.sendMessage('<img src="/chat/services/file?id=' + fileId + '" />');
})
}
}
}
});
akma.UIUtils.addOnPasteListener();
},
sendMessage: function(message){
if(message){
var topicGrid = this;
Ext.Ajax.request({
method: 'POST',
url: topicGrid.store.proxy.url,
params:{
rows: Ext.encode([{"message":message,"topic":{"id":topicGrid.topicId}}])
}
});
}
},
blinkMessage: function (messageElement) {
if (messageElement) {
var blinking = setInterval(function () {
messageElement.removeCls('red');
messageElement.addCls('yellow');
setTimeout(function () {
messageElement.addCls('red');
messageElement.removeCls('yellow');
}, 250)
}, 500);
setTimeout(function () {
clearInterval(blinking);
messageElement.addCls('red');
messageElement.removeCls('yellow');
}, this.showInterval ? this.showInterval : 3000)
}
},
columns: [ {
dataIndex: 'message',
text: 'Message',
renderer: function (value, p, record) {
var firstSpan = "<span id='" + record.data.id + "'>";
var creator = record.data.creator;
return Ext.String.format('<div style="white-space:normal !important;">{3}{1} : {0}{4}</div>',
value,
creator ? '<span style="color: #' + creator.chatColor + ';">' + creator.username + '</span>' : 'N/A',
record.data.id,
firstSpan,
'</span>'
);
}
}
]
});
upd: Seems that the problem is not in View. The bufferedrenderer plugin ties to scroll to the record.
It runs a callback function:
callback: function(range, start, end) {
me.renderRange(start, end, true);
targetRec = store.data.getRange(recordIdx, recordIdx)[0];
.....
store.data.getRange(recordIdx, recordIdx)[0]
tries to get the last record in the store.
....
Ext.Array.push(result, Ext.Array.slice(me.getPage(pageNumber), sliceBegin, sliceEnd));
getPage returns all records of the given page, but the last record is missing i.e. the store was not updated perfectly.
Any ideas how to fix?
The problem is that store.load() doesn't fill up store PageMap with the new data. The simplest fix is using store.reload() instead.
Maybe you are to early when listening to the load event. I am doing roughly the same in my application (not scrolling to the end, but to some arbitrary record after load). I do the view-refresh and bufferedrender-scrollTo in the callback of the store.load().
Given your code this would look like:
this.on('afterrender', function (grid) {
var store = grid.getStore();
store.load({
callback: function {
// snip
var view = topicPanel.getView();
view.refresh();
topicPanel.getPlugin('bufferedrenderer').scrollTo(store.getTotalCount()-1);
}
});
});

Can not export renderer text using highcharts/highstock when click range selector

I have a question related the chart export.
Please see Jsfiddle here
I added a text label using chart.renderer.text on the Yaxis for the latest value of series.
If I directly click button "Export Image". There is no problem, the label can be displayed. I'm using the following way to export image. draw_labels() is a function to draw yaxis label.
$("#b").click(function () {
chart.exportChart(null, {
chart: {
backgroundColor: '#FFFFFF',
width: 972,
height: 480,
events: {
load: function () {
draw_labels(this);
}
}
}
});
});
The problem is after I clicked range selector or change Xaxis range. When I try to export the
chart to image, there is no labels are drawn. The following is the complete code.
The following is the complete code:
$(function () {
var chart;
$.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=aapl-c.json&callback=?', function (data) {
chart = new Highcharts.StockChart({
chart: {
renderTo: 'container',
events: {
load: function () {
draw_labels(this);
$("#b").click(function () {
chart.exportChart(null, {
chart: {
backgroundColor: '#FFFFFF',
width: 972,
height: 480,
events: {
load: function () {
draw_labels(this);
}
}
}
});
});
}
}
},
series: [{
name: 'AAPL',
id: 'test',
data: data,
tooltip: {
valueDecimals: 2
}
}],
navigator: {
enabled: false
},
yAxis: {
tickWidth: 0,
id: 'value_axis',
type: 'linear',
gridLineColor: '#EEE',
lineColor: '#D0CDC9',
lineWidth: 0,
minorTickInterval: null,
opposite: true,
offset: 0
},
xAxis: {
events: {
afterSetExtremes: function (e) {
console.log('test');
$('[id="test_text"]').remove();
draw_labels(chart);
}
}
}
});
});
function draw_labels(chart) {
$(chart.series).each(function (i, serie) {
var s_id = serie.options.id;
var temp_id = s_id;
var point = serie.points[serie.points.length - 1];
if (point) {
var pre, post;
if (point.y) {
var last_value_dis = (point.y).toFixed(1);
yaxis_name = 'value_axis';
//Get Yaxis position
var y_axis = chart.get(yaxis_name);
offsite_yaxis = 0;
element_text = chart.renderer.text(
//the text to render
'<span style="font-size:10px;font-weight:bold;color:' + serie.color + ';">' + last_value_dis + '</span>',
//the 'x' position
y_axis.width + y_axis.offset,
//the 'y' position
chart.plotTop + point.plotY + 3).attr({
id: temp_id + '_text',
zIndex: 999
}).add();
}
}
});
}
});
Here, I have fixed it for you. Here is a saved image:
Following changes have been done:
Added a redraw event to your exportchart
redraw: function () {
$("#test_text").remove() ;
draw_labels(this);
}
Changed this line in afterSetExtremes
$('[id="test_text"]').remove();
to
$("#test_text").remove() ;
Earlier one was not working as expected, so I had to change it.
Problem with disappearing text is related with id, when I removed it, label appears. But then I came across second issue, wrong y position. So i declare global variable, then when you call your function, set position of label, and use in chart exporting this variable. As a result label is exported correct.
http://jsfiddle.net/UGbpJ/11/

Export google chart?

I wrote this code to create chart, table and toolbar.
google.load("visualization", "1", { packages: ["corechart"] });
google.load('visualization', '1', { packages: ['table'] });
//google.setOnLoadCallback(drawChart);
function drawChart() {
$.ajax({
type: "GET",
url: '#Url.Action("GunlukOkumalar", "Enerji")',
data: "startDate=" + $('#start_date').val() + "&endDate=" + $('#end_date').val() + "&sayac_id=" + $("#sayaclar").val(), //belirli aralıklardaki veriyi cekmek için
success: function (result) {
if (result.success) {
var evalledData = eval("(" + result.chartData + ")");
var opts = { curveType: "function", width: '100%', height: 500, pointSize: 5 };
new google.visualization.LineChart($("#chart_div").get(0)).draw(new google.visualization.DataTable(evalledData, 0.5), opts);
$('#chart_div').show();
var visualization;
var data;
var options = { 'showRowNumber': true };
data = new google.visualization.DataTable(evalledData, 0.5);
// Set paging configuration options
// Note: these options are changed by the UI controls in the example.
options['page'] = 'enable';
options['pageSize'] = 10;
options['pagingSymbols'] = { prev: 'prev', next: 'next' };
options['pagingButtonsConfiguration'] = 'auto';
// Create and draw the visualization.
visualization = new google.visualization.Table(document.getElementById('table'));
visualization.draw(data, options);
var components = [
{ type: 'html', datasource: data },
{ type: 'csv', datasource: data }
];
var container = document.getElementById('toolbar_div');
google.visualization.drawToolbar(container, components);
return false;
}
else {
$('#chart_div').html('<span style="color:red;"><b>' + result.Error + '</b></span>');
$('#chart_div').show();
$('#table').html('<span style="color:red;"><b>' + result.Error + '</b></span>');
$('#table').show();
return false;
}
}
});
}
Google example
function drawToolbar() {
var components = [
{type: 'igoogle', datasource: 'https://spreadsheets.google.com/tq?key=pCQbetd-CptHnwJEfo8tALA',
gadget: 'https://www.google.com/ig/modules/pie-chart.xml',
userprefs: {'3d': 1}},
{type: 'html', datasource: 'https://spreadsheets.google.com/tq?key=pCQbetd-CptHnwJEfo8tALA'},
{type: 'csv', datasource: 'https://spreadsheets.google.com/tq?key=pCQbetd-CptHnwJEfo8tALA'},
{type: 'htmlcode', datasource: 'https://spreadsheets.google.com/tq?key=pCQbetd-CptHnwJEfo8tALA',
gadget: 'https://www.google.com/ig/modules/pie-chart.xml',
userprefs: {'3d': 1},
style: 'width: 800px; height: 700px; border: 3px solid purple;'}
];
var container = document.getElementById('toolbar_div');
google.visualization.drawToolbar(container, components);
};
Google get dataSource from url, but I get dataSource dynamicly from controller. When I try to export It forwards page to another page like this:
http://localhost:49972/Enerji/%5Bobject%20Object%5D?tqx=out%3Acsv%3B
How can I use exporting toolbar for dynamic Json data? Is there any example about this topic?
I also had this problem and after a lot of trawling I found this!
https://developers.google.com/chart/interactive/docs/dev/implementing_data_source
I haven't implemented it yet but I reckon it's the way to go.

Resources