jQuery script not running properly - javascript

I'am making a small personal app for creating html tables with jquery. I have this script (which i borrowed from somewhere around here and tweaked it a bit) that would, at the click of a button, add a new column at the end of my table.
function addJSONKey(){
var first = true;
$('#jsonTable').find('tr').each(function(){
$(this).find('th').eq(-1).after(
'<th contentEditable>New Key</th>'
);
if(first === true){
first = false;
// the function does not execute this statement
// even though the debugger breaks here.
$(this).find('td').eq(-1).after(
'<td>Frist</td>'
);
} else {
$(this).find('td').eq(-1).after(
'<td contentEditable>Not First</td>'
);
}
});
}
What i'd like the script to do is, for the first row to be different than the others, but if i run the script it gives back Not First rows everywhere.

You overcomplicated it a little. You can distinguish rows by their indexes and append new th or td accordingly:
function addJSONKey() {
$('#jsonTable').find('tr').each(function(i) {
// Header row
if (i === 0) {
$(this).find('th').eq(-1).after('<th contentEditable>New Key</th>');
}
// First data row
else if (i === 1) {
$(this).append('<td>Frist</td>');
}
// Not header and not the first row
else {
$(this).append('<td contentEditable>Not First</td>');
}
});
}
$('button').click(addJSONKey);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Add</button>
<table id="jsonTable">
<tr>
<th>One</th>
</tr>
<tr>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
</tr>
</table>

replace your method with
function addJSONKey()
{
$( '#jsonTable' ).find( 'tr' ).each(function(){
$(this).find('th').eq(-1).after(
'<th contentEditable>New Key</th>'
);
});
$( '#jsonTable' ).find( 'tr' ).each(function(){
if($(this).find('td').length == 0 )
{
$(this).append('<td>Frist</td>');
}
else
{
$(this).append('<td contentEditable>Not First</td>');
}
});
}
basically your boolean first will only be true for first column of first row.

In your code you counted the 1st row that was the header as first, you want to add to the 1st non-header row, that is the 2nd row, that is index 1, because it's 0 based :)
function addJSONKey(){
$('#jsonTable').find('tr').each(function(row){
$(this).find('th').eq(-1).after('<th contentEditable>New Key</th>');
if(row == 1){
// the function does not execute this statement
// even though the debugger breaks here.
$(this).find('td').eq(-1).after('<td>Frist</td>');
} else {
$(this).find('td').eq(-1).after(
'<td contentEditable>Not First</td>'
);
}
});
}
//addJSONKey();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="jsonTable">
<tr><th>a</th><th>b</th></tr>
<tr><td>10</td><td>11</td></tr>
<tr><td>20</td><td>21</td></tr>
</table>
<button onclick="addJSONKey()">go</button>

Related

How to add a cell in html table and check for duplicates, without entering the following loop?

Hey guys I am trying to add a new cell in html table and while checking for duplicates in the table. I loop over the table to check for duplicates but I want this alert to only show if there is a duplicate or not? Right now the alert is looping with the each function? It's probably an easy task but I can't handle it. Can someone help me?
$("#btnCheck").on("click", function() {
let company_name = $("#test1").val();
$('#companyTable tr').each(function() {
$(this).find('td').each(function() {
if ($(this).text() === company_name) {
alert("duplicate found");
return false;
} else {
alert("duplicate NOT found");
return false;
}
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="companyTable">
<thead>
<tr>
<td>Company Name</td>
</tr>
</thead>
<tbody>
<tr>
<td>toyota</td>
</tr>
<tr>
<td>bmw</td>
</tr>
<tr>
<td>suzuki</td>
</tr>
</tbody>
</table>
<input type="text" id="test1" />
<input type="button" id="btnCheck" value="ADD" />
I'm not common to JQuery, but in casual JavaScript this should work :
document.querySelector("#btnCheck").onclick = () => {
const companyName = document.querySelector("#test1").value;
let found = false;
document.querySelectorAll("#companyTable td").forEach(cell => {
if(cell.innerText == companyName){
found = true
}
})
alert("duplicate "+(found ? "" : "NOT ")+" found");
}
You do not need to query rows then cells.
alerting at each cell isn't the right thing to do. You should (as above) store your result (=found), and at the end of the loop only use your result.
Note: Using forEach in this case doesn't seem the most efficient way. You should rather you a casual for loop in order to break it as soon as you find a match :
const cells = document.querySelectorAll("#companyTable td");
found = false;
for(let i = 0; i < cells.length; i++){
if(cells[i].innerText == companyName) {
found = true;
break; // Stop the loop
}
}
In JQuery I would use something like
$("#companyTable tr td:contains('"+textToSearch+"')")
This should return all TD objects inside TR rows of your TABLE id="companyTable" which contains "textToSearch"
Break early from the outer loop, and only alert if it's not found after the loop:
$("#btnCheck").on("click", function () {
let company_name = $("#test1").val();
let found = false;
$('#companyTable tr').each(function () {
$(this).find('td').each(function() {
if ($(this).text() === company_name) {
alert("duplicate found");
found = true;
return false;
}
});
if (found) {
// no need to search through other rows either
return false;
}
});
if (!found) {
alert("duplicate NOT found");
}
});

Filtering table row by select option

I have a table that I'm filtering by using a select option, but I can't figure out how to go back and show all data after the initial filter. Also I need help drying my code.
// SHOWS INDIVIDUAL FILTER BUT CAN'T SHOW ALL
$(document).ready(function($) {
$("#sortAwardType").change(function() {
$("table").show();
var selection = $(this).val().toUpperCase();
var dataset = $(".awards-body").find("tr");
dataset.show();
if(selection) {
dataset.filter(function(index, item) {
// Filter shows table row with the word 'General'
return $(item).find(":contains('General')").text().toUpperCase().indexOf(selection) === -1;}).hide();
} else {
// .all corresponds to a "Show All" option. When selected the data doesn't show
$("#sortAwardTable").change(function(){
$(".all").dataset.show();
});
}
});
});
// ATTEMPTING DRY CODE. NOW I CAN'T FILTER AT ALL
$(document).ready(function($) {
$("#sortAwardType").change(function() {
$("table").show();
var selection = $(this).val().toUpperCase();
var dataset = $(".awards-body").find("tr");
var match = [
":contains('General')",
":contains('Free')",
":contains('Regional')",
":contains('Demographic')"];
dataset.show();
if(selection) {
dataset.filter(function(index, item) {
return $(item).find(match).text().toUpperCase().indexOf(selection) === -1;}).hide();
} else {
// .all corresponds to a "Show All" option. When selected I want all data to show but instead it only shows an empty table (header present but no rows)
$("#sortAwardTable").change(function(){
$(".all").dataset.show();
});
}
});
});
I don't want to keep repeating the if block only to change the ":contains('_____')". I tried grouping them in an array and assigning them to var match, but then the filter doesn't work.
salam , you have just to put all contains selectors in the same string
$(item).find(":contains('General'),:contains('Free'),:contains('Regional'),:contains('Demographic')").
but if you want take it easy follow my ex:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="searchBox">
<table id='testTable'>
<tr >
<td>aa</td>
<td>bb</td>
<td>cc</td>
</tr>
<tr >
<td>ab</td>
<td>bc</td>
<td>cd</td>
</tr>
<tr >
<td>zz</td>
<td>ee</td>
<td>ff</td>
</tr>
</table>
<script>
$('#searchBox').keyup(function(){
var val = $(this).val().toLowerCase();
if(val ===""){
$("#testTable > tbody > tr").toggle(true);
return;
}
$("#testTable > tbody > tr").toggle(false);
$("#testTable").find("td").each(function(){
if($(this).text().toLowerCase().indexOf(val)>-1)
$(this).parent().toggle(true);
});
});
</script>

Checkbox filter/search button: can't undo filtering when unchecked

I have a table made with datatables. There is checkbox, which, when clicked filters the table to display only the data I want to see. The problem is that when I uncheck the checkbox, the table becomes buggy. The table.destroy() function does seemingly revert the table back to the way it was, although it looks like it destroys a little too much (rows per page suddenly get ignored + can no longer click on cell, which opens up in another window). I'm guessing destroy() is not the correct way to revert back to the original table/data when unchecked. So what is the correct way?
This is what happens:
click on checkbox: filters the data correctly
uncheck checkbox: table looks as if gone back to normal (but hasn't really)
check checkbox again: no longer filters data correctly. (table is now empty)
now it doesn't matter if I check or uncheck, the table stays the same(empty)
Here is my code:
var checkbox = $("#checkB");
checkbox.click(function () {
var table = $('#TABLE_NAME').DataTable();
if (checkbox.is(":checked")) {
$.fn.dataTable.ext.search.push(
function (settings, data, dataIndex) {
var num = Number(data[4]);
if (num > 0) {
return true;
}
return false;
}
);
table.draw();
}
else {
table.destroy();
}
});
I finally found the answer. in the 'Else' part, I just wrote:
else {
$.fn.dataTable.ext.search.pop();
table.draw();
}
et voila!
This is it! I figure out the problem. Here is the final working code.
Hint: I hack around the filter function
var checkbox = $("#checkB");
var table = $('#example').DataTable();
$.fn.dataTable.ext.search.push(
function (settings, data, dataIndex) {
if (checkbox.is(":checked")) {
return Number(data[1]) > 0 ? true : false;
} else {
return true;
}
}
);
checkbox.click(function () {
if (checkbox.is(":checked")) {
table.draw();
} else {
table.draw();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<input type="checkbox" id="checkB" value="Check"> Check this to filter
<table id="example" class="display" style="width:100%">
<thead>
<tr>
<th>Example</th>
<th>Number</th>
</tr>
</thead>
<tbody>
<tr>
<td>Example1</td>
<td>-10</td>
</tr>
<tr>
<td>Example2</td>
<td>10</td>
</tr>
<tr>
<td>Example3</td>
<td>20</td>
</tr>
</tbody>
</table>

How can I fix jquery when i change table elements to div style in body section?

<body>
<input type="text" id="search"/>
<table id="boxdata">
<tr>
<td class="namebox1">jQuery</td>
</tr>
<tr>
<td class="namebox2">javascript</td>
</tr>
<tr>
<td class="namebox3">php</td>
</tr>
<tr>
<td class="namebox4">sql</td>
</tr>
<tr>
<td class="namebox5">XML</td>
</tr>
<tr>
<td class="namebox6">ASP</td>
</tr>
</table>
</body>
<script>
$(document).ready(function(){
$('#search').keyup(function(){
searchBox($(this).val());
});
});
function searchBox(inputVal) {
$('#boxdata').find('tr').each(function(index, row){
var names = $(row).find('td');
var found = false;
if(names.length > 0) {
names.each(function(index, td) {
var regExp = new RegExp(inputVal, 'i');
if(regExp.test($(td).text()) & inputVal != ''){
found = true;
return false;
}
});
if(found == true)
$(row).addClass("red");
else
$(row).removeClass("red");
}
});
}
</script>
there's a textfield for searching words and there are 6 words in the each 6 boxes below textfield.(I omitted css codes. but, it wouldnt matter to solve the problem.). if i type a letter 's' then the words that including letter 's' like 'javascript', 'sql', 'ASP' these font-color will be changed black to red. And i made it by using table elements in html but i'd like to change all elements into div style to put some data fluidly later. i have difficulty to fix especially jquery. how can i fix it?
You can simplify this a little bit.
function searchBox(inputVal) {
var regExp = new RegExp(inputVal, 'i');
$('#boxdata').find('tr').removeClass('red').filter(function() {
return $(this).find('td').filter(function() {
return regExp.test( $(this).text() );
}).length && $.trim(inputVal).length;
}).addClass('red');
}
So remove the red class from all <tr>'s first, then filter them, test the text of each <td>, if it matches, return the <tr> and then add the class red again.
Here's a fiddle
As for changing from a table to div, the jQuery would depend on how you structure your markup, but the principle would remain the same.
Here's another fiddle
You can make javascript code HTML agnostic by using css classes instead of element names. Demo.
function searchBox(inputVal) {
var regExp = new RegExp(inputVal = $.trim(inputVal), 'i'),
highlight = 'red';
$('#wrapper').find('.word') //instead of tr/td/div
.removeClass(highlight)
.each(function(){
var $this = $(this);
inputVal && regExp.test($this.text()) &&
$this.addClass(highlight);
});
}

How to achieve this without refreshing the page using jQuery?

I have a web page that populates a table via jQuery.
Since I only want to change classes of a particular <td> element I used replaceWith. This worked well on the first search, but I realized that I could not asynchronously perform another search without first refreshing my page. I then tried html instead of replaceWith. This worked well, but crammed all the new <td> into one <td> that has the specified id.
How can I achieve this without refreshing the page so that I can get the <td> elements well distributed?
Before updating:
<table>
<tr>
<td>first row</td>
<td>measure1</td>
<td>measure2</td>
<td>measure3</td>
<td>measure4</td>
<td> </td>
</tr>
<tr>
<td>First row</td>
<td id="no_rec" colspan="4"> No record to display!</td>
<td>More+</td>
</tr>
</table>
After updating I expect to have a table of the format:
<table>
<tr>
<td>first row</td>
<td>measure1</td>
<td>measure2</td>
<td>measure3</td>
<td>measure4</td>
<td> </td>
</tr>
<tr>
<td>First row</td>
<td class="new"></td>
<td class="new"></td>
<td class="new"></td>
<td class="new"></td>
<td>More+</td>
</tr>
</table>
My JavaScript:
$('#mybutton').click(function()
{
$.post
(
'search.php',
{
regNo: $("#regNo").val(),
datepicker: $(".datepicker").text()
},
function(data)
{
$.each(data, function(i)
{
var tm = data.time;
add_html='';
for (i=0; i<4; i++)
(i === 0 || i === 2)
? add_html += '<td class="new"></td>'
: add_html += '<td></td>';
$('#no_rec').replaceWith(add_html);
});
},
'json'
);
});
My JsFiddle Attempts
What I did was add id=results to the tr so that I could find and store all td tags and then manipulate them accordingly.
See working jsFiddle demo
All notes are left in the comments of the jQuery, but one that I should mention here is that I added a simulateData() function that basically allows you to click the Update button as many times as you want to see how the code will handle different data that's returned.
HTML
<table border="1">
<tr>
<td>first row/measures</td>
<td>measure1</td>
<td>measure2</td>
<td>measure3</td>
<td>measure4</td>
<td>measure5</td>
</tr>
<tr id="results">
<td>First row</td>
<td colspan="4">No record to display!</td>
<td>More+</td>
</tr>
</table>
<button>Update</button>
jQuery
var noRecord = "<td colspan=\"4\">No record to display!</td>",
currentTime = 0;
$( "button" ).click( function ()
{
var $results = $( "#results" ), // Get the TR.
$tds = $( "#results" ).find( "td" ), // Get the TDs within the TR.
data = simulateData(); // Simulate data.
// Check to see if data was returned.
if ( data === undefined )
{
// Data was not returned.
if ( $results.html().indexOf( noRecord ) === -1 )
{
// Results TR has previous values that need to be removed.
for ( i = 1; i < 5; i++ )
$( $tds[i] ).remove();
// Add back the [No record to display!] TD.
$( noRecord ).insertAfter( $tds[0] );
}
}
else
{
// Data was returned.
$.each( data, function ( i )
{
// Store the current data.
var tm = parseInt( data.time );
// Check to see if the Results TR has previous values or not.
if ( $results.html().indexOf( noRecord ) > -1 )
{
// Results TR does not have previous values.
var html = "";
// Generate new TDs.
for ( i = 1; i < 5; i++ )
html += "<td class=\"new\">" + tm + "</td>";
// Remove [No record to display!] TD and replace with new TDs.
$( $tds[1] ).replaceWith( html );
}
else
{
// Results TR has previous values so we need to loop
// through each existing TD replacing its class and value.
for ( i = 1; i < 5; i++ )
{
if ( i != tm )
{
// Change class to "new" and add stored data value.
$( $tds[i] )
.removeClass( "rr" )
.addClass( "new" )
.text( tm );
}
else
{
// Change class to "rr" and add "ee" value.
$( $tds[i] )
.removeClass( "new" )
.addClass( "rr" )
.text( "ee" );
}
}
}
});
}
});
// This simulates the async calls to search.php to generate
// different times on each click of the Update button.
function simulateData()
{
// Increment our simulated time.
currentTime++;
if ( currentTime > 4 )
{
// Start over by resetting our incrementer.
currentTime = 0;
// Simulate a call that doesn't return data.
return undefined;
}
else
{
return { "time": currentTime }
}
}
Since I only wants to change classes of perticular element I used replaceWith
replaceWith() method entirely replaces all matching elements with the new content.
for simply changing the css class you can use
.addClass()
adds the specified class to matched elements
.removeClass()
removes the specified class from matched elements
.toggleClass()
adds the class if it's not applied, removes it if it's already applied

Categories

Resources