With <canvas> and JavaScript in php,I am trying to draw multiple pie charts.But charts are overlapping.
Here my javascript code:
printf('<script type="text/javascript">');
?>
function drawPie(data)
{
var ctx = $("#mycanvas").get(0).getContext("2d");
var piedata = [];
$.each(data,function(i,val){
piedata.push({value:val.count,color:val.color,label:val.status});
});
new Chart(ctx).Pie(piedata);
}
<?php
printf('</script>');
PHP code:
$data = statusPool($pool);//fetching database values(array() of label and count )
printf('<canvas id="mycanvas" width="500" height="300"></canvas>');
$data3 = json_encode($data, JSON_NUMERIC_CHECK);
echo '<script type="text/javascript"> drawPie('.$data3.'); </script>';
printf( '<table ><tr>' );
$poolArray =array(//some values)
$chartCount = 0;
foreach ( $poolArray as $pool )
{
if ($chartCount == 2)
{
printf('</tr><tr>');
$chartCount = 0;
}
printf('<td style="text-align: center;"><canvas id="mycanvas"width="256" height="256"></canvas>');
$data = statusPool($pool);
$data3 = json_encode($data2, JSON_NUMERIC_CHECK)
echo '<script type="text/javascript"> drawPie(' . $data3 . ');</script>';
$chartCount++;
printf('</a></td>')
}
printf( '</tr></table>' );
First <canvas> is for big pie chart and other small charts will come in table.
But all the charts are overlapped.
Can you tell me how to get rid of that overlapping.
Thanks in advance.
Thank you for adding the screenshot! The problem, as far as I can see, is, that all of your canvas elements have the same ID "mycanvas". In HTML, all objects are supposed to have an unique ID (if you give one to them at all). Classes can be used for more than one object, and one object can have multiple classes. It is like all employees of a company usually have different names (id) to identify them, but several people can be assigned a specific team (class) and people can also be in more than one team. If people have the same name, it usually causes confusion in the office. You have the same problem here.
To fix it, give every canvas an unique id. This could look similar to this:
echo '<td style="text-align: center;"><canvas id="pie-canvas-'
. $canvasId
. '"width="256" height="256"></canvas>';
Pass the ID you gave to your canvas to the function that is drawing it.
echo '<script type="text/javascript">drawPie('
. $canvasId
. ', '
. $data3
. ');</script>';
I don't really know what is in $data2 or $data3, but I assume it also contains something like an ID that you could use for this purpose. If not, let the loop iterate a variable and use its value as ID. When you add the script to draw the current pi in the loop, pass the ID as parameter (if you do not already do it with $data3) and select the particular canvas from the document using
function drawPie(canvasId, data) {
[...]
var ctx = $("#pie-canvas-" + canvasId).getContext("2d");
[...]
}
Btw. you have some errors in your code like missing semicolons, unopened or unclosed HTML tags, etc.
Related
I am building a simple website for my family to track the jigsaw puzzles they own. One feature is the ability to delete a puzzle they no longer own. I intend to pass the row ID to a separate file as an argument, but thought I should put a javascript confirmation popup in the middle. I seem to have everything running almost correctly, but the argument being passed is incorrect and I don't know why. It is passing the ID of the last row in the table, rather than the current row ID. Hoping someone can point me in the right direction.
PHP Code
while ($row = $result->fetch_assoc()) {
echo "<script>var puzzleID = " . $row['id'] . "</script>";
echo "<td><a href='puzzleedit.php?=" . $row['id'] . "'>Edit</a> | <button onclick='confirmationBox()'>Delete</button></td>";
}
JS Code in a separate file
function confirmationBox() {
if (confirm("Are you sure you want to delete this puzzle?")) {
window.location = './puzzledelete.php?=' + puzzleID
} else {
}
}
The interesting thing is that using $row['id'] in the edit link works as expected, it is grabbing the correct row ID from the database. The $row['id'] in the script is grabbing the table's last row ID.
Your loop keeps reassigning puzzleId. When you call confirmationBox(), it will have the last value that was assigned, not the one that was assigned before each <td>.
Instead of using a global variable, use a function parameter.
while ($row = $result->fetch_assoc()) {
echo "<td><a href='puzzleedit.php?=" . $row['id'] . "'>Edit</a> | <button onclick='confirmationBox(" . $row['id'] . ")'>Delete</button></td>";
}
function confirmationBox(puzzleID) {
if (confirm("Are you sure you want to delete this puzzle?")) {
window.location = './puzzledelete.php?=' + puzzleID
} else {
}
}
I'm a 'newbie' on stackoverflow but it is a source that I keep coming to regularly for tips.
I've picked up some code from the simple.html file accompanying the jsPDF auto-table plug-in but as it doesn't appear to pick up data from a php generated table.
I am trying to get the data into a format that can be transformed into a nice pdf report - 'with all the trimmings' - ie; page-breaks, headers on each page, alternate row-colours etc.
I've tried to get the data into a form that can be used by the jsPDF autotable but I'm going wrong in that it is just going through the array and keeping the last record and printing that in pdf format. Code shown below.
<button onclick="generate()">Generate pdf</button>
<script src="/js//jspdf.debug.js"></script>
<script src="/js/jspdf.plugin.autotable.js"></script>
<?php
$link = mysqli_connect('localhost','user','password','database');
if(!$link)
{
echo 'Database Error: ' . mysqli_connect_error() ;
exit;
}
$results=array();
$sql_staff = "SELECT staff_id, staff_firstname, staff_lastname, staff_username, staff_chargerate, staff_lastlogin FROM tblstaff ORDER BY staff_lastname ASC, staff_firstname ASC ";
$result_staff = mysqli_query($link,$sql_staff);
while($row = mysqli_fetch_array($result_staff)){
$results[0] = $row['staff_id'];
$results[1] = $row['staff_firstname'] . " " . $row['staff_lastname'];
$results[2] = $row['staff_username'];
$results[3] = $row['staff_chargerate'];
$results[4] = $row['staff_lastlogin'];
echo json_encode($results);
$data = json_encode($results);
}
?>
<script>
function generate() {
var head = [["ID", "Staff Name", "Username", "Charge-rate", "Last Log-in"]];
var body = [
<?echo $data;?>
];
var doc = new jsPDF();
doc.autoTable({head: head, body: body});
doc.output("dataurlnewwindow");
}
</script>
I think that the problem lays around the line $data = json_encode($results); but I don't know enough about either PHP or Javascript to determine how the code needs to be altered to produce a full PDF report. Can anyone assist please?
Your issue is probably related to overwriting the values in the $results array which means you will get one item instead of an array of items. You probably want something like this:
$results = array();
while($row = mysqli_fetch_array($result_staff)){
$dataRow = array();
array_push($dataRow, $row['staff_id']);
array_push($dataRow, $row['staff_firstname'] . " " . $row['staff_lastname']);
// etc
array_push($results, $dataRow);
}
$data = json_encode($results);
I want to ask advice from you guys since I have a problem of showing html tags within table structure.
Actually, I want to show is "link".
To be clear I will explain you more details.
I am making auto generated table structure view with the help of javascript and jquery that shows data from database and want to show these data as table structure which also include the link that allows user to edit the data. That's it.
See the below image:
As you can see, links are showing as normal characters.
So anyone who knows the answer please advice me.
Below is the code:
//php
$sql = "SELECT * FROM v_category";
$dbaction = new db_action($sql,'G');
$result = $dbaction->db_process();
$dataRows = "Category Name|Remark|Edit|";
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$ctgr_id = $row["ctgr_id"];
$ctgr_name = $row["ctgr_name"];
$remark = $row["remk"];
$link = "<a href='?cv=ms-category&mode=2&id=$ctgr_id'>link</a>";
$dataRows = $dataRows . "**row**" . $ctgr_name . "|";
$dataRows = $dataRows . $remark . "|";
$dataRows = $dataRows . $link;
}
} else {
echo "0 results";
}
echo '<div id="draw-grid" class="tbl-responsive" style="overflow-x:auto;"><script>DrawTable("draw-grid","'.$dataRows.'");</script></div>';
//javascript
function DrawTable(Container,dataRows)
{
dataRows = dataRows.split(ROW_SPLITTER);
var tTable=$('<table>');
//draw the table header
tTable.append(drawHeader(dataRows[0]));
//draw the table body
tTable.append(drawBody(dataRows));
//add table to wrapper container first and then add into the parent container
$('<div>').append(tTable)
.appendTo($('#'+Container));
return;
}
function drawHeader(headerRow)
{
var headerRowColumns = headerRow.split("|");
var tblRow=$('<tr>');
headerRowColumns.forEach(function(element,index) {
$('<th>')
.text(element)
.appendTo(tblRow);
});
return $('<thead>').append(tblRow);
}
function drawBody(objRows)
{
var tBody=$('<tbody>');
objRows.forEach(
function(objRow,index)
{
if(index!=0)
{
tBody.append(drawBodyRow(objRow,index));
}
});
return tBody;
}
function drawBodyRow(bodyRow,rowIndex)
{
var bodyRowColumns = bodyRow.split("|");
var tRow=$('<tr>');
bodyRowColumns.forEach(function(element,columnIndex)
{
$('<td>').text(element).appendTo(tRow);
});
return tRow;
}
$('<td>').text(element).appendTo(tRow);
In this line and others like it, you're setting the inner text of the matched elements to be a value.
This is actually a good thing in almost all cases. You don't want to be interjecting arbitrary HTML into a context where a text value is intended. Otherwise, you open up yourself to potential security issues, or at least, invalid HTML.
What you should be doing instead, if you really intend to inject HTML, is to append those elements to this one.
Your code has other problems too...
$link = "<a href='?cv=ms-category&mode=2&id=$ctgr_id'>link</a>";
In this line, you're interpolating arbitrary data into a URL and into HTML, with nothing being escaped. Use http_build_query() to escape the data for the query string. Then, be sure to use htmlspecialchars() for any arbitrary data injected into HTML to ensure it's escaped for that context.
What i'm trying to do is do display images from a directory and rotate every x seconds, in
this case 2 seconds.
I wrote this java script code and it works great but the image names are hard coded.
<script language="javascript" type="text/javascript">
img2 = new Image()
seconds = "2";
function imgOne()
{
setTimeout("imgTwo()", seconds * 1000);
}
function imgTwo()
{
document.myimg.src = "pics/WM/IMAGE02";
setTimeout("imgThree()", seconds * 1000);
}
function imgThree()
{
document.myimg.src = "pics/WM/IMAGE01";
setTimeout("imgOne()", seconds * 1000);
}
So I'm trying to use PHP to read the directory and create the javascript but am getting an internal server error. I'm using $p so it's img1 instead of imgOne so I can increase it. It loops thru and after the end loops back to 1. Any help is appreciated.
<?php
$files = glob('pics/WM/*.jpg');
echo
'
<script language="javascript" type="text/javascript">
img2 = new Image()
seconds = "2";
function img1()
{
setTimeout("img2()"), seconds * 1000);
}
'
$p=2;
for ($i=0; $i < count($files) $i++)
{
$image=$files[$i];
echo 'function img' .$p . '()'
echo '{'
echo 'document.myimg.src = "' .$image . '";'
$p++;
echo 'set Timeout(img"' .$p . '()", seconds * 1000); '
echo '}'
}
echo 'function img' .$p . '()'
echo '
{
document.img src="IMAGE01";
set Timeout("img1()", seconds * 1000);
}
</script> '
?>
the echostatements in your php scripts are missing the final ;. This should be the problem that causes the internal server error.
How to fix your implementation:
You should write something like
// using multiple echo statements
echo "..... your string ... ";
echo $p;
echo "--- something else ----";
// or you can concatenate strings with .
echo ".... your string ... " . $p . "---- something else ----";
Similar but safer and clearer PHP implementation:
Printing out Javascript code via PHP could be error prone, therefore I would recommend to use output big parts of text outside PHP code, like this
Some text where p = <?php echo $p; ?> is printed out.
How to improve the Javascript part:
Load all images at once
This is not related on the specific question, but simplifies your solution. Regarding your own project (rotating images), as suggested in the comments there are many reusable javascript components you can use (firstly using some javascript libraries, e.g. jQuery). But if you want to develop this feature by yourself, keep in mind that changing the src attribute of an image tells the browser to download it from scratch, resulting in glitches. To solve this issue, you may insert many <img> elements and than display it one at the time (using css styling directives).
Iterate over the images using one timed function
Furthermore, you could simplify your javascript code: instead of using a different function to display each image you can use global variables (i.e. window.my_rotate_current_img_id) or better clojures to select and show the current image:
// 1. Declare an array of img tags ID, identifying the different images
// Note that we are using PHP to generate the array - the implode function
// concatenates array items into a string separated by the first argument
// given
var images = [<?php echo '"' . implode('","', $images) . '"'; ?>];
// 2. Define a function that shows the correct image
function hide_first_and_show_second(first, second){ ... }
// img_num is the number of images to rotate
var update_img = function(idx){
return function(){
hide_idx = idx;
show_idx = (idx + 1) % img_num;
hide_first_and_show_second(hide_idx, show_idx);
}
};
setInterval(update_img(0), 1000);
This are possible (and useful) improvements of your solution for this problem. Hope i clarified.
Sorry to add another JavaScript object to the mix. I'm just having a little trouble wrapping my head around this as it is a little more complex than i have ever dealt with.
Like the title states, i'm trying to create a JavaScript Object or perhaps a multidimensional array of a MySQL Database. For testing purposes i'm only using three tables from my database even though eventually it will store tens of tables. These tables are called "Interfaces", "IPAM", and "DNSF".
The reason i would like to complete this task is that, i am trying to create a heavy ajax page which dynamically knows when tables are added, updated, deleted etc, and automatically reflects this without having to add more code. I am doing this by writing javascript with php in addition to various other ajax callbacks spitting out html and variables.
Let me start out with my hardcoded HTML. All other html is created dynamically. This too will soon be created dynamically to add buttons to my website without adding code.
<body>
<div class = "form">
<button type="button" class = "formbutton" value = "Interfaces" onclick="inputChoice('Interfaces')">Interfaces</button>
<button type="button" class = "formbutton" value = "IPAM" onclick="inputChoice('IPAM')">IPAM</button>
<button type="button" class = "formbutton" value = "DNSR" onclick="inputChoice('DNSR')">DNSR</button>
</div>
<div class = "tableDiv" id="myTableDiv" style="height:1000px;width:1000px;border:1px solid #ccc; overflow: scroll;"><table id = "myTable"></table></div>
</body>
Before any buttons or events are executed, the first thign my page does is issue ajax requests within a $( document ).ready(function() { function. My issue is that i have to code a seperate ajax request for every single table. I'll show an example here where i fetch interface table data:
$.ajax({
url:"/ryan/nonEmber/ajax.php?table=Interfaces",
beforeSend: function(XMLHttpRequest){},
success: function(data, textStatus) {
InterfacesCols = data.split(" ");
InterfacesCols.pop();
$.getJSON("/ryan/nonEmber/getJson.php?table=Interfaces", function( data ){
var items = [];
$.each(data.post, function(key, val){
items.push(val);
});
for(i = 0; i < items.length; i++){
var myString = '<tr id = "visibleRow">';
for(j = 0; j < InterfacesCols.length; j++){
if(InterfacesCols[j] != null){
myString = myString + '<td id = "visibleDef">' + items[i][InterfacesCols[j]] +'</td>';
}
}
myString = myString + '</tr>';
Interfaces.push(myString);
}
});
}
});
This ajax request ultimately creates an array of html strings that are used to create the table. Interfaces[] contains each html row. InterfacesCols contains the names of each column. I have to write this block of code for every single table.
What i want to do is put my "Interfaces[]" like arrays and "InterfacesCols[]" like arrays within a master array so that i can create a template and not have tons of the same code.
Lets call this master array tables. This would allow me to put my ajax in a for loop and loop through every table array rather than hardcode it.
tables[0] would be interfaces[], tables[1] would be ipam etc.
In addition to my ajax request blocks where i initially gather my data from the database. I also have my function "inputChoice(string)", where i actually generate a table from this data. I do so by changing inner html of my table. I dont wan't to have to redirect my page. This works fine, but once again i have to create a new block of code for every single table. These blocks of code are massive right now because they include garbage collection for the DOM and also the code for handling massive data sets(>10,000) without browser slow down. I will refrain from posting that block unless necessary. The ajax calls require the same thing.
Here is the php where i originally create the empty array variables by generating javascript:
<?php
$sql= "SELECT
TABLE_NAME
FROM information_schema.TABLES
WHERE
TABLE_TYPE='BASE TABLE'
AND TABLE_SCHEMA='NJVCtestDB'";
$stmt = $DBH->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
echo '<script>';
try{
$stmt->execute();
echo 'var tables = [];';
while($row = $stmt->fetch()){
echo 'var '.$row['TABLE_NAME'].' =[];';
echo 'tables += '.$row['TABLE_NAME'].';';
echo 'var '.$row['TABLE_NAME'].'Cols =[];';
}
echo 'console.log(tables[1]);';
}catch(PDOException $e){
echo $e;
}
echo '</script>';
?>
The above php is only called by using an statement on my index. No Ajax.
The link my ajax calls is this:
<?
$sql = "DESCRIBE ".$_GET['table'];
$stmt = $DBH->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$colnames;
try{
$stmt->execute();
//$stmt2->execute();
$colnames = $stmt->fetchAll(PDO::FETCH_COLUMN);
}
catch(PDOException $e){
echo $e;
}
foreach($colnames as $value){
print $value ." ";
}
?>
The above ajax servers only the purpose of fetching column names and returning the names in a space delimeted string to be parsed and turned into an array via javascript, which you can see in my ajax call.
My getJson ajax code is here:
<?php
include "connect.php";
$sql = "DESCRIBE ".$_GET['table'];
$stmt = $DBH->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$colnames;
try{
$stmt->execute();
$colnames = $stmt->fetchAll(PDO::FETCH_COLUMN);
}
catch(PDOException $e){
echo $e;
}
$sql = "SELECT * FROM ".$_GET['table']." LIMIT 17000";
$stmt2 = $DBH->prepare($sql);
$stmt2->setFetchMode(PDO::FETCH_ASSOC);
try{
$stmt2->execute();
while($row = $stmt2->fetch()){
foreach($colnames as $value){
if($row[$value] == null){
$row[$value] = "";
}
}
$row = array('id' => $i) + $row;
$items['post'][]=($row);
$i++;
}
}
catch(PDOExcetipn $e){
echo $e;
}
print json_encode($items);
?>
The above php seems slightly redundant to me as i fetch the column names again. However this time i also include the actual data. Line by line.
This is basically all of my code i have written for this project. The only code i did not include was my javascript inputChoice() function. Which as i stated above is very bulky and really doesnt do anything the ajax doesnt do when it comes to utilizing the arrays. This is a massive post, so i apologize for the wall of text. I am not sure exactly what the next step is for me to code this better in the way i described. Any input would be very much appreciated!
If I'm correct you want to automate the table generating.
Your index php block retrieves all tables from the DB.
$sql= "SELECT
TABLE_NAME
FROM information_schema.TABLES
WHERE
TABLE_TYPE='BASE TABLE'
AND TABLE_SCHEMA='NJVCtestDB'";
So we need to add those to a master table pseudo code:
tables = [];
for (table in tableSQL)
{
tables[table] = tableSQL[table];
tables[table]['cols'] = [];
}
Now you have a master table array containing all your tables.
Let's loop through these. pseudo code:
for (table in tables)
{
retrieveColsWithData(table);
}
function retrieveColsWithData(tableKey)
{
//table = key = table name in DB
$.ajax({url:"/ryan/nonEmber/ajax.php?table="+table, etc.
//rest of the ajax call you're doing. Pass the key var to the JSON function
});
}
The function above loops through all the tables and retrieves the colls. When the JSON request returns you simply add the colls to table[key]['cols'].
Now you can simply iterate over the tables master with a for in or Object.keys and draw the HTML containing the data.
You can reuse retrieveColsWithData connected to your inputChoice to reload the data.