Pass an array from php to javascript - javascript

I'm trying to pass an array from php (on a separate file) side to JavaScript and update HTML table. The array on the php side is a result of MySQL query.
Here is what I've done so far:
function updateSensorsTable() {
$.getJSON("/getTableFromDB.php", function (json) {
for (i = 0; i < 8;i++ )
document.getElementById(i).innerHTML = json[i];
});
}
<?php
include("connect_to_mysql.php");
$result = mysql_query("SELECT value FROM sens" );
while ($row = mysql_fetch_row($result)) {
$php_array[]=$row[0];
}
echo json_encode($php_array);
?>

Don't forget to set the header :
header('Content-Type: application/json');
When you do "document.getElementById(i)" you try to access on an element witch having a bad ID (integer)... Here is the rule :
ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").

Here is the complete page
<script type="text/javascript" >
setInterval(updateSensorsTable, 2000);
setInterval(updatePower, 1000);
function showValue(value) {
//show value in html
document.getElementById("brightnesValue").innerHTML = value;
//Set brightness value to DB id=10
callPage('/setValueToDB.php?value=' + value + '& id=10' + '', document.getElementById(''));
}
function TurnLedOn() {
//TODO: need to set the led state and update the sql server
document.getElementById("ledStatus").src = "/LedOn.png";
callPage('/setValueToDB.php?value=1&id=9' + '', document.getElementById(''));
}
function TurnLedOff() {
//TODO: need to set the led state and update the sql server
document.getElementById("ledStatus").src = "/LedOff.png";
callPage('/setValueToDB.php?value=0&id=9' + '', document.getElementById(''));
}
function AjaxCaller() {
var xmlhttp = false;
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
xmlhttp = new XMLHttpRequest();
}
return xmlhttp;
}
function callPage(url, div) {
var ajax = AjaxCaller();
ajax.open("GET", url, true);
ajax.onreadystatechange = function () {
if (ajax.readyState == 4) {
if (ajax.status == 200) {
div.innerHTML = ajax.responseText;
}
}
}
ajax.send(null);
}
function updateSensorsTable() {
for (i = 0; i < 8; i++) {
callPage('/getVarFromDB.php?offset=' + i , document.getElementById(i));
}
/*
$.getJSON("/getTableFromDB.php", function (json) {
for (i = 0; i < 8;i++ )
document.getElementById(i).innerHTML = json[i];
});
*/
}
function updatePower() {
callPage('/getVarFromDB.php?offset=' + 10, document.getElementById('powerValue'));
}
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0"/>
<title>SmartLight</title>
</head>
<body bgcolor="#E6E6FA">
<br></br>
<table class="sensorsTable" align="center">
<thead>
<tr >
<th>Sensor</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">GPS</td>
<td align="center" id="0">0</td>
</tr>
<tr>
<td align="left">Temperature</td>
<td align="center" id="1">0</td>
</tr>
<tr>
<td align="left">Pressure</td>
<td align="center" id="2">0</td>
</tr>
<tr>
<td align="left">Light</td>
<td align="center" id="3">0</td>
</tr>
<tr>
<td align="left">Altitude</td>
<td align="center" id="4">0</td>
</tr>
<tr>
<td align="left">Accelerometer</td>
<td align="center" id="5">0</td>
</tr>
<tr>
<td align="left">Humidity</td>
<td align="center" id="6">0</td>
</tr>
<tr>
<td align="left">Camera</td>
<td align="center" id="7">0</td>
</tr>
</tbody>
</table>
<br></br>
<table class="ledTable" align="center">
<tr>
<td align="center"><input type="image" src="/TurnOn.png" id="turnOn" width="60" height="60" onclick='TurnLedOn()'></td>
<td align="center"><input type="image" src="/TurnOff.png" id="turnOff" width="60" height="60" onclick='TurnLedOff()'></td>
<td align="center"><img src="/LedOn.png" style="width:60px;height:60px" id="ledStatus"></td>
</tr>
<tr>
<td align="center" id="ledOnButton">LED On</td>
<td align="center" id="ledOffButton">LED Off</td>
<td align="center">LED Status</td>
</tr>
</table>
<div align="center">
Brightness:
<input type="range" id="brightnesBar" min="0" max="100" value="0" step="1" onchange="showValue(this.value)" />
<span id="brightnesValue">0</span>
<table align="center" class="power">
<tr>
<td align="center" id="powerValue">0</td>
<td align="left">mW</td>
</tr>
</table>
<div align="center" >LED Power Meter</div>
</div>

Related

Sorting HTML table with subitems with JS

I have the following table:
<table border="0" cellspacing="0" cellpadding="0" id="table1">
<tbody>
<tr>
<th onclick="sortTable(0, this); return false;" class="sort-up" order="-1">ColumnA</th>
<th style="width: 12em;" onclick="sortTable(1, this); return false;" class="sort-none">ColumnB</th>
<th style="width: 9em;" onclick="sortTable(2, this); return false;" class="sort-none">ColumnC</th>
<th style="width: 10em;" onclick="sortTable(3, this); return false;" class="sort-none">ColumnD</th>
<th style="width: 6em;">ColumnE</th>
</tr>
<tr id="tr217E9B6C" type="root" level="217E9B6C" depth="0">
<td class="evenListRow" id="nocenter">
<div class="tier1">Root A</div>
</td>
<td class="evenListRow">1</td>
<td class="evenListRow">2</td>
<td class="evenListRow">3</td>
<td class="evenListRow">4</a>
</td>
</tr>
<tr id="tr217E9B6C-6E781501" type="sub" level="217E9B6C-6E781501" depth="1">
<td class="oddListRow" id="nocenter">
<div class="tier2">Sub A</div>
</td>
<td class="oddListRow">5</td>
<td class="oddListRow">6</td>
<td class="oddListRow">7</td>
<td class="oddListRow">8</td>
</tr>
<tr id="tr217E9B6C-852AB6E5" type="sub" level="217E9B6C-852AB6E5" depth="1">
<td class="evenListRow" id="nocenter">
<div class="tier2">Sub B</div>
</td>
<td class="evenListRow">9</td>
<td class="evenListRow">10</td>
<td class="evenListRow">11</td>
<td class="evenListRow">12</td>
</tr>
<tr id="tr2BE7EAFE" type="root" level="2BE7EAFE" depth="0">
<td class="evenListRow" id="nocenter">
<div class="tier1">Root B</div>
</td>
<td class="evenListRow">13</td>
<td class="evenListRow">14</td>
<td class="evenListRow">15</td>
<td class="evenListRow">16</td>
</tr>
<tr id="tr2BE7EAFE-49A04568" type="sub" level="2BE7EAFE-49A04568" depth="1">
<td class="oddListRow" id="nocenter">
<div class="tier2">Sub C</div>
</td>
<td class="oddListRow">17</td>
<td class="oddListRow">18</td>
<td class="oddListRow">19</td>
<td class="oddListRow">20</td>
</tr>
<tr id="tr2BE7EAFE-DAE218A5" type="sub" level="2BE7EAFE-DAE218A5" depth="1">
<td class="evenListRow" id="nocenter">
<div class="tier2">Sub D</div>
</td>
<td class="evenListRow">21</td>
<td class="evenListRow">22</td>
<td class="evenListRow">23</td>
<td class="evenListRow">24</td>
</tr>
<tr id="tr4FFACE4A" type="root" level="4FFACE4A" depth="0">
<td class="oddListRow" id="nocenter">
<div class="tier1">Root C</div>
</td>
<td class="oddListRow">25</td>
<td class="oddListRow">26</td>
<td class="oddListRow">27</td>
<td class="oddListRow">28</td>
</tr>
<tr id="tr4FFACE4A-B9A443CA" type="sub" level="4FFACE4A-B9A443CA" depth="1">
<td class="evenListRow" id="nocenter">
<div class="tier2">Sub E</div>
</td>
<td class="evenListRow">29</td>
<td class="evenListRow">30</td>
<td class="evenListRow">31</td>
<td class="evenListRow">32</td>
</tr>
</tbody>
</table>
And I want to sort it, first by the "root" then by the "sub" items, which would mean that Root A will always have its Sub A, Sub B under it (sorted as well, but under it)
I used the following code which works on only on the "sub items", I cannot get it to work by doing a "mix", i.e. top and sub (separately sorted)
function sortTable(column, thisrow) {
var order = thisrow.getAttribute('order');
if (!order) {
order = 1;
}
var tbl = document.getElementById("table1").tBodies[0];
if (!tbl) {
return;
}
if (previousSortColumn && previousSortColumn.innerHTML != thisrow.innerHTML) {
previousSortColumn.setAttribute('class', 'sort-none');
}
previousSortColumn = thisrow;
var store = [];
/* Build a store object that has every element in the table, we will use this to sort */
for(var rowpos=1, len=tbl.rows.length; rowpos<len; rowpos++) { // skip row #1 as it is the header
var row = tbl.rows[rowpos];
var i_textContent = row.cells[column].textContent;
while(i_textContent.indexOf(' ') != -1) { // remove spaces
i_textContent = i_textContent.replace(' ', '');
}
var sortnr = i_textContent;
var type = row.getAttribute('type');
var level = row.getAttribute('level');
var depth = row.getAttribute('depth');
store.push({sortnr: sortnr, row:row, storelength:store.length, type:type, level:level, depth:depth});
}
/* We sort first roots then the elements under it */
store.sort(function(x,y) {
var xtype = x['type'];
var ytype = y['type'];
var result;
if (xtype == 'root' && ytype == 'root')
{
result = x['sortnr'].localeCompare(y['sortnr']);
} else {
return 0;
}
if (order == 1) {
return result;
} else {
return -1 * result;
}
});
/* We sort the elements under it */
store.sort(function(x,y) {
var xtype = x['type'];
var ytype = y['type'];
var xlevel = x['level'];
var ylevel = y['level'];
if (xlevel.lastIndexOf('-') > 0) {
xlevel = xlevel.substring(0, xlevel.lastIndexOf('-'));
}
if (ylevel.lastIndexOf('-') > 0) {
ylevel = ylevel.substring(0, ylevel.lastIndexOf('-'));
}
if (xlevel != ylevel || xtype == 'root' || ytype == 'root')
{
return x['storelength'] - y['storelength']; // return order inside array
}
var result = x['sortnr'].localeCompare(y['sortnr']);
if (order == 1) {
return result;
} else {
return -1 * result;
}
});
for(var i=0; i < store.length; i++) {
tbl.appendChild(store[i]['row']);
}
store = null;
}
Update 1:
Clicking once on 'ColumnB' would not affect the table (a bit of a bad example on my part), as the information is already sorted in the correct order, however another click should sort everything in reverse order
So both the Roots would be in reverse other, Root C, Root B, Root A, as well their sub items, Sub D before Sub C, ...
<table border="0" cellspacing="0" cellpadding="0" id="table1">
<tbody>
<tr>
<th onclick="sortTable(0, this); return false;" class="sort-up" order="-1">ColumnA</th>
<th style="width: 12em;" onclick="sortTable(1, this); return false;" class="sort-none">ColumnB</th>
<th style="width: 9em;" onclick="sortTable(2, this); return false;" class="sort-none">ColumnC</th>
<th style="width: 10em;" onclick="sortTable(3, this); return false;" class="sort-none">ColumnD</th>
<th style="width: 6em;">ColumnE</th>
</tr>
<tr id="tr4FFACE4A" type="root" level="4FFACE4A" depth="0">
<td class="oddListRow" id="nocenter">
<div class="tier1">Root C</div>
</td>
<td class="oddListRow">25</td>
<td class="oddListRow">26</td>
<td class="oddListRow">27</td>
<td class="oddListRow">28</td>
</tr>
<tr id="tr4FFACE4A-B9A443CA" type="sub" level="4FFACE4A-B9A443CA" depth="1">
<td class="evenListRow" id="nocenter">
<div class="tier2">Sub E</div>
</td>
<td class="evenListRow">29</td>
<td class="evenListRow">30</td>
<td class="evenListRow">31</td>
<td class="evenListRow">32</td>
</tr>
<tr id="tr2BE7EAFE" type="root" level="2BE7EAFE" depth="0">
<td class="evenListRow" id="nocenter">
<div class="tier1">Root B</div>
</td>
<td class="evenListRow">13</td>
<td class="evenListRow">14</td>
<td class="evenListRow">15</td>
<td class="evenListRow">16</td>
</tr>
<tr id="tr2BE7EAFE-DAE218A5" type="sub" level="2BE7EAFE-DAE218A5" depth="1">
<td class="evenListRow" id="nocenter">
<div class="tier2">Sub D</div>
</td>
<td class="evenListRow">21</td>
<td class="evenListRow">22</td>
<td class="evenListRow">23</td>
<td class="evenListRow">24</td>
</tr>
<tr id="tr2BE7EAFE-49A04568" type="sub" level="2BE7EAFE-49A04568" depth="1">
<td class="oddListRow" id="nocenter">
<div class="tier2">Sub C</div>
</td>
<td class="oddListRow">17</td>
<td class="oddListRow">18</td>
<td class="oddListRow">19</td>
<td class="oddListRow">20</td>
</tr>
<tr id="tr217E9B6C" type="root" level="217E9B6C" depth="0">
<td class="evenListRow" id="nocenter">
<div class="tier1">Root A</div>
</td>
<td class="evenListRow">1</td>
<td class="evenListRow">2</td>
<td class="evenListRow">3</td>
<td class="evenListRow">4</a>
</td>
</tr>
<tr id="tr217E9B6C-852AB6E5" type="sub" level="217E9B6C-852AB6E5" depth="1">
<td class="evenListRow" id="nocenter">
<div class="tier2">Sub B</div>
</td>
<td class="evenListRow">9</td>
<td class="evenListRow">10</td>
<td class="evenListRow">11</td>
<td class="evenListRow">12</td>
</tr>
<tr id="tr217E9B6C-6E781501" type="sub" level="217E9B6C-6E781501" depth="1">
<td class="oddListRow" id="nocenter">
<div class="tier2">Sub A</div>
</td>
<td class="oddListRow">5</td>
<td class="oddListRow">6</td>
<td class="oddListRow">7</td>
<td class="oddListRow">8</td>
</tr>
</tbody>
</table>
I solved your problem. I did reorganize the code to make it a lot more readable. Most of the logic is what you provided, i just added small bits. And btw, you have duplicate id references on id="nocenter" in your html.
Here is a working jsfiddle of my solution. The HTML is exactly the one you provided , with errors and all and no listener on column E. This js fiddle version has some more subs on root A. You can play with it as you will (add extra data). Summary of the code comes after it in the answer.
Update - taken your new input data in the comments , i updated the jsfiddle it would seem i kept the root in place, and it jumped out of subset. It was a matter of changing 1 line in sorting the subs. The new fiddle.
var ASC = 1;
var DESC = -1;
var SORTNR_INDEX = 0;
var LOWER = 1;
var UPPER = 2;
var previousSortColumn ;
var order;
/* The original build store you provided */
var buildStore = function(column,tbl){
var store = [];
for (var rowpos = 1, len = tbl.rows.length; rowpos < len; rowpos++) { // skip row #1 as it is the header
var row = tbl.rows[rowpos];
var i_textContent = row.cells[column].textContent;
while (i_textContent.indexOf(' ') != -1) { // remove spaces
i_textContent = i_textContent.replace(' ', '');
}
var sortnr = i_textContent;
var type = row.getAttribute('type');
var level = row.getAttribute('level');
var depth = row.getAttribute('depth');
store.push({sortnr: sortnr, row: row, storelength: store.length, type: type, level: level, depth: depth});
}
return store;
}
// the order convention you offered
var triggerOrder = function(){
if (order==ASC){
order = DESC;
} else if (order==DESC || !order){
order = ASC;
}
}
// the code you provided
var getLevel = function(obj){
if (obj && obj.lastIndexOf('-') > 0) {
return obj.substring(0, obj.lastIndexOf('-'));
}
return obj;
}
function sortRoot(a,b){
var aSort = a[SORTNR_INDEX], bSort = b[SORTNR_INDEX];
return compareWithOrder(aSort,bSort);
};
var sortSubs = function(x,y){
var xtype = x['type'];
var ytype = y['type'];
if (xtype == 'root'){
return -1;
} else if (xtype == ytype) {
var xSort = x['sortnr'];
var ySort = y['sortnr'];
return compareWithOrder(xSort,ySort);
}
}
var compareWithOrder = function(x,y){
if (isNaN(parseInt(x))) {
return order * x.localeCompare(y);
} else {
x = parseInt(x);
y = parseInt(y);
if (x < y) {
return -1 * order;
} else if (x > y) {
return 1 * order;
} else {
return 0;
}
}
};
//assumes they are aligned by depth (i.e. will always have a root then subs). if not, an additional sort can be made beforehand
function getGroupsByLevel(store){
var group = [];
var groupIndex=0;
var lower =0, upper, sortNo;
if (store.length > 0) {
var x,y;
for (var i = 0; i < store.length; i++) {
x = store[i];
if (store[i+1]){
y = store[i+1]
} else{
y = {};
}
var xtype = x['type'];
var ytype = y['type'];
if (xtype=='root'){
sortNo = x['sortnr'];
}
var xlevel = getLevel(x['level']);
var ylevel = getLevel(y['level']);
if (xlevel != ylevel){
group[groupIndex] = [sortNo,lower,i];
lower=i+1;
groupIndex++;
}
}
}
return group;
};
function sortTable(column, thisrow) {
order = thisrow.getAttribute('order');
triggerOrder();
thisrow.setAttribute('order',order);
var tbl = document.getElementById("table1").tBodies[0];
if (!tbl) return;
/* Build a store object that has every element in the table, we will use this to sort */
var store = buildStore(column,tbl);
var groups = getGroupsByLevel(store);
groups.sort(sortRoot);
var newStore=[];
for (var i=0;i<groups.length;i++){
var group = groups[i];
var rootAndSubs = store.slice(group[LOWER],group[UPPER]+1);
rootAndSubs.sort(sortSubs);
newStore=newStore.concat(rootAndSubs);
}
//update table
for (var i = 0; i < newStore.length; i++) {
tbl.appendChild(newStore[i]['row']);
}
store = null;
order = null;
}
Basically it goes like this:
set +trigger the order
build the store just like you intended
get groups of roots and their subs
sort the groups and then sort the each of the subs for the group
update the view
This is the first approach i thought of.

merging <td> rows in one column of html table

I have a requirement, if i have same data in column1 of 's with same id then i need to merge those cells and show their respective values in column2.
i.e., in fiddle http://jsfiddle.net/7t9qkLc0/12/ the key column have 3rows with data 1 as row value with same id and has corresponding different values in Value column i.e., AA,BB,CC. I want to merge the 3 rows in key Column and display data 1 only once and show their corresponding values in separate rows in value column.
Similarly for data4 and data5 the values are same i.e.,FF and keys are different, i want to merge last 2 rows in Value column and dispaly FF only one time and show corresponding keys in key column. All data i'm getting would be the dynamic data. Please suggest.
Please find the fiddle http://jsfiddle.net/7t9qkLc0/12/
Sample html code:
<table width="300px" height="150px" border="1">
<tr><th>Key</th><th>Value</th></tr>
<tr>
<td id="1">data 1</td>
<td id="aa">AA</td>
</tr>
<tr>
<td id="1">data 1</td>
<td id="bb">BB</td>
</tr>
<tr>
<td id="1">data 1</td>
<td id="cc">CC</td>
</tr>
<tr>
<td id="2">data 2</td>
<td id="dd">DD</td>
</tr>
<tr>
<td id="2">data 2</td>
<td id="ee">EE</td>
</tr>
<tr>
<td id="3">data 3</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="4">data 4</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="5">data 5</td>
<td id="ff">FF</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="3" style="padding-left: 0px; padding-right: 0px; padding-bottom: 0px">
</td>
</tr>
</table>
Building on tkounenis' answer using Rowspan:
One option to implement what you need would be to read all the values in your table after being populated, then use a JS object literal as a data structure to figure out what rows/columns are unique.
A JS object literal requires a unique key which you can map values to. After figuring out what rows/columns should be grouped, you can either edit the original table, or hide the original table and create a new table (I'm creating new tables in this example).
I've created an example for you to create a new table either grouped by key or grouped by value. Try to edit the examples provided to introduce both requirements.
Let me know if you need more help. Best of luck.
JSFiddle: http://jsfiddle.net/biz79/x417905v/
JS (uses jQuery):
sortByCol(0);
sortByCol(1);
function sortByCol(keyCol) {
// keyCol = 0 for first col, 1 for 2nd col
var valCol = (keyCol === 0) ? 1 : 0;
var $rows = $('#presort tr');
var dict = {};
var col1name = $('th').eq(keyCol).html();
var col2name = $('th').eq(valCol).html();
for (var i = 0; i < $rows.length; i++) {
if ($rows.eq(i).children('td').length > 0) {
var key = $rows.eq(i).children('td').eq(keyCol).html();
var val = $rows.eq(i).children('td').eq(valCol).html();
if (key in dict) {
dict[key].push(val);
} else {
dict[key] = [val];
}
}
}
redrawTable(dict,col1name,col2name);
}
function redrawTable(dict,col1name,col2name) {
var $table = $('<table>').attr("border",1);
$table.css( {"width":"300px" } );
$table.append($('<tr><th>' +col1name+ '</th><th>' +col2name+ '</th>'));
for (var prop in dict) {
for (var i = 0, len = dict[prop].length; i< len; i++) {
var $row = $('<tr>');
if ( i == 0) {
$row.append( $("<td>").attr('rowspan',len).html( prop ) );
$row.append( $("<td>").html( dict[prop][i] ) );
}
else {
$row.append( $("<td>").html( dict[prop][i] ) );
}
$table.append($row);
}
}
$('div').after($table);
}
Use the rowspan attribute like so:
<table width="300px" height="150px" border="1">
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr>
<td id="1" rowspan="3">data 1</td>
<td id="aa">AA</td>
</tr>
<tr>
<td id="bb">BB</td>
</tr>
<tr>
<td id="cc">CC</td>
</tr>
<tr>
<td id="2" rowspan="2">data 2</td>
<td id="dd">DD</td>
</tr>
<tr>
<td id="ee">EE</td>
</tr>
<tr>
<td id="3">data 3</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="4">data 4</td>
<td id="ff">FF</td>
</tr>
<tr>
<td id="5">data 5</td>
<td id="ff">FF</td>
</tr>
</table>
http://jsfiddle.net/37b793pz/4/
Can not be used more than once the same id. For that use data-id attribute
HTML:
<table width="300px" height="150px" border="1">
<tr>
<th>Key</th>
<th>Value</th>
</tr>
<tr>
<td data-id="key1">data 1</td>
<td data-id="valaa">AA</td>
</tr>
<tr>
<td data-id="key1">data 1</td>
<td data-id="valbb">BB</td>
</tr>
<tr>
<td data-id="key1">data 1</td>
<td data-id="valcc">CC</td>
</tr>
<tr>
<td data-id="key2">data 2</td>
<td data-id="valdd">DD</td>
</tr>
<tr>
<td data-id="key2">data 2</td>
<td data-id="valee">EE</td>
</tr>
<tr>
<td data-id="key3">data 3</td>
<td data-id="valff">FF</td>
</tr>
<tr>
<td data-id="key4">data 4</td>
<td data-id="valff">FF</td>
</tr>
<tr>
<td data-id="key5">data 5</td>
<td data-id="valff">FF</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="3" style="padding-left: 0px; padding-right: 0px; padding-bottom: 0px"></td>
</tr>
</table>
JQ:
//merge cells in key column
function mergerKey() {
// prevents the same attribute is used more than once Ip
var idA = [];
// finds all cells id column Key
$('td[data-id^="key"]').each(function () {
var id = $(this).attr('data-id');
// prevents the same attribute is used more than once IIp
if ($.inArray(id, idA) == -1) {
idA.push(id);
// finds all cells that have the same data-id attribute
var $td = $('td[data-id="' + id + '"]');
//counts the number of cells with the same data-id
var count = $td.size();
if (count > 1) {
//If there is more than one
//then merging
$td.not(":eq(0)").remove();
$td.attr('rowspan', count);
}
}
})
}
//similar logic as for mergerKey()
function mergerVal() {
var idA = [];
$('td[data-id^="val"]').each(function () {
var id = $(this).attr('data-id');
if ($.inArray(id, idA) == -1) {
idA.push(id);
var $td = $('td[data-id="' + id + '"]');
var count = $td.size();
if (count > 1) {
$td.not(":eq(0)").remove();
$td.attr('rowspan', count);
}
}
})
}
mergerKey();
mergerVal();
Use below snippet of javascript. It should work fine for what you are looking.
<script type="text/javascript">
function mergeCommonCells(table, columnIndexToMerge){
previous = null;
cellToExtend = null;
table.find("td:nth-child("+columnIndexToMerge+")").each(function(){
jthis = $(this);
content = jthis.text();
if(previous == content){
jthis.remove();
if(cellToExtend.attr("rowspan") == undefined){
cellToExtend.attr("rowspan", 2);
}
else{
currentrowspan = parseInt(cellToExtend.attr("rowspan"));
cellToExtend.attr("rowspan", currentrowspan+1);
}
}
else{
previous = content;
cellToExtend = jthis;
}
});
};
mergeCommonCells($("#tableId"), 1);
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>

$.ajax not working in chrome and firefox but is working in IE

I have the following code. It works fine in IE but not in Chrome and Firefox. There is no error displayed. It just doesn't get the value entered. Can someone help me fix the problem. Thanks in advance.
File 'main.php'
---------------
<tr>
<td width="11%" class="style171"></td>
<td width="55%" bgcolor="#A8D3FF" class="style171"><strong>APPROVE</strong></td>
<td width="16%" bgcolor="#A8D3FF" align="center"><input type="radio" name="approve" id="approve" value="1" <?php if ($approve== '1') echo "checked"; ?> /></td>
<td width="18%"></td>
</tr>
<tr>
<td width="11%" class="style171"></td>
<td class="style171" bgcolor="#A8D3FF"><strong>NOT APPROVE</strong></td>
<td bgcolor="#A8D3FF" align="center"><input type="radio" name="approve" id="approve" value="2" onClick="processForm()" <?php if ($approve== '2') echo "checked"; ?> /></td>
<td width="18%"></td>
</tr>
<tr>
<td width="11%" class="style171"></td>
<td colspan="2" align="left"><div id="div_data"></div></td>
<td width="18%"></td>
</tr>
<script type="text/javascript">
function processForm()
{
var val = 0;
if(window.document.getElementById('approve').checked)
var val = 1;
$.ajax( {
type: 'POST',
url: 'not_approved.php',
data: "value="+val,
cache: false,
success: function(html){
$("#div_data").html(html);
}
} );
}
</script>
File 'not_approved.php'
-----------------------
<form id="formt" name="formt" method="post" action="">
<table width="100%" border="0" align="left" cellpadding="1" cellspacing="0" bgcolor="#D8EEFE">
<tbody>
<tr>
<td colspan="3"><table width="100%" border="1" bordercolor="#33CCFF" cellspacing="0" cellpadding="1">
<tbody>
<tr class="style2">
<td align="left"><font color="#FF0000">*</font> Enter your comments here.
<table width="430" border="0">
<tr class="style2">
<td width="10" align="left" valign="top"></td>
<td width="410" colspan="2" align="left" valign="top"><textarea name="comment" id="comment" cols="45" rows="5"><?php echo $comment; ?></textarea></td>
</tr>
</table></td>
</tr>
</tbody>
</table></td>
</tr>
</tbody>
</table>
</form>
Try this
function processForm()
{
var val = 0;
if(window.document.getElementById('approve').checked)
var val = 1;
$.ajax( {
type: 'POST',
url: 'not_approved.php',
data: {value:val},
cache: false,
success: function(html){
$("#div_data").html(html);
}
} );
}
</script>
** The data filed is changed **
You are passing data in wrong way do as below
data: "{'value':"+val+"}",
and if the value is in string then
data: "{'value':'"+val+"'}",
or
data: JSON.stringify({value:val})
Your data variable must not be in string format because its a variable name. You should do it like this:
<script type="text/javascript">
function processForm()
{
var val = 0;
if(window.document.getElementById('approve').checked)
var val = 1;
$.ajax( {
type: 'POST',
url: 'not_approved.php',
data: {
value: val,
}
cache: false,
success: function(html){
$("#div_data").html(html);
}
} );
}
</script>
Here your script variable val value assigned to value variable and for assigning we use colon here ':' instead of = in AJAX. In server side the catching variable must also be of same name i.e value.

Validation on dynamically added rows

I'm cloning a row and I want to check in the database if the code exists. This all works fine on the first row but not on the cloned rows. I have an idea that I have to make the id of the field unique, I have tried to add the the code that checks if the code exist to the add button event but it doesn't work. Can someone please tell me how to merge the two script so it works on the cloned rows.
Code:
HTML
<table>
<tr id="show_codes">
<td colspan="2" class="text-fields" align="center" valign="middle">
<div class="codeForm">
<table class="codeForm" align="left" width="500px" cellpadding="0" style="padding-left: 20px;" cellspacing="0">
<tr>
<td height="15px">Codes that exist is 0011, 1234</td>
</tr>
<tr class="code_row">
<td class="details-border1" height="40px" valign="middle" bgcolor="#f3f3f3" align="center">
<input id="code" value="" class="text ui-widget-content ui-corner-all" type="text" name="code[]" />
<div id="status"></div>
</td>
<td class="details-border2" bgcolor="#f3f3f3" align="center">
<input value="" class="text ui-widget-content ui-corner-all" type="text" name="value[]" />
</td>
<td class="borders-right-bottom" bgcolor="#f3f3f3" align="center">
<input type="button" class="btnDeleteCode" value="Delete" />
</td>
</tr>
</table>
</div>
<table width="500px" align="left">
<tr>
<td align="right"><span style="cursor: pointer; color: #007FC6; font-weight: bold;" id="btnAddCode" value="add more">Add another code</span>
</td>
</tr>
</table>
</td>
</tr>
JQUERY
var dom = {};
dom.query = jQuery.noConflict(true);
dom.query(document).ready(function () {
var clonedRow = dom.query('.code_row').clone().html();
var appendRow = '<tr class = "code_row">' + clonedRow + '</tr>';
var counter = 0;
dom.query('#btnAddCode').click(function () {
dom.query('.codeForm tr:last').after(appendRow);
counter++;
$('.codeForm tr:last input[type="text"]').attr('id', 'code[' + counter + ']');
$('.codeForm tr:last').find('input').val('');
});
dom.query('.btnDeleteCode').live('click', function () {
var rowLength = dom.query('.code_row').length;
if (rowLength > 1) {
deleteRow(this);
} else {
dom.query('.codeForm tr:last').after(appendRow);
deleteRow(this);
}
});
function deleteRow(currentNode) {
dom.query(currentNode).parent().parent().remove();
}
});
pic1 = new Image(16, 16);
pic1.src = "loader.gif";
pic2 = new Image(16, 16);
pic2.src = "tick.gif";
dom.query(document).ready(function () {
dom.query("#code").change(function () {
var usr = dom.query("#code").val();
if (usr.length >= 4) {
dom.query("#status").html('<img src="loader.gif" align="absmiddle"> Checking availability...');
alert(usr);
dom.query.ajax({
type: "POST",
url: "setup_practice_preference_check_code.php",
data: "username=" + usr,
success: function (msg) {
dom.query("#status").ajaxComplete(function (event, request, settings) {
if (msg == 'OK') {
dom.query("#code").removeClass('object_error'); // if necessary
dom.query("#code").addClass("object_ok");
dom.query(this).html(' <img src="tick.gif" align="absmiddle">');
} else {
alert('msg');
dom.query("#code").removeClass('object_ok'); // if necessary
dom.query("#code").addClass("object_error");
dom.query(this).html(msg);
}
});
}
});
} else {
dom.query("#status").html('<font color="red">The username should have at least <strong>4</strong> characters.</font>');
dom.query("#code").removeClass('object_ok'); // if necessary
dom.query("#code").addClass("object_error");
}
});
});
Fiddle
Thanks

jquery sum of dynamically added textboxes

i have a page where i can add and delete rows with a textbox with class 'prijs'. when the page is loaded there is already one row.
now i need to sum the values of all textboxes with class 'prijs' and display it in a TD with id 'totaalexbtw'. here is my problem: it doesn't loop through the added textboxes. also, when a textbox is deleted the total should be affected.
Some help would be very appreciated!! I am stuck for days!
Thanks in advance!
<html>
<head>
<script type="text/javascript" src="javascript/jquery_v2.0.3.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
function kiesklant(str)
{
var xmlhttp;
if (str=="")
{
document.getElementById("klantinfo").innerHTML="<table><tr><td>Naam:</td><td</td></tr><td>Adres:</td><td></td></tr><td>Tel:</td><td></td></tr>";
return;
}
if (window.XMLHttpRequest)
{
xmlhttp = new XMLHttpRequest();
}
else
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("klantinfo").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "kiesklant.php?q="+str, true);
xmlhttp.send();
};
var linenumber = 0;
function addLine()
{
linenumber++;
var newRow = document.createElement('tr');
var newCell = document.createElement('td');
newCell = document.createElement('td');
var inputNode = document.createElement('input');
inputNode.name = 'dienstomschrijving';
inputNode.setAttribute('type', 'text');
inputNode.setAttribute('style', 'width: 200px');
newCell.appendChild(inputNode);
newRow.appendChild(newCell);
newCell = document.createElement('td');
inputNode = document.createElement('input');
inputNode.name = 'prijs';
inputNode.setAttribute('type', 'text');
inputNode.setAttribute('style', 'width: 100px');
inputNode.className = 'prijs';
newCell.appendChild(inputNode);
newRow.appendChild(newCell);
newCell = document.createElement('td');
inputNode = document.createElement('input');
inputNode.name = 'verwijder_dienst';
inputNode.setAttribute('type', 'button');
inputNode.setAttribute('onclick', 'delLine(this)');
inputNode.value = 'Verwijder dienst';
newCell.appendChild(inputNode);
newRow.appendChild(newCell);
document.getElementById('dienst').appendChild(newRow);
};
function delLine(line)
{
var row = line.parentNode.parentNode;
row.parentNode.removeChild(row);
};
function bereken()
{
var sumexbtw = $('.prijs').sum(function()
{
return +parseFloat(this.value) || 0;
});
$('#totaalexbtw').val(sumexbtw.toFixed(2));
var btw = sumexbtw * 0,21;
$('#btw').val(btw.toFixed(2));
var totaal = sumexbtw + btw;
$('#totaal').val(totaal.toFixed(2));
};
$(document).on('change', 'input.prijs', bereken);
</script>
</head>
<body>
<?php
include("function.php");
// haal max factuurnr op uit database
$sth1 = maakConnectie() -> prepare("SELECT MAX(factuurnummer) as 'max' FROM factuur");
$sth1 -> execute();
$result = $sth1 -> fetchAll(PDO :: FETCH_ASSOC);
// tel hier 1 bij op zodat er steeds opeenvolgende nummers worden genereerd
foreach($result as $rij)
{
$factuurnr = $rij['max'] + 1;
}
$datum = date("d-m-Y");
$sth2 = maakConnectie() -> prepare("SELECT voornaam, achternaam FROM gebruiker");
$sth2 -> execute();
$result2 = $sth2 -> fetchAll (PDO::FETCH_ASSOC);
?>
<form method="GET" action="aanmaken_factuur.php" class="formulier">
<table>
<tr>
<td>Factuur nr:</td>
<td align="right"><?php print($factuurnr);?></td>
</tr>
<tr>
<td>Datum:</td>
<td align="right"><?php print($datum);?></td>
</tr>
</table>
<br>
<table>
<tr>
<td><select name="klanten" onchange="kiesklant(this.value)">
<option value="" selected>Kies klant</option>
<?php foreach($result2 as $rij)
{
print("<option value=\"".$rij["voornaam"]." ".$rij["achternaam"]."\">".$rij["voornaam"]." ".$rij["achternaam"]."</option>");
}?>
</select>
</td>
</tr>
</table>
<div id="klantinfo">
<table>
<tr>
<td>Naam:</td>
<td></td>
</tr>
<tr>
<td>Adres:</td>
<td></td>
</tr>
<tr>
<td>Tel:</td>
<td></td>
</tr>
</table>
</div>
<br>
<table id="dienst2">
<tbody id="dienst">
<tr>
<th align="left">Dienstomschrijving</th>
<th align="left">Prijs</th>
</tr>
<tr>
<td><input style="width: 200px" type="text" name="dienstomschrijving"></td>
<td><input style="width: 100px" type="text" name="prijs" class="prijs"></td>
<td><input type="button" name="verwijder_dienst" value="Verwijder dienst" onclick="delLine(this);"/></td>
</tr>
</tbody>
<tr>
<td><input type="button" name="toevoegen_dienst" value="Voeg dienst toe" onclick="addLine();" /></td>
</tr>
</table><br>
<table id="totaal">
<tr>
<td align="right">Totaal excl. BTW</td>
<td align="center" id="totaalexbtw"></td>
</tr>
<tr>
<td align="right">BTW 21%</td>
<td align="center" id="btw"></td>
</tr>
<tr>
<td colspan=2 align="center">_________________________________________</td>
</tr>
<tr>
<td align="right">Factuur totaal</td>
<td align="center" id="totaal"></td>
</tr>
<tr>
<td align="right"><button onclick="index2.php" name="annuleren">Annuleren</button></td>
<td align="right"><input type="submit" name="submit" value="Maak factuur aan"></td>
</tr>
</table>
</form>
There are two errors in your code
$('.prijs').each.change(berekentotaalexbtw());
^^^^ ^^
No need to use each and you are not assigning the function, you are calling it.
$('.prijs').change(berekentotaalexbtw);
Since i just made the same thing yesterday:
(function($) {
$.fn.sum = function (callback) {
var sum = 0;
this.each(function () {
sum += 1 * callback.apply(this);
});
return sum;
};
})(jQuery);
this is just a helper function function so you can do: $('.prijs').sum( .... ); instead of using .each(.... )
and here's your answer
// If you do $('.prijs').change() it binds it to the currently existing elements.
// i think you are adding and deleting them dynamically, so you needed a delegated event.
function berekentotaalexbtw() {
var sum = $('.prijs').sum(function() {
// just a shorter version of all the 'isNan' stuff you got going on.
// defaults to 0 if it's NaN
return +parseFloat(this.value) || 0;
});
// Since you want it printed like a currency: use sum.toFixed(2) to format it :-)
$('#totaalexbtw').val( sum.toFixed(2) );
}
$(document).on('change','input.prijs',berekentotaalexbtw);
// and on deletion of an element: berekentotaalexbtw();

Categories

Resources