Function works in Chrome/Safari but not Firefox - javascript

So I have a table where you can check a table row and it will get the values of each cell in that row and also display another column named Quantity #. The Quantity # column contains a type="number" input. After entering a number, a user will be able to refresh the page and the Quantity # column and the value entered into the input will both remain visible. A user can also hit a "Checkout" button and it will post that data to an email body.
That all works great in Safari and Google Chrome. However, in Firefox, if you enter a value into the input and then refresh for example, the value will no longer be in the input. Also, if you hit the Checkout button and it pastes the data to the email, it will not paste the input value either like it does in Safari/Chrome.
Why is this and what can I do to fix this problem in Firefox?
JavaScript:
$(function($) {
var RowData = (function(storage, storageKey) {
var rowData = readFromSession();
var dataItems = ['loc', 'rp-code', 'sku', 'special-id', 'description', 'quantity', 'unit'];
var emailDelimiters = {
'row': '%0D%0A',
'dataItem': '\xa0\xa0'
};
function readFromSession() {
return JSON.parse(storage.getItem(storageKey) || '{}');
}
function writeToSession() {
storage.setItem(storageKey, JSON.stringify(rowData));
}
function writeRow(tr) {
var $tr = $(tr),
id = $tr.prop('id');
if($tr.find('.check').is(':checked')) {
rowData[id] = {};
for(var i=0; i<dataItems.length; i++) {
rowData[id][dataItems[i]] = $tr.find('.' + dataItems[i]).text();
}
rowData[id].quantity_num = $tr.find('.spinner').val();
} else {
delete rowData[id];
}
writeToSession();
}
function readRow(tr) {
// restore tr's checkbox and spinner value from stored data
var $tr = $(tr),
id = $tr.prop('id'),
row = rowData[id];
if(row) {
$tr.find('.check').prop('checked', true).end()
// .find('.spinner').spinner('value', row.quantity_num); // if using spinner widget
.find('.spinner').val(row.quantity_num); // if using HTML5 <input type="number">
}
}
function toEmailString() {
return $.map(rowData, function(row, id) {
return $.map(row, window.encodeURIComponent).join(emailDelimiters.dataItem);
}).join(emailDelimiters.row);
}
// selectively expose functions as methods of RowData
return {
'writeRow': writeRow,
'readRow': readRow,
'toEmailString': toEmailString
};
})(window.sessionStorage, 'checkedRowData');
$('#merchTable').on('change', '.check', function() { // on changing a table row ...
RowData.writeRow($(this).closest('tr').get(0)); // ... set the corresponding row object in RowData and sessionStorage
}).on('blur', '.spinner', function() { // on leaving a spinner widget
RowData.writeRow($(this).closest('tr').get(0));
});
$('#checkout').on('click', function() { // on clicking the [Checkout] button
var link = "mailto:me#example.com" + "?subject=" + encodeURIComponent("Order") + "&body=" + RowData.toEmailString();
console.log(link);
window.location.href = link;
});
// Call this function on completion of every pagination/search
function restoreVisibleRows() {
$('#merchTable tbody tr').get().forEach(RowData.readRow);
}
restoreVisibleRows();
});
JavaScript that keeps input value and quantity # column displayed on refresh:
$(function(){
var showQuantityHeader = false;
$(':checkbox').each(function() {
// Iterate over the checkboxes and set their "check" values based on the session data
var $el = $(this);
//console.log('element id: ',$el.prop('id'),' sessionStorage[id]: ',sessionStorage[$el.prop('id')]);
$el.prop('checked', sessionStorage[$el.prop('id')] === 'true');
if ($el.prop('checked')) {
//show the quantity cell in the column under header with class num
$el.closest('tr').find('td.quantity_num').toggle(this.checked);
showQuantityHeader = true;
//setupSpinner(this);
var quantity = sessionStorage['value_'+$el.prop('id')];
}
});
if (showQuantityHeader) {
$('#merchTable').find('th.num').show();
//console.log('header with class num: ',$('#merchTable').find('th.num'));
}
$('input:checkbox').on('change', function() {
// save the individual checkbox in the session inside the `change` event,
// using the checkbox "id" attribute
var $el = $(this);
sessionStorage[$el.prop('id')] = $el.is(':checked');
console.log($el);
});
});
HTML:
<section id="checkout-btn">
<button id="checkout" name="order">Checkout</button>
</section>
<br>
<table id="merchTable" cellspacing="5" class="sortable">
<thead>
<tr class="ui-widget-header">
<th class="sorttable_nosort"></th>
<th class="sorttable_nosort">Loc</th>
<th class="merchRow">Report Code</th>
<th class="merchRow">SKU</th>
<th class="merchRow">Special ID</th>
<th class="merchRow">Description</th>
<th class="merchRow">Quantity</th>
<th class="sorttable_nosort">Unit</th>
<th style="display: none;" class="num">Quantity #</th>
</tr>
</thead>
<tbody>
<?php foreach ($dbh->query($query) as $row) {?>
<tr id="<?php echo intval ($row['ID'])?>">
<td class="ui-widget-content"><input type="checkbox" class="check" name="check" id="checkid-<?php echo intval ($row['ID'])?>"></td>
<td class="loc ui-widget-content" data-loc="<?php echo $row['Loc'] ?>"><input type="hidden"><?php echo $row['Loc'];?></td>
<td class="rp-code ui-widget-content" align="center" data-rp-code="<?php echo $row['Rp-Code'] ?>" id="rp-code-<?php echo intval ($row['Rp-Code'])?>"><?php echo $row['Rp-Code'];?></td>
<td class="sku ui-widget-content" data-sku="<?php echo $row['SKU'] ?>" id="sku-<?php echo intval ($row['SKU'])?>"><?php echo $row['SKU'];?></td>
<td class="special-id ui-widget-content" data-special-id="<?php echo $row['Special-ID'] ?>" align="center" id="special-id-<?php echo intval ($row['Special-ID'])?>"><?php echo $row['Special-ID'];?></td>
<td class="description ui-widget-content" data-description="<?php echo htmlspecialchars($row['Description']) ?>" id="description-<?php echo intval ($row['Description'])?>"><?php echo $row['Description'];?></td>
<td class="quantity ui-widget-content" data-quantity="<?php echo $row['Quantity'] ?>" align="center" id="quantity-<?php echo intval ($row['Quantity'])?>"><?php echo $row['Quantity'];?></td>
<td class="unit ui-widget-content" data-unit="<?php echo $row['Unit'] ?>" id="unit-<?php echo intval ($row['Unit'])?>"><?php echo $row['Unit'];?></td>
<td style="display: none;" class="quantity_num ui-widget-content"><input type="number" min="1" max="<?php echo $row['Quantity'];?>" step="1" style="width: 100px;" class="spinner" /></td>
</tr>
<?php } ?>
</tbody>
</table>
EDIT:

#Rataiczak24, it would appear that FF doesn't fire its blur event in exactly the same way as the other browsers.
Storing a row's state is currently done in response quantity_num inputs' blur events. For performance reasons, I was hoping you wouldn't need to do this, but you need to respond to the 'change' event instead of the 'blur' event. Responsiveness of the quantity_num input may suffer.
That should solve both reported problems.
There's some other stuff too :
With my RowData object in place, you shouldn't be interacting with sessionStorage directly (unless of course you use it for other purposes). All interactions should be via the RowData API, and all code outside of RowData() should neither read from nor write to sessionStorage.
If at any point you need confidence that a table row might need to be restored to the state stored in sessionStorage, then call RowData.readRow(tr), or call restoreVisibleRows() to restore all visible rows.
If you follow my instruction "Call this function on completion of every pagination/search", and call restoreVisibleRows(); on page load, then row restoration should not need to be addressed elsewhere.
Almost all of what's in your $(function() { var showQuantityHeader = false; ...; ...; ...; }); above is unnecessary. The only part that's not catered for in RowData is $('#merchTable').find('th.num').show();. For that, you just need to add add a few lines to restoreVisibleRows(), and similarly in response to checkboxes being checked/unchecked.
So, all-in-all, the bottom part of my code suggestion should look like this :
$('#merchTable').on('change', '.check', function() { // on cliking a checkbox
var $this = $(this),
$tr = $this.closest('tr');
$tr.find('td.quantity_num').toggle(this.checked);
$this.closest('table').find('th.num').toggle($('input:checkbox:checked', '#merchTable tbody').length > 0);
RowData.writeRow($tr.get(0)); // store row state
}).on('change', '.spinner', function() { // on changing the value of a "spinner" widget
RowData.writeRow($this.closest('tr').get(0)); // store row state
});
$('#checkout').on('click', function() { // on clicking the [Checkout] button
setTimeout(function() {
var link = "mailto:me#example.com" + "?subject=" + encodeURIComponent("Order") + "&body=" + RowData.toEmailString();
console.log(link);
window.location.href = link;
}, 0);
});
function restoreVisibleRows() {
$('#merchTable tbody tr').get().forEach(RowData.readRow);
if($('input:checkbox:checked', '#merchTable tbody').length > 0) {
$('#merchTable').find('th.num').show();
} else {
$('#merchTable').find('th.num').hide();
}
}
Your own $(".check").change(function(){...}) (if it still exists) can be removed.

Related

Hide table page in javascript

In my code below, when i select a checkbox it displays the name of the item checked. But my problem now is, the table is paginated so when i move to the next page and return, the already checked item goes back unchecked.
The same applies when i check a box and filter using the ajax request, when i return the already checked box will have moved to unchecked state.
How do i hide the table page to resolve this issue?
HTML
<table class="table" id="table" style="background-color:white" >
<thead>
<tr>
<th></th>
<th colspan="5"></th>
<th></th>
</tr>
</thead>
<tbody>
#foreach($items as $item)
<tr>
<td><input onclick="return results(this)" data-item="{{$item->toJson()}}" type="checkbox" id="{!! $item->id !!}" name="{!! $item->name !!}" value="{!! $item->price !!}" /> </td>
<td>{{$item->name }}</td>
</tr>
#endforeach
</tbody>
</table>
{{$items->links()}}
JS
function results(item){
var major = JSON.parse(item.dataset.item);
if(item.checked == true) {
$('.panel').append(
'<div class="container "> '+
'<table style="width:100%;" class="table" id="tables">'+
'<thead>'+'<thead>'+
'<tbody>'+
'<tr>'+ '<td class="name" >'+major.name+'</td>'+] '</tr>'+
'</tbody>'+'</table>'+'</div>')}
} else {
});
}
}
}
AJAX
success: function (data) {
console.log(data);
$("#table").slideDown('fast');
var table = $("#table tbody");
table.html("");
$.each(data, function(idx, elem){
table.append(
"<tr><td><input type='checkbox' onclick='return results(this)' data-item='"+JSON.stringify(elem)+"' id='"+elem.id+"' name='"+elem.name+"' value='"+elem.price+"' data-id="+elem.id+" /></td><td >"+elem.name+"</td><tr>"
);
});
}
Saving state is possible via "JavaScript - localStorage" functionality.
Today browsers have capability to save information that is more "cleaner" and informative then cookies.
On "checkbox" element I would add event listener that would start function called "saveState()". In this function I would save information about checkbox.
function saveState()
{
localStorage.setItem("checkBoxStatus", "Checked");
}
This information is saved into browser`s storage and won't be deleted until you delete it yourself.
To delete it you have two options:
`localStorage.removeItem("checkBoxStatus");`
`localStorage.clear();`
Then when you re-enter that page again, while you are "constructing" view you can add small function that will set state equal to the "saved" one.
function resumeState()
{
if(localStorage.getItem("checkBoxStatus") === "Checked)
//get check box and check or uncheck
}
HOW STORED DATA CAN BE USED
It's my point of view but I prefer building my HTML views via JavaScript, as I find it more cleaner way and easier also, because today you have frequent communication with "JavaScript/Ajax" functions and need more responsiveness.
so I would build my entire view with JavaScript Dom
**
function buildView()
{
var element = document.createElement("div");
var checkBox = document.createElement("input");
checkBox.settAttribute("type", "checkbox");
//here we will check
localStorage.getItem("checkBoxStatus") === "Checked" ? checkBox.setAttribute("checked", "true") : checkBox.setAttribute("checked", false);
element.appendChild(checkBox);
document.body.appendChild(element);
}
**
or use setTimeout function and stick to "HTML" views:
<body onload='setTimeout(buildView(), 2000);>'
this will wait until all the views are constructed and start after it.
You can set correct timing depending on how much data you are loading during "onload" event. If it's small data you can even wait for 1 second -> 1000
function buildView()
{
var checkBox = document.getElementById("checkBox");
//here we will check
if(localStorage.getItem("checkBoxStatus") === "Checked")
{
checkBox.setAttribute("checked", "true");
}
else
{
checkBox.setAttribute("checked", false);
}
}
Remember that main here is to use localStorage functionality to save data and after that how you will use that data, totally depends on developers imagination and creativity
I made a fiddle for you so that you can improve it in the way that you can use it for your purpose,here is the fiddle and the code:
HTML:
<div class="checkbox-set">
</div>
<div id = "result">
</div>
Js:
var id = "";
for(i=1 ; i<8 ;i++){
id="checkbox_"+i;
$('.checkbox-set').append('<input type="checkbox" id="'+ id +'" value="Click on me"/> <label for="'+id+'">Click on me</label> <br/> ');
}
var selected = [];
if(sessionStorage.selected) {
// selected = sessionStorage.selected;
var checkedIds= sessionStorage.selected.split(",");
$.each(checkedIds,function(i){
$("#" + checkedIds[i]).prop('checked', true);
selected.push(checkedIds[i]);
});
}
$('input[type="checkbox"]').change(function() {
if(this.checked) {
$(this).each(function(){
selected.push($(this).attr('id'));
//$("#result").html(selected);
});
}
if(!this.checked) {
const index = selected.indexOf($(this).attr('id'));
var tt= selected.splice(index, 1);
//$("#result").html(selected);
}
sessionStorage.selected = selected;
$("#result").html(sessionStorage.selected);
})
please confirm if it is helpful

Get All Table Row Values through Session Storage

I have an HTML table with one column having checkboxes. If you check a checkbox then press the "Checkout" button, it will take the specified rows and display them in the body of an email.
The top 100 rows are displayed on page load. I also have a search functionality where the user can search for specific rows. The user can maneuver throughout different searches and still keep all of the checkboxes checked with session storage. However, when a user hits "Checkout," the body of the email only displays the table rows that are checked and currently visible on the page.
So, if a user searches for a table row and checks it, but then navigates back to the original top 100 rows, that checked row would not display on the email because it is not displayed on the page at that current moment.
How can I fix this and show ALL rows that have been checked, whether they are visible on the page or not?
I have been told that I am storing the checkboxes in a session but then going back to the UI to read the list of selected items. However, I am unsure how exactly to fix this and would really appreciate some help! Thanks!
JavaScript that includes code to keep all checkboxes checked throughout session:
$(function(){
$(':checkbox').each(function() {
// Iterate over the checkboxes and set their "check" values based on the session data
var $el = $(this);
//console.log('element id: ',$el.prop('id'),' sessionStorage[id]: ',sessionStorage[$el.prop('id')]);
$el.prop('checked', sessionStorage[$el.prop('id')] === 'true');
if ($el.prop('checked')) {
//show the quantity cell in the column under header with class num
$el.closest('tr').find('td.quantity_num').toggle(this.checked);
var quantity = sessionStorage['value_'+$el.prop('id')];
if (quantity) {
$el.closest("tr").find(".spinner" ).spinner( "value", quantity );
}
}
});
$('input:checkbox').on('change', function() {
// save the individual checkbox in the session inside the `change` event,
// using the checkbox "id" attribute
var $el = $(this);
sessionStorage[$el.prop('id')] = $el.is(':checked');
});
});
JavaScript that sends information to email body:
function sendMail() {
var dataItems = [
{ 'clss':'.loc', 'prop':'loc' },
{ 'clss':'.rp-code', 'prop':'rpCode' },
{ 'clss':'.sku', 'prop':'sku' },
{ 'clss':'.special-id', 'prop':'specialId' },
{ 'clss':'.description', 'prop':'description' },
{ 'clss':'.quantity', 'prop':'quantity' },
{ 'clss':'.unit', 'prop':'unit' }
];
var link = "mailto:me#example.com" + "?subject=" + encodeURIComponent("Order") + "&body=";
link += $('#merchTable tr input[name="check"]:checked').closest('tr').get().map(function(tr) {
var str = dataItems.map(function(item) {
return encodeURIComponent($(tr).find(item.clss).data(item.prop)) + '\xa0\xa0';
}).join('');
str += encodeURIComponent($(tr).find('.spinner').spinner('value')) + '%0D%0A';
return str;
}).join('') + '%0D%0A';
console.log(link);
window.location.href = link;
}
HTML Table:
<section id="checkout-btn">
<button id="checkout" name="order" onclick="sendMail(); return false">Checkout</button>
</section>
<br>
<table id="merchTable" cellspacing="5" class="sortable">
<thead>
<tr class="ui-widget-header">
<th class="sorttable_nosort"></th>
<th class="sorttable_nosort">Loc</th>
<th class="merchRow">Report Code</th>
<th class="merchRow">SKU</th>
<th class="merchRow">Special ID</th>
<th class="merchRow">Description</th>
<th class="merchRow">Quantity</th>
<th class="sorttable_nosort">Unit</th>
<th style="display: none;" class="num">Quantity #</th>
</tr>
</thead>
<tbody>
<?php foreach ($dbh->query($query) as $row) {?>
<tr>
<td class="ui-widget-content"><input type="checkbox" class="check" name="check" id="checkid-<?php echo intval ($row['ID'])?>"></td>
<td class="loc ui-widget-content" data-loc="<?php echo $row['Loc'] ?>"><input type="hidden"><?php echo $row['Loc'];?></td>
<td class="rp-code ui-widget-content" align="center" data-rp-code="<?php echo $row['Rp-Code'] ?>" id="rp-code-<?php echo intval ($row['Rp-Code'])?>"><?php echo $row['Rp-Code'];?></td>
<td class="sku ui-widget-content" data-sku="<?php echo $row['SKU'] ?>" id="sku-<?php echo intval ($row['SKU'])?>"><?php echo $row['SKU'];?></td>
<td class="special-id ui-widget-content" data-special-id="<?php echo $row['Special-ID'] ?>" align="center" id="special-id-<?php echo intval ($row['Special-ID'])?>"><?php echo $row['Special-ID'];?></td>
<td class="description ui-widget-content" data-description="<?php echo htmlspecialchars($row['Description']) ?>" id="description-<?php echo intval ($row['Description'])?>"><?php echo $row['Description'];?></td>
<td class="quantity ui-widget-content" data-quantity="<?php echo $row['Quantity'] ?>" align="center" id="quantity-<?php echo intval ($row['Quantity'])?>"><?php echo $row['Quantity'];?></td>
<td class="unit ui-widget-content" data-unit="<?php echo $row['Unit'] ?>" id="unit-<?php echo intval ($row['Unit'])?>"><?php echo $row['Unit'];?></td>
<td style="display: none;" class="quantity_num ui-widget-content"><input disabled="true" type="textbox" style="width: 100px;" class="spinner" id="spin-<?php echo intval ($row['ID'])?>"></td>
</tr>
<?php } ?>
</tbody>
</table>
EDIT:
Function that display the Quantity # column when a row is checked:
$(function () {
$(".check").change(function(){
$(this).closest('tr').find('td.quantity_num').toggle(this.checked);
setupSpinner(this);
console.log('input - checked: ',$('input.check').is(':checked'));
//var quantity = $(this).closest('tr').find('td.quantity').data('quantity');
if($('input.check').is(':checked'))
$(this).closest('table').find('th.num').toggle(true);
else
$(this).closest('table').find('th.num').toggle(false);
});
});
Function for the spinner:
function setupSpinner(checkbox) {
var quantity = $(checkbox).closest('tr').find('td.quantity').data('quantity');
console.log('quantity: ',quantity);
$(checkbox).closest("tr").find(".spinner" ).spinner({
spin: function( event, ui ) {
if ( ui.value > quantity ) {
$( this ).spinner( "value", quantity );
return false;
} else if ( ui.value <= 1 ) {
$( this ).spinner( "value", 1 );
return false;
}
//store value
var test = ui.value;
sessionStorage.setItem('value_'+$(checkbox).prop('id'), JSON.stringify(test));
var testtrue = sessionStorage.getItem('value_'+$(checkbox).prop('id'));
console.log('testtrue: ', JSON.parse(testtrue));
}
});
}
Function that gets values from each cell in checked table row:
$(function () {
$(document).on("click", "#merchTable .check", function () {
var $this = $(this);
var tds = $this.closest('tr').find('td').filter(function () {
return $(this).find('.check').length === 0;
});
var isValid = true;
var errors = '';
var elements = tds;
if (tds.find('td').length > 0) {
elements = tds.find('td');
}
var dict = {};
elements.each(function (index, element) {
var type = $(this).attr('class');
var value = (element.tagName == 'td') ? $(this).val() : $(this).text();
console.log(type);
// ----- Switch statement that provides validation for each table cell -----
switch (type) {
case "loc ui-widget-content":
dict["Loc"] = value;
break;
case "rp-code ui-widget-content":
dict["Rp-Code"] = value;
break;
case "sku ui-widget-content":
dict["SKU"] = value;
break;
case "special-id ui-widget-content":
dict["Special-ID"] = value;
break;
case "description ui-widget-content":
dict["Description"] = value;
break;
case "quantity ui-widget-content":
dict["Quantity"] = value;
break;
case "unit ui-widget-content":
dict["Unit"] = value;
break;
case "quantity_num ui-widget-content":
dict["spinner"] = value;
break;
}
})
if (isValid) {
console.log(dict);
} else {
alert(errors);
}
});
});
Based on this and earlier questions, I understand that you need something that :
stores the state of checked rows in window.sessionStorage.
restores the state of checked rows after pagination/search.
allows the composition of an email body, reflecting all checked rows whether they are currently displayed or not.
Without discipline the code could get really messy. I recommend a singleton object with a simple API, and ended up with the code below.
$(function($) {
// **************************************************************
// RowData acts as an interface beteween high level
// application code and sessionStorage.
// *************************
// RowData is phrased as a singleton object with private data,
// and a bunch of functions, some of which are exposed as methods.
// *************************
// Inner member `rowData` is a javascript representation of all
// checked rows in the session.
// A JSON-encoded version of `rowData` is stored in sessionStorage.
// **************************************************************
var RowData = (function(storage, storageKey) {
var rowData = readFromSession();
var dataItems = ['loc', 'rp-code', 'sku', 'special-id', 'description', 'quantity', 'unit'];
var emailDelimiters = {
'row': '%0D%0A',
'dataItem': '\xa0\xa0'
};
function readFromSession() {
return JSON.parse(storage.getItem(storageKey) || '{}');
}
function writeToSession() {
storage.setItem(storageKey, JSON.stringify(rowData));
}
function writeRow(tr) {
var $tr = $(tr),
id = $tr.prop('id');
if($tr.find('.check').is(':checked')) {
rowData[id] = {};
for(var i=0; i<dataItems.length; i++) {
rowData[id][dataItems[i]] = $tr.find('.' + dataItems[i]).text();
}
// rowData[id].quantity_num = $tr.find('.spinner').spinner('value'); // if using spinner widget
rowData[id].quantity_num = $tr.find('.spinner').val(); // if using HTML5 <input type="number">
} else {
delete rowData[id];
}
writeToSession();
}
function readRow(tr) {
// restore tr's checkbox and spinner value from stored data
var $tr = $(tr),
id = $tr.prop('id'),
row = rowData[id];
if(row) {
$tr.find('.check').prop('checked', true).end()
// .find('.spinner').spinner('value', row.quantity_num); // if using spinner widget
.find('.spinner').val(row.quantity_num); // if using HTML5 <input type="number">
}
}
function toEmailString() {
return $.map(rowData, function(row, id) {
return $.map(row, window.encodeURIComponent).join(emailDelimiters.dataItem);
}).join(emailDelimiters.row);
}
// selectively expose functions as methods of RowData
return {
'writeRow': writeRow,
'readRow': readRow,
'toEmailString': toEmailString
};
})(window.sessionStorage, 'checkedRowData');
// **********************************************************************************************
// With RowData in place to do the hard stuff, the high level application code is really simple
// **********************************************************************************************
$('#merchTable').on('change', '.check', function() { // on changing a table row ...
RowData.writeRow($(this).closest('tr').get(0)); // ... set the corresponding row object in RowData and sessionStorage
}).on('blur', '.spinner', function() { // on leaving a spinner widget
RowData.writeRow($(this).closest('tr').get(0));
});
$('#checkout').on('click', function() { // on clicking the [Checkout] button
var link = "mailto:me#example.com" + "?subject=" + encodeURIComponent("Order") + "&body=" + RowData.toEmailString();
console.log(link);
window.location.href = link;
});
// Call this function on completion of every pagination/search
function restoreVisibleRows() {
$('#merchTable tbody tr').get().forEach(RowData.readRow);
}
// ...
// here, set up table pagination/search, and spinners.
// ...
restoreVisibleRows();
});
minimally tested
Note, everything above relies on table rows being served as follows :
<tr id="<?php echo intval ($row['ID'])?>">
<td class="ui-widget-content"><input type="checkbox" class="check" name="check" /></td>
<td class="loc ui-widget-content"><input type="hidden"><?php echo $row['Loc'];?></td>
<td class="rp-code ui-widget-content" align="center"><?php echo $row['Rp-Code'];?></td>
<td class="sku ui-widget-content"><?php echo $row['SKU'];?></td>
<td class="special-id ui-widget-content" align="center"><?php echo $row['Special-ID'];?></td>
<td class="description ui-widget-content"><?php echo $row['Description'];?></td>
<td class="quantity ui-widget-content" align="center" ><?php echo $row['Quantity'];?></td>
<td class="unit ui-widget-content" ><?php echo $row['Unit'];?></td>
<td style="display: none;" class="quantity_num ui-widget-content"><input disabled="true" type="number" min="1" max="<?php echo $row['Quantity'];?>" step="1" style="width: 100px;" class="spinner" /></td>
</tr>
Here, I :
added id="<?php echo intval ($row['ID'])?>" to the <tr> tag - the RowData interface won't work without it.
removed data-*** and id attributes from the <td> tags - they appear not to be necessary but can be reintroduced if needed for other purposes.

How to clone a row of inputs with the parent element's function together? [duplicate]

This question already has an answer here:
Cloned elements' events corresponding to all elements in the form
(1 answer)
Closed 7 years ago.
I have a small table with two rows. In the first row I have 5 columns. First is select box displaying group names. WHen any of it selected, the second select box with list of item matching the value of selected group would appear in the next column. In third column, I have textbox for price. Followed by textbox for quantity in another.When price and quantity added the total of this will appear in the last column. In the second row I have a submit button with submits the form upon click.ALl these work perfectly fine.
Now I intend to allow users to dynamically add more of the first row so that they can submit multiple items! For that I'll need to add one more button type of input beside the submit.WHen clicked, it should clone the first row of 5 columns and also the function.
I tried:
$("#more_items").on("click",function
{
$("#clone_this").clone(true,true).appendTo("#submit_item");
});
This does clone the row. The first select box when selected from cloned item, the changes happen not to the current cloned row but to the parent row.Also, I couldn't clone more than once!ALso I tried replacing ID with class as I read clone would duplicate the ID yet no avail.
Now, how do I clone with the jquery also working correctly? DO I need to change my script in a way?
Below is my script for reference.
FORM
<form action="#" method="POST" id="submit_item">
<input type="text" name="contract_id" value="" id="contract_id2"/>
<table>
<tr><th>Group Item</th><th>Nama Item</th><th>Harga</th><th>Kuantiti</th><th>Amount</th></tr>
<tr id="clone_this">
<td>
<select name='group' style="width:80px;" id="gr">
<option>Choose group</option>
<?php
$group = $agency->show_all_group();
foreach($group as $k=>$v){
?>
<option value="<?php echo $v['group_id']?>"><?php echo $v['group_name']?></option>
<?php
}
?>
</select>
</td>
<td id="sub_item">
<select name='item' style="width:100px;" id="it_id">
</select>
</td>
<td><input type="text" name="harga" value="" id="harga"/></td>
<td>
<input type='text' size='2' value="" name='qty' id='qty'/>
</td>
<td><input type="text" name="amount" id="amount" value=""/></td>
</tr>
<tr><td colspan="3"><input type="submit" name="submit" value="Next" id="item_s"/></td>
<td><input type="button" value="Add more items" id="more_items"/></td>
</tr>
</table>
</form>
SCRIPT
<script>
var harga;
var qty;
$("#harga").on("keyup",function()
{
console.log($(this).val());
harga = $(this).val();
});
$("#qty").on("keyup",function()
{
console.log($(this).val());
qty = $(this).val();
var amount = harga * qty;
$("#amount").val(amount);
});
$(document).ready( function ()
{
$("#sub_item").hide();
$('#gr').change(function()
{
var gr_id = $(this).find('option:selected').val();
console.log(gr_id);
var agency_id = '<?php echo $_SESSION['agency_id'];?>';
/*show branch for selected department starts*/
var data;
$.ajax({
type: "POST",
dataType: "json",
url: s_path+"get-item.php?group="+gr_id+"&agency="+agency_id, //Relative or absolute path to response.php file
data: data,
success: function(data) {
$("#sub_item").show();
$("#it_id").empty();
for (i = 0; i < data.length; i++)
{
$("#it_id").append("<option value='"+data[i].item_id+"'>"+data[i].item_name+"</option>");
}
if(data.length == "")
{
$("#it_id").append("<option>No items found</option>");
}
console.log(data);
}});//end success
/*show branch ends*/
});
});
$(function()
{
$("#hide1").hide();
$("#hide2").hide();
$("#hide3").hide();
$('#faktor').change(function()
{
var val =$(this).val();
//alert($(this).val());
if($.trim(val)==1)
{
$("#hide1").show();
}else
{
$("#hide1").hide();
}
});
$('#insurance').change(function()
{
$("#hide2").show();
var val =$(this).val();
//alert($(this).val());
if($.trim(val)==1)
{
$("#hide2").show();
}else
{
$("#hide2").hide();
}
});
$('#bon').change(function()
{
$("#hide3").show();
var val =$(this).val();
//alert($(this).val());
if($.trim(val)==1)
{
$("#hide3").show();
}else
{
$("#hide3").hide();
}
});
});
</script>
You should bind your event to your parent element by using the function with delegation property. e.g. ".on()" function.
For example:
$("table.test").on("click","tr",function(){
//do something
});
For all newly created tr element inside the table element with class name ="test" could trigger "click" event due to event delegation. It means after you have clone a new row, your new row could trigger the same event without handling explicitly by yourself
The problem is since you have ids in the elements, when you are cloning you are creating elements with duplicate ids, which is invalid as ID of an element must be unique.
Instead of ID, use class in such cases like
<select name='group' style="width:80px;" class="gr">
....
<td class="sub_item">
<select name='item' style="width:100px;" class="it_id">
$(document).ready(function () {
$('#submit_item .gr').change(function () {
var $this = $(this),
$tr = $this.closest('tr'),
gr_id = $this.find('option:selected').val(),
$subitem = $tr.find('.sub_item'),
$it_id = $tr.find('.it_id');
var agency_id = '<?php echo $_SESSION['agency_id '];?>';
/*show branch for selected department starts*/
var data;
$.ajax({
type: "POST",
dataType: "json",
url: s_path + "get-item.php?group=" + gr_id + "&agency=" + agency_id, //Relative or absolute path to response.php file
data: data,
success: function (data) {
$subitem.show();
$it_id.empty();
for (i = 0; i < data.length; i++) {
$it_id.append("<option value='" + data[i].item_id + "'>" + data[i].item_name + "</option>");
}
if (data.length == "") {
$it_id.append("<option>No items found</option>");
}
console.log(data);
}
}); //end success
/*show branch ends*/
});
});

checked all/ unchecked all but limit row for check

I have
<thead>
<tr>
<th>Num</th>
<th>name</th>
<th>date</th>
<th><input type="checkbox" name="m_check" id="m_check" /></th>
</tr>
</thead>
<tbody>
<!-- i have loop for get data -->
<tr>
<td>$Num</td>
<td>$name</td>
<td>$date</td>
<td><input type="checkbox" name="e_check[]" value="<?php echo $companys->data[$i]['com_id'] ?>" class ="e_check" id="e_check_<?php echo $companys->data[$i]['com_id'] ?>" /></td>
</tr>
<!-- end loop for get data -->
</tbody>
this is my script
$('#m_check').change('change',function() {
if ($(this).is(':checked')) {
$('input[name="e_check[]"]:checkbox').attr('checked', true);
$('#ib_email').removeAttr("disabled");
} else {
$('input[name="e_check[]"]:checkbox').attr('checked', false);
$('#ib_email').attr("disabled", "disabled");
}
});
my problem is i need when user checked on m_check it's check element of e_check but check only 10, if my e_check more than 10 also.
please help me to correct my js
I also see this but i still can not custom my code :(
**Confirm my code is not wrong for user checked all, it's checked element row all, unchecked and it's unchecked all element row but i need when user checked all button it's checked element row limit 10 row top and other is still not check
There are a few mistakes in the jQuery. Prop should be used instead of attributes for the checked prop. Also ':checkbox' is not necessary when name="e_check[]" is already a unique identifier. Lastly, checkout the snippet at the bottom to grab the number. With it, you can set the checking behavior to reflect the number grabbed.
$('#m_check').change('change', function () {
if ($(this).is(':checked')) {
$('[name="e_check[]"]').prop('checked', true);
$('#ib_email').removeAttr("disabled");
} else {
$('[name="e_check[]"]').prop('checked', false);
$('#ib_email').attr("disabled", "disabled");
}
var $num = $(this).closest('table').find('td:first');
$num = parseInt($num);
});
You should do it like
$(document).on('change', '#m_check', function() {
$('#m_check').click(function () {
if ($(this).is(':checked')) {
$('input[type=checkbox].e_check').map(function (_, el) {
$(el).prop('checked', true);
});
} else {
$('input[type=checkbox].e_check').map(function (_, el) {
$(el).prop('checked', false);
});
}
});
});
or
$('#m_check').change(function() {
});
Edited:
Now when you will click on <input type="checkbox" name="m_check" id="m_check" /> All of your records will be checked.
you can do in this way.
I am assuming there is class tablecheckbox attachewd to tbody to
uniquely identify the checkbox.
$('#m_check').on('change',function() {
if ($(this).is(':checked')) {
if( $(".tablecheckbox tr input[type='checkbox']").length > 10){
$(".tablecheckbox tr input[type='checkbox']").slice(0,10).prop('checked',true)
}else{
$(".tablecheckbox tr input[type='checkbox']").prop('checked',true)
}
$('#ib_email').removeAttr("disabled");
} else {
$(".tablecheckbox tr input[type='checkbox']").slice(0,10).prop('checked',false)
$('#ib_email').attr("disabled", "disabled");
}
});

Loading Database Records into a table using AJAX?

I have been given a code to modify for database records on a website using ajax.
I have the function correctly querying data but the table displayed does not get any of the records displayed with in it. I have code of the functions and the html below.
Please see this link of current version: http://www.eng.nene.ac.uk/~10406206/CSY2028/Ajax/Ajax.html
Function of loadrecords with a callback not sure why a callback is used
<script language="Javascript">
var xmlHttpReq = false;
var xmlHttpReq2 = false;
var xmlHttpReq3 = false;
function loadDatabaseRecordsCallback ()
{
if (xmlHttpReq.readyState == 4)
{
alert ("From Server (Load Records):List.php" + xmlHttpReq.responseText);
var record = xmlHttpReq.responseXML.getElementsByTagName('record');
var s = "";
for (var i = 0; i < record.length; i ++)
{
var rec = record[i];
var id = rec.getElementsByTagName("ID")[0].firstChild.data;
var carname = rec.getElementsByTagName("CARNAME")[0].firstChild.data;
var fueltype = rec.getElementsByTagName("FUELTYPE")[0].firstChild.data;
var transmission = rec.getElementsByTagName("TRANSMISSION")[0].firstChild.data;
var enginesize = rec.getElementsByTagName("ENGINESIZE")[0].firstChild.data;
var doors = rec.getElementsByTagName("DOORS")[0].firstChild.data;
var total = rec.getElementsByTagName("TOTAL")[0].firstChild.data;
var available = rec.getElementsByTagName("AVAILABLE")[0].firstChild.data;
appendRecord (id, carname, fueltype, transmission, enginesize, doors, total, available);
}
}
}
function loadDatabaseRecords ()
{
// Mozilla/Safari
if (window.XMLHttpRequest)
{
xmlHttpReq = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject)
{
xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
alert ("To Server (Load Records): List.php");
xmlHttpReq.open('GET', "List.php", true);
xmlHttpReq.onreadystatechange = loadDatabaseRecordsCallback;
xmlHttpReq.send(null);
}
on the same page as the function is the table which is below
<body>
<form name="f1">
<input value="Load Database" type="button" onclick='JavaScript:loadDatabaseRecords()'></p>
</form>
<table id="DBTable" border="2">
<tr>
<td width="20">ID</td>
<td width="100">Car Name</td>
<td width="100">Fuel Type</td>
<td width="100">Transmission</td>
<td width="80">Engine size</td>
<td width="20">Doors</td>
<td width="20">Total</td>
<td width="20">Available</td>
</tr>
<form name="myform">
<tr>
<td><input type="text" name="id"></td>
<td><input type="text" name="carname"></td>
<td><input type="text" name="fueltype"></td>
<td><input type="text" name="transmission"></td>
<td><input type="text" name="enginesize"></td>
<td><input type="text" name="doors"></td>
<td><input type="text" name="total"></td>
<td><input type="text" name="available"></td>
<td colspan="2"><input type="button" value="add" onClick="JavaScript:addNewRecord()"></td>
<td colspan="2"><input type="checkbox" value="update" onClick="JavaScript:updateRecord()"></td>
<td colspan="2"><input type="checkbox" value="delete" onClick="JavaScript:deleteRecord()"></td>
</tr>
</form>
</table>
</body>
The function calls the List.php which is coded as follows
<?php
$link = mysql_connect ("194.81.104.22", "********", "*****");
mysql_select_db ("*******");
$query = "SELECT * from XYZ";
$result = mysql_query ($query);
for ($i = 0; $i < mysql_num_rows ($result); $i ++)
{
$row = mysql_fetch_object ($result);
print "<b>Car Name:</b> <i>$row->CARNAME</i><br>";
print "<b>Fuel Type:</b> <i>$row->FUELTYPE</i><br>";
print "<b>Transmission:</b> <i>$row->TRANSMISSION</i><br>";
print "<b>Total:</b> <i>$row->TOTAL</i><br>";
print "<b>Available:</b> <i>$row->AVAILABLE</i><br><br>";
}
mysql_close ($link);
?>
So, if you have seen the website you will see that you press the load database button and a box appears with all the database entries. However, once you press enter the table on the page remains empty.
My question is why?
can you explain to me where the problem is?
New to Ajax and apologies if I broke rules on posts it's my first one.
I am not clear with php, but I remember from my asp + ajax experiences:
You bring data back to your browser, but you should "re-paint" the page - you can do this in javascript, or may-be PHP has some ready solutions for this.
When you validated your method appendRecord receive valid values - find your table (DBTable) with javascript by id, and update the values of the row / columns by your record.
I'd recommend you to take a look on http://www.w3schools.com/php/php_ajax_database.asp
You bring data back to your browser, but you should "re-paint" the page - you can do this in javascript, or may-be PHP has some ready solutions for this.
When you validated your method appendRecord receive valid values - find your table (DBTable) with javascript by id, and update the values of the row / columns by your record.

Categories