I'm having a bit of an issue with some JS/JQuery. I am using some script to create an array from the data within the <TH> tags, then doing some formatting of that data to create new content and styles for a responsive table.
<script>
$( document ).ready(function() {
// Setup an array to collect the data from TH elements
var tableArray = [];
$("table th").each(function(index){
var $this = $(this);
tableArray[index] = $this.text();
});
console.log(tableArray);
alert(tableArray);
// Create class name based on th values and store as variable
var tableString = tableArray.join();
tableString = tableString.replace(/,/g, '_')
tableString = tableString.replace(/ /g, '-')
var tableClass = ".responsive-table."+tableString;
console.log(tableClass);
// Push tableClass variable into the table HTML element
var applyTableClass = tableClass;
applyTableClass = applyTableClass.replace(/\./gi, " ") //converts the style declaration into something i can insert into table tag (minus the dots!)
console.log(applyTableClass);
$( "table" ).addClass( applyTableClass );
// Create a loop which will print out all the necessary css declarations (into a string variable) based on the amount of TH elements
var i = 0;
var styleTag = "";
while (tableArray[i]) {
styleTag += tableClass+" td:nth-of-type("+[i+1]+"):before { content: '"+tableArray[i]+"'; }";
i++;
}
// Push the styleTag variable into the HTML style tag
$('style#jquery-inserted-css').html(styleTag);
// Below is just a test script to check that values are being collected and printed properly (use for testing)
//$('#css_scope').html('<p>'+styleTag+'</p>');
});
</script>
This works great when there is a single table within the page, but not if there is additional tables. The reason is that the loop that creates the array keeps going and does not know to stop and return at the end of one table, then create a new array for the next table. I am imagining that I need to set up a loop that creates the arrays as well.
This is where I am quit stuck with my limited scripting skills. Can anyone please suggest a way to get my code to loop through multiple tables, to create multiple arrays which then create separate style declarations?
You can loop through each table instead of querying all tables at once:
$( document ).ready(function() {
$("table").each(function () {
var tableArray = [];
$(this).find("th").each(function (index) {
var $this = $(this);
tableArray[index] = $this.text();
});
console.log(tableArray);
alert(tableArray);
// Create class name based on th values and store as variable
var tableString = tableArray.join();
tableString = tableString.replace(/,/g, '_')
tableString = tableString.replace(/ /g, '-')
var tableClass = ".responsive-table." + tableString;
console.log(tableClass);
// Push tableClass variable into the table HTML element
var applyTableClass = tableClass;
applyTableClass = applyTableClass.replace(/\./gi, " ") //converts the style declaration into something i can insert into table tag (minus the dots!)
console.log(applyTableClass);
$(this).addClass(applyTableClass);
// Create a loop which will print out all the necessary css declarations (into a string variable) based on the amount of TH elements
var i = 0;
var styleTag = "";
while (tableArray[i]) {
styleTag += tableClass + " td:nth-of-type(" + [i + 1] + "):before { content: '" + tableArray[i] + "'; }";
i++;
}
// Push the styleTag variable into the HTML style tag
$('style#jquery-inserted-css').append(styleTag);
// Below is just a test script to check that values are being collected and printed properly (use for testing)
//$('#css_scope').html('<p>'+styleTag+'</p>');
});
});
Note that I change $("table th") to $(this).find("th"), $("table") to $(this) and $('style#jquery-inserted-css').html(styleTag); to $('style#jquery-inserted-css').append(styleTag);.
Hope this help.
Related
I have created a dynamic table in html click here to view image the rows are created dynamically in javascript please refer the image click here to view image the data for table is fetched from firebase.
The problem I am facing is that the rows are getting added at the end of the table repeatedly resulting in duplicate rows please refer the image click here to view image how do I remove old rows and add new updated rows using javascript.
I have updated the snapshot.forEach loop with comments.
snapshot.forEach(function (data) {
var val = data.val();
var trow = document.createElement('tr');
var tdata = document.createElement('td');
var tdata1 = document.createElement('td');
tdata.innerHTML = val.Name;
tdata1.innerHTML = val.Votes;
trow.appendChild(tdata);
trow.appendChild(tdata1);
// set the Name as data-id attribute
// which can be used to query the existing row
tdata.setAttribute('data-id', val.Name);
// append the trow to tbdy
// only if there's no row with data-id value of val.Name
// otherwise update the vote column of the existing row
var existingRow = tbdy.querySelector('[data-id="' + val.Name + '"]');
if (!existingRow) {
tbdy.appendChild(trow);
} else {
existingRow.querySelectorAll("td")[1].innerHTML = val.Votes;
}
});
I am using HTML and Java script and below mention solution is working fine for many of the columns that i am using.
dynamically filter rows of a HTML table using JavaScript
var filters=['hide_broj_pu','hide_naziv_pu','hide_ID','hide_naselje','hide_zupanija'];
function ExcludeRows(cls){
var skipRows=[];
for(i=0;i<filters.length;i++)
if(filters[i]!=cls) skipRows.push(filters[i]);
var pattern=skipRows.join('|')
return pattern;
}
function Filter(srcField){
var node=srcField.parentNode;
var index=srcField.parentNode.cellIndex;
//all the DATA rows
var dataRows= document.getElementsByClassName("row");
//ensure that dataRows do not have any filter class added already
var kids= dataRows.length;
var filter ='hide_'+srcField.id;
var pattern = ExcludeRows(filter);
var skipRow = new RegExp(pattern,"gi");
var searchReg =new RegExp('^'+srcField.value,'gi');
var replaceCls= new RegExp(filter,'gi');
for(i=0; i< kids ; i++){
//skip if already filter applied
if(dataRows[i].className.match(skipRow)) continue;
//now we know which column to search
//remove current filter
dataRows[i].className=dataRows[i].className.replace(replaceCls,'');
if(!dataRows[i].cells[index].innerHTML.trim().match(searchReg))
dataRows[i].className=dataRows[i].className +' '+ filter;
}
}
It filters well for like this,
<td class="R0C1"><s:property value="owner" /></td>
However, Above solution won't work if my columns have values that are Href links as shown below. For example:
<td class="R0C1"><s:property value="prs"/>
</td>
What what changes i need to do with Java Script filter function that can also work equally well for link elements.
That code filters by the start of an entry.
To work for href, remove the '^'+.
To match only in href (to avoid false positives, e.g. href, target, blank) do this:
// var searchReg = new RegExp(srcField.value, 'gi');
var aTag = dataRows[i].cells[index].getElementsByTagName('a')[0];
var href = aTag ? aTag.getAttribute("href") : '';
if (!href.match(searchReg))
dataRows[i].className = dataRows[i].className + ' ' + filter;
My ToDo List dont wanna work the way i want. I've just been working with JavaScript for 2 weeks sthis is very new to me, therefor the code maybe doesnt look that nice.
The result comes out wrong. If I type in "buy food" the first line gonna show just that, but the next time I wanna add "walk the dog", then it displays
buy food
buy food
walk the dog
I hope you understand my problem. It also ends the unordered list tag after the first click and adds the rest of the things in another.
Here's the JavaScript:
var taskList = [];
var text = "<ul>"
function addToList() {
var task = document.getElementById("toDoTask").value;
taskList.push(task);
for(i = 0; i < taskList.length; i++){
text += "<li>" + taskList[i] + "</li>" ;
}
text += "</ul>";
document.getElementById("todoList").innerHTML = text;
}
The issue is you're closing the ul tag after adding each item. Instead of concatenating raw HTML, consider using element objects and appending, and using a text node object to handle the user input - this removes the possibility of a DOM Based XSS vulnerability.
window.onload = function() {
var taskList = [];
var container = document.getElementById("todoList");
document.getElementById("add").onclick = addToList;
function addToList() {
var task = document.getElementById("toDoTask").value;
taskList.push(task);
var ul = document.createElement('ul');
var li;
for (i = 0; i < taskList.length; i++) {
li = document.createElement('li');
li.appendChild(document.createTextNode(taskList[i]))
ul.appendChild(li);
}
container.innerHTML = '';
container.appendChild(ul);
}
};
Task:
<input id="toDoTask" /> <input type="button" id="add" value="Add" />
<div id="todoList">
</div>
You should not use the innerHtml. This replace all the text of your content. You should just add the li to your ul.
You can do that by using the append function by jquery Append
your <ul> must contain an id like this <ul id="toDoList">
then you make $("#toDoList").append("yourTask");
yourTask must contains the li.
With this, you don't need to iterate on all your element list
Not sure, but you seem to keep adding to text the second time, so text will be something like <ul><li>buy food</li></ul><li>buy food</li><li>walk the dog</li></ul>, which is invalid HTML by the way, but gets outputted anyway...
On each call of function addToList() you should reset the variable text.
For example:
function addToList() {
var task = document.getElementById("toDoTask").value;
taskList.push(task);
text="";
for(i = 0; i < taskList.length; i++){
text += "<li>" + taskList[i] + "</li>" ;
}
text += "</ul>";
document.getElementById("todoList").innerHTML = text;
}
The whole list of items in array will appends to variable text on each call.
I'm trying to dynamically create divtags for each cell of my table so that I can later fill them in with other stuff. However, when I tried doing this:
newhtml+="<div id ='" + (j) +"'><td class = 'unselected'> ? </td></div>"
and later using it it acted as if it never created it.
So after browsing stackoverflow I found out that you should use this line of code to dynamically create a div tag:
var divtag = document.createElement('div');
But my question is how do I implement it into my js code?
Here is the section of code that is supposed to create divtags for later referencing:
newhtml+="<tr>";
for (var j = 0; j < $tblcols; j++){
newhtml+="<div id ='" + (j) +"'><td class = 'unselected'> ? </td></div>";
And here is the section that uses it:
divtag = document.getElementById("'" + (++$counter2) + "'");
newhtml +="<td class = 'solved'><img src ='sc2units/" + $counter2 + ".jpg'></td>";
divtag.innerHTML = newhtml;
each section is a nested for loop that goes through the entire array of data that needs outputted.
EDIT: If there is an easier way to fill cells with data in an array I would be happy to know.
I'm not sure on your table, or setup, or exact needs.... But I believe you want to give content to certain table cells after you've already created the cells. You're on to the right idea with naming them, but you can't wrap <td>s in <div>s so your next best option is to simply name the <td>s themselves.
You could also add the content right inside the second loop, but we'll run with this.
HTML
<table id="myTable">
<tr>
<td>[ content ]</td>
</tr>
<tr>
<td>[ content ]</td>
<td>[ content ]</td>
</tr>
[ etc ]
</table>
JavaScript
var tbl = document.getElementById("myTable"),
rows = tbl.getElementsByTagName("tr");
// loop all rows
for (var r = 0; r < rows.length; r++){
// loop all cols within the row
var cols = rows[r].getElementsByTagName("td");
for (var c = 0; c < cols.length; c++){
cols[c].id = "row-" + r + "_col-" + c;
}
}
// usage
document.getElementById("row-1_col-1").innerHTML = "JS POWER";
http://jsfiddle.net/daCrosby/tJYNM/
You can create the elements separately then organize them later, inserting one inside the other. Something like:
var mydiv = document.createElement("DIV");
var mytd = document.createElement("TD");
mytd.innerHTML = "some basic text";
mydiv.appendChild(mytd); // insert the TD inside the DIV
document.body.appendChild(mydiv); // insert the DIV in the document's body
I just don't know what's about putting TD's inside DIV's...
If the table id is known – so the table can be obtained with docoument.getElementById(table_id) – how can I append a TR element to that table in the easiest way?
The TR is as follows:
<tr><td><span>something here..</span></td></tr>
The first uses DOM methods, and the second uses the non-standard but widely supprted innerHTML
var tr = document.createElement("tr");
var td = document.createElement("td");
var span = document.createElement("span");
var text = document.createTextNode("something here..");
span.appendChild(text);
td.appendChild(span);
tr.appendChild(td);
tbody.appendChild(tr);
OR
tbody.innerHTML += "<tr><td><span>something here..</span></td></tr>"
The most straightforward, standards compliant and library-independent method to insert a table row is using the insertRow method of the table object.
var tableRef = document.getElementById(tableID);
// Insert a row in the table at row index 0
var newRow = tableRef.insertRow(0);
P.S. Works in IE6 too, though it may have some quirks at times.
Using jQuery:
$('#table_id > tbody').append('<tr><td><span>something here..</span></td></tr>');
I know some may cringe at the mention of jQuery. Including a framework to do just this one thing is probably overkill. but I rarely find that I only need to do "just one thing" with javascript. The hand-coded solution is to create each of the elements required, then add them in the proper sequence (from inner to outer) to the other elements, then finally add the new row to the table.
If you're not opposed to using jQuery, you can use either of the following where "tblId" is the id of your table and "_html" is a string representation of your table row:
$(_html).insertAfter("#tblId tr:last");
or
$("#tblId tr:last").after(_html);
i use this function to append a bunch of rows into a table. its about 100% faster then jquery for large chunks of data. the only downside is that if your rows have script tags inside of them, the scripts wont be executed on load in IE
function appendRows(node, html){
var temp = document.createElement("div");
var tbody = node.parentNode;
var nextSib = node.nextSibling;
temp.innerHTML = "<table><tbody>"+html;
var rows = temp.firstChild.firstChild.childNodes;
while(rows.length){
tbody.insertBefore(rows[0], nextSib);
}
}
where node is the row to append after, and html is the rows to append
Really simple example:
<html>
<table id = 'test'>
<tr><td>Thanks tvanfosson!</td></tr>
</table>
</html>
<script type="text/javascript" charset="utf-8">
var table = document.getElementById('test');
table.innerHTML += '<tr><td><span>something here..</span></td></tr>';
</script>
I use this, works softly:
var changeInnerHTMLOfMyCuteTbodyById = function (id_tbody, inner_html)
{
//preparing
var my_tbody = document.getElementById (id_tbody);
var my_table = my_tbody.parentNode;
my_table.removeChild (my_tbody);
//creating dom tree
var html = '<table style=\'display:none;\'><tbody id='+ id_tbody+'>' +
inner_html + '</tbody></table>';
var tmp_div = document.createElement ('div');
tmp_div.innerHTML = html;
document.body.appendChild (tmp_div);
//moving the tbody
my_table.appendChild (document.getElementById (id_tbody));
}
You can do this:
changeInnerHTMLOfMyCuteTbodyById('id_tbody', document.getElementById ('id_tbody').innerHTML + '<tr> ... </tr>');