I'm beginning to use html charts to display data coming from json files. Up until five days ago, I very rarely did anything with html charts. But now that's all I do.
So I'm using an anychart chart, and I've been trying to find a way to populate the chart with a 'json` file.
After much trial-error, I was able to somewhat separate the data and move it to a json file. The problem is that the file's not completely json string.
As you can see, MyFile.json has the json string and some chart components. I would like my json file to be only json data; everything else should be in the html, another javascript, or anywhere else. But it cannot be in the json file.
In other words, MyFile.json should only include this:
{"x": "January","value": 10000},{"x": "February","value": 12000}, {"x": "March","value": 18000}]
Is this possible? Any help is appreciated. Thanks.
Here's MyFile.json:
{
"chart": {
"type": "line",
"series": [{
"seriesType": "spline",
"data": [{
"x": "January",
"value": 10000
}, {
"x": "February",
"value": 12000
}, {
"x": "March",
"value": 18000
}]
}],
"container": "container"
}
}
And here's my html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.anychart.com/js/7.13.1/anychart-bundle.min.js"></script>
<link rel="stylesheet" href="https://cdn.anychart.com/css/latest/anychart-ui.min.css">
</head>
<body>
<div id="container"></div>
</body>
</html>
<script>
$(document).ready(function(){
$.getJSON('MyFile.json', function(data) {
console.log(data);
anychart.fromJson(data).draw();
});
});
</script>
If I understood your question correctly... There might be a way within Anycharts to do this in a better way (like assign an object as the "settings" then assign a different one wit the "data"), but here's one way that you could implement this yourself:
JSON file:
[{
"x": "January",
"value": 10000
}, {
"x": "February",
"value": 12000
}, {
"x": "March",
"value": 18000
}]
AJAX request in javascript file:
$(document).ready(function(){
$.getJSON('MyFile.json', function(data) {
var wrapper = {
"chart": {
"type": "line",
"series": [{
"seriesType": "spline",
"data": data // adding the ajax response data
}],
"container": "container"
}
};
anychart.fromJson(wrapper).draw();
});
});
You can embed json data in a html element using data-* attributes.
One approach is to append each chart into the container first and then set jquery data with the series.
$.getJSON('MyFile.json', function (charts) {
for (var i = 0, len = charts.length; i < len; i++) {
$('#container').append('<div id="chart_' + i + '"></div>');
$('chart_' + i).data('series', charts[i].series.data);
}
});
Related
I have a site with two vega-lite graphs that show different aspects of the same dataset, which is generated dynamically (similar to this example). Currently they both hold their own version of this dataset.
Since the dataset tends to get quite big I would like them to share the data between them so they use less memory.
Since the data will be updated later (from the function update_vega()) I can't just put it into a variable and embed it in both diagrams.
Is it possible in vega-lite to have multiple graphs sharing the same data-object and how can I do it?
Here is my code (I have only been learning javascript 3 days ago, so I am very happy about feedback on every level):
<!DOCTYPE html>
<html>
<body>
<!-- setup of the vega graph -->
<script src="https://cdn.jsdelivr.net/npm/vega#5.10.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite#4.6.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed#6.3.2"></script>
<div id="vega_graph_one"></div>
<div id="vega_graph_two"></div>
<script>
var vlSpec_one = {
$schema: 'https://vega.github.io/schema/vega-lite/v4.json',
data: { name: 'table', values: [{"time":11, "age": 4},{"time":12, "age": 4},{"time":11, "age": 5}]},
width: 400,
mark: 'bar',
encoding: {
x: {field: 'time', type: 'quantitative', binned: true},
y: {aggregate: "count", type: 'quantitative'},
color: {field: 'age', type: 'quantitative'}
}
}
var vlSpec_two = {
$schema: 'https://vega.github.io/schema/vega-lite/v4.json',
data: { name: 'table', values: [{"time":11, "age": 4},{"time":12, "age": 4},{"time":11, "age": 5}]},
width: 400,
mark: 'point',
encoding: {
x: {field: 'time', type: 'quantitative'},
y: {field: 'age', type: 'quantitative'},
}
}
// two global variables so the view can be updated from an outside function
var view_one;
var view_two;
vegaEmbed('#vega_graph_one', vlSpec_one).then(
result => { view_one = result.view;},
reason => { console.error(reason);}
)
vegaEmbed('#vega_graph_two', vlSpec_two).then(
result => { view_two = result.view;},
reason => { console.error(reason);}
)
// update the vega graph from outside
// call with update_vega([{"time":11, "age": 4},{"time":12, "age": 4},{"time":9, "age": 6}])
function update_vega(event_data){
var changeSet = vega.changeset()
.insert(
event_data
);
// data dublication happense here
view_one.change("table", changeSet).run();
view_two.change("table", changeSet).run();
}
</script>
</body>
</html>
First, consider putting your data in javascript function and call it in data, should be easier to maintain for both data and chart:
function getData(){
var mydata = [{"time":11,"age": 4},{"time":12,"age": 4},{"time":11, "age":5}];
return mydata;
}
Then you can call it:
{
"data": getData(),
"mark": {"type" : "bar"}
}
There are several concepts that help achieving data sharing based on your needs.
You need just one vegaEmbed and one vlSpec that utilizes one of the following:
Layers
Put data on top of all layers and refer to it from each mark's layer
{
"data": {"values":getData()},
"layer": [
{
"mark": {"type" : "bar"}
},
{
"mark": {"type" : "point"}
}
]
}
Concat
vconcat, hconcat, and concat can be used to produce multiple charts of different mark each using same data, it doesn't perfectly suite your case because you don't have the same x and y fields in every mark. Read more on Concatenating views
{
"data": {"values":getData()},
"concat": [
{
"mark": {"type" : "line"},
"encoding": {
"x": {"field": "time"},
"y": {"field": "age"}
}
},
{
"mark": {"type" : "bar"},
"encoding": {
"x": {"field": "time"},
"y": {"field": "age"}
}
}
]
}
I used the code from this github gist that allows you to save a single content into a VCF file.
<!doctype html>
<html>
<head>
<script type="text/javascript" src="vcard2.js"></script>
</head>
<script type="text/javascript">
// From JSON
var johnSmith = {
"version": "4.0",
"n": "SMITH;John;;",
"fn": "John Smith",
"nickname":"js",
"title": "Missing man too",
"tel": [
{"value": "555-555-555", "type": "cell"}
],
"email": [
{ "value": "john.smith#work.com", "type": "work" },
{ "value": "john.smith#home.com", "type": "home" }
]
}
var link = vCard.export(johnSmith, "John Smith", false) // use parameter true to force download
document.body.appendChild(link)
</script>
</body>
</html>
This worked for single content as file see JSfiddle.
My question is how to add multiple contents into same VCF file.
In the fiddle you provided just edit the dump() function to accept array. Then iterate the array and perform the exact same operations, combining the output (split with \n) into one variable.
dump: function(cards) {
var cardsLength = cards.length;
var cardsStr = "";
for (var cardsIndex = 0; cardsIndex < cardsLength; cardsIndex++) {
var card = cards[cardsIndex];
//...existing code... just remove the return
cardsStr+=str+"\n";
}
return cardsStr;
}
Now call vCard.export() and pass an array of objects instead of object.
Try it here: JSFiddle
I have a js file that graphs a function with all the necessary parameters. I wish to do something like this in html:
<script src="js/index2.js" value = {{GraphData}}></script>
the js file looks something like this
var chart = AmCharts.makeChart("chartdiv", {
"graphs": [{
"id": "g3",
"valueAxis": "v1",
...
}],
"Data" = {{GraphData}}
})
Is there a way to transfer the graph data to the js file?
There's a fundamental misunderstanding here about the function of the script tag. "value" is not a valid attribute of the HTML script tag, which is used to import the text contents of a JavaScript file into your HTML file.
To achieve what you want, you can simply remove:
<script src="js/index2.js" value = {{GraphData}}></script>
and replace it with what you want imported:
var chart = AmCharts.makeChart("chartdiv", {
"graphs": [{
"id": "g3",
"valueAxis": "v1",
...
}],
"Data" = {{GraphData}}
})
More info on the HTML script tag here and here.
If you want to keep this script external, then you can use it to define a function that takes {{GraphData}} as an argument like this:
function graphData(gd) {
var chart = AmCharts.makeChart("chartdiv", {
"graphs": [{
"id": "g3",
"valueAxis": "v1",
...
}],
"Data" = gd
});
}
and then call that function in your HTML file like this:
<script src="js/index2.js"></script>
<script>
graphData({{GraphData}})
</script>
I have created a simple form using alpacajs, as per the documentation provided by alpacajs.org we can use properties such as optionsSource, schemaSource, viewSource, dataSource for loading the external json files into our application. But what i need is i need to use only one json file for all these. I mean instead of using all these 3 different properties can i use only one parameter for loading the single json file which comes from the backend. please check my code below..
<html>
<head>
<meta charset="UTF-8">
<title>My Little Alpaca Form</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"> </script>
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script src="//code.cloudcms.com/alpaca/1.5.22/bootstrap/alpaca.min.js"></script>
<!-- typeahead.js https://github.com/twitter/typeahead.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.10.5/bloodhound.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.10.5/typeahead.bundle.min.js"></script>
<link href="//code.cloudcms.com/alpaca/1.5.22/bootstrap/alpaca.min.css" rel="stylesheet" />
<link type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/>
</head>
<body>
<div id="form1"></div>
<script type="text/javascript">
$(document).ready(function() {
$("#form1").alpaca({
"dataSource": "/fulfiller/connector-custom-data.json",
"schemaSource": "/fulfiller/connector-custom-schema.json",
"optionsSource": "/fulfiller/connector-custom-options.json",
"viewSource": "/fulfiller/connector-custom-view.json",
"view": {
"parent": "bootstrap-edit",
"layout": {
"template": "threeColumnGridLayout",
"bindings": {
"requestedfor": "column-1",
"location": "column-2",
"shortdescription": "column-3",
"description": "column-3",
}
},
"templates": {
"threeColumnGridLayout": '<div class="row">' + '{{#if options.label}}<h2>{{options.label}}</h2><span></span>{{/if}}' + '{{#if options.helper}}<p>{{options.helper}}</p>{{/if}}' + '<div id="column-1" class="col-md-6"> </div>' + '<div id="column-2" class="col-md-6"> </div>' + '<div id="column-3" class="col-md-12"> </div>' + '<div class="clear"></div>' + '</div>'
}
},
"options": {
"fields": {
"requestedfor": {
"type": "text",
"id": "requestedfor",
"label": "*Requested For",
"typeahead": {
"config": {},
"datasets": {
"type": "remote",
"displayKey": "value",
"templates": {},
"source": "http://www.alpacajs.org/data/tokenfield-ajax1.json"
}
}
},
"location": {
"type": "text",
"label": "*Location"
},
"shortdescription": {
"type": "text",
"label": "Short Description"
},
"description": {
"type": "textarea",
"rows": 5,
"cols": 40,
"label": "Description"
}
},
"form": {
"attributes": {
"action": "#",
"method": "post"
},
"buttons": {
"submit": {
"value": "Submit",
"class": "btn btn-default"
}
}
}
}
});
});
</script>
</body>
</html>
So here in the above code i have used these urls for loading json data..
"dataSource": "/fulfiller/connector-custom-data.json"
"schemaSource": "/fulfiller/connector-custom-schema.json"
"optionsSource": "/fulfiller/connector-custom-options.json"
"viewSource": "/fulfiller/connector-custom-view.json"
So instead of using these 3 different properties can i use only one property like "oneSingleJSONSource": "oneJSONRemoteFile.json"
Can anybody provide inputs?
For Alpaca to be inialized it must have a DOM element + a config object that contains the schema, options and other properties that Alpaca already knew in its core code, so in your case this is possible if you try to modify the alpaca core code... If your objective is only to optimize resource loading you can use only one json file that contains all the configuration and input them in the alpaca initialization $(dom).alpaca(_json_data_from_loaded_file). And if you want to have only schema, options and view settings in on file you should divide the data loaded to 3 objects, 1 for schema, 1 for options and the last one for view settings.
Tell me if you want more details on achieving this.
I'll be glad to help.
Trying to get the certain fields to display, ideally in a table (headings, rows & columns). And looking for a best way find fields in a Json feed. I tried using the controller to find the fields then pass that data to the view in the HTML.
Is there something wrong in the controller with respect to the Json? the fields are empty. Seems like nothing is passed from the controller to the view ? This is what I tried:
<!doctype html>
<html ng-app="app" >
<head>
<meta charset="utf-8">
<title>LIVE</title>
<!-- <link rel="stylesheet" href="style.css"> -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js"></script>
<script>
var app = angular.module('app', []);
app.controller('DataCtrl', function ($scope, $http) {
$scope.result = {
"data": {
"transactionList": [{
"barcode": "52905819992681",
"training": 0,
"tranNo": 1,
"userId": "8796093054980",
"retailerId": "defaultRetailer",
"storeId": "12Store",
"deviceId": "afd03463-9ee7-45d4-9d2e-8d64a683f126",
"tillId": "2",
"tranTypeId": "regularSale",
"isTranVoid": 0,
"totalItems": 1,
"merchTotal": 50.0,
"promoTotal": 0.0
}, {
"barcode": "52905819592681",
"training": 0,
"tranNo": 1,
"userId": "8796093054980",
"retailerId": "defaultRetailer",
"storeId": "23Store",
"deviceId": "afd03463-9ee7-45d4-9d2e-8d64a683f126",
"tillId": "2",
"tranTypeId": "regularSale",
"isTranVoid": 0,
"totalItems": 1,
"merchTotal": 50.0,
"promoTotal": 0.0
}]
}
}
};
$scope.elements = $scope.result.data.transactionList.map(function (res) {
var e = {};
e.transTypeId = res.transTypeId;
e.userId = res.userId;
e.storeId = res.storeId;
return e;
});
});
</script>
</head>
<body ng-controller="DataCtrl">
<h1>Live from the JSON feed</h1>
<ul>
<li ng-repeat="e in elements">
{{ e.transTypeId}}: {{ e.userId }}, {{ e.storeId }}
</li>
</ul>
</body>
</html>
You have a extra } in your $scope.result. It should be like:
$scope.result = {
"data": {
"transactionList": [{
"barcode": "52905819992681",
"training": 0,
"tranNo": 1,
"userId": "8796093054980",
"retailerId": "defaultRetailer",
"storeId": "12Store",
"deviceId": "afd03463-9ee7-45d4-9d2e-8d64a683f126",
"tillId": "2",
"tranTypeId": "regularSale",
"isTranVoid": 0,
"totalItems": 1,
"merchTotal": 50.0,
"promoTotal": 0.0
}, {
"barcode": "52905819592681",
"training": 0,
"tranNo": 1,
"userId": "8796093054980",
"retailerId": "defaultRetailer",
"storeId": "23Store",
"deviceId": "afd03463-9ee7-45d4-9d2e-8d64a683f126",
"tillId": "2",
"tranTypeId": "regularSale",
"isTranVoid": 0,
"totalItems": 1,
"merchTotal": 50.0,
"promoTotal": 0.0
}]
}
};
// get rid of this};
Here is working plunkr
Perhaps a }; too many?
Automatic indentation usually makes those kinds of errors apparent.
Have you tried to use ng-model="...", it gives you the opportunity to overwrite an attribute or to show it. You can try it with
<input type="number" ng-model="someID" disabled="disabled">
*disabled if u need readOnly on that field.
and see how it works, maybe it can help you out.
regards
I may be wrong, but you are trying to read json data directly without parsing it?
MDN JSON.parse()
Also it would be nice if you upload your code on something like http://jsfiddle.net
This way people can test it out.