I've got a script on my website which checks for new database entries every second and updates puts them into a table.
I'm having a problem where the script is deleting the table headers from the page. They still appear in the source code (Right clicking and displaying page source), but they don't appear visible to the user.
The problem seems to lie within "while (tbl.lastChild != tbl.firstChild) { tbl.removeChild(tbl.lastChild); }", but if I remove this line of code, the script will continuously display the same data, over and over again. For example, if I have name 1, name 2 and name 3 in the database. All three will be displayed, and then repeated.
How can I display the table headers, while stopping the data from repeating?
My full script code is:
function tick() {
var xhttp = new XMLHttpRequest();
xhttp.onload = (function() {
var data = JSON.parse(xhttp.responseText);
var tbl = document.getElementById("reports");
while (tbl.lastChild != tbl.firstChild) { tbl.removeChild(tbl.lastChild); }
function cell(data) {
var c = document.createElement("td");
c.appendChild(document.createTextNode(data));
return c;
}
for (var i = 0; i < data.length; i++) {
var row = document.createElement("tr");
row.appendChild(cell(data[i]["id"]));
row.appendChild(cell(data[i]["firstname"]));
row.appendChild(cell(data[i]["lastname"]));
row.appendChild(cell(data[i]["date"]));
var a = document.createElement("a");
var c = document.createElement("td");
a.href = "view.php?id=" + data[i]["id"];
a.appendChild(document.createTextNode("View ID"));
c.appendChild(a);
row.appendChild(c);
tbl.appendChild(row);
setTimeout(tick, 1000);
}
});
xhttp.open("GET", "reportload.php", true);
xhttp.send("");
}
addEventListener("DOMContentLoaded", function() {
tick();
});
You can try create next html table and use it:
<table>
<thead>
<tr>
<th>title1</th>
<th>title1</th>
</tr>
</thead>
<tbody id="reports">
<tr>
<td>value</td>
<td>value</td>
</tr>
</tbody>
</table>
The childern of the HTML node are not only TRs, but also any portion of whitespaces between them, so Your loop probably deletes all TRs and leaves only the first portion of whitespaces.
I would suggest to put header in THEAD and data rows in TBODY and then operate only on TBODY, leaving the header intact.
Related
I have a table as the following datatable table :
<button id="addRow">Add New Row</button><br>
<table class="table table-striped table-bordered table-hover " id="example" cellSpacing=0 width="100%">
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
</tr>
</thead>
<tr style="text-align: center;">
<td>hola</td>
<td>ciao</td>
<td>bonjour</td>
<td>yo</td>
<td>salut</td>
</tr>
</table>
I'd like to append elements using a javascript script as the following :
<script type="text/javascript">
$(document).ready(function () {
debugger;
var t = $('#example').DataTable({ "searching": true, "paging": true });
var counter = 1;
$('#addRow').on('click', function ciicici() {
var now = new Date();
var now = now.toMysqlFormat();
var tii = new Date();
tii.setSeconds(tii.getSeconds() - 50000);
var tii = tii.toMysqlFormat();
$.post( "sqlmachine_test_ajax.php", { timing: now,seconding: tii })
.done(function( data ) {
t.row.add([
counter +'.1',
counter +'.2',
counter +'.3',
counter +'.4',
counter +'.5'
]).draw();
counter++;
// });
//setTimeout(function(){ciicici();}, 5000);
}); // Automatically add a first row of data
$('#addRow').click();
});
</script>
The two are working properly, the only thins is that I'd like to retreive the elements to append trough an Jquery AJAX script.
Let's say I have a php page sending back 5 values I'd like to add to each column (instead of the counter1, counter2 etc...) as the following :
<?php
echo 'counter1, counter2, counter3, counter4, counter5';
?>
and in the javascript I wanted to put simply :
...
.done(function( data ) {
t.row.add([
data //(instead of the counters)
]).draw();
counter++;
...
I have tried this, as well as arrays and json encoded arrays, but all I get is the 5 results in the same first cell of the table.
So how could I append the ajax php response to a table as data in different cells of the table?
marko
When you get your data back from the call, you have to separate using .split().
so you can do this when you get your callback
.done(function( data ) {
var splitData = data.split(", ") //Split your data with the comma and space
$.each(splitData, function(e){ //For each piece of data
//Add your rows here one by one
t.row.add([
splitData[e] //Make sure the 'e' in the function and here are the same
]).draw();
})
counter++;
});
This a loose answer, I'll try to add more soon.
Edit: More info
what I normally do is echo everything with separators. So, in your case, I would echo 1, 2, 3, 4, 5:A, B, C, D, E. So when the data returns, that's what you'll see.
In your data success, you would do something like
var dataParts = data.split(":") //This splits your data into the 2 parts using the : separator
var dataPart1 = dataParts[0] //This will get 1, 2, 3, 4, 5
var dataPart2 = dataParts[1] //this will get A, B, C, D, E
Then from there, you split using commas.
var dataPieces1 = dataPart1.split(', ');
var dataPieces2 = dataPart2.split(', ');
Then run the loops. (using javascript's for loop is usually better than using jQuery's .each())
for(var i = 0; i < dataPieces1.length; i++){ //Start your for loop on the first part
//Create a row here using dataPieces1[i], this will loop and make a new
//row every time the next loop finishes
for(var j = 0; j < dataPieces2.length; j++){ //Start the second loop
//Not sure how you would want to do this, but here's some example code
//Since you're inside a row now, append your dataPieces2[j] to that row
//This will loop for every dataPieces2 and append each one as a column
//in that single row.
}
}
I am working on a scheduling project and have run into an issue with finding the column index of a selected cell (so that i may then get the appropriate header for the column). The issue comes into play when a previous cell(or cells) have/has a rowspan. In which case the cell index is off by that amount of cells. I have been at this since yesterday. My current attempt involves using a solution I found in previous posts, and this is this:
parentTr.find('>td, >th').each(function(i,o) {
if ( this == reference )
{
cellNum = i;
var counter = columnNum;
while ( counter-- )
{
$(this).closest('tr').next().find('>td,>th').each(function(i,o)
{
if ( cellNum == i )
{
$(this).addClass('rowspan-affected');
$(this).attr('colNum', columnNum);
}
});
}
}
});
})
The problem is that this solution counts the number of rowspanned cells on the entire page. I need a count of the rowspanned cells for only the current clicked cell, and then be able to add that count to index so I can get the proper header. What I have been trying looks like this:
var $this = $(this);
//get the row header contents
var row = $this.parent('tr').contents('th:eq(0)').html();
//trying this
var colCount = $(this).prevAll().find('td').parent('tr').attr('rowspan');
alert (colCount);
//used to get the cell index
var rowIndex = $(this).parent().index('.main tbody tr');
var tdIndex = $(this).index('.main tbody tr:eq('+rowIndex+') td');
//alert ("tdindex " + (tdIndex+1));
var headerObj = $(this).parents('.main').find('th').eq(tdIndex+1);
//strip whitespace before passing
var toPass = $.trim(headerObj.text());
//toPass = $.trim(toPass)
//alert (toPass);
This information is gathered and then passed to a new form with the selected information used to populate the form.
If anyone can help me with this, I would be greatly appreciative!!!
Coming from Adobe Flex I am used to having data available in an ArrayCollection and when I want to display the selected item's data I can use something like sourcedata.getItemAt(x) which gives me all the returned data from that index.
Now working in php and javascript I am looking for when a user clicks a row of data (in a table with onClick on the row, to get able to look in my data variable $results, and then populate a text input with the values from that row. My problem is I have no idea how to use javascript to look into the variable that contains all my data and just pull out one row based on either an index or a matching variable (primary key for instance).
Anyone know how to do this. Prefer not firing off a 'read' query to have to bang against the mySQL server again when I can deliver the data in the original pull.
Thanks!
I'd make a large AJAX/JSON request and modify the given data by JavaScript.
The code below is an example of an actual request. The JS is using jQuery, for easier management of JSON results. The container object may be extended with some methods for entering the result object into the table and so forth.
PHP:
$result = array();
$r = mysql_query("SELECT * FROM table WHERE quantifier = 'this_section'");
while($row = mysql_fetch_assoc($r))
$result[$row['id']] = $row;
echo json_encode($result);
JavaScript + jQuery:
container.result = {};
container.doStuff = function () {
// do something with the this.result
console.debug(this.result[0]);
}
// asynchronus request
$.ajax({
url: url,
dataType: 'json',
data: data,
success: function(result){
container.result = result;
}
});
This is a good question! AJAXy stuff is so simple in concept but when you're working with vanilla code there are so many holes that seem impossible to fill.
The first thing you need to do is identify each row in the table in your HTML. Here's a simple way to do it:
<tr class="tablerow" id="row-<?= $row->id ">
<td><input type="text" class="rowinput" /></td>
</tr>
I also gave the row a non-unique class of tablerow. Now to give them some actions! I'm using jQuery here, which will do all of the heavy lifting for us.
<script type="text/javascript">
$(function(){
$('.tablerow').click(function(){
var row_id = $(this).attr('id').replace('row-','');
$.getJSON('script.php', {id: row_id}, function(rs){
if (rs.id && rs.data) {
$('#row-' + rs.id).find('.rowinput').val(rs.data);
}
});
});
});
</script>
Then in script.php you'll want to do something like this:
$id = (int) $_GET['id'];
$rs = mysql_query("SELECT data FROM table WHERE id = '$id' LIMIT 1");
if ($rs && mysql_num_rows($rs)) {
print json_encode(mysql_fetch_array($rs, MYSQL_ASSOC));
}
Maybe you can give each row a radio button. You can use JavaScript to trigger an action on selections in the radio button group. Later, when everything is working, you can hide the actual radio button using CSS and make the entire row a label which means that a click on the row will effectively click the radio button. This way, it will also be accessible, since there is an action input element, you are just hiding it.
I'd simply store the DB field name in the td element (well... a slightly different field name as there's no reason to expose production DB field names to anyone to cares to view the page source) and then extract it with using the dataset properties.
Alternatively, you could just set a class attribute instead.
Your PHP would look something like:
<tr>
<td data-name="<?=echo "FavoriteColor"?>"></td>
</tr>
or
<tr>
<td class="<?=echo "FavoriteColor"?>"></td>
</tr>
The javascript would look a little like:
var Test;
if (!Test) {
Test = {
};
}
(function () {
Test.trClick = function (e) {
var tdCollection,
i,
field = 'FavoriteColor',
div = document.createElement('div');
tdCollection = this.getElementsByTagName('td');
div.innerText = function () {
var data;
for (i = 0; i < tdCollection.length; i += 1) {
if (tdCollection[i].dataset['name'] === field) { // or tdCollection[i].className.indexOf(field) > -1
data = tdCollection[i].innerText;
return data;
}
}
}();
document.body.appendChild(div);
};
Test.addClicker = function () {
var table = document.getElementById('myQueryRenderedAsTable'),
i;
for (i = 0; i < table.tBodies[0].children.length; i += 1) {
table.tBodies[0].children[i].onclick = Test.trClick;
}
};
Test.addClicker();
}());
Working fiddle with dataset: http://jsfiddle.net/R5eVa/1/
Working fiddle with class: http://jsfiddle.net/R5eVa/2/
<html>
<head>
<script src="jquery-1.4.4.js"></script>
<script>
$('table').each(function(a, tbl) {
var currentTableRows = $(tbl).attr('rows').length - 1;
$(tbl).find('th').each(function(i) {
var remove = 0;
var currentTable = $(this).parents('table');
var tds = currentTable.find('tr td:nth-child(' + (i + 1) + ')');
tds.each(function(j) { if (this.innerHTML == '') remove++; });
if (remove == currentTableRows) {
$(this).hide();
tds.hide();
}
});
});
</script>
</head>
<body>
<table border="1" >
<tr><td colspan="4" > alaa </td></tr>
<tr><th>Column1</th><th>Column2</th><th>Column3</th><th>Column4</th></tr>
<tr ><td>1st</td><td>1.1</td><td></td><td></td></tr>
<tr class="data"><td>2nd</td><td>2.1</td><td></td><td></td></tr>
<tr class="data"><td>3rd</td><td>3.1</td><td></td><td>1</td></tr>
<tr class="data"><td>4th</td><td></td><td></td><td></td></tr>
<tr ><td></td><td></td><td></td><td></td></tr>
<tr class="data"><td></td><td></td><td></td><td></td></tr>
</table>
</body>
here is my code ... I thought that the problem from the library, so I tried many libraries such as jQuery 1.4.4 , 1.5.2 and others
Here is the test and it works fine there http://jsfiddle.net/nlovatt/JsLn8/
but in my file .. it doesn't work ..
regards,
There are two reasons your code isn't working.
1) You're executing the script immediately upon loading of the HEAD, at this stage, your table doesn't exist and so it does nothing. To fix this, make sure you execute it on page load instead.
2) When you're comparing the number of blank cells in the column with the number of total rows in the table, you're missing the fact that most of your columns don't have the same number of rows as the table (your first row is only one column wide). You need to compare to the number of rows in the actual column, or better yet, just do the reverse thing and check for non-empty columns.
The full code then becomes:
$(document).ready(function() {
$('table').each(function(a, tbl) {
$(tbl).find('th').each(function(i) {
var remove = true;
var currentTable = $(this).parents('table');
var tds = currentTable.find('tr td:nth-child(' + (i + 1) + ')');
tds.each(function(j) { if (this.innerHTML != '') remove = false; });
if (remove) {
$(this).hide();
tds.hide();
}
});
});
});
try it like this
$('#mytable tr th').each(function(i) {
//select all td in this column
var tds = $(this).parents('table')
.find('tr td:nth-child(' + (i + 1) + ')');
//check if all the cells in this column are empty
if(tds.length == tds.filter(':empty').length) {
//hide header
$(this).hide();
//hide cells
tds.hide();
}
});
for hiding columns in table if all cells in column are empty
I have a javascript code helping me to dynamically create row after row in a table and to delete a row from that table.
each row has four cells. cell 1 for instance contains a text zone.
to differentiate cell1 from row 1 with cell1 from row 2, I rename my cell 1 like that cell1.name= cell1.name + '_' + row.rowIndex.
I create a submit button so that I could read data entered by a user in the rows of the table and I try to print $_GET. but there is nothing inside. How could I access to my DOM objects in PHP?
I am grateful for your help.
my HTML + PHP code
<body >
<?php
if (isset($_GET['Enter'])){
print_r($_GET);
}
?>
<h1> Create an Item </h1>
<form method="GET" action="func.html">
<table align="center" border = "2" cellspacing ="0" cellpadding="3" id="table">
<tr><td><b>Functionality Name:</b></td> <td><b>Description:</b></td> <td><b>Status:</b></td> <td><input type="button" Name= "Ajouter" Value="Ajouter" onclick="go()"></td></tr>
</table>
<input type="submit" name="submit" value="Enter">
</form>
</body>
and my Javascript code:
<script>
function getXhr(){
var xhr = null;
if(window.XMLHttpRequest) // Firefox and others
xhr = new XMLHttpRequest();
else if(window.ActiveXObject){ // Internet Explorer
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
else { // XMLHttpRequest not supported by your browser
alert(" Your browser does not support XMLHTTPRequest objects...");
xhr = false;
}
return xhr
}
/**
* method called when the user clicks on the button
*/
function go(){
var xhr = getXhr()
// We defined what we gonna do with the response
xhr.onreadystatechange = function(){
// We do somthing once the server's response is OK
if(xhr.readyState == 4 && xhr.status == 200){
var body = document.getElementsByTagName("body")[0];
// Retrieve <table> ID and create a <tbody> element
var tbl = document.getElementById("table");
var tblBody = document.createElement("tbody");
var row = document.createElement("tr");
var cell_1 = document.createElement("td");
var cell_2 = document.createElement("td");
var cell_3 = document.createElement("td");
var cell_4 = document.createElement("td");
// Create the first cell which is a text zone
var cell1=document.createElement("input");
cell1.type="text";
cell1.name="fname";
cell1.size="20";
cell1.maxlength="50";
cell_1.appendChild(cell1);
// Create the second cell which is a text area
var cell2=document.createElement("textarea");
cell2.name="fdescription";
cell2.rows="2";
cell2.cols="30";
cell_2.appendChild(cell2);
// Create the second cell which is a combo box
var cell3 = document.createElement("div");
cell3.id="rs";
cell3.innerHTML=xhr.responseText;
cell_3.appendChild(cell3);
// Create the fourth cell which is a button
var cell4=document.createElement("input");
cell4.type="button";
cell4.value="Delete"
cell4.onclick=delRow;
cell_4.appendChild(cell4);
// add cells to the row
row.appendChild(cell_1);
row.appendChild(cell_2);
row.appendChild(cell_3);
row.appendChild(cell_4);
// add the row to the end of the table body
tblBody.appendChild(row);
// put the <tbody> in the <table>
tbl.appendChild(tblBody);
// Rename cells with the row index
var ind=row.rowIndex;
var liste_fname = row.getElementsByTagName("input");
for(i=0; i < liste_fname.length; i++)
{
if(liste_fname[i].name == "fname")
{
liste_fname[i].name = liste_fname[i].name + "_" + ind; //give fname_1, fname_2, fname_3, ...
}
}
var fd = row.getElementsByTagName("textarea");
fd[0].name = fd[0].name + "_" + ind;
var cd = row.getElementsByTagName("div");
cd[0].id = cd[0].id + "_" + ind;
var selectname = row.getElementsByTagName("select");
selectname[0].name = selectname[0].name + "_" + ind;
// appends <table> into <body>
body.appendChild(tbl);
// sets the border attribute of tbl to 1;
tbl.setAttribute("border", "1");
}
}
xhr.open("GET","fstatus.php",true);
xhr.send(null);
}
function delRow(){
var i= this.parentNode.parentNode.rowIndex;
document.getElementById('table').deleteRow(i);
}
</script>
Best regards,
Billy
Because PHP is server side and Javascript is Client side you can't directly access elements on the page.
In order to access elements you need to post back to the server via a FORM or some AJAX.
You might look into jQuery to help you do this since it makes it easier to call your PHP programs and manipulate the DOM.
I'm going to second the use of jQuery. It'll be tidier and keep you neatly in a single paradigm during this particular task.
One way to do this with PHP would be to dump your DOM object into JSON and then use PHP's JSON support. Depending on your purposes, you can roll your own class to process the JSON data or just grab it from the array you get from json_decode(). Another way would be to dump the object into its representative HTML and pass that to your PHP script rather than the DOM object. You can then reparse it using The Simple HTML DOM Parser, an easy-to-use, freely available DOM parser for PHP.
Of course, you should note that you're adding two processing steps here. If you can do the processing you need to do without switching languages, you're saving time and a bit of sanity.
Well... for starters you want to see if $_GET['submit'] is set not $_GET['Enter'] because $_GET['submit'] should have the value of 'Enter'.
Also, each of your textarea's need to have a different name from the rest, so they don't overwrite each other ( Or they need to have a name that ends in [] (square brackets) and then php will turn them into an array).
And once the html is submitted... the DOM doesn't exist anymore so PHP can't really access it except through ajaxy kinf of stuff.
your cell name should not named like that ... it should be like this
<input type='text' name='username[]' value=''/>
<input type='text' name='username[]' value=''/>
<input type='text' name='username[]' value=''/>
.....
<input type='submit' name='submit' value='submit'/>
so you can access from php as array of username
$_GET[username][0] for example will display the first username etc ...
btw, try to use prototype or jquery (javascript framwork) it will simplify your life a lot.
to post data using jquery using ajax:
var url = 'your.server.com/post/fstatus.php';
var data = $('#myform_id').serialize();
$.post(url, data , function(result){
//... if the data was alright or submited ...
alert(result);
},"json");
isn't it easier ? :)
to append a simply type:
var newfield="<div id='rs'><textarea name='mytextarea'></div>"; $('#your_target_id').append(newfield);
in your php type
<?php print_r($_GET); ?>
and you will see what i mean :)
I cannot stress enough - use jQuery. Your life will be an order of magnitude simpler.