Need help with a javascript code.
I am new to javascript and I have written this javascript class to generate a table nested in an unordered list. I want to save the state on the table as on the main page I have multiple tabs and when I come back to the tab which displays this table it should have the same state as before. In my main script file I am creating an instance of this class and generating the custom table from the data only once during initialisation. I am calling the updateTable() method to add new data to the table every time this tab is opened, which adds new data to the ul and returns this.ul . I am able the save the state of the table but after the first time when I come back to this tab I am unable to trigger click events. Somehow the event handlers are not getting called after the 1st time.
import {TaskQueue} from './run-task-queue.js';
export class Table {
constructor(groups,file_dir, list_type) {
this.ul = $('<ul style="padding-top:10px;"></ul>');
this.data = groups;
this.type = list_type;
this.file_dir = file_dir;
this.selected = {};
this.runTaskQueue = new TaskQueue();
}
addTableHeader() {
var hdr = $('<li></li>');
var hdrDiv = $('<div class="row" style="margin:0;background-color:aliceblue"></div>');
var hdrCheckbox = $('<div class="my-auto" style="padding:10px"><input class="float-left" type="checkbox" style="cursor:pointer"></div>');
var hdrPlayIconDiv = $('<div class="my-auto float-right" style="padding:10px; flex:1; color:green;"></div>');
var hdrPlayIcon = $('<i class=" fa fa-play float-right" data-run-status="notrunning" style="cursor:pointer"></i>');
hdrPlayIcon.on('click',function(e){
status = e['target'].getAttribute("data-run-status");
if(status === 'running') {
e['target'].classList = ''
e['target'].classList = 'fa fa-play float-right';
e['target'].setAttribute("data-run-status", "notrunning");
this.runTaskQueue.clearTaskQueue();
}
else {
e['target'].classList = ''
e['target'].classList = 'fa fa-pause float-right';
e['target'].setAttribute("data-run-status", "running");
this.runTaskQueue.enqueueTaskList(this.selected);
}
}.bind(this));
hdr.css('cursor','default');
hdrDiv.append(hdrCheckbox);
hdrPlayIconDiv.append(hdrPlayIcon);
hdrDiv.append(hdrPlayIconDiv);
hdr.append(hdrDiv)
this.ul.append(hdr);
}
generateTableRow(val) {
var row = $('<tr></tr>');
var cell = $('<td></td>').text(val);
if(this.type === 'test') {
var checkboxCell = $('<td></td>');
var checkbox = $('<input type="checkbox">');
checkbox.on('click', function(e){
if(!e.target.checked)
delete this.selected[val]
else {
var task = {};
task['file_name'] = val;
task['file_dir'] = this.file_dir;
var x = ($(e.target).parent().siblings()[2]);
task['element'] = x.children[0].children[0];
task['doneClassList'] = "fa fa-play float-right";
task['queueClassList'] = "fa fab fa-stack-overflow float-right",
task['runningClassList'] = "fa fa-spinner fa-spin float-right",
this.selected[val] = task;
}
console.log(this.selected)
}.bind(this));
checkboxCell.append(checkbox);
row.append(checkboxCell);
}
row.append(cell);
if(this.type ==='replay' || this.type ==='test') {
var editIcon = $('<td style="flex:1;"><div class="my-auto float-right" style="padding:10px; color:#15AABF;"><i class=" fa fa-edit float-right"></i></div></td>');
row.append(editIcon);
}
if(this.type === 'test') {
var playIcon = $('<td style="flex:1;"><div class="my-auto float-right" style="padding:10px; color:green;"><i class="fa fa-play float-right"></i></div></td>');
playIcon.on('click', function(e){
console.log(e);
console.log(this);
var element = e['target'];
// element.classList.remove("fa-play");
// element.classList.add('fa-spinner');
// element.classList.add('fa-spin');
this.runTaskQueue.enqueueTask({'file_name': val,'file_dir': this.file_dir, 'element':e.target,
'queueClassList' : "fa fab fa-stack-overflow float-right",
'runningClassList': "fa fa-spinner fa-spin float-right",
'doneClassList':"fa fa-play float-right"});
//e['target'].classList.remove('color','blue');
}.bind(this))
row.append(playIcon);
}
return row;
}
generateTableListItem(key) {
var li = $('<li class="hide_group"></li>');
var div = $('<div class="row" style="margin:0;"></div>');
var p = $('<div class="my-auto" style="padding:10px;flex:1"></div>').append($('<p class="my-auto"></p>').text(key));
var i = $('<div class="my-auto float-right" style="padding:10px" ><i class=" fa fa-plus float-right"></i></div>');
p.on('click',function(){
$(this).parent().parent().toggleClass('hide_group');
});
i.on('click',function(){
$(this).parent().parent().toggleClass('hide_group');
})
var nestedTable = $('<table class="tabel table-hover" style="width:98%; margin-left:20px;"></table>');
this.data[key].forEach(val => {
var row = this.generateTableRow(val);
nestedTable.append(row);
})
if(this.type === 'test'){
var checkbox = $(`<div class="my-auto" style="padding:10px"><input class="float-left" type="checkbox" ></div>`);
checkbox.on('click', function(){
console.log('checkbox -clicked')
});
div.append(checkbox);
}
div.append(p);
div.append(i);
li.append(div);
li.append(nestedTable);
return li;
}
generateTableFromGroups() {
this.ul.empty();
if(this.type === 'test')
this.addTableHeader();
Object.keys(this.data).forEach(key => {
var li = this.generateTableListItem(key);
this.ul.append(li);
})
console.log('this.ul');
console.log(this.ul);
return this.ul;
}
updateTable(data) {
var currentData = this.data;
var currentKeys = Object.keys(currentData);
var newData = data;
var newKeys = Object.keys(newData);
var deltaPositive = newKeys.filter(x => !currentKeys.includes(x));
deltaPositive.forEach(key => {
this.data[key] = newData[key];
this.generateTableListItem(key);
});
console.log('this.ul');
console.log(this.ul);
return this.ul;
}
}
Parts of the main script file, the init() function gets the initial data and initialises the tables. $.fn.show_files_list is attached to a button and is responsible for updating the table and displaying it. The table is being displayed when I click this button, but inside the table I have some buttons that should trigger some events. When I come to this tab for the first time all the buttons in the generated table work fine but if I leave this tab and come back to this tab the buttons in the table stop working.
import {Table} from './table-module.js';
$(document).ready(function(){
var testTable;
var replayTable;
const get_file_list = (url) => {
var dfd = jQuery.Deferred();
fetch(url)
.then((resp) => (resp.ok) ?resp.json() : new Error('something went wrong'))
.then(function(data) {
dfd.resolve(data);
})
.catch(err => {
console.log(err);
dfd.reject(err);
})
return dfd.promise();
}
$.fn.show_files_list = function(key1, key2, table) {
$(this).siblings().removeClass('btn-info');
$(this).siblings().addClass('btn-outline-info');
$(this).removeClass('btn-outline-info');
$(this).addClass('btn-info');
get_file_list('/get_file_list')
.done( (all_files) => {
var dir = all_files[key1];
var files = all_files[key2];
var groups = group_files(files);
console.log('Display Table');
var genTable = table.updateTable(groups);
$('#display_files').empty();
$('#display_files').append(genTable);
})
.fail(function(err) {
console.log(err);
});
}
const init = () => {
get_file_list('/get_file_list')
.done( (all_files) => {
var test_dir = all_files['test_dir'];
var test_files = all_files['test_files'];
var test_groups = group_files(test_files);
testTable = new Table(test_groups, test_dir, 'test');
testTable.generateTableFromGroups();
var replay_dir = all_files['repaly_dir'];
var replay_files = all_files['replay_files'];
var replay_groups = group_files(replay_files);
replayTable = new Table(replay_groups, replay_dir, 'replays');
replayTable.generateTableFromGroups();
$.fn.show_logs('aut');
})
.fail((err) => {
console.log(err);
})
}
init();
}
It would be a great help if someone could point me in the right direction.