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
Related
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.
I have a jquery function, that activates only when a table row is clicked and if so, it invokes controller method. However, this row also contains checkbox, and if i click it i don't want this method to be called. I tried checking the clicked element type or other parameters like class, but it seems to only apply to the entire row. Any ideas how to make it work?
JQuery:
function AllowTableRowsToBeClicked() {
$('#pref-table tbody tr').click(function () {
var resourceName = $(this).attr('title');
var categoryName = $('#pref-table').attr('name');
var url = "/Home/GetSpecific";
$.post(url, { categoryName: categoryName, resourceName: myClass }, function (data) {
});
});
}
cshtml:
<table class="table table-striped table-hover margin-top-20 pref-table" id="pref-table" name=#Model.CurrentItemMode>
#for (int i = 0; i < Model.BiData.Count; i++)
{
<tr id=#Model.BiData[i].Name name=#i title="#Model.BiData[i].Name" class="tableRow">
#Html.Hidden("resourceList[" + i + "]", Model.BiData[i].Name)
<th>
#Html.CheckBox("checkBoxList[" + i + "]", Model.BiData[i].Selected, new { #class = "resourceCheckbox" })
</th>
<th>
#Model.BiData[i].Name
</th>
</tr>
}
</table>
If your checkbox has some id like box then you can check if the event originated from that checkbox and stop processing.
$('#pref-table').on('click',function (event) {
if(event.target.id === 'box'){
return;
}
var resourceName = $(this).attr('title');
var categoryName = $('#pref-table').attr('name');
var url = "/Home/GetSpecific";
$.post(url, { categoryName: categoryName, resourceName: myClass }, function (data) {
});
Here's a Pen to demonstrate the idea.
Try event.stopPropagation():
$('#pref-table input[type="checkbox"]').click(function(e) {
e.stopPropagation();
});
Using eventPropagation in the example below:
Html
<table width="100%">
<tr style="background:yellow">
<td>
<input type="checkbox" />
</td>
</tr>
</table>
javascript/jquery
$(document).ready(function() {
$('table tr').click(function(e) {
alert("row clicked");
});
$('input[type=checkbox]').click(function(e) {
e.stopPropagation();
alert("checkbox clicked")
});
});
Jsfiddle demo
I think your problem is you don't want to activate your event code when user clicks on checkbox, irrespective of checkbox state.
$('#pref-table tbody tr').click(function (event) {
if($(event.target).is(":checkbox")) return;
// your event code
});
I am unable to check an option from jquery multi-select dropdown list
even after being able to find the option in the multi-select list.
Please advise me what I am missing. Thanks!!
//this is my multi-select dropdown<br/>
$("#ddlCountries").multiselect();
var country = "USA";
//I tried below, but it did not work
//$("#ddlCountries").multiselect("widget").find(":checkbox[value='" + country + "']").attr("checked", true);
Response # Bhavin:
I did as per you, still not getting expected result. Please see below.
$(document).ready(function () {
$("#ddlCountries").multiselect();
$("#ddlCountries").multiselect('uncheckAll');
}
function ddlRole_OnChange(){
//client object of ddlRoles combobox
var roles = $(this).data('tComboBox');
//selected item from ddlRoles
var selectedRole = roles.text();
if (selectedRole.toLowerCase() === "admin"){
//custom yes/no dialog box (first param is Title, second param is Question, third param is callback function)
YesNoJqueryDailogBox('Admin Configuration:', 'Need Admin Role ?', 'selectForAdminRole');
}
}
function selectForAdminRole(){
$(document).ready(function (){
$("#ddlCountries").multiselect();
$("#ddlCountries").multiselect('uncheckAll');
var country = "USA";
$("#ddlCountries").multiselect("widget").find(":checkbox[value='" + country + "']").prop('checked', true);
});
}
Response # Ziv Weissman
MVC view (.cshtml)
<tr>
<td align="left" valign="middle" width="30%">
#if (ViewBag.Roles != null)
{
#(
Html.Telerik().ComboBox().Name("ddlRole") #*server-side combobox name*#
.BindTo((IEnumerable<SelectListItem>)ViewBag.Roles) #*server-side ddlRole binding in page load*#
.ClientEvents(events => events.OnChange("ddlRole_OnChange")) #*server-side ddlRole change event*#
)
}
</td>
</tr>
<tr>
<td align="left" valign="middle" width="15%" height="40" >
Countries <span class="mandatory">*</span>
</td>
<td align="left" valign="middle" width="20%" >
#if (ViewBag.Countries != null)
{
#*server-side ddlCountries dropdown binding in page load*#
#Html.DropDownList("ddlCountries", (IEnumerable<SelectListItem>)ViewBag.Countries)
}
</td>
</tr>
Solved: Refreshing ddlCountries dropdown after checking the option solved the problem.
var countries= $("#ddlCountries").multiselect('uncheckAll');
countries.children('option').each(function (){
var countryNameText = $(this).text();
if (countryNameText == "admin"){
$(this).attr('selected', 'selected');
}
});
$("#ddlCountries").multiselect("refresh");
Thanks all of you!
you must refresh multiSelect, and why you add $(document).ready inside selectForAdminRole function
$("#ddlCountries").find("option[value=" + ce + "]").prop("selected", true)
$("#ddlCountries").multiselect("refresh")
and you can use this
$("#ddlCountries").val("USA");
$("#ddlCountries").multiselect("refresh")
If I put onload event twice or setTimeout works.
I used the first option as workaround, it's ugly but works fine.
$(document).ready(function() {
$(document).ready(function() {
$('#id').multiselect();
});
});
$(document).ready(function() {
setTimeout(function() {
$('#id').multiselect();
}, 500);
});
jQuery: 1.8.3
Bootstrap: 3.0.3
Multiselect: 0.9.13
Its working for me you can try this
$("#Id").find("option[value=" + $(this).val() + "]").prop("selected", true);
$("#Id").material_select();
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");
}
});
In the table the first column is editable and after edit it/change it I want to show the alert as Changed. I am calling the check function after 5000ms.
Adding Code Snippet for My code
Something I missed or wrong somewhere. Please Help.
Here is the Code.
var table = $("table tbody");
table.find('tr').each(function (i) {
var $tds = $(this).find('td'),
id = $tds.eq(0).text(),
product = $tds.eq(1).text();
$check = function() {
if(($tds.eq(0).text() != id) && ($tds.eq(1).text() != product)){
alert("Changed");
}
else{
alert("Not changed");
}
}
setInterval(function() { $check(); }, 5000);
alert(id + ":" + product);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td contentEditable>63</td>
<td>Computer</td>
</tr>
</tbody>
</table>
if(($tds.eq(0).text() != id) && ($tds.eq(1).text() != product)){
This only triggers when both fields changed, change it to a "||"
Also check out this: https://developer.mozilla.org/en-US/docs/Web/Events/input for capturing contenteditable changes.