How to add text via chart.renderer.text in Highcharts? - text

I have succeeded adding additional text to my charts, like here. This, I achieved through adding a "function(chart)" to my "var chart = new Highcharts.Chart"
$.get('xxx.csv', function(data)
{
var chart = new Highcharts.Chart({
...
plotOptions:
{
series:
{
....
}
}
}, function(chart)
{
chart.renderer.text('The dotted line represents ...', 100, 86)
.css({
fontSize: '13px',
color: '#666666'
})
.add();
}
)};
My current format is however different:
$(function () {
var options =
{
chart:
{
...
},
...
};
$.get('xxx.csv', function(data)
{
var series = {
data: []
};
var temp = []
// Split the lines
var lines = data.split('\n');
// For each line, split the record into seperate attributes
$.each(lines, function(lineNo, line) {
var items = line.split(',');
if (lineNo !== 0) {
var xValue = +items[0],
kwh = parseFloat(items[2] / 1000);
if (!isNaN(kwh)) {
series.data.push({x:xValue,y: kwh, extra:items[1]});
}
}
});
// Push the completed series
options.series.push(series);
new Highcharts.Chart(options);
});
});
Now, I wonder how I can add a chart.renderer.text to the graph. I have tried different things, but didn't succeed. Where and how am I supposed to add the code for the text now? Here is a fiddle for this. Thanks for any hints!

You can add your text inside load event callback function of your chart. You can add this function inside your options - options.chart.events object.
http://api.highcharts.com/highcharts#chart.events.load
options.chart.events = {
load: function() {
var chart = this;
chart.renderer.text('The dotted line represents ...', 100, 186)
.css({
fontSize: '13px',
color: '#666666'
})
.add();
}
}
Here you can see an example how it can work:
http://jsfiddle.net/17ed42pa/1/
Best regards.

Related

How to fix ProcessBar to the top line in Nodejs CLI?

The terminal out is:
but actually this is what I really want:
progressbar will alway be the fist line,and got a response,then show it at below.
anyway to fix that?
Nodejs:
var request = require('request');
var ProgressBar = require('progress');
var year=[14,15,16];
var month=[1,2,3,4,5,6,7];
var bar = new ProgressBar('Processing [:bar] :percent', {
complete: '=',
incomplete: '-',
width: 30,
total: year.length*month.length,
});
/*-------------------------------------*/
function init(year,month){
check(year,month);
}
function check(year,month){
var options = { method: 'POST',
url: 'http://dev.site/date.php',
formData:{year:year,month:month}
};
request(options, function (error, response, body) {
if (error) {
console.log(error);;
}
if (body=='A task #') {
bar.tick();
console.log('\n'+body+year+':'+month);
}else{
bar.tick();
}
})
}
/*-------------------------------------*/
for (var i = 0; i < year.length; i++) {
for (var n = 0; n < month.length; n++) {
init(year[i],month[n]);
}
}
Using ansi-escapes you may be able to do this.
Here's a standalone version:
const ProgressBar = require('progress');
const ansiEscapes = require('ansi-escapes');
const write = process.stdout.write.bind(process.stdout);
let bar = new ProgressBar('Processing [:bar] :percent', {
complete : '=',
incomplete : '-',
width : 30,
total : 100
});
// Start by clearing the screen and positioning the cursor on the second line
// (because the progress bar will be positioned on the first line)
write(ansiEscapes.clearScreen + ansiEscapes.cursorTo(0, 1));
let i = 0;
setInterval(() => {
// Save cursor position and move it to the top left corner.
write(ansiEscapes.cursorSavePosition + ansiEscapes.cursorTo(0, 0));
// Update the progress bar.
bar.tick();
// Restore the cursor position.
write(ansiEscapes.cursorRestorePosition);
// Write a message every 10 ticks.
if (++i % 10 === 0) {
console.log('Now at', i);
}
// We're done.
if (i === 100) {
process.exit(0);
}
}, 100);

Use Socket.io to fill google Area Chart - 'google.visualization.DataTable is not a constructor'

I use NodeJS and Socket.io to get data from a database. I now want to fill a google area chart with these data but i kind of fail at doing it.
The data is transmitted as Objects. Each Object contains two values (datetime and value). I append these values to an array and then store them in a DataTable:
google.load('visualization', '1', {
packages: ['corechart']
});
google.setOnLoadCallback(drawChart);
var socket = io();
getData();
function drawChart(dataArray) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'DateTime');
data.addColumn('number', 'Value');
for (var i = 0; i < dataArray.length; i += 2) {
console.log(dataArray[0]);
data.addRow([dataArray[i], dataArray[i + 1]]);
}
var chart = new google.visualization.AreaChart(document.getElementById('chart'));
chart.draw(data, {
title: "Data Visualization",
isStacked: true,
width: '50%',
height: '50%',
vAxis: {
title: 'Data v-Axis'
},
hAxis: {
title: 'Data h-Axis'
}
})
}
function getData() {
socket.emit('GET');
socket.on('serverSent', function (data) {
var processedData = processData(data);
drawChart(processedData);
})
}
function processData(data) {
var arr = new Array();
jQuery.each(data, function (index, object) {
arr.push(object['datetime'], parseInt(object['value']));
})
return arr;
}
If i call my website i see the chart but without any values and the error message `google.visualization.DataTable is not a constructor´. So what am i doing wrong?
The problem is drawChart is being called twice.
From both google.setOnLoadCallback and getData.
If getData is called before google.setOnLoadCallback,
then google.visualization.DataTable will not be recognized.
In addition, it is recommended to use loader.js vs. jsapi.
See Load the Libraries for more info...
As such, please try the following...
Replace...
<script src="https://www.google.com/jsapi"></script>
With...
<script src="https://www.gstatic.com/charts/loader.js"></script>
And try something like...
google.charts.load('current', {
callback: init,
packages: ['corechart']
});
function init() {
var socket = io();
socket.emit('GET');
socket.on('serverSent', function (data) {
var processedData = processData(data);
drawChart(processedData);
});
}
function drawChart(dataArray) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'DateTime');
data.addColumn('number', 'Value');
for (var i = 0; i < dataArray.length; i += 2) {
console.log(dataArray[0]);
data.addRow([dataArray[i], dataArray[i + 1]]);
}
var chart = new google.visualization.AreaChart(document.getElementById('chart'));
chart.draw(data, {
title: "Data Visualization",
isStacked: true,
width: '50%',
height: '50%',
vAxis: {
title: 'Data v-Axis'
},
hAxis: {
title: 'Data h-Axis'
}
})
}

Save and Restore rectangles with connections in Draw2D.js touch via JSON

How do I create rectangles with 4 ports (each side) in a correct way, so I can save and restore them via JSON?
I tried this one, but only the rectangles are been saved. The connections and labels got lost.
JSFiddle: http://jsfiddle.net/xfvf4/36/
Create two elements (Add) - move them and connect them
Write: This gives the content as JSON-Array
Read: Should make the grafic out of the JSON-Array
The last point doesn't work.
JS:
var LabelRectangle = draw2d.shape.basic.Rectangle.extend({
NAME: "draw2d.shape.basic.Rectangle",
init: function (attr) {
this._super(attr);
this.label = new draw2d.shape.basic.Label({
text: "Text",
fontColor: "#0d0d0d",
stroke: 0
});
this.add(this.label, new draw2d.layout.locator.CenterLocator(this));
this.label.installEditor(new draw2d.ui.LabelInplaceEditor());
this.createPort("hybrid", new draw2d.layout.locator.BottomLocator(this));
},
getPersistentAttributes: function () {
var memento = this._super();
memento.labels = [];
var ports = [];
ports = this.getPorts();
memento.ports = [];
console.log(ports);
this.children.each(function (i, e) {
console.log(e);
memento.labels.push({
id: e.figure.getId(),
label: e.figure.getText(),
locator: e.locator.NAME
});
ports.each(function (i, e) {
memento.ports.push({
//id: e.id,
name: e.name,
locator: e.locator.NAME
});
});
});
return memento;
},
setPersistentAttributes: function (memento) {
this._super(memento);
this.resetChildren();
$.each(memento.labels, $.proxy(function (i, e) {
var label = new draw2d.shape.basic.Label(e.label);
var locator = eval("new " + e.locator + "()");
locator.setParent(this);
this.add(label, locator);
}, this));
}
});
$(window).load(function () {
var canvas = new draw2d.Canvas("gfx_holder");
$("#add").click(function (e) { // Add a new rectangle
var rect = new LabelRectangle({
width: 200,
height: 40,
radius: 3,
bgColor: '#ffffff',
stroke: 0
});
rect.createPort("hybrid", new draw2d.layout.locator.OutputPortLocator(rect));
rect.createPort("hybrid", new draw2d.layout.locator.InputPortLocator(rect));
rect.createPort("hybrid", new draw2d.layout.locator.TopLocator(rect));
canvas.add(rect, 150, 200);
});
$("#write").click(function (e) { // Write to pre-Element (JSON)
var writer = new draw2d.io.json.Writer();
writer.marshal(canvas, function(json){
$("#json").text(JSON.stringify(json,null,2));
$('#gfx_holder').empty();
});
});
$("#read").click(function (e) { // Read from pre-Element (JSON)
var canvas = new draw2d.Canvas("gfx_holder");
var jsonDocument = $('#json').text();
var reader = new draw2d.io.json.Reader();
reader.unmarshal(canvas, jsonDocument);
});
});
HTML:
<ul class="toolbar">
<li>Add</li>
<li>Write</li>
<li>Read</li>
</ul>
<div id="container" class="boxed">
<div onselectstart="javascript:/*IE8 hack*/return false" id="gfx_holder" style="width:100%; height:100%; ">
</div>
<pre id="json" style="overflow:auto;position:absolute; top:10px; right:10px; width:350; height:500;background:white;border:1px solid gray">
</pre>
</div>
Just use the write.js and Reader.js in the "json"-Folder of Draw2D.js 5.0.4 and this code:
$(window).load(function () {
var canvas = new draw2d.Canvas("gfx_holder");
// unmarshal the JSON document into the canvas
// (load)
var reader = new draw2d.io.json.Reader();
reader.unmarshal(canvas, jsonDocument);
// display the JSON document in the preview DIV
//
displayJSON(canvas);
// add an event listener to the Canvas for change notifications.
// We just dump the current canvas document into the DIV
//
canvas.getCommandStack().addEventListener(function(e){
if(e.isPostChangeEvent()){
displayJSON(canvas);
}
});
});
function displayJSON(canvas){
var writer = new draw2d.io.json.Writer();
writer.marshal(canvas,function(json){
$("#json").text(JSON.stringify(json, null, 2));
});
}
This should work:
var LabelRectangle = draw2d.shape.basic.Rectangle.extend({
NAME: "draw2d.shape.basic.Rectangle",
init: function (attr) {
this._super(attr);
this.label = new draw2d.shape.basic.Label({
text: "Text",
fontColor: "#0d0d0d",
stroke: 0
});
this.add(this.label, new draw2d.layout.locator.CenterLocator(this));
this.label.installEditor(new draw2d.ui.LabelInplaceEditor());
},
getPersistentAttributes: function () {
var memento = this._super();
memento.labels = [];
memento.ports = [];
this.getPorts().each(function(i,port){
memento.ports.push({
name : port.getName(),
port : port.NAME,
locator: port.getLocator().NAME
});
});
this.children.each(function (i, e) {
memento.labels.push({
id: e.figure.getId(),
label: e.figure.getText(),
locator: e.locator.NAME
});
});
return memento;
},
setPersistentAttributes: function (memento) {
this._super(memento);
this.resetChildren();
if(typeof memento.ports !=="undefined"){
this.resetPorts();
$.each(memento.ports, $.proxy(function(i,e){
var port = eval("new "+e.port+"()");
var locator = eval("new "+e.locator+"()");
this.add(port, locator);
port.setName(e.name);
},this));
}
$.each(memento.labels, $.proxy(function (i, e) {
var label = new draw2d.shape.basic.Label(e.label);
var locator = eval("new " + e.locator + "()");
locator.setParent(this);
this.add(label, locator);
}, this));
}
});

nodejs - how to keep an status at top of stdout

I'm trying to output something like these:
counter is: 10 <= fixed line and auto updating
console.logs, etc... <= other console.logs, errors, defaul outputs
console.logs, etc...
console.logs, etc...
console.logs, etc...
Is this possible?
I have tried with process.stdout.write() but it is not working.
var counter = 0;
setInterval(function(){
counter++;
process.stdout.write("counter is " + counter + " \r");
}, 500);
setInterval(function(){
console.log('some output');
}, 1500);
Here's an example using blessed:
var blessed = require('blessed');
var screen = blessed.screen(),
body = blessed.box({
top: 1,
left: 0,
width: '100%',
height: '99%'
}),
statusbar = blessed.box({
top: 0,
left: 0,
width: '100%',
height: 1,
style: {
fg: 'white',
bg: 'blue'
}
});
screen.append(statusbar);
screen.append(body);
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});
function status(text) { statusbar.setContent(text); screen.render(); }
function log(text) { body.insertLine(0, text); screen.render(); }
var c = 1;
setInterval(function() {
status((new Date()).toISOString());
log('This is line #' + (c++));
}, 100);
Here's a simpler example that has almost the same effect (the status bar doesn't fill in extra space with background color):
var screen = blessed.screen(),
body = blessed.box({
top: 0,
left: 0,
width: '100%',
height: '100%',
tags: true
});
screen.append(body);
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});
function status(text) {
body.setLine(0, '{blue-bg}' + text + '{/blue-bg}');
screen.render();
}
function log(text) {
body.insertLine(1, text);
screen.render();
}
var c = 1;
setInterval(function() {
status((new Date()).toISOString());
log('This is line #' + (c++));
}, 100);
Aside there are a lot of node modules that can help you do this,(blessed, ncurses, ansi, termhelper), for educational purposes you can also do it with vanilla node easily using process.stdout.moveCursor:
var logs = [];
function log(text) {
logs.push(text);
console.log(text);
}
function changeCounter(n) {
process.stdout.moveCursor(0, -logs.length - 1);
printCounter(n);
logs.forEach(function (log) { console.log(log) });
}
function printCounter(n) {
console.log('Counter is:', n);
}
// Now lets test
printCounter(0);
var i = 1;
setInterval(function () {
log('meoww');
changeCounter(i++);
});
Though you have to write to extra code to prevent overflowing terminal.
A traditional library for doing that sort of thing (drawing text at other than the bottom of the screen) is "curses"...there are bindings for Node.js but there is also "blessed" (ha ha) which looks easier to use: https://github.com/chjj/blessed

Secondary tile web url

I have to pin secondary tile in my windows phone 8.1 application.
I followed the msdn tutorial : http://code.msdn.microsoft.com/windowsapps/secondary-tiles-sample-edf2a178/
It does work with internal image (ms-appx://.. ) but not with web url (http://)
working sample:
var logo = new Windows.Foundation.Uri("ms-appx:///Images/square30x30Tile-sdk.png");
var currentTime = new Date();
var TileActivationArguments = data.ad_id + " WasPinnedAt=" + currentTime;
var tile = new Windows.UI.StartScreen.SecondaryTile(data.ad_id,
data.subject,
TileActivationArguments,
logo,
Windows.UI.StartScreen.TileSize.square150x150);
tile.visualElements.foregroundText = Windows.UI.StartScreen.ForegroundText.light;
tile.visualElements.square30x30Logo = logo;
tile.visualElements.showNameOnSquare150x150Logo = true;
var selectionRect = this.element.getBoundingClientRect();
// Now let's try to pin the tile.
// We'll make the same fundamental call as we did in pinByElement, but this time we'll return a promise.
return new WinJS.Promise(function (complete, error, progress) {
tile.requestCreateForSelectionAsync({ x: selectionRect.left, y: selectionRect.top, width: selectionRect.width, height: selectionRect.height }, Windows.UI.Popups.Placement.above).done(function (isCreated) {
if (isCreated) {
complete(true);
} else {
complete(false);
}
});
});
And if I use
var logo = new Windows.Foundation.Uri(data.images[0]);
I got an invalid parameter exception.
You can take a look at the documentation for the SecondaryTile.Logo property. In it you'll see this:
The location of the image. This can be expressed as one of these schemes:
ms-appx:///
ms-appdata:///local/
You can download the image first and then set it using the ms-appdata:///local/ scheme. I'm not sure that changing the logo with something from the Internet is a good idea, though. This should be the app's logo, so it should be in the package.
I found the solution
fileExists: function (fileName) {
var applicationData = Windows.Storage.ApplicationData.current;
var folder = applicationData.localFolder;
return folder.getFileAsync(fileName).then(function (file) {
return file;
}, function (err) {
return null;
});
},
download: function (imgUrl, imgName) {
return WinJS.xhr({ url: imgUrl, responseType: "blob" }).then(function (result) {
var blob = result.response;
var applicationData = Windows.Storage.ApplicationData.current;
var folder = applicationData.localFolder;
return folder.createFileAsync(imgName, Windows.Storage.
CreationCollisionOption.replaceExisting).then(function (file) {
// Open the returned file in order to copy the data
return file.openAsync(Windows.Storage.FileAccessMode.readWrite).
then(function (stream) {
return Windows.Storage.Streams.RandomAccessStream.copyAsync
(blob.msDetachStream(), stream).then(function () {
// Copy the stream from the blob to the File stream
return stream.flushAsync().then(function () {
stream.close();
});
});
});
});
}, function (e) {
//var msg = new Windows.UI.Popups.MessageDialog(e.message);
//msg.showAsync();
});
},
var self = this;
this.download(data.images[0], data.ad_id).then(function () {
self.fileExists(data.ad_id).then(function (file) {
var logo = new Windows.Foundation.Uri("ms-appdata:///Local/" + data.ad_id);
....
I need to download the image, store it and then I can use ms-appdata:///Local

Resources