JQuery .appendTo() adding rows multiple times - javascript

Bit of a strange problem, but I'm not sure how to fix it.
While inside of the code below, I'm trying to take all of the element of a table a sort them based on the row heading that was clicked.
The starting HTML:
<table id="PracticeTable" class="col-md-10 col-md-offset-2">
<tr id="Column Names">
<td class="ClientID col-xs-1">Client ID</td>
<td class="ClientName col-xs-1">Client Name</td>
<td class="PracticeID col-xs-1">Practice</td>
</tr>
#for (int i = 0; i < ViewBag.ClientDatabase.getDatabase().Count; i++)
{
#:<tr class="DataRow">
<td class="ClientID col-xs-1" data-name="#ViewBag.ClientDatabase.getByIndex(i).Id">#ViewBag.ClientDatabase.getByIndex(i).Id</td>
<td class="ClientName col-md-2 col-xs-1" data-name="#ViewBag.ClientDatabase.getByIndex(i).getClientName">#ViewBag.ClientDatabase.getByIndex(i).getClientName</td>
<td class="PracticeIDs col-xs-1" data-name="#ViewBag.ClientDatabase.getByIndex(i).getPracticeID">#ViewBag.ClientDatabase.getByIndex(i).getPracticeID</td>
<td class="EditButtons col-xs-1" data-bind="visible: editVisible">Edit</td>
#:</tr>
}
Example of one of the click functions:
jQuery(document).ready(function () {
$(".ClientName").click(function () {
alert("Name Clicked");
var clients = $(".DataRow");
var compareLine = $(clients).children(".ClientName");
compareLine.sort(function (a, b) {
var an = $(a).attr("data-name");
var bn = $(b).attr("data-name");
alert(an + " " + bn);
if (an > bn) {
return 1;
}
if (an < bn) {
return -1;
}
return 0;
});
compareLine.detach().appendTo(clients);
});
});
When I attempt to append the lines as above, the names from Client Name appear in every row. Is there something I'm missing? I tried to loop through the data in compareLine to add them individually, but I couldn't figure it out.
EDIT: Removing duplicated code from a fix attempt that wasn't fully removed.

If you want to sort the rows, I think you just need to make a small change:
jQuery(document).ready(function () {
$(".ClientName").click(function () {
alert("Name Clicked");
var clients = $(".DataRow");
clients.sort(function(a, b) {
var an = $(a).children(".ClientName").attr("data-name");
var bn = $(b).children(".ClientName").attr("data-name");
alert(an + " " + bn);
if (an > bn) {
return 1;
}
if (an < bn) {
return -1;
}
return 0;
});
clients.detach().appendTo("#PracticeTable");
});
});
Seems like your sort function was designed to be working with the rows, but you were sorting a collection of the columns.

Related

Replace style with JS to multiple clases

How can i do this code work with multiple classes?
$("td.field_358").each(function() {
var td = document.getElementsByClassName('field_358');
for (i = 0; i < td.length; i++) {
if (td[i].innerHTML.indexOf('Yes') !== -1) {
td[i].style.backgroundColor = '#f7fef7';
} else if (td[i].innerHTML.indexOf('No') !== -1) {
td[i].style.backgroundColor = '#fbe8ea';
}
}
})
Actually i'm repeating the code for diferents classes, just replacing the class... field_358, field_123...etc.
Its possible to do something more handy like:
$("td.field_358", "td.field_359", "td.field_360").each(function() {
var td = document.getElementsByClassName('field_358', 'field_359', 'field_360');
});
I'm a JS Noob...
You may put all the css-classes you're interested in in an array and iterate over that. For each iteration you execute the code you've already got:
['field_358', 'field_359', 'field_360'].forEach(function (cssClass) {
var td = document.getElementsByClassName(cssClass);
for (i = 0; i < td.length; i++) {
if (td[i].innerHTML.indexOf('Yes') !== -1) {
td[i].style.backgroundColor = '#f7fef7';
} else if (td[i].innerHTML.indexOf('No') !== -1) {
td[i].style.backgroundColor = '#fbe8ea';
}
}
});
A working example may be found at https://jsfiddle.net/9sba06r4/3
Side note: You don't need jQuery for this task, just a more-or-less up-to-date browser.
Sources: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
Here's a reusable function that allows you to pass an array of numbers representing the ids you wish to target, and also allows you to pass in strings representing the colors you wish to use for highlighting.
You simply define your arguments to the function and call it.
const ids = [1, 2, 3, 4];
const yesColor = '#37fef7';
const noColor = '#fbe8ea';
highlightTds(ids, yesColor, noColor);
function highlightTds(ids, yesColor, noColor) {
ids.map(id => {
const tds = document.querySelectorAll(`.field_${id}`);
for (const key of Object.keys(tds)) {
if (tds[key].innerHTML.indexOf('Yes')) {
tds[key].style.backgroundColor = yesColor;
} else if (tds[key].innerHTML.indexOf('No')) {
tds[key].style.backgroundColor = noColor;
}
}
});
}
<table>
<tr>
<td class="field_1">Yes</td>
</tr>
<tr>
<td class="field_2">No</td>
</tr>
<tr>
<td class="field_3">Yes</td>
</tr>
<tr>
<td class="field_4">No</td>
</tr>
<tr>
<td class="field_2">Yes</td>
</tr>
<tr>
<td class="field_1">No</td>
</tr>
</table>

Looping object inside a table cell and create a unordered list

I have this table that has a column in which the cell may or may not contain a value, but when it does, it is in a JSON format; otherwise it will be empty (null).
<table>
<tbody>
<tr>
<td>Barley</td>
<td>AK, AZ</td>
<td class="fpdCell">[{"date":"06/01/2016","error":"Double/Triple cropping","id":2},{"date":"06/07/2016","error":"Lack of Planting Dates Established","id":2}]</td>
<td>null</td>
</tr>
<tr>
<td>Barley</td>
<td>AK, AZ, AR</td>
<td class="fpdCell">[{"date":"06/04/2016","error":"No Error Found","id":3},{"date":"06/27/2016","error":"Lack of Planting Dates Established","id":3},{"date":"06/28/2016","error":"Weather Patterns","id":3}]</td>
<td>null</td>
</tr>
<tr>
<td>Burley Tobacco</td>
<td>null</td>
<td class="fpdCell">null</td>
<td>null</td>
</tr>
<tr>
<td>Fire Cured Tobbacco</td>
<td>null</td>
<td class="fpdCell">null</td>
<td>null</td>
</tr>
<tr>
<td>Flue Cured Tobacco</td>
<td>null</td>
<td class="fpdCell">null</td>
<td>null</td>
</tr>
<tr>
<td>Oats</td>
<td>null</td>
<td class="fpdCell">null</td>
<td>null</td>
</tr>
What I need to do is to loop through each of the cells with the fpdCell class, loop the object inside of each of those cell, create a list and add them as list element.
This is as far as I was able to get. I really don't know how to move forward from here.
var theCells = $('.fpdCell');
$.each(theCells, function(index, value) {
var cellValues = $.parseJSON(value.textContent);
if (cellValues != 'null') {
console.log(cellValues);
value.textContent = '';
$(value).append('<ul class="list-group ul'+index+'"></ul>')
//then add <li class="list-group-item">Test</li>
//Not working------------------
/*
for (var u = 0; u < cellValues. length; u++) {
$('ul' + index).append('<li class="list-group-item">'+cellValues[u].date+'</li>');
console.log(cellValues[u].date);
}
*/
}
});
Thanks in advance.
To achieve this you just need two loops, one to go through the .fpdCell elements, the other to go through the parsed JSON and build the HTML of the ul. Try this:
$('.fpdCell').each(function() {
var $el = $(this), html = '';
$.each(JSON.parse($el.text()), function(i, obj) {
html += '<li class="list-group-item">' + obj.date + '</li>';
})
$el.append('<ul>' + html + '</ul>');
});
Working example
var theCells = $('.fpdCell');
$.each(theCells, function() {
var cellValues = $.parseJSON($(this).text());
if (cellValues != 'null') {
console.log(cellValues);
$(this).html("");
var list = '<ul class="list-group ul'+index+'">';
for (var u = 0; u < cellValues.length; u++) {
list+='<li class="list-group-item">'+cellValues[u].date+'</li>';
console.log(cellValues[u].date);
}
if(cellValues.length>0)
list+="</ul>";
$(this).append(list);
}
The objects in the fpdcell columns are array objects which you may have missed in your logic.
One more thing, may be a typo, but, you missed the . in the commented code to append list items to the ul :)
Here is a solution which loops through the array and then loops through the individual elements in each array element to create a linear list.
var theCells = $('.fpdCell');
$.each(theCells, function(index, value) {
var cellValues = JSON.parse(value.textContent);
if (cellValues != 'null') {
$(value).html('<ul class="list-group ul'+index+'"></ul>');
$.each(cellValues, function(cellValueIndex, cellValue){
for (var prop in cellValue) {
$('.ul'+index).append('<li class="list-group-item">'+ cellValue[prop] +'</li>');
}
});
} else {
$(value).html('');
}
});
This may not be the exact solution to what you are looking for but, should help you along the line you would want to go. Happy coding.
Here is a fiddle with the solution JSFiddle

sort parent element based on contents of child element - javascript/jquery

I have a monthly calendar which displays days with events happening in this day. This is how generated HTML looks like:
<table class="event-cal">
<tbody>
<tr class="eventcont event-93">
<td class="eventtime">19:00</td>
<td><a class="calendar-title" href="#>Event title</a><br></td></tr>
<tr class="eventcont event-237">
<td class="eventtime">13:00</td>
<td><a class="calendar-title" href="#">Event 2 title</a><br></td></tr>
</tbody>
</table>
What I want to do is to order tr.eventcont elements based on contents of .eventtime child element. Ordering has to be done within .event-cal element which contains these particular .eventcont elements because I will have several .event-cal elements in the page.
Here is the code I have so far but what it does it takes all tr.eventcont elements from page and pastes them all into each .event-cal table.
$( document ).ready(function() {
var list = $(".event-cal").find(".eventcont");
list.sort(sortDesc);
$(".event-cal").html("");
$(".event-cal").append(list);
});
function sortDesc(a, b){
var test1 = jQuery(a);
var test2 = jQuery(b);
return test1.find(".eventtime").text() > test2.find(".eventtime").text();
}
You need to run your function for each table using jquery.fn.each
$('.event-cal').each(function() {
var table = $(this),
list = table.find('.eventcont').sort(sortDesc);
table.empty().append(list);
});
Check this fiddle
$(".event-cal").each(function(){
var events=$('tr',this);
events.sort(function (a, b) {
a = parseInt($('.eventtime',a).text().replace(':',''));
b = parseInt($('.eventtime',b).text().replace(':',''));
if(a > b) {
return 1;
} else if(a < b) {
return -1;
} else {
return 0;
}
});
$(this).html(events);
});

JQuery sort items by last name

I want to have sorting on the last name and text to be replaced but I am not able to do it. I have tried following.
HTML
<div id="sort-by-name">
<table>
<tbody>
<tr>
<tr>
<td class="names">
<span class="toggle"></span> Betty j. Sean
</td>
</tr>
<tr>
<td class="names">
<span class="toggle"></span> Ali Khan
</td>
</tr>
<tr>
<td class="names">
<span class="toggle"></span> Will Turner
</td>
</tr>
</tbody>
</table>
</div>
// Sort names
var items = [];
$('#ByMember table tbody .irwMemberName').each(function () {
items.push($(this).html());
});
items.sort();
console.log(items);
I have also try adding a class to last name word. Then applied above sort function it actually sorts all last names but how I can sort whole by that and replace.
$("#sort-by-name table tbody .names").html(function(index, old) {
return old.replace(/(\b\w+)$/, '<span class="name_identifier">$1</span>');
});
Please let me know if I am not clear. Also Ignore any typo's I have modified code here for post.
You can do it like this. Check fiddle: Fiddle
var els = $("#sort-by-name table tbody tr")
.sort(function(a,b){
var t1 = $(a).find('.names')[0].innerText.split(' ').pop(),
t2 = $(b).find('.names')[0].innerText.split(' ').pop();
if(t2 < t1) {
return 1;
} else {
return -1;
}
})
.each(function() {
var t = this.innerText.replace(/(\w+)$/, '<span class="name_identifier">$1</span>');
return $(this).html( t );
});
$('#bodyid').html(els);
To add to Nikolay's answer, I've built a version that works both on Firefox and Chrome.
var els = $("#sort-by-name table tbody tr")
.sort(function(a, b) {
var t1 = $(a).find('.names')[0].textContent.split(' ').pop(),
t2 = $(b).find('.names')[0].textContent.split(' ').pop();
if (t2 < t1) {
return 1;
} else {
return -1;
}
})
.each(function() {
debugger;
var t = this.textContent.trim().replace(/(\w+)$/, '<span class="name_identifier">$1</span>')
return $(this).html(t);
});
$('#bodyid').html(els);
JSFiddle

SPA - search html table

I'm building a single page application in which i have a html table and i need to implement a search box that loops through the rows of the table and hides the ones that don't match the search-box text. The problem is that being a SPA all the javascript code i found on the internet that does this thing is based on $(document).ready(function() so it doesn't work. I tried the folowing approach:
In my viewmodel.js i have:
function filter2(search, tblData) {
window.phrase = document.getElementById(search).value;
var words = window.phrase.toLowerCase().split(" ");
var table = document.getElementById(tblData);
var ele;
for (var r = 1; r < table.rows.length; r++) {
ele = table.rows[r].innerHTML.replace(/<^>+>/g, "");
var displayStyle = 'none';
for (var i = 0; i < words.length; i++) {
if (ele.toLowerCase().indexOf(words[i]) >= 0)
displayStyle = '';
else {
displayStyle = 'none';
break;
}
}
table.rows[r].style.display = displayStyle;
}
}
and in my view.html:
<input type="text" id="search" placeholder="Search..." data-bind="click: filter2"/>
,where tblData is my html table and search is my searchbox.
This is not working, if anyone has any idea please share. Thank you in advance.
EDIT: This is the html for my table:
<table id="tblData"class="table table-striped" >
<thead>
<tr><th>Domain Name</th><th>Full name</th><th style="text-align:center">Email</th></tr>
</thead>
<tbody data-bind="foreach: employee">
<tr>
<td style="width:100px" data-bind="text: username"></td>
<td style="width:120px"data-bind="text: fullName"></td>
<td style="text-align:right;width:120px" data-bind="text: email"></td>
</tr>
</tbody>
</table>
Don't do vanilla javascript DOM manipulations if you use knockout. Filtering is quite simple, you just have to keep an observableArray of all your elements, and declare a computed that returns the filtered elements.
For a simple example, see this model:
function Model() {
var self = this
this.input = ko.observable("");
this.all = ko.observableArray(["John","James","Mark"]);
this.filtered = ko.computed(function() {
return ko.utils.arrayFilter(self.all(), function(item) {
return item.indexOf(self.input()) !== -1;
});
});
}
with this HTML:
<input placeholder="Type to filter" data-bind="value: input, valueUpdate: 'keyup'"/>
<ul data-bind="foreach: filtered">
<li data-bind="text: $data"></li>
</ul>
You can test it here: http://jsfiddle.net/qFYbW/1/

Categories

Resources