最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jQuery sortable keep table's width - Stack Overflow

programmeradmin4浏览0评论

Couldn't find a simple solution for jquery's sortable to keep width of table during dragging element, forcePlaceholderSize is not actually working this time, if table have some large element - if i start dragging it then the table resized to still-in-table element's max width, so here is what I've done:

jQuery("#sortable1").sortable({
    items: "tbody:not([not-sortable])",
    cursor: "move",
    zIndex: 9999,
    start: function (event, ui) {
        var colW = jQuery(".faq_glyph_owner").width();
        self.textWidth = ui.item.innerWidth() - colW * 3;
        jQuery(".faq_text").width(self.textWidth);
        jQuery("#sortable1").css("table-layout", "fixed");
        ui.item.find("div").parent().width(self.textWidth + colW);
    },
    stop: function (event, ui) {
        jQuery("#sortable1").css("table-layout", "auto");
    }
});

So i'm generally just counting size as it supposed to be and apply fixed layout to table, here is sample of this with table. So my question is : Is there any built-in ways to keep table width during sorting, as if dragged element is still inside table? Please note that i do not want to keep table's layout fixed.

P.S. please ignore 'jQuery', we just still have legacy prototype code that interferes with it

Couldn't find a simple solution for jquery's sortable to keep width of table during dragging element, forcePlaceholderSize is not actually working this time, if table have some large element - if i start dragging it then the table resized to still-in-table element's max width, so here is what I've done:

jQuery("#sortable1").sortable({
    items: "tbody:not([not-sortable])",
    cursor: "move",
    zIndex: 9999,
    start: function (event, ui) {
        var colW = jQuery(".faq_glyph_owner").width();
        self.textWidth = ui.item.innerWidth() - colW * 3;
        jQuery(".faq_text").width(self.textWidth);
        jQuery("#sortable1").css("table-layout", "fixed");
        ui.item.find("div").parent().width(self.textWidth + colW);
    },
    stop: function (event, ui) {
        jQuery("#sortable1").css("table-layout", "auto");
    }
});

So i'm generally just counting size as it supposed to be and apply fixed layout to table, here is sample of this with table. So my question is : Is there any built-in ways to keep table width during sorting, as if dragged element is still inside table? Please note that i do not want to keep table's layout fixed.

P.S. please ignore 'jQuery', we just still have legacy prototype code that interferes with it

Share Improve this question edited Feb 15, 2017 at 7:08 Dmytro Grynets asked Feb 14, 2017 at 18:24 Dmytro GrynetsDmytro Grynets 95311 silver badges29 bronze badges 1
  • 1 What you already have is the most straightforward way of achieving this behaviour. The forcePlaceholderSize option will only set the placeholder's size if it's non-visible otherwise (ie. it's a 0-width rectangle, which, here, it isn't). If you want to be thorough, create a new widget, inheriting from sortable, and write a custom placeholder, but that's a lot of additional work for a similar effect – blgt Commented Feb 22, 2017 at 15:11
Add a comment  | 

5 Answers 5

Reset to default 8
var fixHelper = function(e, ui) {  
  ui.children().each(function() {  
  console.log(e);
    $(this).width($(this).width());  
  });  
  return ui;  
};

$("#sortable1 tbody").sortable({  
    helper: fixHelper  
}).disableSelection();

JSfiddle

Source article

How about this:

$("#sortable1").sortable({
        items: "tbody:not([not-sortable])",
        helper: 'clone',
        cursor: "move",
        zIndex: 9999,
        start: function (event, ui) {
            $(ui.item[0]).show().css('opacity','0');
        },
        stop: function (event, ui) {
            $(ui.item[0]).css('opacity','1');
        }
    });

You are basically cloning the element and instead of hiding it whilst moving, you just apply opacity of 0 and then applying opacity of 1 once dropped. I didn't really have time to test it.

This is the code I use for this. I create a helper function that gets the height and width of everything in the row and then explicitly sets it to those heights and widths, plus adds a row back in as a placeholder.

var fixHelper = function (e, ui) {
    ui.children().each(function () {
        if ($(this).children().length > 0) {
            fixHelper(e, $(this));
        }
        if(parseInt($(this).css("margin-left")) != 0)
            $(this).css("margin-left", $(this).css("margin-left"));

        if (parseInt($(this).css("margin-right")) != 0)
            $(this).css("margin-right", $(this).css("margin-right"));

        $(this).width($(this).realWidth(true));
        $(this).height($(this).realHeight(true));
    });

    ui.height(ui.realHeight());
    return ui;
};

var unfixHelper = function (ui) {
    ui.children().each(function () {
        if ($(this).children().length > 0) {
            unfixHelper($(this));
        }
        $(this).css("margin-left", "");
        $(this).css("margin-right", "");
        $(this).css("width", "");
        $(this).css("height", "");
    });
    ui.css("height", "");
};


var sortableOptions = new Object({
    items: "tbody:not([not-sortable])",
    cursor: "move",
    zIndex: 9999,
    helper: fixHelper,
    start: function (e, ui) {
        ui.placeholder.height(ui.item.height());
        ui.placeholder.html("<td colspan=\"10\">&nbsp;</td>");
    },
    stop: function (e, ui) {
        unfixHelper(ui.item);
        ui.placeholder.html("");
    }   
});

jQuery("#sortable1").sortable(sortableOptions);

Another file (real-dimensions.js):

$.fn.realWidth = function (inner) {
    var $t = $(this);
    var rect = this[0].getBoundingClientRect();

    var width;
    if (rect.width) {
        // `width` is available for IE9+
        width = rect.width;

    } else {
        // Calculate width for IE8 and below
        width = rect.right - rect.left;
    }

    if (inner)
        width -= parseInt($t.css("padding-left")) + parseInt($t.css("padding-right"));

    return width;
}

$.fn.realHeight = function (inner) {
    var $t = $(this);
    var rect = this[0].getBoundingClientRect();

    var height;
    if (rect.height) {
        // `height` is available for IE9+
        height = rect.height;
    } else {
        // Calculate height for IE8 and below
        height = rect.top - rect.bottom;
    }

    if (inner)
        height -= parseInt($t.css("padding-top")) + parseInt($t.css("padding-bottom"));

    return height;
}

There is an option called helper in the sortable widget. Its purpose is to add some behaviour to the dragging display action. The relevant part of the modification is:

jQuery('#sortable1').sortable({
    helper: fixedWidth
});

function fixedWidth(e, ui) {
    var max_w = 0;
    // get the max width from all the children
    ui.children().each(function() {
        var w = $(this).width();
        if (w > max_w) max_w = w;
    });
    // set the width of the table to be the max
    $('#sortable1').width(max_w);
    return ui; 
}

A full implementation can be found in this JSFiddle. I got inspiration from this blog.

Also, if you mind my opinion, I would build this structure in a simpler way, using <ul> instead of <table>. Like this. You only have to style the <ul> in order to have a fixed width.

  1. add colgroup to table tag
    <colgroup>
       <col style="width: 0%"/>
       <col style="width: 0%"/>
       <col style="width: 100%"/>
       <col style="width: 0%"/>
    </colgroup>
  1. set width in 'table'
    table {
      border-collapse : collapse;
      width: 550px;
    }
发布评论

评论列表(0)

  1. 暂无评论