My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more

Need help with a javascript code.

Chandrashekhar Choudhary's photo
Chandrashekhar Choudhary
·May 18, 2020

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.