Check for editable column in a table with jQuery function - javascript

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.

Related

jQuery stop script execution after if condition within click event

In this table, the rows are selectable only when Approved? column is empty. User can also add text in Deny Reason column.
When Deny button clicked, I want to make sure all deny reasons are filled in all selected rows before the rest of action can be executed. I tried to use return false , e.stopPropagation() , e.stopImmediatePropagation() and none of those works. As you can see in my example, alert("test") will always be executed. I want to stop that. Could you help?
$(function() {
var table = $("#myDataTable").DataTable({
info: false,
paging: false,
searching: false,
sorting: false
});
$("#myDataTable tbody").on('click', 'tr', function() {
var tr = $(this).closest("tr");
var rowText = tr.children("td").text();
var approveDeny = tr.children("td:nth-child(2)").text();
if (approveDeny == "") {
$(this).toggleClass('selected');
}
});
$("#myDataTable tbody tr td:nth-child(4)").click(function(e) {
if ($(this).prev().prev().text() == "") {
var text = $(this).text();
$(this).text('');
$('<textarea />').appendTo($(this)).val(text).select().blur(function() {
var newText = $(this).val();
var parentCell = $(this).parent();
parentCell.find('textarea').remove();
table.cell(parentCell).data(newText).draw();
});
}
e.stopPropagation();
});
$("#btnDeny").click(function(e) {
table.cells('.selected',3).every(function(rowIdx, tableLoop, rowLoop) {
var data = this.data();
if(data == "") {
alert( rowIdx + " is empty, you have to fill it.");
return false;
}
console.log(data);
});
alert("test");
});
});
<link href="https://cdn.datatables.net/1.10.10/css/jquery.dataTables.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.10/js/jquery.dataTables.min.js"></script>
<table id="myDataTable" class="table">
<thead>
<tr>
<th>Name</th>
<th>Approved?</th>
<th>Date</th>
<th>Deny Reason</th>
</tr>
</thead>
<tbody>
<tr id="1">
<td>Mickey Mouse</td>
<td>Yes</td>
<td>1/1/2016</td>
<td></td>
</tr>
<tr id="2">
<td>Minnie Mouse</td>
<td></td>
<td>1/3/2016</td>
<td></td>
</tr>
<tr id="3">
<td>Donald Duck</td>
<td></td>
<td>1/5/2016</td>
<td></td>
</tr>
</tbody>
</table>
<br/>
<div>
<input type="button" id="btnApprove" value="Approve">
<input type="button" id="btnDeny" value="Deny">
</div>
You can use a variable outside of the scope of your inner .every() function and change it within that function so you know if the data is valid or not.
$("#btnDeny").click(function(e) { // Outer scope function
var valid = true;
table.cells('.selected',3).every(function(rowIdx, tableLoop, rowLoop) { // inner scope function
var data = this.data();
if(data == "") {
valid = false;
alert( rowIdx + " is empty, you have to fill it.");
}
});
if (valid)
alert("Data valid");
});
Right, you need to assign the boolean output of every() to a variable, and then execute your alert only if that variable is true. Right now the result of the every() call is ignored, and the alert is executed regardless. Something like:
var isValid = table.cells('.selected',3).every(function(rowIdx, tableLoop, rowLoop) {
var data = this.data();
if(data == "") {
alert( rowIdx + " is empty, you have to fill it.");
return false;
}
console.log(data);
});
if (isValid) {
alert("test");
}

Jquery - check if checkbox was clicked

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
});

Hiding/Displaying columns using jQuery, checkboxes, and local storage

I have a page where a user submits a query using MVC, and the user can select the columns that are shown using checkboxes. After the user selects the query parameters and columns to view, the user is then sent to another page where a roster of individuals are shown. Checkbox data is stored using local storage, and used on the roster page where there are also checkboxes that the user can use to hide or display columns.
I have a working version, but the code looks awful and I think there is a better way to do this with less lines of code.
Here are the checkboxes used on the query page:
<div id="grpChkBox">
<input type="checkbox" class="columnSelect" name="fullName" /> Full Name
<input type="checkbox" class="columnSelect" name="type" /> Type
<input type="checkbox" class="columnSelect" name="ID" /> ID Number
</div>
Here is the script used to select columns and set values in local storage:
<script type ="text/javascript">
//Default is that all columns are selected
$("#grpChkBox input:checkbox").attr("checked", "checked");
localStorage.setItem("fullName", 1);
localStorage.setItem("type", 1);
localStorage.setItem("ID", 1);
$(function () {
if (localStorage.getItem("fullName") !== null) {
$("input[name='fullName']").attr("checked", "checked");
}
});
$("input[name='fullName']").click(function () {
if ($(this).is(":checked")) {localStorage.setItem("fullName", 1);}
else {localStorage.removeItem("fullName");}
});
$(function () {
if (localStorage.getItem("type") !== null) {$("input[name='type']").attr("checked", "checked");}
});
$("input[name='type']").click(function () {
if ($(this).is(":checked")) { localStorage.setItem("type", 1); }
else {localStorage.removeItem("type"); }
});
$(function () {
if (localStorage.getItem("ID")== null) { $("input[name='ID']").attr("checked", "checked"); }
});
$("input[name='ID']").click(function () {
if ($(this).is(":checked")) { localStorage.setItem("ID", 1); }
else { localStorage.removeItem("ID"); }
});
As you can see, I am creating a function for each checkbox and corresponding column, and there should be a way that I can enumerate columns/checkbox to do this with less lines of code. Just not sure how.
This is the HTML for the roster that is generated on the next page:
<table class="MainContent" style="width: 100%;" id="rosterTable">
<tr>
<th class="fullName" title="Full Name">Name</a></th>
<th class="type" title="Type">Type</a></th>
<th class="ID" title="ID Number">ID Number</a></th>
</tr>
<tr>
<td>Name 1</td>
<td>Type 1</td>
<td>ID Number 1</td>
</tr>
<tr>
<td>Name 2</td>
<td>Type 2</td>
<td>ID Number 2</td>
</tr>
</table>
It also has the same checkboxes as the previous page:
<div id="grpChkBox">
<input type="checkbox" class="columnSelect" name="fullName" /> Full Name
<input type="checkbox" class="columnSelect" name="type" /> Type
<input type="checkbox" class="columnSelect" name="ID" /> ID Number
</div>
And here's the script that reads local storage, and hides/displays columns after the roster is generated:
<script type="text/javascript">
// Reads local storage and check or unchecks, hides/displays
$(document).ready(function () {
if (localStorage.getItem("fullName") !== null) {
$("input[name='fullName']").attr("checked", "checked");
}
else {
var index = $("#rosterTable th").filter(".fullName").index();
$("#rosterTable").find('tr :nth-child(' + (index + 1) + ')').hide();
}
if (localStorage.getItem("type") !== null) {
$("input[name='type']").attr("checked", "checked");
}
else {
var index = $("#rosterTable th").filter(".type").index();
$("#rosterTable").find('tr :nth-child(' + (index + 1) + ')').hide();
}
if (localStorage.getItem("ID") !== null) { $("input[name='ID']").attr("checked", "checked"); }
else {
var index = $("#rosterTable th").filter(".ID").index();
$("#rosterTable").find('tr :nth-child(' + (index + 1) + ')').hide();
}
//After roster is generated users can hide display columns
$(function () {
var $chk = $("#grpChkBox input:checkbox");
var $tbl = $("#rosterTable");
var $tblhead = $("#rosterTable th");
//$chk.prop("checked", true);
$chk.click(function () {
var colToHide = $tblhead.filter("." + $(this).attr("name"));
var index = $(colToHide).index();
$tbl.find('tr :nth-child(' + (index + 1) + ')').toggle();
});
});
</script>
Once again, this should be done with less lines of code than using a case for each column and checkbox. I need to deploy this solution to multiple pages with different columns, so I would like to do this with more dynamic code. I'm pretty sure this could be done with less lines of code.
All help is appreciated
Looks like I found a solution myself. Here's what I did:
First, I replaced localStorage with sessionStorage.
I replaced the section where I set each sessionStorage object explicitly with this:
var selected = [];
$('#grpChkBox input[type=checkbox]').each(function () {
if ($(this).attr("checked")) {
sessionStorage.setItem(($(this).attr('name')), 1);
} else { sessionStorage.removeItem(($(this).attr('name'))); }
});
I replaced all the functions for checking the each sessionStorage value and populating each checkboxes with:
for (var i = 0, len = sessionStorage.length; i < len; i++) {
var key = sessionStorage.key(i);
var value = sessionStorage[key];
//document.write(key + " => " + value + "\n");
if (sessionStorage.getItem(key) !== null) {
$("input[name='" + key + "']").attr("checked", "checked");
}
}
I replaced all the click functions for each checkbox with this:
$('#grpChkBox input[type=checkbox]').click(function () {
if ($(this.name).attr("checked")) {sessionStorage.setItem(this.name, 1); }
else {sessionStorage.removeItem(this.name);}
})
On the page where the roster is created, I replaced all the functions for checking the each sessionStorage value and populating each checkboxes with:
for (var i = 0, len = sessionStorage.length; i < len; i++) {
var key = sessionStorage.key(i);
var value = sessionStorage[key];
//document.write(key + " => " + value + "\n");
if (sessionStorage.getItem(key) !== null) {
$("input[name='" + key + "']").attr("checked", "checked");
}
}
Instead of checking checkboxes that are checked, I am using unchecked values since the sessionStorage will have the corresponding keys/values removed. I replaced the many functions for determining which column is hidden with:
var selected = [];
$('#grpChkBox input:checkbox:not(:checked)').each(function() {
var index = $("#rosterTable th").filter("."+($(this).attr('name'))).index();
$("#rosterTable").find('tr :nth-child(' + (index + 1) + ')').hide();
});
That's it. The only thing that would make the over deployment of this simpler is if I could dynamically create checkboxes based on table header names.

jQuery find checkbox in first td

I have many tables and in that I want to do the following,
find a table which is present in class.
find first tr, first td in a table
check checkbox present first td in a table
if checkbox present in first td then add class.
Below is my code which is not working
function myFunction() {
debugger;
var FindClass = $("table.Panel");
debugger;
var FindClass = $(".Panel table.Table");
debugger;
debugger;
if (FindClass != null) {
$("#FindClass tr").find("td:first").tagname("input");
}
}
We can do this in 2 achieve this in 2 simple ways...
Find a table with the class selector. By conditional check we can add the class to the checkbox.
Implementing the complete code in a single line with out performing the conditional operations.
HTML
<table class="Panel">
<tr>
<td><input type="checkbox" /></td>
<td><p>Test</p></td>
</tr>
<tr>
<td>Second TD</td>
</tr>
</table>
jQuery (1st method)
if($('table.Panel').length > 0) {
var tblCheckbox = $('table.Panel tr:first td:first input[type=checkbox]');
if(tblCheckbox.length > 0) {
tblCheckbox.addClass('clstochkbox');
}
}
jQuery (1st method)
$('table.Panel tr:first td:first input[type=checkbox]').addClass('clstochkbox');
http://jsfiddle.net/64jv3z6d/
Check for .length property as jQuery objects are never null. And name it different.
var panelTable = $(".Panel table.Table");
if (panelTable.length) {
// panelTable has elements
}
You can do like this
var chk_box = $("table.Panel tr:first td:first")
.find('input type=["checkbox"]');
if(chk_box.length) {
$(chk_box.addClass('x')
}
We can do this in also this way.
<script type="text/javascript">
function myFunction() {
debugger;
var headerRow = $("table.Panel tr:first th:first");
debugger;
if (headerRow != null) {
var checkbox = headerRow.find("input[type=checkbox]");
if (checkbox[0].type == 'checkbox') {
headerRow.addClass('checkboxColumns');
alert('checkbox Found')
} else {
alert('not found')
}
}
}
</script>

How to hide any row in a table whose third cell value does not match a given string in JQuery

If i have a table:
<table id="myTable">
<tr>
<td>1</td><td>2</td><td>NoMatch</td><td>4</td>
</tr>
<tr>
<td>1</td><td>2</td><td>Match</td><td>4</td>
</tr>
</table>
I have been trying:
$(document).ready(function () {
$('input#myInput').keyup(function (val) {
// for each third td of each row, if this value does not contain: this.val() then hide it
});
});
Something like this:
var $cells = $('#myTable tr td:nth-child(3)'),
$hidden = $();
$('#myInput').keyup(function () {
var search = this.value;
var $to_hide = $cells.filter(function() {
return $(this).text() !== search;
}).parent();
$hidden.not($to_hide.get()).show();
$hidden = $to_hide.hide();
});
I assumed that when you say contains, you mean that the text has to be equal to the provided input (otherwise NoMatch and Match would not make sense). But if the content of cell just has to contain the search string as substring, you can use .indexOf() [docs].
DEMO
There are other things you have to consider, like what should happen when the search string is empty, but this is for you to play around ;)
Use "this" in your key up event handler to get the value of the input.
$(document).ready(function () {
$('input#myInput').keyup(function () {
//add if statement
alert($(this).val());
});
});
Not quite sure what you are trying to do with the table. There is not enough information.
Try this:
jsfiddle
HTML
<table id="myTable">
<tr>
<td>1</td><td>2</td><td>NoMatch</td><td>4</td>
</tr>
<tr>
<td>1</td><td>2</td><td>Match</td><td>4</td>
</tr>
</table>
<input id="myInput"/>
Javascript/Jquery
$('#myInput').keyup(function () {
var me = $(this);
var val = me.val();
$("#myTable tr").each(function() {
var tr = $(this);
var td = tr.find("td:eq(2)");
if(td.text().substring(0, val.length) === val) {
tr.show();
} else {
tr.hide();
}
});
});

Categories