Sorting dynamic table in jquery - javascript

Sorry but I'm completly new to js and jquery.
I got dynamic table which values are in localstorage. I can add new row, delete row, and edit cells. This is working.
I want to add a sorting this table by clicked colum. I found here code and try it. It just working when I write table and not use my javascript to add rows from localstorage. Table in two cases looks same in html code. I have no idead why sorting isnt working with dynamic table.
This is w/o my dynamic table from localstore, sorting as supposed to:
http://jsfiddle.net/eW8Kg/1/
This is with table from localstorage(not working in jsfiddle?) on my comupter this is working good, but table is not sorting! (I left this static values):
http://jsfiddle.net/XAu5G/
I think my problem can be in creation of table content:
var Html = "<tbody>";
for (var i = 1; i < localStorage.length; i++) {
var input = "<td><input style='border:hidden' class=\"fields\" name = " + localStorage.key(i) + " type='text' onchange='change(\"" + localStorage.key(i) + "\")' /></td>"
Html += "<tr class=\"field\">";
for (var j = 0; j < 4; ++j) {
Html += input;
}
var button = "<td><input type='button' value = 'UsuĊ„' onclick='Remove(\"" + localStorage.key(i) + "\")'></td>";
Html += button + "</tr>";
}
Html += "<tr id=\"actions\"></tr></tbody>"
document.getElementById("list").innerHTML += Html;
This jquery code do sorting:
$(document).ready(function() {
var table = $('#list');
jQuery.fn.sortElements = (function() {
var sort = [].sort;
return function(comparator, getSortable) {
getSortable = getSortable || function() {return this;};
var placements = this.map(function() {
var sortElement = getSortable.call(this),
parentNode = sortElement.parentNode,
// Since the element itself will change position, we have
// to have some way of storing it's original position in
// the DOM. The easiest way is to have a 'flag' node:
nextSibling = parentNode.insertBefore(
document.createTextNode(''),
sortElement.nextSibling
);
return function() {
if (parentNode === this) {
throw new Error(
"You can't sort elements if any one is a descendant of another."
);
}
// Insert before flag:
parentNode.insertBefore(this, nextSibling);
// Remove flag:
parentNode.removeChild(nextSibling);
};
});
return sort.call(this, comparator).each(function(i) {
placements[i].call(getSortable.call(this));
});
};
})();
$('#x').click(function(){
$('#list').hide();
});
$('#nazwa-header').wrapInner('<span title="sort this column"/>').each(function() {
var th = $(this),
thIndex = th.index(),
inverse = false;
th.on('click', function() {
table.find('td').filter(function() {
return $(this).index() === thIndex;
}).sortElements(function(a, b) {
console.log($(a).find('input').val(),$(b).find('input').val());
return $(a).find('input').val() > $(b).find('input').val() ?
inverse ? -1 : 1
: inverse ? 1 : -1;
}, function() {
// parentNode is the element we want to move
return this.parentNode;
});
inverse = !inverse;
});
});
});

Related

How to get the key names from the JavaScript array?

I am creating a page where I want to print the values like below the code snippet using the map function in JavaScript.
var kvArray = [{a:1, b:2},{a:3, b:4},{a:5, b:6}];
function getValue(item,index) {
var vm="<table/>"
var fullValue =[item.a +" "+ item.b];
var v=vm+fullValue
return v;
}
function myFunction() {
document.getElementById("demo").innerHTML =kvArray.map(getValue).join(" ")
}
I am getting the output like this:
1 2
3 4
5 6
But I want the actual output like this:
a b
1 2
3 4
5 6
Please see the following snippet for a working example:
var kvArray = [{a:1, b:2},{a:3, b:4},{a:5, b:6}]
var asCell = v => `<td>${v}</td>`
var asRow = v => `<tr>${v}</tr>`
$('#demo > thead > tr').html(
Object.keys(kvArray[0]).map(key => asCell(key))
)
$('#demo > tbody').html(
kvArray.map(entry => {
return asRow(Object.keys(entry).map(k => {
return asCell(entry[k])
}).join())
})
)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="demo">
<thead>
<tr></tr>
</thead>
<tbody></tbody>
</table>
I used Object.keys(kvArray[0]) to get the "column names".
var kvArray = [{a:1, b:2},{a:3, b:4},{a:5, b:6}];
function getValue(item,index)
{
var vm="<table/>"
var fullValue =[item.a +" "+ item.b];
var v=vm+fullValue
return v;
}
function createTable(kvArray)
{
var tableOpening="<table>";
var tableClosing="</table>";
var headerOpening= "<th>";
var headerClosing= "</th>";
var rowOpening= "<tr>";
var rowClosing= "</tr>";
var cellOpening= "<td>";
var cellClosing= "</td>";
// get the keys from the first element
var keys = Object.keys(kvArray && kvArray[0]) ;
// create a header
var header = rowOpening;
for (var keyIndex in keys) {
header += headerOpening + keys[keyIndex] + headerClosing + "\n";
}
header += rowClosing;
var table = tableOpening + header;
// create a row for each element
for (var itemIndex in kvArray) {
// open the row element
var rowLine = rowOpening;
for (var keyIndex in keys) {
// fill the cells
rowLine += cellOpening + kvArray[itemIndex][keys[keyIndex]] + cellClosing + "\n";
}
// close the row element
rowLine += rowClosing;
// add the current row to the table
table += rowLine;
}
// close the table
table += tableClosing;
return table;
}
Now just use this function for creating a table like so:
document.getElementById("demo").innerHTML = createTable(kvArray);
I know this is not as short as some of the answers given here, but it is much simpler to understand, as you obviously lack some concepts, namely your code was creating in each row and you were lucky it worked.

.every method not matching all elements to IF statement

I have a function that scans the child elements of a td element in a table for the string "green.png" in the columns declared in the "columns" array. It then passes the result to a function which reorders the table based on the result.
I am using the .every method to ensure that all the child elements in the selected columns contain "green.png" before executing, however it executes when any of the columns contain this value.
My understanding of the .every method is that it will ensures the condition is met for every object in the array before executing, but this is not occurring. Could someone advise what is missing/incorrect with my code?
Here is the code that parses the element:
function checkRowGreen(tenant) {
var columns = ["COLUMN1", "COLUMN2", "COLUMN3", "COLUMN4", "COLUMN5"];
var count = 0;
columns.every(function(column) {
var element = document.getElementById(tenant + column);
if(element != null && element.firstElementChild != null && element.firstElementChild.src.indexOf('green.png') > -1) {
console.log("[INFO] Found successful PNG on " + tenant + " column " + column + " - found " + count);
count++;
}
});
return count > 0;
}
And here is the code that reorders the table:
if(checkRowGreen(tenant)) {
var row = document.getElementById(tenant + "Row");
var table = document.getElementById("tenantTable");
if(row == null || table == null) return true;
var cells = row.getElementsByTagName("td");
table.deleteRow(row.rowIndex);
var newRow = table.insertRow(-1);
newRow.id = rowID;
for(var i = cells.length-1; i >= 0; i--) {
bugout.log("[INFO] inserting cell.." + i + " out of " + cells.length);
var newCell = newRow.insertCell(0);
newCell.innerHTML = cells[i].innerHTML;
newCell.id = cells[i].id;
}
}
Syntax should be something like:
if(myArray.every(myFuncName))
{
...
}
or
var result = myArray.every(myFuncName);
or
var result = mArray.every(element => element.age >= 5);
etc.

How can I show only the row of a table that has the same value that was entered in a textbox with jquery

I have a table of rank where I type the ID of the rank and it shows me only the column line that has this line as my code:
$('button').click(function () {
var data = $("textarea").val();
var rank = $("#rank").val();
if(rank == ""){
alert("digit rank number");
}
else{
data = data.replace(/\s/, " #");
data = data.replace(/([0-9]\s)/g, "$1#");
var lines = data.split("#"),
output = [],
i;
for (i = 0; i < lines.length; i++)
output.push("<tr><td>" + lines[i].slice(0,-1).split(",").join("</td><td>") + "</td></tr>");
output = "<table>" + output.join("") + "</table>";
var valuefinal = $(output).find('tr').filter(function(){
return $(this).children('td').eq(1).text() == rank;
});
$('#fileDisplayArea').html(valuefinal);
}
});
I'm doing this filter in that part of the code
var valuefinal = $(output).find('tr').filter(function(){
return $(this).children('td').eq(1).text() == rank;
});
$('#fileDisplayArea').html(valuefinal);
DEMO CODE
(Forgive me if you did not understand something, my english sucks. I hope it is clear what I need.)
You need to change this -
return $(this).children('td').eq(1).text() == rank;
to this -
return $(this).children('td').eq(0).text() == rank;
.eq() is a zero-based array method.
http://jsfiddle.net/jayblanchard/qM6Fj/19/
http://api.jquery.com/eq/
You need to have a search feature for the contents you have displayed in the table is what i got.....
You can use jQuery DataTable for this purpose which does this job link .. scroll down to see the table show with sort, search etc features

Sorting disrupts the changing of nr

I have a problem with the sorting of a Javascript list. The list that is created when a text area is filled and a grading is chosen. It looks like this:
var element = '<li class="lista">' + filmen + '<span class="betyg">' + changeNumber(grade) + '</span></li>';
film_list.append(element);
I also have a function that converts the number in the span element to stars, it looks like this:
function changeNumber(number) {
var stars = "";
for(var i = 0; i < number; i++) {
stars += "*";
}
return stars;
}
The problem is that there are two buttons to sort the list, high and low depending on the grade, and when I push the buttons the list is sorted correctly. However, the stars disappear and the numbers turn up again. I have tried to call the function changeNumber from the sorting button but it doesn't seem to work. I'm not sure what I should use as the argument. Any suggestions as to what I should do?
The sorting function looks like this:
var button_high = $('#high');
var betyg_array = new Array();
button_high.click(function () {
$list = $("#filmerna ul");
$("#filmerna ul li")
.remove();
betyg_array.sort(function (x, y) {
return y[1] - x[1]
});
$.each(betyg_array, function () {
$nyFilm = $("<li />");
$nyFilm.attr("class", "lista")
$nyFilm.text($(this)[0]);
$nyBetyg = $("<span />");
$nyBetyg.attr("class", "betyg");
$nyBetyg.text($(this)[1]);
$nyBetyg.appendTo($nyFilm);
$nyFilm.appendTo($list);
changeNumber();
});
});
var button_high = $('#high');
var betyg_array = new Array();
button_high.click(function () {
$list = $("#filmerna ul");
$("#filmerna ul li")
.remove();
betyg_array.sort(function (x, y) {
return y[1] - x[1]
});
$.each(betyg_array, function () {
$nyFilm = $("<li />");
$nyFilm.attr("class", "lista")
$nyFilm.text($(this)[0]);
$nyBetyg = $("<span />");
$nyBetyg.attr("class", "betyg");
$nyBetyg.text($(this)[1]);
var stars = $nyBetyg.text(betyg_array); //this line and the line below was the solution
$nyBetyg.text(changeNumber(stars));
$nyBetyg.appendTo($nyFilm);
$nyFilm.appendTo($list);
});
});

Traversing table and returning clicked element's placement

I have an onclick function attached to each <td> element. The function needs to know the placement in the table (row and column).
I found an attribute called rowIndex for <tr>s, but that would involve getting the parent element and still doesn't help with column number.
Here is my function so far (it's within a loop, so it's attaching to every td)
td.onclick = function(event) {
event = (event) ? event : window.event;
console.log('rowIndex, colIndex');
}
I could figure this out with jQuery, but I'm trying to do without.
My first thoughts were:
var rows = document.getElementsByTagName('tr');
var cells = document.getElementsByTagName('td');
var cellsPerRow = cells.length/rows.length;
var i = 0;
for (r=0;r<rows.length;r++){
for (c=0;c<cellsPerRow;c++){
cells[i].setAttribute('data-col',c + 1);
cells[i].setAttribute('data-row',r + 1);
cells[i].onclick = function(){
var row = this.getAttribute('data-row');
var col = this.getAttribute('data-col');
alert('Row: ' + row + '; col: ' + col);
};
i++;
}
}
JS Fiddle demo.
This was then refined to:
var cells = document.getElementsByTagName('td');
for (i=0;i<cells.length;i++){
cells[i].onclick = function(){
var row = this.parentNode.rowIndex + 1;
var col = this.cellIndex + 1;
alert('Row: ' + row + '; col: ' + col);
};
}
JS Fiddle demo.
element.cellIndex
will give you the column zero-indexed position.
Example
Is it possible in your situation to echo out the row and column into the td element's id in the server-side script? Such as ...id="' . $row . '_' . $col . '"...
Then it's just a case of parsing the values out from this.id.
Here you go: - http://jsfiddle.net/FloydPink/Lu8Yw/
var tds = document.getElementsByTagName('td');
for (var i = 0; i < tds.length; i++) {
var td = tds[i];
td.onclick = function(event) {
event = (event) ? event : window.event;
console.log('rowIndex: ' + this.parentNode.rowIndex + ', colIndex: ' + this.cellIndex);
}
}
First, creating click events for each td is not efficient. Recommend using event delegation. You can google it for the benefits of using Event delegation.
http://www.nczonline.net/blog/2009/06/30/event-delegation-in-javascript/
Basically, the more cells you have in the table, the more memory will be consumed. Instead of creating multiple cells, create one single event to delegate.
var table = document.getElementById('test-table');
table.onclick = function(e) {
var target = e.target,
parent;
if (target.tagName === 'TD') {
parent = target.parentNode;
console.log('rowIndex', parent.getAttribute('rowindex'), 'colIndex', target.getAttribute('colindex'));
}
}
Here is the example in jsfiddle http://jsfiddle.net/EWGzB/1/

Categories

Resources