TableSorter sorting empty input in Td - javascript

I'm testing tablesorter and my table is :
Table
It contains list of products and one product has 2 rows, one row contains its name and the other is the input field for the user to make changes.
I would like to do a tablesorter to sort the products with the empty input fields to the top of the table.
Table Expected Result
It means the products which don't have text in the input fields will be displayed on top.
I'm using tablesorter jquery.
my HTML Table: Tr1 holds first 'data' line, TR2 holds the input fields;
<table class="tablesorter">
<thead>
<tr>
<th class="sorter-inputs empty-top code">Code</th>
<th class="sorter-inputs empty-top designation">Designation</th>
</tr>
</thead>
<tbody>
<tr class='tr1'>
<td>
<div class='code'> </div>
</td>
<td>
<div class='designation'>abc 111</div>
</td>
</tr>
<tr class='tr2'>
<td>
<input type="text" class='CodeInput'/>
</td>
<td>
<input type="text" class='designationInput'/>
</td>
</tr>
...
</tbody> </table>

If you are using my fork of tablesorter, you have two options.
1) Leave out the input rows and use the editable widget, which actually makes the table cell editable using contenteditable. This does require a modern browser.
2) Use the input parser & set the emptyTo option to keep empty rows at the top (demo)
NOTE: the parser-input-select.js file used in the demo is actually pointing to the master branch of the repository.
HTML
<table class="tablesorter">
<thead>
<tr>
<th class="sorter-inputs empty-top code">Code</th>
<th class="sorter-inputs empty-top designation">Designation</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div> </div>
<input type="text" />
</td>
<td>
<div>abc 111</div>
<input type="text" />
</td>
</tr>
...
</tbody>
</table>
* Note *: I don't think using child rows will work in this case because the sort would occur based on the parent row content. So I added a <div> to each cell with the labels.
CSS
html { box-sizing: border-box; }
*, *:before, *:after { box-sizing: inherit; }
.code { width: 20%; }
.designation { width: 80%; }
input { width: 90%; margin: 4px; background: #fc7565; border: solid 1px #999; }
table { border-collapse: collapsed; border-spacing: 0; }
.tablesorter-blue tbody td { padding: 0; vertical-align: bottom; }
td div { background: #ccc; padding: 4px; }
Script
$(function () {
$('table').tablesorter({
theme: 'blue'
});
});

Related

How to make a partially un-editable table cell?

This might be kind of a weird question, but is it possible to build table cells that are partially editable, but also partially un-editable? By this I mean, I want to use JavaScript to make a majority of the cell editable by setting .contentEditable = true in JavaScript (already done). However, I also want a portion (preferably on the right side) to be text that cannot be written over or edited.
What I'm trying to do here is make most of the table cell editable to put in raw data, i.e. numbers. But to leave an stagnate section with a unit, so that the unit doesn't actually get taken as input (it's more just like decoration).
I've drawn a mock-up of what I'm imagining, if this helps:
So far, I've tried adding a <input> element after the initial input following <td>, then style the input to set point-events: none. But this does not look good and ends up creating an input form inside of a content editable cell, which isn't really what I want, and ends up looking like this:
I think it would have to use some CSS overlay and not actually be apart of the table HTML. Either way, how would I go about this?
You could just use two span elements, make one of them contenteditable. Example:
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid black;
}
.input {
display: flex;
justify-content: space-between
}
span {
padding: 0.5em;
}
.value {
flex-grow: 1;
}
<table>
<thead>
<tr>
<th>Heading 1</th>
<th>Heading 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Entry 1</td>
<td class="input"><span class="value" contenteditable="">10</span><span class="unit">kg</span></td>
</tr>
<tr>
<td>Entry 1</td>
<td class="input"><span class="value" contenteditable="">20</span><span class="unit">kg</span></td>
</tr>
</tbody>
</table>
Alternatively, you could use the after pseudo-selector to add the unit. Example:
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid black;
}
.value::after {
content: " kg";
}
<table>
<thead>
<tr>
<th>Heading 1</th>
<th>Heading 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Entry 1</td>
<td class="input"><span class="value" contenteditable="">10</span></td>
</tr>
<tr>
<td>Entry 1</td>
<td class="input"><span class="value" contenteditable="">20</span></td>
</tr>
</tbody>
</table>

How to show 'no results try again' on a jquery toggle search filter

I am customizing this basic jQuery Data Table with Search Filter tutorial for my own use and it works great except I can't figure out how to toggle to show a specific message when the filter returns no results: https://www.coderbench.com/develop-jquery-data-table-search-filter/
Here is the script:
$(document).ready(function(){
$("#txtsearch").keyup(function(){
var value = $(this).val().toLowerCase();
$("#table tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
This works for what I need except I want to display the following text above my table when there are no row matches and all rows are toggled hidden:
<span class="warning">Your search returned no results, please modify your entry.</span>
I imagine there's some elaborate conditional statement I could make here but I'm wondering if there's a simple way to do this....as is often the case. Thanks! Here is the full sample page:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
<script>
$(document).ready(function(){
$("#txtsearch").keyup(function(){
var value = $(this).val().toLowerCase();
$("#table tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
</script>
<style>
table {
font-family: arial;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #e3e3e3;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #efefef;
}
</style>
<div>
<input id="txtsearch" type="text" placeholder="Search Here..." />
<br><br>
<table>
<thead>
<tr>
<th>Movies</th>
<th>Rating</th>
</tr>
</thead>
<tbody id="table">
<tr>
<td>Spiderman Homecoming</td>
<td>9/10</td>
</tr>
<tr>
<td>Wonder Woman</td>
<td>8/10</td>
</tr>
<tr>
<td>The Guardians of Galaxy 2</td>
<td>8/10</td>
</tr>
<tr>
<td>Ant Man</td>
<td>7.5/10</td>
</tr>
</tbody>
</table>
</div>
Here's my try.
I don't use jQuery much so feel free to adapt things to a more "jQuery"-way.
const warning = document.querySelector('.warning');
const table = document.querySelector('table');
$(document).ready(function() {
$("#txtsearch").keyup(function() {
let value = $(this).val().toLowerCase();
let numberOfResults = 0;
$("#table tr").filter((index, tableRow) => {
let isAMatch = $(tableRow).text().toLowerCase().indexOf(value) > -1;
$(tableRow).toggle(isAMatch);
if (isAMatch) {
numberOfResults++;
}
});
if (numberOfResults === 0) {
warning.classList.add('show')
table.classList.add('no-results');
} else {
warning.classList.remove('show');
table.classList.remove('no-results');
}
});
});
table {
font-family: arial;
border-collapse: collapse;
width: 100%;
}
table.no-results {
display: none;
}
td,
th {
border: 1px solid #e3e3e3;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #efefef;
}
.warning {
margin-bottom: 10px;
display: none;
}
.warning.show {
display: block;
}
<div>
<span class="warning">Your search returned no results, please modify your entry.</span>
<input id="txtsearch" type="text" placeholder="Search Here..." />
<br><br>
<table>
<thead>
<tr>
<th>Movies</th>
<th>Rating</th>
</tr>
</thead>
<tbody id="table">
<tr>
<td>Spiderman Homecoming</td>
<td>9/10</td>
</tr>
<tr>
<td>Wonder Woman</td>
<td>8/10</td>
</tr>
<tr>
<td>The Guardians of Galaxy 2</td>
<td>8/10</td>
</tr>
<tr>
<td>Ant Man</td>
<td>7.5/10</td>
</tr>
</tbody>
</table>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>

adding dynamically the data into the columns of the table in JavaScript

function add_fields() {
document.getElementById('myTable').innerHTML += '<tr> <td> <textarea name = "Product ID" placeholder = "Product ID" style = "resize: none; width: 100%;" document.getElementById("1")></textarea></td> <td> <textarea name = "Title" placeholder = "Title" style = "resize: none; width: 100%;"></textarea></td><td> <textarea name = "startdate" placeholder = "startdate" style = "resize: none; width: 100%;"></textarea></td> </tr>';
}
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
<div class="set-form">
<input type="button" id="more_fields" onclick="add_fields();" value="Add More" class="btn btn-info" />
</div>
<table id="myTable">
product id : <input type="text" name="fname" id="1"><br>
<thead>
<tr>
<th>Product ID</th>
<th>Title</th>
<th>Start Date</th>
<th>End Date</th>
<th>Excl</th>
<th>Territory</th>
<th>Media</th>
<th>Language</th>
<th>Format</th>
<th>Acquiring Division</th>
<th>Owner</th>
</tr>
</thead>
</table>
I want to add dynamically to the table by selecting the id whenever the user enters the data the data should add automatically to the table.
Is there any better way I want to add a column to the table and data to be added at once but I could not figure out so I planned the above code.
Any suggestions?
Playing a little with your code, I made the following modifications…
HTML stays in HTML, I've added a tr with id="row-type". It's hidden but the content is used to add a new tr when you click Add More. I've modified your existing function accordingly.
CSS stays in CSS, I've moved the table textarea style in the CSS.
As it's not recommended to use .innerHTML +=, I replaced it with .appendChild(…).
I've added a button in the row-type element. So that, when you click Submit, the content of the row is converted from textareas to texts.
As we're only adding in the 3 first tds, I've removed some of the other tds in the HTML to shorten the snippet. But it works exactly the same with all of it (I tried).
I've added a cancel function, in case you finally don't want to add.
…and ended-up with this working snippet:
(See comments in the code for more details)
// TAKIT: Now the content is in the HTML, append it to the current table
function add_fields() {
// TAKIT: Replaced .innerHTML as it's not recommended
var newElement = document.createElement('tr');
newElement.innerHTML = document.getElementById('row-type').innerHTML;
document.getElementById('myTable').appendChild(newElement);
}
// TAKIT: Added this function for when you click on the submit button
function put_in_table(elm) {
var tds = elm.closest('tr').children; // Get all tds of the line you just clicked "submit"
for (var i = 0; i < tds.length; i++) { // For all tds
// replace the HTML with the text value of the textarea (that removes the textareas)
if (tds[i].innerHTML)
tds[i].innerText = tds[i].children[0].value || '';
}
}
// TAKIT: Added this function to cancel the add
function cancel_add(elm) {
elm.closest('tr').outerHTML = ''; // Empty current tr
}
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
/* TAKIT: Added hidden on row type, and moved style of textareas here */
#row-type {
display: none;
}
table textarea {
resize: none;
width: 100%;
}
<div class="set-form"><input type="button" id="more_fields" onclick="add_fields();" value="Add More" class="btn btn-info" /></div>
<table id="myTable">
<!-- TAKIT: Added p element here, it's proper. What is it used for, by the way? -->
<p>product id : <input type="text" name="fname" id="1"></p>
<thead>
<tr>
<th>Product ID</th>
<th>Title</th>
<th>Start Date</th>
<th>End Date</th>
<th>Excl</th>
</tr>
</thead>
<tbody>
<!-- TAKIT: Added body and the "row-type" in it, so that HTML stays in HTML -->
<tr id="row-type">
<td><textarea name="Product ID" placeholder="Product ID"></textarea></td>
<td><textarea name="Title" placeholder="Title"></textarea></td>
<td><input name="startdate" type="date"></td>
<td><input name="enddat" type="date"></td>
<td>
<button onclick="put_in_table(this);">Submit</button> <button onclick="cancel_add(this);">Cancel</button>
</td>
</tr>
</tbody>
</table>
Hope it helps.
I find it easiest to just have a div/span which I write a table in dynamically with javascript, e.g.
example_array = [["Name","Age"],["Antonio","35"]];
function array_to_table(my_array){
my_table_html = '<table>';
for(var i = 0; i<my_array.length; i++){
my_table_html += "<tr>";
for(var j = 0; j < my_array[i].length; j++){
my_table_html += "<td>"+my_array[i][j]+"</td>";
}
my_table_html += "</tr>";
}
my_table_html += '</table>';
document.getElementById("mytable").innerHTML = my_table_html;
}
array_to_table(example_array);
<div id="mytable"></div>
When you have this framework for creating/updating tables, you can edit the array that's fed into the function to dynamically update your table.
Here is a working example, enter the desired values in the first row (I have only the first three elements here). Then click Add, the row will be added to the table.
function add_fields() {
// select the input values
let productId = document.querySelector('#productId').value
let title = document.querySelector('#title').value
let startDate = document.querySelector('#startDate').value
// prepare a new row
let tr = document.createElement('tr')
tr.innerHTML = `
<tr>
<td>
<div id="productId" style="resize: none; width: 100%;">${productId}</div>
</td>
<td>
<div id="title" style="resize: none; width: 100%;">${title}</div>
</td>
<td>
<div id="startDate" style="resize: none; width: 100%;">${startDate}</div>
</td>
</tr>
`
// remove content of textareas
document.querySelector('#productId').value = ''
document.querySelector('#title').value = ''
document.querySelector('#startDate').value = ''
// append a new row to the table
document.querySelector('#myTable').appendChild(tr)
}
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
<div class="set-form">
<input type="button" id="more_fields" onclick="add_fields();" value="Add" class="btn btn-info" />
</div>
</head>
<body>
<table id="myTable">
<thead>
<tr>
<th>Product ID</th>
<th>Title</th>
<th>Start Date</th>
<th>End Date</th>
<th>Excl</th>
<th>Territory</th>
<th>Media</th>
<th>Language</th>
<th>Format</th>
<th>Acquiring Division</th>
<th>Owner</th>
</tr>
<tr>
<td>
<textarea id="productId" placeholder="Product ID" style="resize: none; width: 100%;"></textarea>
</td>
<td>
<textarea id="title" placeholder="Title" style="resize: none; width: 100%;"></textarea></td>
<td>
<textarea id="startDate" placeholder="startdate" style="resize: none; width: 100%;"></textarea> </td>
</tr>
</thead>
</table>
Here are a couple things you might want to know:
I'm using the method querySelector() from document to select an element from the DOM by its class or id. Don't forget to add the # to . before the actual name.
Access the value of an element of type textarea with its property value.
No use of innerHTML += as it will force the browser to re-render all the content of #myTable even if you're just adding a row. Best way is to prepare an element as I do and append it to the table with appendChild().
To easily write HTML inside JavaScript code, you can use backticks `` and insert JS variables directly in the markup with the ${} syntax.

How to stop a cell's content from being used to calculate column width

I have a table with a dynamic width, and with each column being a dynamic portion of that width, depending on cell contents.
In the headers of that table, I have an input set to 100% width, which is initially hidden. When triggered, the input appears. Unfortunately, if the column's cell's contents are quite narrow, the column widths are then recalculated and the width jumps.
How do I set the input to just fill up the cell's width & not push it wider?
I don't believe there is a solution, but I thought I'd ask the larger community before giving up. My guess is I can't without hard-coding widths, but that's out of the question.
Edit: My solution has been to let the browser do the cell width calculations, then using Javascript, explicitly set the column widths to whatever was calculated. This allows the cell contents to determine the width, but I still get set-width behaviour.
function toggleInput(){
var target = document.querySelector('.hidden')
var newStyle = (target.style.display == 'block') ? 'none' : 'block';
document.querySelector('.hidden').style.display = newStyle;
}
document.querySelector('th').addEventListener('click',toggleInput);
table,td,th{
border:1px solid red;
}
*{
box-sizing:border-box;
}
table,
input{
width:100%;
}
.hidden{
display:none;
}
<table>
<thead>
<tr>
<th>
Click me
<div class="hidden">
<input />
</div>
</th>
<th>
</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Blah
</td>
<td>
Some longer text to stretch
</td>
<td>
More text
</td>
</tbody>
</table>
By using the following CSS:
table { table-layout:fixed }
Your code with the fix:
function toggleInput(){
var target = document.querySelector('.hidden')
var newStyle = (target.style.display == 'block') ? 'none' : 'block';
document.querySelector('.hidden').style.display = newStyle;
}
document.querySelector('th').addEventListener('click',toggleInput);
table,td,th{
border:1px solid red;
}
*{
box-sizing:border-box;
}
table,
input{
width:100%;
}
table { table-layout:fixed; }
.hidden{
display:none;
}
<table>
<thead>
<tr>
<th>
Click me
<div class="hidden">
<input />
</div>
</th>
<th>
</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Blah
</td>
<td>
Some longer text to stretch
</td>
<td>
More text
</td>
</tbody>
</table>

Get value in cell of HTML table with Razor

I have a table that looks like such:
<div style="float: left;">
<table id="table_id">
<thead style="background: #DAE6F0;">
<th width="96">Action</th>
<th width="110.5">Location</th>
<th width="107">SelectionType</th>
</thead>
<tbody>
#foreach (var item in Model.List)
{
<tr>
<td style="width: 49px; cursor: pointer"><a class="display" onclick=" getTeplate(#item.Id); ">Display</a></td>
<td style="width: 49px; cursor: pointer"><a class="delete" onclick=" deleteTemplate(#item.Id); ">Delete</a></td>
<td style="width: 120px; text-align: center">#Html.DisplayFor(modelItem => item.AdvertisementLocation)</td>
<td style="width: 107px; text-align: center">#Html.DisplayFor(modelItem => item.AdvertisementSelectionType)</td>
</tr>
}
</tbody>
</table>
The first column displays the word "Display" which is a link that when clicked fires a function to get the contents of a template and display it. It does this by sending the Id to the function that is associated with that row. On load I populate a list with all the ads, and then foreach ad in the list a row is added to the table.
My question is how could I access the Id that is associated with the the Display column for that row with javascript. the work flow is a user can select an ad and edit it, upon update I refresh the page for the changes to be displayed in the table, and the table loads with row 1 in focus. I would would like to be able to focus the table on the row that had just been updated.

Categories

Resources