Search code examples
jquery-uiresizablejquery-ui-resizabletablecolumn

jQueryUI resizable - when you change the width of a column - all the other speakers twitch


I use jQueryUI resizable for resizing columns in the table. When you change the width of one column, the other columns must remain unchanged. Should only varies the width of the table

Why do you change the width of one column, while others twitch? If all columns to make the minimum width, and then begin to increase the width of the last column (right column), all the others begin to twitch.

<div class="table-wrapper">
    <table id="table">
    <tbody>
        <tr>
            <td class="gray">Zagreb</td>
            <td class="gray">Kinshasa</td>
            <td class="gray">Kishinev</td>
            <td class="gray">Krakow</td>
            <td class="gray">Lima</td>
            <td class="gray">Lisbon</td>
        </tr>
        <tr>
            <td>Zagreb</td>
            <td>Kinshasa</td>
            <td>Kishinev</td>
            <td>Krakow</td>
            <td>Lima</td>
            <td>Lisbon</td>
        </tr>
        <tr>
            <td>Zagreb</td>
            <td>Kinshasa</td>
            <td>Kishinev</td>
            <td>Krakow</td>
            <td>Lima</td>
            <td>Lisbon</td>
        </tr>
        <tr>
            <td>Zagreb</td>
            <td>Kinshasa</td>
            <td>Kishinev</td>
            <td>Krakow</td>
            <td>Lima</td>
            <td>Lisbon</td>
        </tr>
        <tr>
            <td>London</td>
            <td>Los Angeles</td>
            <td>Luxembourg</td>
            <td>Madrid</td>
            <td>Manila</td>
            <td>Mexico</td>
        </tr>
        <tr>
            <td>Milan</td>
            <td>Montreal</td>
            <td>Mumbai</td>
            <td>Nairobi</td>
            <td>Nicosia</td>
            <td>New York</td>
        </tr>
        <tr>
            <td>Osaka</td>
            <td>Oslo</td>
            <td>Ottawa</td>
            <td>Paris</td>
            <td>Prague</td>
            <td>Riga</td>
        </tr>
        <tr>
            <td>Rome</td>
            <td>Rotterdam</td>
            <td>Salvador</td>
            <td>Samarkand</td>
            <td>Sydney</td>
            <td>Singapore</td>
        </tr>
        <tr>
            <td>Sofia</td>
            <td>Istanbul</td>
            <td>Taipei</td>
            <td>Tbilisi</td>
            <td>Zurich</td>
            <td>Chicago</td>
        </tr>
    </tbody>
    </table>
</div>

JS code:

$(document).ready(function(e)
{
var $table = $("#table");
var startW = 0;
var startW_neighbor = 0;
var td_index_neighbor = 0;
var ui_minColWidth = 0;

$table.find("tr:first th, tr:first td").resizable(
    {
        handles: 'e',
        minWidth: 30,
        start : function(event,ui)
        {
            ui_minColWidth = $(this).resizable( "option", "minWidth");
            startW = $(this).width();
            startW_neighbor = ui.element.parents('.table-wrapper').find('table#table').width();
        },
        stop: function (event, ui)
        {

        },
        resize: function (event, ui)
        {
            var td_width = ui.element.width();
            var table = ui.element.parents('.table-wrapper').find('table#table');
            var d = Number(td_width) - Number(ui.originalSize.width);

            td_width = Number(startW_neighbor) + Number(d) - 2;
            table.width(td_width);
        }
    });
});

In example: http://jsfiddle.net/djmartini/08p3Lqcm/


Solution

  • You're at the same time interfering with normal behavior of resizable and relying on it to calculate some values, so at some point it breaks. In that case you're calculating the width difference based on resizable behavior and applying it to change the behavior. But when resizable doesn't have any more place to resize, the difference is 0, hence nothing moves anymore. If you want to change the behavior of resizable, you could work with mouse position and micro manage the change in width. In that case you'll need to handle cases where your mouse moves, but nothing gets resized. This happens when columns cannot reduce size anymore. Something like this seems to work:

      $table.find("tr:first th, tr:first td").resizable({
            handles: 'e',
            minWidth: 30,
            start: function (event, ui) {
                ui_minColWidth = $(this).resizable("option", "minWidth");
                startW = $(this).width();
                td_width = startW;//this to check if width can change
                startW_neighbor = ui.element.parents('.table-wrapper').find('table#table').width();
                startMouseX = event.pageX;//to calculate mouse diffrence
            },
            stop: function (event, ui) {
    
            },
            resize: function (event, ui) {;
                var mouseDiff = event.pageX - startMouseX;//mouse mouvement
                //If the mouse is negative, it can resize only if column 
                //isn't at min width. When mouse positive resize always.
                if (ui.element.width() != td_width || mouseDiff > 0) {
                    td_width = ui.element.width();
    
                    var table = ui.element.parents('.table-wrapper').find('table#table');
    
                    var d = Number(td_width) - Number(ui.originalSize.width);
    
    
                    table_width = Number(startW_neighbor) + mouseDiff;
                    table.width(table_width);
    
                }
            }
        });
    

    fiddle: http://jsfiddle.net/wLbn5qjk/1/

    EDIT: You can push this logic and work with alsoResize, the result is a bit better:

    $table.find("tr:first th, tr:first td").resizable({
                handles: 'e',
                minWidth: 30,
                alsoResize: 'table',
                start: function (event, ui) {
                    ui_minColWidth = $(this).resizable("option", "minWidth");
                    startW = $(this).width();
                    td_width = ui.element.width();
                    startW_neighbor = ui.element.parents('.table-wrapper').find('table#table').width();
                    startMouseX = event.pageX;
                },
                stop: function (event, ui) {
    
                },
                resize: function (event, ui) {;
                    var mouseDiff = event.pageX - startMouseX;
                    if (ui.element.width() == td_width && mouseDiff < 0) {;
                        $('table').width(table_width);
                    }
                    td_width = ui.element.width();
                    table_width = $('table').width()
    
                }
            });
    

    http://jsfiddle.net/hrzj68wp/1/