jQuery multiple sortable tables - javascript

This question is best read with the fiddle open ;). I've got a tables inside a table. The inside grey tables need to be sorted in there own container. So the grey rows can only be moved in the grey table. But the white rows need to move there grey table with them. So you cannot move a white row or a grey table on there own, they are connected.
Here is my fiddle for what I got right now:
fiddle
options = {
helper: (event, ui) ->
children = ui.children()
view = ui.clone()
view.children().each (index) ->
$(#).width(children.eq(index).width())
return view
}
$('#ccc').find('tbody').sortable(options)
I've been cracking my head on this all day but I cannot figure out how to like a grey table to a white row.

With your current html structure this is quite difficult to achieve.
First of all you need two sortables (one to sort big chunks with white headers and second to sort inside grey tables).
You want to be able to move big tables with small ones inside but as these were all inside sibling elements (tr) it was not really possible (so I've added multiple <tbody>s in there).
Anyway here's the working fiddle: https://jsfiddle.net/9vmvjqm4/5/
You still need to exclude thead from being sortable. I don't like CoffeeScript so I left that (add items : ':not(thead)') to options (or sth like that, there are topics how to do that on stackOverflow).
Also, have a look at this: http://johnny.github.io/jquery-sortable/

Related

Remove a class based on width of a table

I am building a table with user selected columns. The user has 2 different view options. 1 with everything contained in the body with a scroll bar and 1 with everything expanded and sticky headers. The user can click a button to expand the table. I am using Jquery to add a class to the user table to expand it.
Normal Table -
Expanded Table -
The issue I am having is that if only a couple of columns are selected and the user is in expanded view it looks really strange.
What I would like to do is if the table's width is smaller that the body(white background) then remove the expanded class and revert to normal view.
I have tried
if (window.getComputedStyle(document.getElementById('userTable')).width <= window.getComputedStyle(document.getElementsByClassName('siteBody')[0]).width) {
$('#userTable').removeClass('isExpanded');
$('.siteBody').removeClass('expandContainer');
}
Any help would be awesome! Thanks in advance and stay safe.
I think your code should work with this small change:
if (window.getComputedStyle(document.getElementById('userTable')).width <= window.getComputedStyle(document.getElementsByClassName('siteBody')[0]).width) {
$("#userTable").removeClass('isExpanded');
$('.siteBody').removeClass('expandContainer');
}
You have to put the jQuery selector #userTable within quotes, otherwise jQuery would not be able to figure out which element to perform the removeClass action for.

How can I reliably track the bottom of a dynamically updating HTML table?

I've read similar questions on SO about how to do this, but my setup is slightly different and the solutions proposed on those questions, have produced a strange result.
On my page I have a DIV, whose height is fixed which I've given the ID table-container. As the ID suggests, it contains a table (id="myTable"), which has a row appended to the bottom every few seconds using JavaScript. The effect I am trying to achieve is that as the table grows in size, and beyond the size of the table container, the table-container DIV will scroll down so that the last row is always visible.
I've used the following JavaScript to achieve this:
$('#table-container').scrollTop ($('#myTable tr:last').position().top);
This works fine for the first 20 or so row additions, but after that it loses track of the bottom row completely. I can't figure out why it starts off so well, and then messes up.
I've created a JSFiddle which illustrates the problem.
https://jsfiddle.net/crickes/meqzf4g1/16/
Why can't you just do $('#table-container').scrollTop ($('#myTable').height() ); ?

script.aculo.us Sortable with delimiters

I'd like to use Script.aculo.us Sortable to sort elements of a horizontal list (let's say some little boxes). The problem is that these boxes have to be separated from each other by another boxes of a different kind, which shouldn't be movable, but they have to be always there in between these sortable boxes, one between each pair of movable boxes.
Let's mark movable boxes by [M] and unmovable delimiters by [D]. Then the situation is as follows:
[M1][D][M2][D][M3][D][M4]
Now, when a user drags, for example, the [M2] movable box to the position of [M4], the situation should become as follows:
[M1][D][M3][D][M4][D][M2]
and when he moves the [M4] movable box into the [M2] position, the situation should be like below:
[M1][D][M3][D][M4][D][M2]
But the following settings are forbidden:
[M1][D][M3][M4][D][D][M2]
[M1][D][M4][D][M2][M3][D]
that is, no two delimiters should be near each other, and no delimiter should be left in front or at the end of the sequence.
How can I make something like that using Script.aculo.us Sortables? Is it possible at all?
I think I've figured a way to make it: It could be done by CSS rules.
I simply set the following rule for my list element:
li:before {
content: "[D]"; /* my delimiter */
}
li:first-child:before {
content: "";
}
This makes that all list elements but first will have [D] text attached before them in their container.
Now when I move around my list items (Draggables of a Sortable), the CSS keeps these delimiters updated: when I drag an element to the beginning of the list, it gains :fisrt-child pseudo-class, so it appears without the delimiter. At any other place in the list it lacks this pseudo-class, so the delimiter appears in front of it.
So looks like the problem is solved.

How to create a div that apears below a table row

Like in this demo
http://demos.telerik.com/aspnet-ajax/grid/examples/hierarchy/nestedviewtemplate/defaultcs.aspx
Except In this demo it's being added as an additional row. (click one of the ">" things and check the page source, it added a new row to the table). If I used this strategy, It would be difficult to sort, using a standard Jquery plugin, like table sorter.
Ideas?
went away and did some thinking about my comment, about finding row height and overlaying the div.. it's so close, but I'm no jQuery whiz, so perhaps someone can help tidy this up
I have it showing/hiding the div in the right position IF the div/row is closed before the next one is opened.. but if you click button 2 while div one is opened is doesn't get the right top position (it gets the position the row was at after being expanded not the original row position), I'm sure there must be a way to get that position while the rows are not expanded and store it??
anyway have at it.. I know it's very long-winded, variable wise, because I can only apply the CSS logic - I don't know enough about js or jquery functions and storing.. also I thought if I explained how I got to my variables and which ones were needed it might help those who do know how to make this better ;)
the input/buttons have no text but they're the click trigger
position() is maybe not the right thing to use, it needs for the div to be able to find the original position of the related row (inside table-wrap div?)
?
here's the Example
You can't. A <div> is not a valid child of <table> or <tbody>. You'll need to use a <tr>.
I don't know how that plugin works, but perhaps there's support for sorting multiple <tbody> elements, which would allow you to group your sets of rows.
That div is inside a td which is hidden until you click the >
Here is a demo: http://jsfiddle.net/maniator/7RLhL/1/
I don't know if you can do that. Putting a tag like inside a table isn't valid (X)HTML, and so probably won't give you the effect you were looking for
If you look at that demo, they're using a second <tr> below the first one with a <td> that spans most of the columns.
You can embed a detail table inside a table cell under each description cell which will be not visible and make it visible on tr click:
http://jsfiddle.net/bouillard/QmK4Z/
As mentioned in other answers, we cannot add a div inside the table without it being in a TD. However, there might be something that can be done to place the div over the row. To have the effect of the div being shown as inside the row, we could increase the height of the row while the div is being shown. Here is the very basic demo. Since the div is not really inside the table, if the table happens to sort, you would probably want to hide the div or relocate it to the new TR location. It would present its own challenges but you could play with it and see if it works for you.
I have an idea. It's really ugly. The only think I could think of doing is before sorting the rows, detach the additional rows(with the div) and use JQuery to store it somehow. Then after the sorting is done reattach the rows(with the div) in the right place(s).
That could, no I should say WILL, get ugly really fast, especially with paging and filtering...
You can use getBoundingClientRect to get the element's position and then set those values to a div css position left and top. Must also take into account the window scroll as getBoundingClientRect will return it relative to the window viewport.
The following example will locate a div named #tooltip under any tr row when hovering over it. I'm using jQuery for convenience but you can translate to vanilla JS easily.
<script>
$("tr").hover(
function () {
const row = this;
const bounds = row.getBoundingClientRect();
tooltip.css({
left: bounds.left + window.scrollX,
top: bounds.bottom + window.scrollY
});
},
function () {}
);
</script>
<table> ... </table>
<div id="#tooltip"> ... </div>
Be sure to make div positioning absolute and also to skip pointer events or the div will block hover events from reaching the table elements.
<style>
#tooltip {
position: absolute;
pointer-events: none;
}
</style>
Good luck!

How do I stop dynamic JavaScript tables from moving other elements around when I add rows to the table?

I have an HTML page that has static tables placed in the page because these never change. I have a main table that houses all the elements to keep everything aligned. This is probably what is causing the problem.
I have the main table with 2 tables within it. Each row in the first inner table, called dropDownTable, usually has up to about 10 rows. dropDownTable is in the following format:
td1: text; td2: select element; td3: text (this part is dynamically updated).
The second table, called showDetails, uses the options from the select element in the rows in dropDownTable to query a database (onchange attribute), get some information and then display each element that is found. The response from the database is up to 150 character strings, usually shorter though.The user then clicks an element in the details that updates the third column in the dropDownTable.
I'm not really sure if this is a JavaScript or HTML problem but each time the showDetails table updates, it pushes the bottom of the main table down. There are 2 buttons at the bottom of the main table that move each time the user changes the select in the second column of dropDownTable.
It very aesthetically displeasing.
Any ideas would be greatly appreciated. I have had this problem before but with other elements.
are you adding more content, thus making the table taller?
I cant quite understand what your problem is exactly, but:
td
{
vertical-align: top;
}
will keep everything in the top of its cell, rather than centering to the tallest column.
You shouldnt be using tables for layout, tables are for tabular data. have a read of this
if you want to fix the heght of the table, do:
table
{
height: 400px; /* replace with your heihgt */
}

Categories

Resources