fooplugins / FooTable

jQuery plugin to make HTML tables responsive
https://fooplugins.com/plugins/footable-jquery/
Other
2.13k stars 637 forks source link

td data loss (display blank) in expanded table after multiple toggles before expansion #783

Open rolandshc opened 6 years ago

rolandshc commented 6 years ago

I have a asp.net grid table using footable 3.1.6 with 25 TR and 26 inner rows for each expandable inner table TR when expanding. The plug-in works fine normally but sometimes when I click on the TR element I need to wait 5 sec to wait til it completed expansion. Tested that when I click it multiple times quickly before it expands, it does expand but the data inside the expanded table td data would lost.

What I am guessing is that the plugin is running some javascript functions to form the inner table when I first click, then the function is being called multiple times before the inner table successfully created, which is the reason why the result is broken.

I have added some flags in the footable.js (3.1.6) in ontoggle function, onexpand and oncollapse to not allow them to trigger at the same time to prevent the above data display error occur.

Til now my codes work fine, here is my code

at the beginning of the function, initialize the flag functionIsRunning (you can search "/* @lends FooTable.Row /" to find the location)

var functionIsRunning = false;

(function($, F){
    var functionIsRunning = false;

    F.Row = F.Class.extend(/** @lends FooTable.Row */{

in expand.ft.row event, after self.ft.raise('expanded.ft.row', [self]);

add

functionIsRunning = false;

    expand: function(){
            if (!this.created) return;
            var self = this;
            /**
             * The expand.ft.row event is raised before the the row is expanded.
             * Calling preventDefault on this event will stop the row being expanded.
             * @event FooTable.Row#"expand.ft.row"
             * @param {jQuery.Event} e - The jQuery.Event object for the event.
             * @param {FooTable.Table} ft - The instance of the plugin raising the event.
             * @param {FooTable.Row} row - The row about to be expanded.
             */

            self.ft.raise('expand.ft.row',[self]).then(function(){
                self.__hidden__ = F.arr.map(self.cells, function(cell){
                    return cell.column.hidden && cell.column.visible ? cell : null;
                });

                if (self.__hidden__.length > 0){
                    self.$details.insertAfter(self.$el)
                        .children('td').first()
                        .attr('colspan', self.ft.columns.visibleColspan);

                    F.arr.each(self.__hidden__, function(cell){
                        cell.collapse();
                    });
                }
                self.$el.attr('data-expanded', true);
                self.$toggle.removeClass('fooicon-plus').addClass('fooicon-minus');
                self.expanded = true;
                self.ft.raise('expanded.ft.row', [self]);
                functionIsRunning = false;
            });
        },

In collapse.ft.row event,

functionIsRunning = false;

collapse: function(setExpanded){
            if (!this.created) return;
            var self = this;
            /**
             * The collapse.ft.row event is raised before the the row is collapsed.
             * Calling preventDefault on this event will stop the row being collapsed.
             * @event FooTable.Row#"collapse.ft.row"
             * @param {jQuery.Event} e - The jQuery.Event object for the event.
             * @param {FooTable.Table} ft - The instance of the plugin raising the event.
             * @param {FooTable.Row} row - The row about to be expanded.
             */
            self.ft.raise('collapse.ft.row',[self]).then(function(){
                F.arr.each(self.__hidden__, function(cell){
                    cell.restore();
                });
                self.$details.detach();
                self.$el.removeAttr('data-expanded');
                self.$toggle.removeClass('fooicon-minus').addClass('fooicon-plus');
                if (F.is.boolean(setExpanded) ? setExpanded : true) self.expanded = false;
                self.ft.raise('collapsed.ft.row', [self]);
                functionIsRunning = false;
            });
        },

in _ontoggle event, add the flag logic to detect whether the code has been completed or not to prevent multiple triggering

if (!functionIsRunning) { functionIsRunning = true; self.toggle(); }

_onToggle: function (e) {
            var self = e.data.self;
            if ($(e.target).is(self.ft.rows.toggleSelector)){

              if (!functionIsRunning) {
                functionIsRunning = true;
                self.toggle();
              }

            }
        }

Hope to get some comments with it, thanks