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

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');
},

Related

Cannot read property 'createDocumentFragment' of undefined on Table reformatting

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.

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.

How could I call a JQuery function upon a button click?

I have a JQuery function that fetches and displays a page worth of images through the use of JSON files. I want to display the next set of images upon a button click, but that requires adding on a short string to the request url, which is found and stored in a var when I first run the script. I need to call this JQuery function again and pass the string var to it (lastId in code below). I am an utter noob with JavaScript in general and don't know how to go about doing that.
Here is a full version of the code:
$(function runthis(un){
var lastId;
un = typeof un !== 'undefined' ? un : "";
$('#domainform').on('submit', function(event){
event.preventDefault();
$('#content').html('<center><img src="img/loader.gif" alt="loading..."></center>');
//var lastId;
var domain = $('#s').val();
var newdomain = domain.replace(/\//g, ''); // remove all slashes
var requrl = "http://www.reddit.com/r/";
var getmore;
getmore = "?after=t3_"+un;
var fullurlll = requrl + domain + ".json" + getmore;
$.getJSON(fullurlll, function(json){
var listing = json.data.children;
var html = '<ul class="linklist">\n';
for(var i=0, l=listing.length; i<20; i++) {
var obj = listing[i].data;
var votes = obj.score;
var title = obj.title;
var subtime = obj.created_utc;
var thumb = obj.thumbnail;
var subrdt = "/r/"+obj.subreddit;
var redditurl = "http://www.reddit.com"+obj.permalink;
var subrdturl = "http://www.reddit.com/r/"+obj.subreddit+"/";
var exturl = obj.url;
var imgr = exturl;
var imgrlnk = imgr.replace("target=%22_blank%22","");
var length = 14;
var myString = imgrlnk;
var mycon = imgrlnk;
var end = mycon.substring(0,14);
myString.slice(-4);
var test1 = myString.charAt(0);
var test2 = myString.charAt(1);
var timeago = timeSince(subtime);
if(obj.thumbnail === 'default' || obj.thumbnail === 'nsfw' || obj.thumbnail === '')
thumb = 'img/default-thumb.png';
if(end == "http://i.imgur" ){
$("#MyEdit").html(exturl);
html += '<li class="clearfix">\n';
html += '<img src="'+imgrlnk+'" style="max-width:100%; max-height:750px;">\n';
html += '</li>\n';
html += '<div class="linkdetails"><h2>'+title+'</h2>\n';
/*html += '<p class="subrdt">posted to '+subrdt+' '+timeago+'</p>'; /*'+test1+test2+'*/
html += '</div></li>\n';
}
if (listing && listing.length > 0) {
lastId = listing[listing.length - 1].data.id;
} else {
lastId = undefined;
}
} // end for{} loop
htmlOutput(html);
}); // end getJSON()
}); // end .on(submit) listener
function htmlOutput(html) {
html += '</ul>';
$('#content').html(html);
}
});
The way you currently are executing the function run this doesn't ever leave you a handle to that function. This means it only really exists in the context of document.ready (what $(function()) is a shortcut for).
What you want to do instead is to keep a reference to this function for later use.
If you want to be able to put it directly into an onclick='' you will need to put the function in global,
eg:
var myFunction = function() { /*Stuff here*/}
$(myFunction)
this declares a function called myFunction and then tells jQuery to execute it on document ready
Global is generally considered pretty naughty to edit. One slightly better option would be to assign the click to the button inside your javascript
eg:
$(function(){
var myFunction = function() { /*Stuff here*/}
myFunction(); //call it here
$('#my-button-id').click(myFunction);//attach a click event to the button
)
This means that the function myFunction only exists in the scope of your document.ready, not in global scope (and you don't need onclick='' at all)
tTo add listener on some event you can use live('click',function(){}) Like yhis:
<div id="my-button">some content</div>
<script type="text/javascript">
$('#my-button').live('click',function(){
//your code
})
</script>

How can I get data of selected table rows?

I am using the following snippet and from this I can find the index of a row which one is selected on the basis of checkbox on every row of the table.How can I modify this snippet so that I can get the selected row data instead of index?
Please Help!!
<script>
function myfunction3() {
var element_table = document.getElementsByName('collection');
var element_tableRows = element_table[0].rows;
var selectedTr = new Array();
var data = "";
for (var i = 0; i < element_tableRows.length; i++) {
var checkerbox = element_tableRows[i].cells[0].firstChild;
if (checkerbox.checked) {
data = data+ element_tableRows[i].getAttribute("name");
}
}
var element_paragraph = document.getElementsByName('description');
element_paragraph.innerHTML = data;
alert(data);
}
</script>
as TJ says, i dont see any index in your code. but try something like this which is cleaner
$('.collection tr').each(function () {
//processing this row
$(this).find('td input:checked').each(function () {
// there is checkbox and it is checked, do your business with it
var value_of_checkbox = $(this).val(); // which is 'data' that you wanted
});
});

JSF Extended Datatable Sorting and Filtering

I have a extended datatable, RICHFACES 3.3.3 with sorting and filtering enabled. The table is rendered dynamically. Based on the requirement, I need to disable certain rows(which contain editable fields) when the table is displayed.
I have that logic written in a Javascript function rowBlur(), and call it whenever the page is displayed. Hence, when the table is loaded the required rows are disabled as expected. The problem is whenever I filter/sort the table, the disabled rows get enabled again.
Is there any way I can call the javascript function whenever filter or sort happens?
Here is the code:
HtmlExtendedDataTable dynamicDataTable = new HtmlExtendedDataTable();
dynamicDataTable.setOnkeydown("filterAllOnEnter(event)");
function filterAllOnEnter(event) {
if(event.keyCode == 13) {
jQuery(".rich-filter-input").blur();
rowblur();
return false;
} else
return true;
}
// js code////////////
<script>
function show(){
val = '${myController.mergeWorkMap}';
}
</script>
<script>
function rowblur(){
for(var i=0;i<7;i++){
var firstCol = "myForm:dynamicTable:"+i+":col0" ;
var secondCol = "myForm:dynamicTable:"+i+":col1" ;
var merge =document.getElementById(firstCol).textContent;
var work =document.getElementById(secondCol).textContent;
var obj = JSON.parse(val).mergeWorkMap;
if(!(work == obj[merge])){
var col3 = "myForm:dynamicTable:" + i + ":col3";
var col4 = "myForm:dynamicTable:" + i + ":col4";
var col5 = "myForm:dynamicTable:" + i + ":col5";
var col6 = "myForm:dynamicTable:" + i + ":col6";
document.getElementById(col3).disabled = true;
document.getElementById(col4).disabled = true;
document.getElementById(col5).disabled = true;
document.getElementById(col6).disabled = true;
}
}
}
</script>
The rowblur() won't work properly on filtering, and on sorting the columns it won't work at all.

Categories