I'm very new to javascript (like 98.9%), so apologies in advance if this is a dumb question...
I currently have a list of book titles, and I am trying to put a small graph next to each bulleted item in the list. So to generate the graph, I'm using flot, and setting it up to use a stacked bar chart, horizontally.
Now my list may be 2, may be 20 items long. It all depends on the user who is logged in.
The challenge I have is that flot seems to work on the basis that a specifically identified HTML place holder must be set up for the graph, and then the javascript (external file in my case) which generates the graph, puts the resulting graphic into that specified placeholder.
If I've got more than one item, I need to dynamically create more unique in both the View, and then also in the javascript.
I could probably do it by writing my embedding my javascript in the View, and using some PHP to create the id's, but somehow that doesn't sound right - I'd rather try keep the neat seperation of unobtrusive JavaScript, View, Model, CSS etc.
Some pointers please...?
(This is PHP, CodeIgniter, JavaScript and CSS3)
[EDIT: Code example]
Below is not working code - it's "mid-experiment"
This is my JavaScript (in a separate myJS.js file)
function plotWithOptions(t,a,p) {
$(function () {
var d1 = [[t,10]];
var d2 = [[a,10]];
var d3 = [[p,10]];
$.plot($("#placeholder"), [ d1, d2, d3 ], {
series: {
stack: 0,
fill: true,
linewidth: 1,
bars: { show: true, barWidth: 10, horizontal: true}
},
xaxis: {max: 100, show:false},
yaxis: {max: 100, show:false},
grid: {show: false}
});
});
}
This is my View (CodeIgniter)
<script src="/assets/myJS.js"></script>
<script src="/assets/jquery.js"></script>
<script src="/assets/jquery.flot.js"></script>
<script src="/assets/jquery.flot.stack.js"></script>
<p>This book is rated....
<div id="placeholder1" style="width:300px;height:100px;"></div>
<script> plotWithOptions(28,14,11); </script>
<p>This book is rated....
<div id="placeholder2" style="width:300px;height:100px;"></div>
<script> plotWithOptions(28,27,1); </script>
<p>This book is rated....
<div id="placeholder3" style="width:300px;height:100px;"></div>
<script> plotWithOptions(28,27,26); </script>
<p>This book is rated....
<div id="placeholder4" style="width:300px;height:100px;"></div>
<script> plotWithOptions(28,14,11); </script>
I've managed to find a solution. I'm not sure if there is a "more correct" way of doing it, but the cost-benefit of finding a "purer/more elegant answer" is a beyond me right now.
This is the JavaScript file myGraphs.js
function plotWithOptions(n,t,a,p) {
$(function () {
var d1 = [[t,10]];
var d2 = [[a,10]];
var d3 = [[p,10]];
var divReference = "#placeholder"+n
$.plot($(divReference), [ d1, d2, d3 ], {
series: {
stack: 0,
fill: true,
linewidth: 1,
bars: { show: true, barWidth: 10, horizontal: true}
},
xaxis: {max: 100, show:false},
yaxis: {max: 100, show:false},
grid: {show: false}
});
});
}
And this is my CodeIgniter View
<script src="/assets/myGraphs.js"></script>
<script src="/assets/jquery.js"></script>
<script src="/assets/jquery.flot.js"></script>
<script src="/assets/jquery.flot.stack.js"></script>
<div id="Whatever">
<ul>
<?php
for ($i=1; $i<=5; $i++) {
echo "\n".'<li>';
echo "\n".'<div id="placeholder'.$i.'" style="width:300px;height:20px;"></div>';
echo "\n".'<script>plotWithOptions('.$i.',28,14,11); </script>';
echo "\n".'</li>';
}
?>
</ul>
</div>
Related
I am a beginner when it comes to the following technologies:
- ASP.NET MVC
- Entity Framework
- JavaScript (in this instance, CanvasJS)
I am trying to render a chart based on a Data Model that I have created in my solution. I am following the tutorial here (adapted to my own purposes) https://canvasjs.com/docs/charts/integration/asp-net-mvc-charts/how-to/asp-net-mvc-charts-data-entity-database/ and I have completed the following.
Created a Model of my data via EF
Passed that data from my Controller to my View
Attempted to render the chart in the View CSHTML
However, the chart does not render. When I use Chrome Debugging, the Javascript shows that the 'result' is my strongly typed model, but this must be incorrect as the error is Uncaught SyntaxError: Unexpected end of input
The rendered Javascript is as follows:
<h2>StoreView - Testing this for store group P777S001</h2>
<hr />
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<div class="text-info">Here are some examples of sales data via Entity Framework</div>
</div>
<div class="col-md-6">
<div id="chartContainer"></div>
</div>
</div>
</div>
<script type="text/javascript">
var result = System.Collections.Generic.List`1[InSiteDashboard.Models.InSiteStoreSalesSummaryTable];
var datapoints = [];
for (var i = 0; i < result.length; i++) {
datapoints.push({ label: result[i].x, y: result[i].y });
}
$(function () {
var chart = new CanvasJS.Chart("chartContainer", {
theme: "light2",
zoomEnabled: true,
animationEnabled: true,
title: { text: "Line chart" },
data: [{
type: "line",
dataPoints: dataPoints,
}]
});
chart.render();
});
</script>
I am passing this to the View using the following code (it's prototyping so the code is messy apologies)
Controller:
string _servername = $"P{store}S001";
var sales = insite.InSiteStoreSalesSummaryTables.Where(s => s.ServerName == _servername && s.daily_sales_figure > 0);
//var storeEntries = db.StoreSystemInformations.Where(s => s.StoreNumber == store);
if (sales == null)
{
return HttpNotFound();
}
ViewBag.TestValue = $"Testing this for store group {_servername}";
return View(sales.ToList());
Can anyone see something I'm obviously doing wrong here?
From first glance, I assumed your problem seem occurred because of this line:
var result = System.Collections.Generic.List`1[InSiteDashboard.Models.InSiteStoreSalesSummaryTable];
I think you're passing list directly to a JS definition intended to create JS array, but Razor returns fully-qualified name of the List<InSiteDashboard.Models.InSiteStoreSalesSummaryTable> collection because Razor implicitly called ToString() in the view instead of iterating it.
Since List``1[InSiteDashboard.Models.InSiteStoreSalesSummaryTable] is not recognized as a JS identifier or property, then "Unexpected end of input" message was thrown because of invalid syntax.
You could use model serialization to pass List<T> collection as JS array, as in example below (assumed you have model directive with #model IEnumerable<InSiteStoreSalesSummaryTable> or #model List<InSiteStoreSalesSummaryTable> as implied by return View(sales.ToList())):
// standard way
var result = JSON.parse('#Html.Raw(Json.Encode(Model))');
// using Newtonsoft.Json library
var result = JSON.parse('#Html.Raw(JsonConvert.SerializeObject(Model))');
Here is an example implementation of the script:
#model IEnumerable<InSiteStoreSalesSummaryTable>
<!-- other HTML elements, skipped for brevity -->
<script>
var result = JSON.parse('#Html.Raw(Json.Encode(Model))');
var datapoints = [];
for (var i = 0; i < result.length; i++) {
datapoints.push({ label: result[i].x, y: result[i].y });
}
$(function () {
var chart = new CanvasJS.Chart("chartContainer", {
theme: "light2",
zoomEnabled: true,
animationEnabled: true,
title: { text: "Line chart" },
data: [{
type: "line",
dataPoints: dataPoints,
}]
});
chart.render();
});
</script>
I am new to web based visualization tool I used chartjs before but I did not find any solution for chartjs so, I transferred to canvasjs.Now I'm done creating the chart and it is successfully shown, thus I want to make it moving without refreshing because the data from the database is constantly moving. Here is my code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title></title>
<script type="text/javascript" src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<script type="text/javascript" src="https://canvasjs.com/assets/script/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
window.onload = function () {
$.getJSON("json.php", function(result){
var dps= [];
//Insert Array Assignment function here
for(var i=0; i<result.length;i++) {
dps.push({"label":result[i].ts, "y":result[i].ph});
}
//Insert Chart-making function here
var chart = new CanvasJS.Chart("chartContainer", {
zoomEnabled:true,
panEnabled:true,
animationEnabled:true,
title:{
text: "myChart from mySQL database"
},
axisX:{
title: "TimeStamp"
},
axisY:{
title: "myDataPoints",
minimum: 0
},
data: [{
type: "spline",
dataPoints:
dps
}]
});
chart.render();
});
}
</script>
</head>
<body>
<div id="chartContainer" style="width: 800px; height: 380px;"></div>
</body>
</html>
now, I would like to ask for help out there What do I need to keep this chart moving...??
If you want the lines to move, you need to remove dataPoints from the beginning of the array. You can do so using shift function in JS.
for(var i=0; i<result.length;i++) {
dps.push({"label":result[i].ts, "y":result[i].ph});
dps.shift();
}
This would do the trick for you.
Below is the code I have for displaying the Chart . I am unsure as to what is going wrong here.
Please bear with me , this is the first time I have asked a question in this forum.
Thank you for your help
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(DrawChart);
function DrawChart() {
var data = google.visualization.arrayToDataTable([
['Short Shipment', 'Product Questions', 'Product Service Request', 'Billing Question','Product Issue','Return or Exchange Request','- None -'],
[1, 3, 4, 8, 8, 11, 283]]);
var options = {
chart: {
title: 'Case Issue Summary'
},
bars: 'horizontal'
};
var chart = new google.charts.Bar(document.getElementById('BarChartCase'));
chart.draw(data, options);
}
</script>
</head>
<body padding="0.5in 0.5in 0.5in 0.5in" size="Letter">
<div id="BarChartCase" style="width: 200px; height: 100px;"> </div>
</body>
</html>
Your code is 99/100 copied from developers.google.com/chart/....
The only changes you made is the width and height to 200 and 100.
Change it to a greater number and you'll be able to see your bar chart.
codepen copy
What I am trying to do with the chartist.js is allow for variable to change the values in the array which creates the chart.
So I am using the donut chart which I am using a series of 2 inside that array and 1 label.
var x = 20,
y = 60,
var chart = new Chartist.Pie('.ct-chart', {
series: [x, y],
labels: [43]
}, {
donut: true,
showLabel: true
});
I am getting an error when trying to set the x & y variables of Uncaught SyntaxError: Unexpected token var I know this is a bit of a schoolboy error but I want to make sure I am doing this the right way but not sure - the end goal is to have two input boxes which I can submit two values which in turn change the chart values and create the donut chart.
<!DOCTYPE html>
<html>
<head>
.....
</head>
<body>
<script>
function onDrawClick() {
var x = document.getElementById("xFieldId").value;
var y = document.getElementById("yFieldId").value;
var chart = new Chartist.Pie('.ct-chart', {
series: [x, y],
labels: [43]
}, {
donut: true,
showLabel: true
});
}
</script>
<div class="ct-chart"></div>
<input type="number" id="xFieldId">
<input type="number" id="yFieldId">
<button onclick="onDrawClick()">Show</button>
</body>
</html>
Your code with full example.
I found an interesting and nice gauge on the justgage.com site.
I really would like to insert gauge meter on my app written in the Flask and using Jinja2 templating language. But unfortunately I don't know how.
In the above site they show that I just need to insert the following code:
<script>
var g = new JustGage({
id: "gauge",
value: 67,
min: 0,
max: 100,
title: "Visitors"
});
</script>
OK, but I also would like to set and update some its parameters (i.e. value, max, etc.) by Jinja markups {{ }} or in the Python and then export all (from <script> to </script>) to Jinja. For example:
value: {{ my_val_from_the_database }}
It's possible to do that in the Jinja2 or Python/Flask? Or is there another way to do this?
Many thanks in advance!
You have already found the answer
Yes you can assign the value from jinja
<html>
<head>
<script>
var g = new JustGage({
id: "gauge",
value: {{value}},
min: 0,
max: 100,
title: {{gage_tile}}
});
</script>
.....
In python
data = {
"value" : custom_value,
"gage_title" : custom_title
}
render('template.html', data)