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 |5 Answers
Reset to default 8var 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\"> </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.
- add colgroup to table tag
<colgroup>
<col style="width: 0%"/>
<col style="width: 0%"/>
<col style="width: 100%"/>
<col style="width: 0%"/>
</colgroup>
- set width in 'table'
table {
border-collapse : collapse;
width: 550px;
}
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