Cannot read property 'createDocumentFragment' of undefined on Table reformatting - javascript

I am trying to reformat the table by doing some changes in the existing table in my application. I have searched on internet for below error but I haven't found any solution for this.
Error I am getting is as below:
Cannot read property 'createDocumentFragment' of undefined
Here is my
function editTable()
{
// debugger;
// remove blank td pair
$('#prodHold tr td').each(function() {
// debugger;
if ($(this).text() == ''){
$(this).prev('td').remove();
$(this).remove();
}
});
// get array of all tds
var tds = $('#prodHold tr td').length;
var td_arr = [];
for(var i=0; i<tds; i++){
// if($(this).text()!== ''){
// td_arr.push($('#prodHold tr td').eq(i).html());
// }
if($(this).html()!== ''){
td_arr.push($('#prodHold tr td').eq(i).html());
}
}
// prepare table, wrap tr for every 4 tds, *according to your table sample
var e = '<tr>';
for(var i=1; i<=td_arr.length; i++){
if(i%4 == 0){
e = e + '<td>' + td_arr[i-1] + '</td></tr><tr>';
}
else{
e = e + '<td>' + td_arr[i-1] + '</td>';
}
}
// append
$('#prodHold').html(e);
}
$(document).ready(function () {
editTable();
});
Getting error on below line
td_arr.push($('#prodHold tr td').eq(i).html());
Code I am using from the question posted on below
Remove content from table and reformat the table
Please guide me If I am doing anything wrong here.

The error seems to be triggered on $(this).html(), because this does not refer to a DOM element. You are using this in a normal for loop, while you probably intended it to be used in a jQuery each loop callback.
Like this:
// get array of all tds
var tds = $('#prodHold tr td'); // not length
var td_arr = [];
tds.each(function() {
if($(this).html()!== ''){
td_arr.push($(this).html());
}
})
NB: You should really reconsider if the erroneous code you received as an answer deserved to be marked accepted.

Related

DataTables won't convert HTML table without an alert() beforehand

I'm building a page that makes an Ajax call to retrieve a .csv file, and load the values into an HTML table. I call it in a $(document).ready(function(){ ltm.init(); }); call at the bottom of the HTML file.
It loops over the rows of the CSV file, and constructs an HTML table in a javascript variable, then hands the table off to the DOM using $('#myTable').html(table_data). The next function, ltm.convertTableToDataTable() uses $('#myTable').DataTable() to convert it to a simple DataTable. However, it's not firing. I added a button to call the convertTableToDataTable() function, and when I click it, it works fine, and the DataTable is fully functional.
If I put an alert() in the convertTableToDataTable immediately before the $('#myTable').DataTable(), the alert displays, and the table converts properly. If I move the alert to after the .DataTable() call, the alert displays, and the table does not convert.
I've tried using setTimeout($('#myTable').DataTable(),5000); to introduce a delay before the .DataTable() call, but that doesn't work either.
How can I get this to load in the data and create a DataTable thing on my page without the alert?
Here's my genericized javascript snippet:
var ltm = {
// local variables
urlCSV: 'myData.csv',
init: function() {
ltm.loadCSVDataIntoTable();
//alert('convertTableToDataTable fired!');
ltm.convertTableToDataTable();
// Bind click events
$('#btnLoadCSVData').click(function() {
ltm.loadCSVDataIntoTable();
});
$('#btnMakeDataTable').click(function() {
ltm.convertTableToDataTable();
});
},
loadCSVDataIntoTable: function() {
// The URL contains the .csv file. The first row of the file is the column headers.
$.ajax({
url:ltm.urlCSV,
dataType:"text",
success:function(csvData) {
var my_data = csvData.split(/\r?\n|\r/);
// var table_start = '<table class="table table-bordered table-striped" id="tblLTMStrains">';
var table_start = '<table class="display" id="tblLTMStrains">';
var table_end = '</table>';
var table_head_start = '<thead><tr>';
var table_head_end = '</tr></thead>';
var table_head = '';
var table_foot_start = '<tfoot><tr>';
var table_foot_end = '</tr></tfoot>';
var table_body_start = '<tbody>';
var table_body_end = '</tbody>';
var table_rows = '';
var table_data = '';
for(var intRow = 0; intRow<my_data.length; intRow++)
{
if (intRow===0) { // First row contains column headers
var cell_data = my_data[intRow].split(",");
for(var cell_intRow=0; cell_intRow<cell_data.length; cell_intRow++)
{
table_head += '<th>'+cell_data[cell_intRow]+'</th>';
}
} else {
if (my_data[intRow].length > 0) { // Gracefully handle null lines
var cell_data = my_data[intRow].split(",");
var blnLoadRow = true;
if ([Some conditions under which I want to filter out the row]) {
blnLoadRow = false;
}
if (blnLoadRow){
var thisRow = $('#templateDataRow').html();
// Can't put the <tr> content in a DIV without it stripping out all the tags
// Also, even if I don't put a <tbody> in, the DOM will create one anyway, so strip it out too.
thisRow = thisRow.replace("<table>","");
thisRow = thisRow.replace("<tbody>","");
thisRow = thisRow.replace("</tbody>","");
thisRow = thisRow.replace("</table>","");
thisRow = thisRow.replace("__MYFIELD0__",cell_data[0]);
thisRow = thisRow.replace("__MYFIELD1__",cell_data[1]);
thisRow = thisRow.replace("__MYFIELD2__",cell_data[2]);
thisRow = thisRow.replace("__MYFIELD3__",cell_data[3]);
thisRow = thisRow.replace("__MYFIELD4__",cell_data[4]);
table_rows += thisRow;
}
}
}
}
table_data = table_start;
table_data += table_head_start + table_head + table_head_end;
table_data += table_foot_start + table_head + table_foot_end;
table_data += table_body_start + table_rows + table_body_end;
table_data += table_end;
$('#divMyTable').html(table_data);
}
});
},
convertTableToDataTable: function() {
//alert('convertTableToDataTable fired - BEFORE!');
$('#myTable').DataTable();
//alert('convertTableToDataTable fired! - AFTER');
},
lastFunction: function() {} // all previous closing curly braces should have a comma after them
} // end of the ltm object.
change
$('#divMyTable').html(table_data);
to
$('#divMyTable').html(table_data).onload().DataTable();
this will make sure, DataTable is fired when html is loaded.
and remove the
convertTableToDataTable: function() {
//alert('convertTableToDataTable fired - BEFORE!');
$('#myTable').DataTable();
//alert('convertTableToDataTable fired! - AFTER');
},

Add doubleclick handler on table cell after response

I would like to add a doubleclick event handler to table cell AFTER the table was "downloaded" from a servlet and "inserted" by javascript.
I have a javascript cycle that iterate on a xml response to map datas ini table. Said that a cell can be
<td class='red' ></td>
I want to add a function on that cell, I've tried several solution, but none works.One is:
$(".red").on("dblclick",myfunction);
Help?
Update:
Table constructor ofter response received
function handleResponse(responseXML) {
var i;
var x=responseXML.getElementsByTagName("row");
var out="<table><tr><th >Description</th><th >State</th><th>Note</th></tr>";
for(i=0;i<x.length;i++){
out+="<tr>";
var Description = x[i].getElementsByTagName("Description")[0].childNodes[0].nodeValue;
var State = x[i].getElementsByTagName("State")[0].childNodes[0].nodeValue;
var note = x[i].getElementsByTagName("Note")[0].childNodes[0];
var note_text=" ";
if (!(typeof note === "undefined") && !(note=='null')) {
note_text=note.nodeValue;
}
out += "<td>"+Description+ "</td>";
if(State==0)
out+="<td class='white' ></td>";
else if(State==1)
out+="<td class='red' ></td>";
else if(State==2)
out+="<td class='yellow' ></td>";
else if(State==3)
out+="<td class='green' ></td>";
out+="<td>" + note_text + "</td></tr>";
}
var output = document.getElementById("mytable");
out+="</table>";
$().on("click",".red",update()); //here is the point
output.innerHTML=out;
}
Update:
Based on your comments you can try this:
When you print the td change the template a little:
out+="<td class='red' ondblclick='openModal()'></td>";
And then in your js file add something like this.
$(document).ready(function() {
function openModal() {
alert( "Double clicked." );
// Or call your other function here...
};
});
You can do it with several ways also, check here: http://www.w3schools.com/jsref/event_ondblclick.asp

Output values from the array in desired order?

I have array with the multiple records, each record has ID, event name and customer name. My algorithm that I use does not seem to work the way I want. Before I start to loop through array I set the empty variable outside of the loop var eventId; then I started looping and inside of the loop I have multiple if statement. So if eventId is empty I want to append tr with event name and below that another tr with customer name. Then next time if my eventId is not empty I want to check if name match with the record, if they match I just want to append td inside of existing tr and output customer name. If they do not match I want to output new tr with event name and new tr with customer name. I have working example here, it looks like that I have Test 1 outputted twice on the screen and I do not want that. I should have event name only once and all customers for that event below that event.
Here is my code:
https://jsfiddle.net/dmilos89/t1v2r8jm/3/
Please if you see where my code is breaking let me know. I think that I have problem with appending elements or my algorithm is missing something. Thanks in advance.
Javascript code:
$( document ).ready(function() {
var myRes = [];
myRes.push({'myId':"42",'eventName':"Test 1",'rCustomer':"Mike, Allan"});
myRes.push({'myId':"42",'eventName':"Test 1",'rCustumer':"Gates, Bill"});
myRes.push({'myId':"19",'eventName':"Spring 2016",'rCustomer':"John, Bill"});
myRes.push({'myId':"19",'eventName':"Spring 2016",'rCustomer':"Adams, Ron"});
myRes.push({'myId':"31",'eventName':"May Test 1",'rCustomer':"Steve, Marie"});
myRes.push({'myId':"42",'eventName':"Test 1",'rCustomer':"Ariel, Bill"});
myRes.push({'myId':"32",'eventName':"Fall 2016",'rCustomer':"Ron, Nill"});
myRes.push({'myId':"32",'eventName':"Fall 2016",'rCustomer':"Kim, Alen"});
myRes.push({'myId':"32",'eventName':"Fall 2016",'rCustomer':"Will, Huges"});
myRes.push({'myId':"32",'eventName':"Fall 2016",'rCustomer':"Seth, Peak"});
var eventId = '';
var count = 1;
for(var i=0; i< myRes.length; i++){
if(eventId != ''){
if(eventId == myRes[i].myId){
$('#row_' + count).append('<td>'+myRes[i].rCustomer+'</td>');
}else{
eventId = myRes[i].myId;
count++;
$('.myReservation').append('<tr><td><b>Event: '+myRes[i].eventName+'</b></td></tr>');
$('.myReservation').append('<tr id="row_"'+count+'><td>'+myRes[i].rCustomer+'</td></tr>');
}
}else{
eventId = myRes[i].myId;
$('.myReservation').append('<tr><td><b>Event: '+myRes[i].eventName+'</b></td></tr>');
$('.myReservation').append('<tr id="row_"'+count+'><td>'+myRes[i].rCustomer+'</td></tr>');
}
}
});
HTML code:
<table>
<tbody class="myReservation">
</tbody>
</table>
You misplaced the double quote when inserting tr elements with ids.
Replace <tr id="row_"'+count+'> with <tr id="row_'+count+'">.
Update: this achieves what you (probably) want:
var found = [];
for (var i = 0; i < myRes.length; i++) {
if (found[myRes[i].myId] === 1) {
$('#row_' + myRes[i].myId).append('<td>' + myRes[i].rCustomer + '</td>');
} else {
found[myRes[i].myId] = 1;
$('.myReservation').append('<tr><td><b>Event: ' + myRes[i].eventName + '</b></td></tr>');
$('.myReservation').append('<tr id="row_' + myRes[i].myId + '"><td>' + myRes[i].rCustomer + '</td></tr>');
}
}
Your problem is that you append a new element on every loop:
First, you are testing if "eventId" is not empty. If it is, you are setting it with the current loop iteration "myId"
eventId = myRes[i].myId;
$('.myReservation').append('<tr><td><b>Event: '+myRes[i].eventName+'</b></td></tr>');
$('.myReservation').append('<tr id="row_"'+count+'><td>'+myRes[i].rCustomer+'</td></tr>');
According to your data, eventId is now 42 and your output is :
<tr><td><b>Event: Test 1</b></td></tr>
<tr id="row_" 1=""><td>Mike, Allan</td></tr>
(by the way, there is a syntax error here and it explains why the next iteration doesn't append data)
Then, on the next iteration, eventId is still 42 so you are doing this
$('#row_' + count).append('<td>'+myRes[i].rCustomer+'</td>');
The output is the same at this point (see above the syntax error on the first answer)
On the next loop iteration, myId will be now 19 so you are overriding eventid and appending tr in consequence
loops keep going...
Until myId is again equal to 42 :
myRes.push({'myId':"42",'eventName':"Test 1",'rCustomer':"Ariel, Bill"});
Here you doesn't want "Event: Test 1" appearing two times, but on the last loop iteration myId was 31
myRes.push({'myId':"31",'eventName':"May Test 1",'rCustomer':"Steve, Marie"});
So on the if test, eventId is NOT equal to myRes[i].myId, therefore your script appends a new tr with duplicate event.
One solution could be this one:
$( document ).ready(function() {
var myRes = [];
myRes.push({'myId':"42",'eventName':"Test 1",'rCustomer':"Mike, Allan"});
myRes.push({'myId':"42",'eventName':"Test 1",'rCustomer':"Gates, Bill"});
myRes.push({'myId':"19",'eventName':"Spring 2016",'rCustomer':"John, Bill"});
myRes.push({'myId':"19",'eventName':"Spring 2016",'rCustomer':"Adams, Ron"});
myRes.push({'myId':"31",'eventName':"May Test 1",'rCustomer':"Steve, Marie"});
myRes.push({'myId':"42",'eventName':"Test 1",'rCustomer':"Ariel, Bill"});
myRes.push({'myId':"32",'eventName':"Fall 2016",'rCustomer':"Ron, Nill"});
myRes.push({'myId':"32",'eventName':"Fall 2016",'rCustomer':"Kim, Alen"});
myRes.push({'myId':"32",'eventName':"Fall 2016",'rCustomer':"Will, Huges"});
myRes.push({'myId':"32",'eventName':"Fall 2016",'rCustomer':"Seth, Peak"});
myRes.forEach(function(value, key) {
var table = $('.myReservation2');
var elemInTable = table.find('tr#row_'+value.myId); // $('#row_42') as an example
// If row doesn't exists, create it with it's customers
if(!elemInTable.length) {
table.append('<tr id="row_'+value.myId+'"><td>'+value.eventName+'</td></tr>');
elemInTable = table.find('tr#row_'+value.myId);
elemInTable.after('<tr><td>'+value.rCustomer+'</td></tr>');
}
// If it already exists, simply add the customers
else {
elemInTable.after('<tr><td>'+value.rCustomer+'</td></tr>');
}
})
});
However, I don't think it is the proper way to do it, actually, I think that you should reorganize your data (if your context permits it) like this :
myRes.push({'myId':"42",'eventName':"Test 1",'rCustomer': ["Mike, Allan", "Gates", "Bill", "..."]})
(sorry for my english by the way)

Creating separate arrays from TH data in different tables

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.

cannot set selectedIndex off select with javascript

I have this code and I keep getting undefined if I test the selectedIndex.
alert(x.selectedIndex);
So, setting it is also a problem.
Does anyone possibly see what the problem is?
//makes list off tags
function ttyps_select(data,naamsel,selectid, containerid){
if(!ttyps.length){
jQuery.each(data, function(index, itemData) {
ttyps.push( new Tagtype(itemData.tag_id, itemData.tag ));
});
}
opties = "<option value=\"-1\"></option>\n";
for(var i=0; i<ttyps.length; i++) {
var dfnkey = ttyps[i].tag_id;
var dfnsel = ttyps[i].tag;
if (dfnkey==selectid) {
opties +="<option value="+ttyps[i].tag_id+" SELECTED>"+dfnsel+"</option>\n";
} else {
opties +="<option value="+dfnkey+">"+dfnsel+"</option>\n";
}
}
$("<select name=\"" + naamsel + "\" size=\"1\" ></select>")
.html(opties)
.change(function(e){
select_tag(containerid);
})
.appendTo("#"+naamsel);
}
function select_tag(id) {
var x = $('#frmttypid'+id+' select');
var ttidx = x.val();
var tag = getTagtype(ttidx).tag;
x.selectedIndex=0;
x.blur();
if( tag ){
document.forms['frmtags']['frmtag'+id].value=tag;
}
}
thanks, Richard
$('selector') (jQuery) returns an object with array-like collection of matched DOM nodes. Your x variable is an jQuery object, not a reference to any particular <select/> element. use
x[0].selectedIndex
x[0] is a reference to the first DOM node in the jQuery object.

Categories