I have used highcharts single line series graph. It seems to work all fine but when I resize the page (just to check responsiveness or just it on mobile). The values disappear. I can see error in console logs.
That's how I generate the chart
Highcharts.stockChart('nav-chart', {
tooltip: {
pointFormat:"{point.y:.3f}\u20ac"
},
chart: {
type: 'line',
zoomType: 'x',
pinchType: 'x',
panning: false,
<?php if (is_front_page()){ ?>
height: 700,
<?php } else { ?>
height: 500,
events: {
load: updateLegendLabel
}
<?php } ?>
},
updateLegendLabel has some computation that generates the labels.
var chrt = !this.chart ? this : this.chart;
chrt.update({
legend: {
useHTML: true,
symbolPadding: 0,
symbolWidth: 0,
symbolHeight: 0,
symbolRadius: 0,
labelFormatter: function() {
var lastVal = this.yData[this.yData.length - 1],
chart = this.chart,
xAxis = this.xAxis,
points = this.points,
avg = 0,
counter = 0,
min, max;
... there is some business logic down there
points var becomes null when I resize the page. Why is that so? Do I need to reupdate dataset or what?
Nesting Server and Client side logic is not good. Better is to seperate logic using like this. Bellow one is just for idea not a exact code. But can be fixed if you provide complete code separating your server logic from client side logic.
<script>
//before graph area started
var dataA = '<?php echo $dataA;?>';
var dataB = '<?php echo $dataB;?>';
//graph logic started
// your graph code which can use above variables
// but the variable need to be available can be evaluated from your draw script.
</script>
then use these variables in your graph script.
Because on resizing of browser, graph is redrawing and its looking data is not available when graph is redrawing. But if above logic will be used then data will be available on every redraw
Related
`<script>
Chart.pluginService.register({
beforeDraw: function (chart) {
var width = chart.chart.width,
height = chart.chart.height,
ctx = chart.chart.ctx;
ctx.restore();
var fontSize = (height / 114).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "middle";
var text = chart.config.options.elements.center.text,
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
});
// chart1
var data = {
labels: ["Red", "Blue"],
datasets: [{
data: [50],
backgroundColor: ["#BEFF60", "#36A2EB"],
hoverBackgroundColor: ["#BEFF60", "#36A2EB"]
}]
};
var promisedDeliveryChart = new Chart(document.getElementById('myChart1'), {
type: 'doughnut',
data: data,
options: {
title: {
display: true,
text: 'OEE Chart'
},
elements: {
center: {
text: parseInt(<?php echo json_encode($OEE); ?>) + '%', //set as you wish
}
},
cutout Percentage: 85,
legend: {
display: false
}
}
});
</script>
`
I have few questions here.
I have already created Plugins Service and doughnut chart code where I standardize everything including having a text in between the doughnut chart - how can I small changes the Plugin Service so that where I can add picture send towards backwards and bring the text infront?? - Is it possible this same Plugin Service used after modification answers given by anyone where for other charts but dont want to add the picture and text as other charts will be either bar graph or line chart etc... can anyone guide me with these kind of things. I'm not sure how to do it.. any advice??
If lets say I want to do chartsJS for stepped line chart how is that?? I tried using the same Plugin Service but failed. if if each type of chart need to use different plugins I can do it... but the issue I will create their separate files and call them in PHP index folder (as the main file running the website but when I add the JavaScript link and add call the name from the JS file into the PHP index file failed. Hopefully someone can guide me or advice me on this
when i use the same PluginService(which is used for doughnut chart) i cannot show the results for barchart , line chart etc using the same PluginService when i pass <php json() file ?> from the database file i created to pass the data into data[] in chartJS
-dscsccsss\\\\\\
the question I am asking is from a code-architecture point of view. I am preparing a report in php which is built with a string $message and then send via a php mail function.
For example the report is built in the php file like that(basically concatenates strings):
$message .= <<<HTML
</td>
</tr>
</tbody>
</table>
HTML;
Further, I would like to include a chart. However, trying the following example and sending it per mail I get no chart and an empty <div style="width:900px;min-height:500px"></div> ==$0 value.
$message.=<<<HTML
<tr valign="top" align="center">
<script type="text/javascript">
google.charts.load("current", {packages:['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Element', 'Density', { role: 'style' }],
['Copper', 8.94, '#b87333', ],
['Silver', 10.49, 'silver'],
['Gold', 19.30, 'gold'],
['Platinum', 21.45, 'color: #e5e4e2' ]
]);
var options = {
title: "Density of Precious Metals, in g/cm^3",
bar: {groupWidth: '95%'},
legend: 'none',
};
var chart_div = document.getElementById('chart_div');
var chart = new google.visualization.ColumnChart(chart_div);
// Wait for the chart to finish drawing before calling the getImageURI() method.
google.visualization.events.addListener(chart, 'ready', function () {
chart_div.innerHTML = '<img src="' + chart.getImageURI() + '">';
console.log(chart_div.innerHTML);
});
chart.draw(data, options);
}
</script>
<div id='chart_div'></div>
</tr>
HTML;
My guess is that javascript is not accepted by f.ex. GMail. Hence, I am trying to create a png beforehand which is then included in the report.
My preferred way of doing this would be the google charts library, however, it has no support for php and is entirely based on JavaScript.
Hence, my questions are:
How can I use the google chart library in my code?
Any other suggestions if above does not work?
I appreciate if you could provide an example!
Thx in advance!
Email clients strip Javascript, SVG, and other formats, so you can't use a chart library directly in email.
Your options include:
Use getImageURI to generate a PNG of your chart and send it to your server to be emailed. This is probably the best solution if you know a client will load every chart before it needs to be emailed.
Use a tool like wkhtmltoimage to "headlessly" render a webpage that displays your charts and save it as an image.
Use a chart image rendering web service like QuickChart to generate the chart image (fyi: this is an open-source project that I started).
QuickChart in particular is built on Chart.js, so you'd have to create a Chart.js chart definition as a string:
$chartConfig = "{
type: 'bar',
data: {
labels: ['Copper', 'Silver', 'Gold', 'Platinum'],
datasets: [{
data: [8.94, 10.49, 19.30, 21.45],
backgroundColor: ['#b87333', 'silver', 'gold', '#e5e4e2'],
}]
},
options: {
title: {
display: true,
text: 'Density of Precious Metals, in g/cm^3',
},
legend: {
display: false
}
}
}";
I've used a static string to match your example, but you can include dynamic variables like in any other PHP string.
Then encode this string into a URL:
$chartUrl = 'https://quickchart.io/chart?c=' . urlencode($chartConfig);
This URL returns a chart that looks like this:
Finally, add the chart to your email body as an HTML image tag:
$message .= "<img src=\"$chartUrl\"/>";
How I can insert array value in php and mysql from variable Var s1, s2, s3:
$(function () {
var s1 = [100, 200, 300]; //How to Get Value from mysql database
var s2 = [30, 80, 90]; //How to Get Value from mysql database
var s3 = [120, 90, 80]; //How to Get Value from mysql database
// Can specify a custom tick Array.
// Ticks should match up one for each y value (category) in the series.
var ticks = ['2010', '2011', '2012'];
var plot1 = $.jqplot('chart3', [s1, s2, s3], {
// The "seriesDefaults" option is an options object that will
// be applied to all series in the chart.
seriesDefaults: {
shadow: true, // show shadow or not.
renderer: $.jqplot.BarRenderer,
rendererOptions: {
fillToZero: true
}
},
// Custom labels for the series are specified with the "label"
// option on the series option. Here a series option object
// is specified for each series.
series: [
{label: 'Hotel'},
{label: 'Event Regristration'},
{label: 'Airfare'}
],
// Show the legend and put it outside the grid, but inside the
// plot container, shrinking the grid to accomodate the legend.
// A value of "outside" would not shrink the grid and allow
// the legend to overflow the container.
legend: {
show: true,
placement: 'outsideGrid'
},
axes: {
// Use a category axis on the x axis and use our custom ticks.
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
ticks: ticks
},
// Pad the y axis just a little so bars can get close to, but
// not touch, the grid boundaries. 1.2 is the default padding.
yaxis: {
pad: 1.05,
tickOptions: {
formatString: '$%d'
}
}
},
grid: {
borderColor: '#000', // CSS color spec for border around grid.
borderWidth: 2.0, // pixel width of border around grid.
shadow: true // draw a shadow for grid.
}
});
// Bind a listener to the "jqplotDataClick" event. Here, simply change
// the text of the info3 element to show what series and ponit were
// clicked along with the data for that point.
$('#chart3').bind('jqplotDataClick',
function (ev, seriesIndex, pointIndex, data) {
$('#info3').html('series: ' + seriesIndex + ', point: ' + pointIndex + ', data: ' + data);
});
});
2 ways:
Ajax
Use: $.getJSON ( http://api.jquery.com/jQuery.getJSON/ )
var ses = {};
$.getJSON('page_adress.php', {variable_you_want_to_pass1: 'its value', variable_you_want_to_pass2: 'var 2 value'}, function(data) {
ses = data;
});
In your PHP:
<?php
$passed_var_1 = $_REQUEST['variable_you_want_to_pass1'];
//.... etc
//Here you get your data from mysql, cast it into array
header('Content-type: application/json');
echo json_encode($dbdata);
?>
So basically after request finishes you will have exact array you had in PHP transferred in JavaScript. Have in mind that this technique uses AJAX. If you want to avoid that, you will have to use second technique.
Dynamically Creating JS
Make PHP generate your javascript. In this case you would have in your main page
<script src="js_data.js.php" type="text/javascript"></script>
In your js_data.js.php file:
<?php
header("content-type: application/x-javascript");
$s1 = array(100,200,300);
//....
var s1 = [<?=implode(', ', $s1)?>],
s2 = [<?=implode(', ', $s2)?>],
s3 = [<?=implode(', ', $s3)?>];
?>
First method (w/o ajax & json)(untidy-way)
First fetch the value from database and have it in PHP variable.
Then put html element in page and assign the value to it.
Then use it in javascript using document.getElement method.
// assume that you have got value from database in $valueFrmDB.
$valueFrmDB;
Now, take html element(you might have to take more than one)
<input type="hidden" id="something" name="something" value="echo value of $valueFrmDB here" />;
Then, in javascript
var vfd = document.getElementById('something').value;
convert string to array
Second method(with ajax and json)(simple & correct but must know ajax and json)
Use ajax to fetch the values from database
Then use json to pass that values to javascript
simply you can do this by:
<?php
$query = mysql_query("SELECT * FROM attendence");
$results = array(array());
while($line = mysql_fetch_array($query)){
$results[] = $line;
}
?>
Javascript
<script type="text/javascript">
$(document).ready(function(){
var data = <?php echo json_encode($results); ?>; //array uses here
var plot1 = jQuery.jqplot ('chart1', [data],
{
seriesDefaults: {
renderer: jQuery.jqplot.PieRenderer,
rendererOptions: {
showDataLabels: true}
},
legend: { show:true, location: 'e' }
});
});
</script>
I am having problems plotting my pie chart using jqplot.
After getting my results from php i have converted it to json using json_encode. The output is
{"a":2,"b":1,"c":5,"d":650}
Now when i try to put these results into my javascript
<script class="code" type="text/javascript">
$(document).ready(function(){
// method 1
//var data1 = document.getElementById("dataArray").value;
//eval('data1 = '+data+';');
// method 2
var data1 = <?php echo json_encode($data); ?>;
var plot1 = jQuery.jqplot ('Chart', [data1],
{
seriesDefaults: {
// Make this a pie chart.
renderer: jQuery.jqplot.PieRenderer,
rendererOptions: {
// Put data labels on the pie slices.
// By default, labels show the percentage of the slice.
showDataLabels: true
}
},
legend: { show:true, location: 'e' }
}
);
});
</script>
I've tried two methods, the first to put it inside a hidden field, and the second to retrieve straight from PHP. Both of which result in Uncaught. No plot target specified errors in my Chrome console.
What is it I am doing wrong here?
Thanks guys.
As Asad mentioned, my stupid mistake was that Chart was not specified as an element. So yeah if anyone else ever comes into the same problem, be sure to check that out. :)
I'm trying to modify Gaya Design's Tabbed Content (Available Here) to have the current tab persist when the page is reloaded, yet have it change when a new tab is clicked. I've already changed it a little to be able to change default tab by using a PHP GET variable. The current condition of the page I'm working on can be viewed here.
So here's my likely scenario. If you've clicked on the link above, you'll see I'm working on a simple PHP shopping cart. Now when a user clicks an add link, it has to reload the page, and when it does that it resets the tab. So, I'm thinking this should easily be solved with a cookie that updates whenever a new tab is clicked....I'm just not too sure how to go about this. Any thoughts, suggestions, or advice will be greatly appreciated.
Here's my current JS:
var TabbedContent = {
init: function() {
$(".category").click(function() {
var background = $(this).parent().find(".selected");
$(background).stop().animate({
left: $(this).position()['left']
}, {
duration: 350
});
TabbedContent.slideContent($(this));
});
},
slideContent: function(obj) {
var margin = $(obj).parent().parent().find(".sliderContainer").width();
margin = margin * ($(obj).prevAll().size() - 1);
margin = margin * -1;
$(obj).parent().parent().find(".displayContent").stop().animate({
marginLeft: margin + "px"
}, {
duration: 1
});
},
gotab: function( obj ) {
var background = $(obj).parent().find(".selected");
$(background).stop().animate({
left: $(obj).position()['left']
}, {
duration: 1
});
TabbedContent.slideContent( $(obj) );
}
}
$(document).ready(function() {
TabbedContent.init();
});
Here's how a tab is initialized when it is linked to:
<?php
// Load a specific tab if required
if(isset($_GET['tab'])) {
// Array storing possible tab IDs
$tabChoices = array('productsTab', 'specsTab', 'brochuresTab', 'bannersTab', 'kitsTab', 'displaysTab');
$tab = '';
if(in_array($_GET['tab'], $tabChoices)) $tab = $_GET['tab'];
// Default to productsTab if not in array list
else $tab = 'productsTab';
// JS to actually do the switch
echo '<script>$(document).ready(function() {TabbedContent.gotab($("#' . $tab . '"))});</script>';
}
?>
You're painting yourself into a corner by inline scripting a solution. You should always only have one $(document).ready... call in your entire product, in order to avoid order dependent explosions in code, and have a clear point of entry.
That said, you are almost there. Instead of calling a function, assign a value.
echo "<script>var selectedTab=$tab;</script>"
Then during your initialization function, make use of that value. My example is in global scope. There may be a race condition if you try to assign it to a namespace. In that case, try putting that script at the bottom of the page.
One more suggestion, have one and only one function handle all of your animations calls for that object.
Instead of using get/post params you could use hash; creating links like this in the tabs:
<a class="tab_item" href="#one_go" id="one">
And then put this in the javascript:
var gototab = document.location.hash.replace('_go',"")
if(gototab){
$(gototab).each(function(){
var pos = $(this).prevAll(".tab_item").length,
left = pos * $(this).outerWidth(),
margin = pos * $(this).parent().parent().find(".slide_content").width() * -1;
$(this).parent().find('.moving_bg').css('left',left)
$(this).parent().parent().find(".tabslider").css('margin-left',margin)
})
}