Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add/remove columns #189

Closed
tophstar opened this issue Dec 3, 2012 · 5 comments
Closed

add/remove columns #189

tophstar opened this issue Dec 3, 2012 · 5 comments

Comments

@tophstar
Copy link

tophstar commented Dec 3, 2012

Hi Mottie,

Just a quick features question. Is there a widget in the works for the possibility of adding and removing columns?

Thanks,
Tophstar

@Mottie
Copy link
Owner

Mottie commented Dec 3, 2012

I don't have anything in the works for adding and removing columns, but I was thinking about a widget that would hide or show columns.

I was just making a demo to show you how it could be done when I realized that the thead of the table doesn't update when the update method is used. I'll have to work on that and include it in the next update.

@tophstar
Copy link
Author

tophstar commented Dec 7, 2012

Here's my attempt at creating a widget that hide/shows columns on the page. I haven't completely abstracted it to into the widgets.js, but it is general enough to work on any table that uses a tablesorter with filters. I threw the code in my layout of the framework im using (zend's MVC) so it is available to any page in my application. It's a starting point anyway.

it requires putting a TD in the THEAD of the table

<td class="col-control" style = "padding: 0 30px 0 45px;" data-cookie-name="enter_a_name_here_by_page">&nbsp</td>

and this script...

function createCookie(name,value,days) {
    if (days) {
        var date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        var expires = "; expires="+date.toGMTString();
    }
    else var expires = "";
        old_cookie=readCookie(name);
        if(false){//old_cookie!=null){
            document.cookie = old_cookie+name+"="+value+expires+"; path=/";
        }else{
            document.cookie = name+"="+value+expires+"; path=/";
        }
}

function eraseCookie(name) {
    createCookie(name,"",-1);
}

//get the cooking info
function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

/*************************************************************************************************************************
* ABSTRACTION Controls for hide/show table columns **********************************************************************
**************************************************************************************************************************
*/
function colControlStartup(){

    $('.col-control').each(function(){

        var thisColControl = this;

        name = $(thisColControl).attr('data-cookie-name');
        var cookie = readCookie('column-selection-'+name);


        var jsonCookie;
        var columnsArray = Array();
        var noCookie = false;
        if(cookie!=null){
            jsonCookie=$.parseJSON(cookie);

            for(var col in jsonCookie){
                columnsArray.push(jsonCookie[col]);
            }

        }else{
            noCookie = true;
        }

        var table = $(thisColControl).parentsUntil('.tablesorter').parent('table');

        //indexing columns set-up
        $('th.tablesorter-header', table).each(function(){
            var columnIndex = ($(this).attr('data-column'));
            columnIndex++;
            $('tbody tr,thead tr',table).each(function(){
                $('td:nth-child('+columnIndex+')',this).attr('data-column',(columnIndex-1));
            });
        });

        //executing default show/hide columns
        $('th.tablesorter-header', table).each(function(){

            var header = $(this);

            if($.inArray($(this).attr('data-column'), columnsArray)!=-1 || noCookie == true){
                $('thead tr th, thead tr td, tbody tr td', table).each(function(){
                    if($(this).attr('data-column')==$(header).attr('data-column')){
                        $(this).show();
                    }
                });
            }else{
                $('thead tr th, thead tr td, tbody tr td', table).each(function(){
                    if($(this).attr('data-column')==$(header).attr('data-column')){
                        $(this).hide();
                    }
                });
            }
        });

    });
}

/*
* This event will create the column control dialog box, set the prefrered columns as checked/unchecked,
* bind the hide/show event to checking/unchecking, or close the dialog box
*/
$('.col-control').click(function(){

    $('#col-control-dialog').dialog('close');

    var thisColControl = this;

    var table = $(thisColControl).parentsUntil('.tablesorter').parent('table');

    name = $(thisColControl).attr('data-cookie-name');
    var cookie = readCookie('column-selection-'+name);


    var jsonCookie;
    var columnsArray = Array();
    var noCookie = false;
    if(cookie!=null){
        jsonCookie=$.parseJSON(cookie);

        for(var col in jsonCookie){
            columnsArray.push(jsonCookie[col]);
        }

    }else{
        noCookie = true;
    }

    if(typeof($(thisColControl).attr('data-navstate'))=='undefined' || $('.col-control').attr('data-navstate')=='closed'){

        var colControlDialog = '<div id="col-control-dialog" title="select columns" style="display:none" data-navstate="closed">'
        +'<form id="col-control-form"><table><tr><td style="width:50%"><table>';

        $('div', $(thisColControl).siblings()).each(function(){
            colControlDialog=colControlDialog.concat('<tr>'
            +'<td>'
            +'<input type="checkbox" class="controlled-column" name = "'
            +$(this).html()
            +'" value = "'
            +$(this).parent().attr('data-column')
            +'"');


            if($.inArray($(this).parent().attr('data-column'), columnsArray)!=-1  || $(this).parent().is(':visible')){
                colControlDialog=colControlDialog.concat(' checked="yes"');
            }
            colControlDialog=colControlDialog.concat('/><a>'
            +$(this).html()
            +'</a><br/>'
            +'</td>'
            +'</tr>');
        });

        colControlDialog=colControlDialog.concat('</table></td><td>');

        //Add in the stored outputs
        colControlDialog= colControlDialog.concat('<input type="button" id="load-outputs" value="Load Stored View Outputs"/>'
        +'<input type="button" id="store-outputs" value="Store View Outputs"/>');

        //Finish the table
        colControlDialog = colControlDialog.concat('</td></tr></table></form></div>');

        //append the dialog box to the col-control table
        $(table).append(colControlDialog);

        $('#col-control-dialog').dialog({
            autoOpen:false,
            modal:false,
            height:400,
            width:500,
            draggable: true,
            resizable: false,
            buttons:{

                Save:function(){
                    var columnSelection = JSON.stringify($('#col-control-form').serializeJSON());
                    createCookie('column-selection-'+name,columnSelection,1000);
                }
            },
            open: function(){

                var target = $(thisColControl).parentsUntil('thead').parent();

                $('#col-control-dialog').dialog('widget').position({
                    my: 'right top',
                    at: 'right top',
                    of: target

                });
            },
            close: function(){
                $(thisColControl).attr('data-navstate', 'closed');
                $('#col-control-dialog').remove();
            }

        });

        $('#col-control-dialog').dialog('open');
        $(thisColControl).attr('data-navstate', 'opened');


        //Bind a hook into the newly added checkboxes for a change event.  This will show/hide the column.
        $('.controlled-column').change(function(){

            checkbox=$(this);


            if($(this).is(':checked')){
                $('tr th, tr td', table).each(function(){
                    if($(this).attr('data-column')==$(checkbox).val()){
                        $(this).show();
                    }
                });
            }
            else{
                $('tr th, tr td', table).each(function(){
                    if($(this).attr('data-column')==$(checkbox).val()){
                        $(this).hide();
                    }
                });
            }

        });

        //Bind Hook to open dialog box for stored outputs
        $('#load-outputs').on('click',function(){
            $('#outputs-popup').dialog('open');
        });

        $('#store-outputs').on('click',function(){
            storeOutputs();
        });
    }else{
        //$('#col-control-dialog').dialog('close');
    }
});

/*
*  This jquery call will bind the column control event after the tablesorter has been completely initialized.  Otherwise, the
*  filter is created last and will not be included in the initial startup for the column control.
*/
$('.tablesorter').bind('tablesorter-initialized', function(e, table){

    ///Column Control Stuff....
    colControlStartup();
});

@tommykamkcm
Copy link

Hi tophstar, just want to give you a suggestion to improve the performance plus browser compatibility (especially the shitty IE7,8) of the widget.

Instead of calling hide() or show(), it is better to removeClass('hide') or addClass('hide') with css: .hide{ display: none; }

The reason is hide() or show() modify the style properties of every single s. For example, if there are 1000 , number of changes = 1000 and number of reflow (related to DOM manipulation) = 1000 as well.

FYI, https://developers.google.com/speed/articles/reflow

Cheers
Tommy

@lanzelotik
Copy link

Hi tophstar.
Can you please write a full example how to add column

@Mottie
Copy link
Owner

Mottie commented Dec 14, 2013

You can now use the updateAll method to update the table cache after adding a new column of data. Here is a demo:

var $table = $('table').tablesorter({
        theme: 'blue',
        widgets: ['zebra', 'columns']
    }),
    // column index
    index = 0,
    // column data to add to the table
    columns = ['firstName', 'lastName', 'phone|format', 'streetAddress',
        'email', 'city', 'usState|abbr'];

$('button').click(function () {
    var url = "http://www.filltext.com/?callback=?";
    $.getJSON(url, {
        'rows': 10, // number of rows in the table
        'data': '{' + columns[index] + '}'
    })
    .done(function (data) {
        // add new header cell
        $table.find('thead tr').append('<th>' + columns[index].split('|')[0] + '</th>');
        // increment index to next column
        index = (index + 1) % columns.length;
        // add new cell to each tbody row
        $.each(data, function (i, item) {
            var html = "<td>" + item.data + "</td>";
            $table.find('tbody tr').eq(i).append(html);
        });
        // update cache
        $table.trigger('updateAll');
    });
});

And if you mean a column selector to show/hide columns, please refer to issue #318.

@Mottie Mottie closed this as completed Dec 14, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants