Building dynamic HighCharts and image Highcharts with (mostly) one codebase? - node.js

We're already creating dynamic HighCharts for our webpages--these have a few javascript dependencies and a chart-generation script. We'd like to start creating PDFs of these charts using the new HighCharts/Node/PhantomJS suite HighCharts has rigged up (see press release). Our image-gen node server would run on a separate box/vm. How can we do this without having to maintain two separate codebases for the same chart? I'm not too familiar with Node yet, so I'm not sure how requesting the scripts with a web request would work. I'm guessing a lot of HighCharts users that want to start generating some of their charts as images server-side will run into a similar issue with managing two related codesets...
In essence, we already have have this:
Webserver -> JSON (data) + foo.js + bar.js + foo.html -> webpage with dynamic charts.
We'd like to build:
Web-server -> JSON (data) + separate Node Server + foo.js + bar.js -> images available via web request
Obviously some redundancy. How can we manage the dependencies?

While node is awesome, I felt that approach was needlessly complex, with having to many moving parts that could break. So I did the super simple solution of creating files dynamically. The only problem i faced was deleting the temporary file after adding it to the pdf. It would break the PDF from rendering. And setting the directory to /tmp, crashed phantomjs. The best idea i came up with currently is putting the tempory generated files, in a temp directory, then deleting everything in that directory every night, with a cronjob.
I post this out of code simplicity. It should be in a function, to maintain code re-usability.
<?php
$TmpInFileName = 'tmp/graph_'.md5($CurrentDate.rand(666,9482845713)).'.js';
$TmpGraphFileName = 'tmp/pnggraph_'.md5($CurrentDate.rand(2666,54713)).'.png';
$Data = "
{
chart: {
zoomType: 'xy',
width: 700,
height: 520
},
credits: {
enabled: false
},
colors: [
'#2f7ed8',
'#910000',
'#8bbc21',
'#1aadce',
'#492970',
'#f28f43',
'#77a1e5',
'#c42525',
'#a6c96a'
],
title: {
text: 'Sample Graph - created at ".date('m/d/Y g:i:s a')."',
style: {
fontSize: '16px',
}
},
xAxis: [{
categories: ['00:00', '00:15', '00:30', '00:45', '01:00', '01:15', '01:30']
}],
yAxis: [{
labels: {
format: '{value}',
style: {
fontSize: '14px',
color: Highcharts.getOptions().colors[1]
}
},
title: {
text: 'Y axis',
style: {
fontSize: '16px',
color: Highcharts.getOptions().colors[1]
}
}
}, { // Secondary yAxis
title: {
text: 'Sec Yaxis',
style: {
fontSize: '16px',
color: Highcharts.getOptions().colors[0]
}
},
labels: {
format: '{value}',
style: {
fontSize: '14px',
color: Highcharts.getOptions().colors[0]
}
},
opposite: true
}],
tooltip: {
shared: true
},
legend: {
layout: 'horizontal',
backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'
},
series: [{
name: 'first',
type: 'spline',
yAxis: 1,
data: [0, -119.9502311075212, -119.96203992145706, -119.98172620218355, -119.71898290168028, -119.97023935590325, -119.95230287195413]
},
{
name: 'second',
type: 'spline',
yAxis: 1,
data: [0, -119.24222667756482, -119.60905809195222, -119.63522965403729, -119.11011466187935, -119.63643171374981, -119.54969080301575]
},{
name: 'third',
type: 'column',
data: [10, 11, 9, 7, 5, 2, 7]
},{
name: 'fourth',
type: 'column',
data: [0, -0.7080044299563895, -0.35298182950484147, -0.34649654814626274, -0.6088682398009269, -0.33380764215343106, -0.40261206893838164]
}]
}";
try {
$myfile = fopen($TmpInFileName, "w") or die("Unable to open file!");
fwrite($myfile, $Data);
fclose($myfile);
} catch (Exception $e) {
echo 'Error: '.$e.' <br />';
}
$URL_Command = "phantomjs /highcharts/exporting-server/phantomjs/highcharts-convert.js -infile $TmpInFileName -outfile $TmpGraphFileName -width 600";
exec($URL_Command);
echo '<img src="'.$TmpGraphFileName.'" alt="Could not load img: '.$TmpGraphFileName.'">';
?>
I hope this helps. I couldn't find a good solution that didn't involve Node.JS or Java to do this. I wanted a pure PHP solution.

We decided to pass the entire highcharts config object (e.g. Highcharts.chart(configObj)) to the node server as a URL-encoded string. We had to put a few rendering functions over on the node server, but it wasn't too bad. We also stuck some of the rendering functions in the string config object. Not the most beautiful result, but it worked.

Related

Using IIPImage server with openseadragon

I have the IIPImage server running and I am trying to display a deepzoom image but fail
This is how I am doing it :
var tileSource =
{
Image:
{
xmlns: "http://schemas.microsoft.com/deepzoom/2008",
Url: "http://127.0.0.1/fcgi-bin/iipsrv.fcgi?
DeepZoom=E:/DeepZoomFile/10580_12079_1121935_stitch_files/",
Format: "jpg",
Overlap: "2",
TileSize: "256",
Size:
{
Height: "38290",
Width: "17953"
}
}
};
And the important line is :
Url: "http://127.0.0.1/fcgi-bin/iipsrv.fcgi?DeepZoom=E:/DeepZoomFile/10580_12079_1121935_stitch_files/"
I am getting errors from the browser that "fail to load tile image"
Any help or example of how should I do it ?
Thanks
No . It doesn't work with a suffix of DZI

Change color of JointJS Rappid object (via modifying different instance in the left-nav menu and also modify via Rappid Inspector color picker)?

I basically want to change the color of a JointJS shape in their RAPPID environment I'm trialing.
Here is some background on what I have so far and what I want to achieve:
I have a JointJS shape called ChristmasTree that extends joint.dia.Element.
Basically the svg string that builds this ChristmasTree object is a path of the tree (svg path element), and multiple ornaments on it (4 svg circles/ellipses which have id's and classes that I would assume I can use to modify the colors).
I set some initial values for the ornaments via the style attr inside the svg string.
Once I place that in the left RAPPID menu, the user can drag that one Christmas Tree with red balls on it, yay.
Question ###1:
But I would like to place a 2nd ChristmasTree shape in the left menu without creating another main object that has Green balls... How would I achieve this?
In my below code, christmas_tree_style_2 should override the .ornament class with
'fill': "#00ff00", but doesn't (in the left menu, its still red)?
In fact, christmas_tree_style_1, i also tried to override with a Blue ball 'fill': "#0000ff", but its still red.
How can I achieve a left-nav override of the shape?
Question ###2:
Pretend you help me resolve previous issue. You can drag and drop 2 multiple color ChristmasTree's from the left-menu nav into the main RAPPID content area.
I'd like to now change the colors dynamically through the inspector.
I added a color inspector that shows up in the RAPPID right-nav menu for every element with:
'ornament_fill': { label: 'Color of christmas-tree-ornament's fill', type: 'color', group: 'generalinfo', index: 2 }
But not sure how to create an event to dynamically change the color of the ornaments. Any idea? Thanks!
Here is the important part's of the code below.
And also here is an actual working example (but the left-nav initial override and right-nav Inspector color override dont work, hence my 2 questions):
http://armyofda12mnkeys.kissr.com/rappid_christmastree/index.html
(sorry i couldnt find a CDN for rappid.js to add to JSFiddle so it was easier to upload the folder to a site). The applicable files to my question are app.js and rappid-custom-shapes.js.
#
//svg for Christmas Tree + its ornaments... will be added to ChristmasTree shape/obj below
var ChristmasTreeSVGstr = "<g class="rotatable"><g class="scalable">
...
<path id="christmastreestrokeid" class="christmastreestroke" ... />
<circle id="ornament1" class="ornament" r="24" cy="350" cx="120"
style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament2" class="ornament" rx="30" ry="25" cy="83" cx="231"
style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament3" class="ornament" rx="28" ry="38" cy="343" cx="331"
style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament4" class="ornament" rx="63" ry="54" cy="238" cx="230"
style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
</g></g>";
#
//default Christmas Tree
joint.shapes.basic.ChristmasTree = joint.dia.Element.extend({
markup: ChristmasTreeSVGstr,
defaults: joint.util.deepSupplement({
type: "basic",
name: 'Initial Christmas Tree label text',
size: {
width: 20,
height: 20
},
attrs: {
".christmastreestroke": {
stroke: 'green',
'stroke-width': '100px',
'fill-opacity': 1,
width: 10,
height: 15
},
".ornament": {
'fill': "#00ff00",
'fill-opacity': 1
},
"#ornament3": {
'fill': "#0000FF",
'stroke': "green",
'stroke-width': '5px',
'fill-opacity': .5
}
}
}, joint.dia.Element.prototype.defaults)
});
#
//RAPPID left menu christmas trees (2 variations of the initial ChristmasTree object, so I need to override some of the colors)
var christmas_tree_style_1 = new joint.shapes.basic.ChristmasTree({
position: { x: 0, y: 0 },
size: {
width: 40,
height: 50
},
attr: {
".christmastreestroke": {
stroke: 'green',
'stroke-width': '100px',
'fill-opacity': 1,
},
".ornament": {
'fill': "#0000ff",
'fill-opacity': 1
},
"#ornament3": {
'fill': "#0000FF",
'stroke': "green",
'stroke-width': '5px',
'fill-opacity': .5
}
}
});
var christmas_tree_style_2 = new joint.shapes.basic.ChristmasTree({
position: { x: 0, y: 0 },
size: {
width: 40,
height: 50
},
attr: {
".christmastreestroke": {
stroke: 'blue',
'stroke-width': '100px',
'fill-opacity': 1,
},
".ornament": {
'fill': "#00ff00",
'fill-opacity': 1
},
"#ornament3": {
'fill': "yellow",
'stroke': "yellow",
'stroke-width': '5px',
'fill-opacity': 1
}
}
});
//add to left menu
stencil.load([christmas_tree_style_1, christmas_tree_style_2], 'customchristmastrees');
#
//add it to the inspector
function createInspector(cellView) {
if (!inspector || inspector.options.cellView !== cellView) {
if (inspector) {
// Set unsaved changes to the model and clean up the old inspector if there was one.
inspector.updateCell();
inspector.remove();
}
//if(cellView.$el.hasClass('class')) // certain element should get certain things more in inspector?
//how to determine different shapes?
inspector = new joint.ui.Inspector({
inputs: {
'name': { label: 'Name of Christmas Tree', type: 'text', group: 'generalinfo', index: 1 },
'ornament_fill': { label: 'Color of christmas-tree-ornaments fill', type: 'color', group: 'generalinfo', index: 2 },
},
groups: {
generalinfo: { label: 'General Info', index: 1 },
},
cellView: cellView
});
$('.inspector-container').html(inspector.render().el);
}
}
Question #1: you need to remove style properties from the markup if you want to change them through the attr property on the element. I removed the fill, stroke, stroke-width from the markup:
var ChristmasTreeSVGstr = "<g class="rotatable"><g class="scalable">
...
<path id="christmastreestrokeid" class="christmastreestroke" ... />
<circle id="ornament1" class="ornament" r="24" cy="350" cx="120"
style="fill-rule:evenodd;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament2" class="ornament" rx="30" ry="25" cy="83" cx="231"
style="fill-rule:evenodd;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament3" class="ornament" rx="28" ry="38" cy="343" cx="331"
style="fill-rule:evenodd;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
<ellipse id="ornament4" class="ornament" rx="63" ry="54" cy="238" cx="230"
style="fill-rule:evenodd;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">...</circle>
</g></g>";
then you can customize the shape as follows:
var rb = new joint.shapes.basic.ChristmasTree({
position: { x: 50, y: 50 },
size: { width: 100, height: 150 },
attrs: {
".ornament": {
'fill-opacity': 1,
stroke: 'pink',
'stroke-width': 5,
fill: 'blue'
}
}
});
Question #2:
in case you sorted out the issue #1 you can simply sync the values directly with the attrs:
inspector = new joint.ui.Inspector({
inputs: {
'name': { label: 'Name of Christmas Tree', type: 'text', group: 'generalinfo', index: 1 },
attrs: {
'.ornament': {
fill: {
label: 'Color of christmas-tree-ornaments fill',
type: 'color',
group: 'generalinfo',
index: 2
}
}
},
},
groups: {
generalinfo: { label: 'General Info', index: 1 },
},
cellView: cellView
});

Sencha - Add custom attributes to element

I want my div to look like this
<div id="example" customAtt="try"></div>
How can I add custom attribute to panel,button etc. in sencha?
thank you
If it's a Ext.Component, you can do the following
listeners: {
afterrender: function (component) {
component.getEl().dom.setAttribute("myCustomAttribute", "SOME_VALUE");
}
}
You can use autoEl in classic framework:
Ext.create({
xtype: 'component',
renderTo: Ext.getBody(),
html: 'Hi !!!',
id: "example",
autoEl: {
customAtt: "try"
}
});
Crate ...
<div class="x-component x-component-default x-border-box" customatt="try" id="example">Hi !!!</div>
You can easily add custom attributes, the same way you define config attributes.
mycont = {
xtype: 'container',
id: 'cont123',
width: 300,
height: 100,
customAttribute1: customAttribute1Value
customAttribute2: customAttribute2Value
...
}

Why does my gridPanel in a tabPanel show the wrong height?

In the attached image, the grid does not show properly. The grid is inside a tabpanel. The layout of the tab is = 'fit'.
What setting error is causing the behavior?
EDIT:
Here is the class definition for the tabpanel: Our tab is the one called 'External ID'
/*
* File: SomeTabPanel.ui.js
* Date: Mon May 02 2011 18:08:34 GMT-0400 (Eastern Daylight Time)
*
* This file was generated by Ext Designer version xds-1.0.3.2.
* http://www.extjs.com/products/designer/
*
* This file will be auto-generated each and everytime you export.
*
* Do NOT hand edit this file.
*/
SomeTabPanelUi = Ext.extend(Ext.TabPanel, {
activeTab: 0,
forceLayout: true,
border: false,
enableTabScroll: true,
initComponent: function() {
this.items = [{
xtype: 'panel',
title: 'General',
layout: 'table',
tpl: '',
ref: 'GeneralTab',
layoutConfig: {
columns: 2
},
items: [{
xtype: 'form',
title: 'Corporate',
height: 500,
width: 500,
animCollapse: false,
items: [{
xtype: 'box',
ref: '../../coporateBox'
}]
}]
},{
xtype: 'panel',
title: 'External ID',
layout: 'fit',
ref: 'ExtIdTab',
id: ''
}];
SomeTabPanelUi.superclass.initComponent.call(this);
}
});
Looks like you need to set a height for the grid somehow. Either a manual height declaration, autoHeight: true, or inherited height from a parent container.
Does the parent tabPanel have a height declared/inherited?
Setting layout: 'fit' is a good start for the containing tab, but without some code or a test case, I can't be more helpful.
It should work as described, so you must have something wrong in your code. Post your layout code if you want more help.

Auto width in a BorderLayout panel

I am trying a implement a really simple layout using BorderLayout.
var summary = new Ext.Panel({
region:'west',
id:'summary',
title:'Summary layout',
header: true,
split:true,
collapseMode: 'mini',
collapsible: true,
width: 200,
minSize: 175,
maxSize: 400,
layout:'vbox',
align: 'stretch',
items: [{
html: Ext.example.shortBogusMarkup,
title:'Navigation',
autoScroll:true,
border:false,
flex: 1
},{
title:'Settings',
html: Ext.example.shortBogusMarkup,
border:false,
autoScroll:true,
iconCls:'settings',
flex: 1
}]
});
The layout renders well, but when I change the width using the handle, the two panels inside the vbox don't resize.
I tried any kind of configuration I thought of, but i did not work.
(layout fit, width auto, autoWidth, etc...)
What do I miss? Thanks
For me, it doesn't work.
But this code works :
layout:{
type:'vbox',
align:'stretch'
}
I finally found by myself.
I set the layout options not correctly
I had to change to
...
layout:'vbox',
layoutConfig: {
align: 'stretch'
},
items: [{
...

Resources