While creating mixed chart in Zingchart we can pass the type attribute values with values array. But I'm not sure when reading data from CSV how this can be achieved.
I want to create mixed chart as on fiddle link below but data is to be read from a csv file.
var myConfig =
{
"type":"mixed",
"series":[
{
"values":[51,53,47,60,48,52,75,52,55,47,60,48],
"type":"bar",
"hover-state":{
"visible":0
}
},
{
"values":[69,68,54,48,70,74,98,70,72,68,49,69],
"type":"line"
}
]
}
zingchart.render({
id : 'myChart',
data : myConfig,
height: 500,
width: 725
});
<script src="https://cdn.zingchart.com/zingchart.min.js"></script>
<div id="myChart"></div>
I put together a demo for you using the sample data you provided in one of your related questions. If you go to this demo page and upload the CSV you originally provided, you should get this chart:
ZingChart includes a CSV parser for basic charts, but a more complex case like this requires a bit of preprocessing to get your data where it needs to be. I used PapaParse for this demo, but there are other parsing libraries available.
Here's the JavaScript. I'm using a simple file input in the HTML to get the CSV.
var csvData;
var limit = [],
normal = [],
excess = [],
dates = [];
var myConfig = {
theme: "none",
"type": "mixed",
"scale-x": {
"items-overlap":true,
"max-items":9999,
values: dates,
guide: {
visible: 0
},
item:{
angle:45
}
},
"series": [{
"type": "bar",
"values": normal,
"stacked": true,
"background-color": "#4372C1",
"hover-state": {
"visible": 0
}
}, {
"type": "bar",
"values": excess,
"stacked": true,
"background-color": "#EB7D33",
"hover-state": {
"visible": 0
}
}, {
"type": "line",
"values": limit
}]
};
/* Get the file and parse with PapaParse */
function parseFile(e) {
var file = e.target.files[0];
Papa.parse(file, {
delimiter: ",",
complete: function(results) {
results.data.shift(); //the first array is header values, we don't need these
csvData = results.data;
prepChart(csvData);
}
});
}
/* Process the results from the PapaParse(d) CSV and populate
** the arrays for each chart series and scale-x values
*/
function prepChart(data) {
var excessVal;
//PapaParse data is in a 2d array
for (var i = 0; i < data.length; i++) {
//save reference to your excess value
//cast all numeric values to int (they're originally strings)
var excessVal = parseInt(data[i][4]);
//date, limit value, and normal value can all be pushed to their arrays
dates.push(data[i][0]);
limit.push(parseInt(data[i][1]));
normal.push(parseInt(data[i][3]));
/* we must push a null value into the excess
** series if there is no excess for this node
*/
if (excessVal == 0) {
excess.push(null);
} else {
excess.push(excessVal);
}
}
//render your chart
zingchart.render({
id: 'myChart',
data: myConfig,
height: 500,
width: 725
});
}
$(document).ready(function() {
$('#csv-file').change(parseFile);
});
Related
I want to populate data two levels deep. Therefore I wrote the following:
let homepage = qs.stringify({
populate: '*',
},{
encodeValuesOnly: true, // prettify URL
});
This returns the following JSON:
{
"data": {
"id": 1,
"attributes": {
},
"att1": {
},
"att2": {
},
"att3": {
},
"att4": [],
"Projekte": {
}
}
},
"meta": {}
}
The nested Object “Projekte” now does contain an image. How can I access it?
You should specify the fields you want to populate. In your case :
let homepage = qs.stringify({
populate: 'Projekte',
},{
encodeValuesOnly: true, // prettify URL
});
I have a scatter plot Vizframe chart in which I need to include a linear regression/trend line. Any idea how this can be done? It appears this is not something offered by vizframe 'out of box'? I can't find a solution for this!
Question:
Any suggestions on a feasible way to implement a regression line on a Scatter Plot Vizframe chart?
Here is the code I have for the setup. The scatter plot opens in a dialog/modal when a button is pressed.
sap.ui.define([
'jquery.sap.global',
'vizConcept/controller/BaseController',
'sap/ui/model/json/JSONModel',
'vizConcept/model/viewControls',
'sap/m/Button',
'sap/m/Dialog',
],
function (jQuery, BaseController, JSONModel, viewControls, Button, Dialog) {
"use strict";
var controls;
var mainController = BaseController.extend("vizConcept.controller.Main", {
onInit: function(oEvent) {
// Access/expose the defined model(s) configured in the Component.js or Manifest.json within the controller.
this.getView().setModel(this.getOwnerComponent().getModel("products"), "products");
var oModel = this.getView().getModel("products");
this.getView().setModel(oModel);
var sUrl = "#" + this.getOwnerComponent().getRouter().getURL("page2");
$(function() {
var dataset = new sap.viz.ui5.data.FlattenedDataset({
dimensions : [
{
axis : 1,
name : 'Award Date',
value : "{AwdDate}"
}
],
measures : [
{
group: 1,
name : 'Award Date',
value : '{Hist}'
},
{
group: 2,
name : 'Current PPI',
value : '{Current}'
}
],
data : {
path : "/ProductCollection"
}
});
var scatterViz = new sap.viz.ui5.Scatter({
id : "idscatter",
width : "1000px",
height : "400px",
title : {
text : 'Pricing Tool Scatter Plot Example'
},
xAxis : {
title : {
visible : true
}
},
yAxis : {
title : {
visible : true
}
},
dataset : dataset
});
scatterViz.setModel(sap.ui.getCore().getModel());
scatterViz.setModel(oModel);
var dlg = new sap.m.Dialog({
id: 'vizModal',
title: 'Scatter Plot Example Viz',
width : "1800px",
height : "600px",
content : [scatterViz],
beginButton: new Button({
text: 'Close',
press: function () {
dlg.close();
}
})
});
(new sap.m.Button({
text: 'open',
type: 'Accept',
press: function() {
dlg.open();
scatterViz.invalidate();
}
})).placeAt('content');
});
},
onToPage2 : function () {
this.getOwnerComponent().getRouter().navTo("page2");
},
});
return mainController;
});
Edit
Here is the 'products' model that is outputted on the vizframe chart. I have the products model defined in the manifest.json but the connection there is fine:
products model
{
"ProductCollection": [
{
"Item": "1",
"AwdDate": "20160715",
"Hist": 171.9,
"Current": 183
},
{
"Item": "2",
"AwdDate": "20160701",
"Hist" : 144.3,
"Current": 158.6
},
{
"Item": "3",
"AwdDate": "20150701",
"Hist": 160,
"Current": 165
},
{
"Item": "1",
"AwdDate": "20160715",
"Hist": 201,
"Current": 167
},
{
"Item": "2",
"AwdDate": "20160801",
"Hist" : 175.3,
"Current": 178.2
},
{
"Item": "3",
"AwdDate": "20150721",
"Hist": 160,
"Current": 147
},
{
"Item": "1",
"AwdDate": "20160715",
"Hist": 175.9,
"Current": 185.2
},
{
"Item": "2",
"AwdDate": "20161101",
"Hist" : 165.3,
"Current": 158.2
},
{
"Item": "3",
"AwdDate": "201700101",
"Hist": 160,
"Current": 165
},
{
"Item": "4",
"AwdDate": "201600401",
"Hist": 173,
"Current": 177
}
]
};
Edit 2
Here is my attempt at the solution offered here. But nothing appears after this is included in the onInit() function of the controller.
var regressionData = [];
for (var i = 0; i < 10; i++) {
regressionData[i] = [oData.ProductCollection[i].Current, oData.ProductCollection[i].Hist];
};
regression('linear', regressionData);
Unfortunately, you have some limitations inherent to the viz charts. Namely:
You cannot add "oblique" reference lines (= the trend line) to the chart. You can only add vertical / horizontal ones via the Reference Line feature. Check out the (non-intuitive) documentation on this: Viz Charts Documentation (look at the plotArea.referenceLine.line; it is just a number = will be a horizontal / vertical line depending on your chart type or orientation).
You cannot combine a scatter plot with a line chart. If you look in the same Viz Charts Documentation, you will see that in the Combination "chapter" on the left hand side, there is no "Line - Scatter" combination.
Also, your X values (AwDate) are ABAP-style dates as string. It is more appropriate to use a date / time chart to correctly display them. Anyway, regression makes a lot more sense when you use dates. Otherwise your data is "categorical" and the only way you can make regression is by sorting them and considering them equidistant on the X axis - not what you would normally want if you have non-equidistant data (like the one in your example).
My proposal would be to:
Use a line chart instead of a scatter chart (such that you can also display the trend line).
Convert the ABAP-style strings into dates, such that you can use a timeseries chart. You have some "wrong" dates in your example data btw: "201600401".
Do the regression for whatever you want and add it as a separate "trend" series. You will need to compute a point on the "trend" series for each point on your other series (basically, you will have to add a "trend" attribute to each line in your ProductCollection). If you are using an OData model, then you will need to either switch to an JSON client model or do some ugly workarounds with formatters.
As requested, I made an example implementation here: https://jsfiddle.net/93mx0yvt/23/. The regression algorithm I borrowed from here: https://dracoblue.net/dev/linear-least-squares-in-javascript/. The main points of the code are:
// format for parsing the ABAP-style dates
var oFormat = DateFormat.getDateInstance({
pattern: "yyyyMMdd"
});
// maps an ProductCollection entry to a new object
// which has the parsed date (and only the needed attributes)
var fnMapData = function(oEntry) {
return {
date: oFormat.parse(oEntry.AwdDate),
current: oEntry.Current,
historical: oEntry.Hist
};
};
var fnProcessData = function(oD) {
var aEntries = oD.ProductCollection.map(fnMapData),
aXs = aEntries.map(function(oE) { // get the Xs
// we take the millis to be able to do arithmetics
return oE.date.getTime();
}),
aYs = aEntries.map(function(oE) { // get the Ys (hist)
return oE.historical;
}),
//changed the function to only return only result Ys
aRs = findLineByLeastSquares(aXs, aYs);
//save the Ys into the result
for (var i = 0; i < aEntries.length; ++i) {
aEntries[i].trend = aRs[i];
}
return {
data: aEntries
};
};
You can use then the data returned by the fnProcessData function inside a JSONModel and then build a simple multi-series date/time line chart based on it.
I want to sort the W2ui grid date column in 'dd/mm/yyy' but when multiple records are in grid the date not sorted properly
i am using w2ui['grid'].sort('dd/mm/yyyy',event)
Sorry, but your code w2ui['grid'].sort('dd/mm/yyyy',event) does not make any sense.
Assuming your grid has a column called date that you want to sort descending, you'd have to call: w2ui.grid.sort('date', 'desc')
(Note that w2ui['grid'] and w2ui.grid is the same, you can pick whichever syntax you prefer).
Please see the docs for grid.sort: http://w2ui.com/web/docs/w2grid.sort
If this does not help you should provide a basic jsfiddle, with your grid columns and a few sample records.
Sorting on a date column on w2ui grid should be like below. You should provide an extra field, name as "yourDateSortable", which contains sortable string properly.
In my example "yourDateSortable" is formated version of "yourDate" in "YYYYMMDD" date format. Notice that "yourDateSortable" is hidden field. It is used for only sorting instead of "yourDate".
var dataParam = [
{
"id": 1,
"data": {
"yourDate": "27/09/2014 00:00:00",
"yourDateSortable": "20140927"
}
},
{
"id": 2,
"data": {
"yourDate": "01/03/2014 00:00:00",
"yourDateSortable": "20140301"
}
},
{
"id": 3,
"data": {
"yourDate": "10/01/2022 00:00:00",
"yourDateSortable": "20220110"
}
},
{
"id": 4,
"data": {
"yourDate": "25/04/2015 00:00:00",
"yourDateSortable": "20150425"
}
}
];
$('#resultList').w2grid({
...
columns: [
{field: 'data.yourDateSortable', text: 'Your_Date_Field Hidden', size: '90px', min: '150', sortable: true, hidden:true },
{field: 'yourDateVisible', text: 'Your_Date_Field', size: '90px', min: '150', sortable: true,
render: function (record) {
var a = moment(record.data.yourDate, "DD/MM/YYYY hh:mm").format('DD/MM/YYYY hh:mm') ;
return '<span title="' + a + '">' + a + '</span>';
} }
],
records: dataParam,
...
onSort: function (event){
if (event.field == "yourDateVisible") {
event.preventDefault();
w2ui['grid'].sort('data.yourDateSortable');
event.onComplete = function () {
w2ui['grid'].sort('data.yourDateSortable');
}
}
}
});
In a web page hosted in Google cloud storage, I will like to show revision history, which require listing all versions of the object.
Sending GET request to the bucket with ?versions parameter return list versions all objects. Is there any way to list all versions of a single object, as in gsutil ls -la, in javascript?
There is not. The closest you can do is to use versions=true and prefix=YOUR_OBJECT_NAME.
GCS will respond with a listing of objects beginning with all of the versions of your object and continuing on to any other objects that begin with YOUR_OBJECT_NAME. You'll have to check those items to see when the listing runs out of versions of your object and moves on to other objects.
If it so happens that only one object begins with YOUR_OBJECT_NAME (for example, your object is "foo.txt" and there are no files named, say, "foo.txt.backup", you will get exactly the files you want. You probably don't want to rely on this as a general practice, though.
Brondon's answer work with XML, but not with gapi client.
/**
* Get versions meta data of the object.
* #return {goog.async.Deferred} return history of the object.
*/
mbi.data.Object.prototype.history = function() {
var df = new goog.async.Deferred();
var use_gapi = true;
var name = this.getName();
if (use_gapi) {
// GAPI does not return result for versions request.
var params = {
'bucket': this.getBucketName(),
'versions': true,
'prefix': name
};
// console.log(params);
var req = gapi.client.rpcRequest('storage.buckets.get',
mbi.app.base.GAPI_STORAGE_VERSION, params);
req.execute(function(json, row) {
if (json) {
df.callback(json);
} else {
df.errback();
throw new Error(row);
}
});
} else {
var xm = mbi.data.Object.getXhr();
var uri = new goog.Uri(this.getUrl());
uri.setParameterValue('versions', 'true');
uri.setParameterValue('max-keys', '25');
uri.setParameterValue('prefix', name);
var url = uri.setPath('').setFragment('').toString();
xm.send(url, url, 'GET', null, {}, 1, function(e) {
var xhr = /** #type {goog.net.XhrIo} */ (e.target);
if (xhr.isSuccess()) {
var xml = xhr.getResponseXml();
// console.log(xml);
var json = mbi.utils.xml.xml2json(xml);
var items = json['ListBucketResult']['Version'];
var versions = goog.isArray(items) ? items : items ? [items] : [];
versions = versions.filter(function(x) {
return x['Key'] == name;
});
df.callback(versions);
} else {
df.errback(xhr.getStatus() + ' ' + xhr.getResponseText());
}
});
}
return df;
};
GAPI return as follow without version meta:
[
{
"id": "gapiRpc",
"result": {
"kind": "storage#bucket",
"id": "mbiwiki-test",
"name": "mbiwiki-test",
"timeCreated": "2013-08-20T01:18:46.957Z",
"metageneration": "9",
"owner": {
"entity": "group-00b4903a97262a358b97b95b39df60893ece79605b60280ad389c889abf70645",
"entityId": "00b4903a97262a358b97b95b39df60893ece79605b60280ad389c889abf70645"
},
"location": "US",
"website": {
"mainPageSuffix": "index.html",
"notFoundPage": "error404.html"
},
"versioning": {
"enabled": true
},
"cors": [
{
"origin": [
"http://static.mechanobio.info",
"http://mbinfo-backend.appspot.com",
"https://mbinfo-backend.appspot.com",
"http://localhost",
"chrome-extension://pbcpfkkhmlbicomenogobbagaaenlnpd",
"chrome-extension://mhigmmbegkpdlhjaphlffclbgkgelnbe",
"chrome-extension://jhmklemcneaienackijjhdikoicmoepp"
],
"method": [
"GET",
"HEAD",
"POST",
"PUT",
"DELETE",
"PATCH"
],
"responseHeader": [
"content-type",
"Authorization",
"Cache-Control",
"x-goog-meta-reviewer"
]
}
],
"storageClass": "STANDARD",
"etag": "CAk="
}
}
]
I have put together a simple jsfiddle demonstrating the issue. It has a grid with two records. One has a true value in in the Boolean column and the other has a false.
I have logged the data to the console so you can see the values that the grid is getting.
Yet the grid shows false for both rows.
http://jsfiddle.net/codeowl/KhBMT/
Thanks for your time,
Scott
Code for StackOverflow:
var _Data = [
{ "SL_TestData_ID": "1", "SL_TestData_String": "Bool is 1", "SL_TestData_Boolean": "1" },
{ "SL_TestData_ID": "2", "SL_TestData_String": "Bool is 0", "SL_TestData_Boolean": "0" }
];
var _kendoDataSource = new kendo.data.DataSource({
transport: {
read: function (options) {
console.log('Transport READ Event Raised - Data: ', JSON.stringify(_Data, null, 4));
options.success(_Data);
}
},
schema: {
model: {
id: "SL_TestData_ID",
fields: {
SL_TestData_ID: { editable: false, nullable: false },
SL_TestData_String: { type: "string" },
SL_TestData_Boolean: { type: "boolean" }
}
}
},
error: function (a) {
$('#TestGrid').data("kendoGrid").cancelChanges();
}
});
// Initialize Grid
$("#TestGrid").kendoGrid({
columns: [
{ field: "SL_TestData_ID", title: "ID" },
{ field: "SL_TestData_String", title: "String" },
{ field: "SL_TestData_Boolean", title: "Boolean" }
],
dataSource: _kendoDataSource
});
I found that if I altered my select statement to return "TRUE"/"FALSE" for my TINYINT column in the database it worked. Eg;
SELECT
SL_TestData_ID,
SL_TestData_Number,
SL_TestData_String,
SL_TestData_Date,
SL_TestData_DateTime,
if (SL_TestData_Boolean = 1, "TRUE", "FALSE") as SL_TestData_Boolean
FROM
SL_TestData;
Regards,
Scott