When dragging a row with hidden fields, the thead and tbody sections in JQueryUI sortable shrink

I am working with a table that contains various rows and fields. In one row, I have two fields set to display:none;. When I drag this row, it creates a lateral padding effect in the <tbody> and the <thead>, rather than shrinking the table itself.

In the following JsFiddle, you can see that the first row does not function correctly, while the second row, which only has one field with display:none;, works as expected.

If you have any questions, feel free to ask.

Example of Errors: https://i.sstatic.net/Sutpz.png

Table Behavior During Dragging:

https://i.sstatic.net/mJhHv.png

Initially, I attempted to solve the issue by counting the number of <td> elements with the class .hidden-td (the class with display: none;) and identifying the element with the class .placeholder-style (the class associated with the <tr> generated during dragging). However, this approach did not work as expected.

To determine the number of fields with the class .hidden-td, I used the following line of code:

var numcells = $('.hidden-td').length;

Issue:

In one row, I have 9 elements, while in another, there are only 8. Within my function start(), I hide a single column in the placeholder. Consequently, when I drag the first row, one column remains without the .hidden-td class, resulting in an empty space at the end of the columns.

How can I resolve this problem?

Visit the JSFiddle for reference.

Answer №1

After facing challenges with the sortable plugin myself over the past few days, I have identified some key changes that need to be implemented:

  1. Include the helper function to ensure the correct sizes are created on the draggable object for accurate sizing.

  2. In the start function, merge the item HTML with the placeholder HTML to maintain identical placeholders.

Code:

$("#tbodyproject").sortable({
    items: "> tr",
    appendTo: "parent",
    helper: "clone",
    placeholder: "placeholder-style",
    start: function(event, ui) {
      $(this).find('.placeholder-style td:nth-child(2)').addClass('hidden-td')

      //copy item html to placeholder html

      ui.placeholder.html(ui.item.html());

      //hide the items but keep the height/width. 
      ui.placeholder.css('visibility', 'hidden');
    },
    stop: function(event, ui) {
        ui.item.css('display', '')
    },

    //add helper function to keep draggable object the same width
    helper: function(e, tr)
    {
        var $originals = tr.children();
        var $helper = tr.clone();
        $helper.children().each(function(index)
        {
        // Set helper cell sizes to match the original sizes
        $(this).width($originals.eq(index).width());
        });
        return $helper;
    },
    update: function( event, ui ) {
        let newOrder = $(this).sortable('toArray');
        $.ajax({
            type: "POST",
            url:'/admin/projects/updateOrder',
            data: {ids: newOrder}
        })
       .done(function( msg ) {
        location.reload();        
       });
    }
}).disableSelection();

Check out the updated fiddle here

Answer №2

Upon creation of the placeholder, it will generate an empty row with a number of cells equal to the number in the row.

You have applied the class hidden-td to the second child, thus hiding one cell. While this works for rows 2 and above, it does not fit the first row where there is an additional cell. Check out the placeholder for the second row:

<td colspan="1">&nbsp;</td><td colspan="1" class="hidden-td">&nbsp;</td><td colspan="1">&nbsp;</td><td colspan="1">&nbsp;</td><td colspan="1">&nbsp;</td><td colspan="1">&nbsp;</td><td colspan="1">&nbsp;</td><td colspan="1">&nbsp;</td>

For the first row:

<td colspan="1">&nbsp;</td><td colspan="1" class="hidden-td">&nbsp;</td><td colspan="1">&nbsp;</td><td colspan="1">&nbsp;</td><td colspan="1">&nbsp;</td><td colspan="1">&nbsp;</td><td colspan="1">&nbsp;</td><td colspan="1">&nbsp;</td><td colspan="1">&nbsp;</td>

To rectify this issue, you can hide all cells in the placeholder and only display the necessary ones using CSS:

.placeholder-style td {
  display: none;
}

.placeholder-style td:nth-child(-n+7) {
  display: table-cell;
}

See the updated result here: https://jsfiddle.net/3g3bt80e/1/

Answer №3

If you're looking to implement a sorting functionality for your project, consider using the code snippet provided below.

$("#tabs").tabs();

$("#tbodyproject").sortable({
    items: "> tr",
    appendTo: "parent",
    helper: "clone",
    placeholder: "placeholder-style",
    start: function(event, ui) {
      ui.helper.css('display', 'table');
     // console.log(ui.placeholder.html())
    },
    stop: function(event, ui) {
        ui.item.css('display', '')
    },
    update: function( event, ui ) {
        let newOrder = $(this).sortable('toArray');
        $.ajax({
            type: "POST",
            url:'/admin/projects/updateOrder',
            data: {ids: newOrder}
        })
       .done(function( msg ) {
        location.reload();        
       });
    }
}).disableSelection();
img {
  width: 100px;
}
.hidden-td{
  display:none;
}
.table{
  background-color:green;
  border:0;
  width:100%;
}
.trdrag{
  background-color:yellow;
}
.trdrag.ui-sortable-handle td.tdslug, .trdrag.ui-sortable-handle td.tdslug img{
  text-align:center;
  align-items:center;
  display: table-cell;
  justify-content: center;
}
.trdrag.ui-sortable-handle td.tdslug{
  white-space:normal;
  word-wrap: break-word;
}
.trdrag.ui-sortable-handle td.tdslug img{
  padding-left:1rem;
}
.trdrag.ui-sortable-handle {
  text-align:center;
  align-items:center;
  display: table-row;
  justify-content: center;
  width:100%;
  margin-left: .3rem;
}
  
.thcenter{
  background-color:grey !important;
}
.ui-sortable-helper {
  left:0px!important;
}
.idrow{
  width:5%;
}
.tdvisible{
  width:5%;
}
.tdslug{
  width:10%;
}
.tdimg{
  width:15%;
}
.tdorder{
  width:20%;
}
.tdacciones{
  width:40%;
}

.placeholder-style td {
  display: none;
}

.placeholder-style td:nth-child(-n+7) {
  display: table-cell;
}
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
<script
  src="https://code.jquery.com/jquery-3.2.1.min.js"
  integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
  crossorigin="anonymous"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<div id="tabs">
        <div class="col-md-12">
            <div id="table1">
              <table class="table">
                <thead>
                  <tr>
                    <th class="thcenter">ID</th>
                    <th class="thcenter">Visible</th>
                    <th class="thcenter">Nombre</th>
                    <th class="thcenter">Header</th>
                    <th class="thcenter">Home</th>
                    <th class="thcenter">Orden</th>
                    <th class="thcenter"><span class="glyphicon glyphicon-cog"></span>Acciones</th>
                  </tr>
                </thead>
                <tbody id="tbodyproject"> 
                   <!-- Inserted rows and columns here -->
                </tbody>
              </table>
              <br><br>
            </div>
        </div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Refresh Angular component upon navigation

I have set up routes for my module: const routes: Routes = [ { path: ":level1/:level2/:level3", component: CategoriesComponent }, { path: ":level1/:level2", component: CategoriesComponent}, { path: ":level1", component: ...

Get a confirmation from Ajax, PHP, and Mysql after successfully inserting data

Here is my AJAX call to submit a form to a MySQL database using a PHP file on a server: <script type"text/javascript"> $(document).ready(function(){ $("form#submit").submit(function() { // storing form values and sending via AJAX var fn ...

What is the most effective method for organizing and retrieving information on numerous topics?

Recently, I have been working on a simple chat bot project using JavaScript for the purpose of practice and enjoyment. My intention is to build upon this project and optimize it as I progress. One issue I have encountered is the inefficiency of the search ...

Can an onSnapshot event be set up for an array in order to track changes?

In my system, each user is associated with multiple groups. Each user's group membership is stored as an array within their user document. Additionally, there is a tasks collection where each task contains an array of authorizedGroups that correspond ...

Embedding a for loop within a function

My goal is to halt a for loop once it reaches a specific input value. I managed to accomplish this task when executing the loop outside of a function. For instance, if I set the input variable to 'not leak', I want the loop to stop at 'not&a ...

Angular error: Trying to assign a value of type ArrayBuffer to a string type

Is there a way to display a preview of a selected image before uploading it to the server? Here is an example in HTML: <div id="drop_zone" (drop)="dropHandler($event)" (dragover)="onDragover($event)"> <p>drag one or more files to ...

Changing field names in Mongoose before inserting them into the database

I have a database schema set up as follows const UserSchema = new Schema({ first_name: "john", last_name: "doe" }) When data is received on my API route, it looks like this in the response body request.body = { firstName: "joh ...

Customize menu items in Angular ui-grid when right clicking on a cell

Seeking help with Angular UI-grid for a specific feature needed: I want to display a custom menu when a user right-clicks on a specific 'CELL/Column' in the grid, such as 'B' in the example image below. When the user right-clicks, the ...

Using query strings to manipulate the URL of an iframe and add additional information

I am facing a challenge with integrating my legacy perl application into an MVC application. I have set up a structure where the legacy application is loaded into an iframe within default.aspx, but I need to capture the URL of each page within the iframe a ...

Adding an object array to a new array - Step by step guide

I am working with an array of states const states = [{id:1,name:"New York",cities:[...]},{id:2,name:"California",cities:[...]}] My goal is to extract all cities and store them in a new array using methods ... const cities = [] this.s ...

The .click function in jQuery ceases to function after being utilized once

I've encountered an issue with my .click jQuery function. The desired behavior is that when I click the button, one div should be hidden (display:none) and another div should be shown (display:block). This works as expected the first time the button i ...

Synchronizing scrolling across multiple scroll bars with jQuery

I have divided a lengthy table into smaller tables to incorporate scrollbars at intervals along the table. I currently have a script that syncs the top scrollbar with the one below the next table. However, is there a way to connect all the tables so that t ...

Grouping Columns in Firefox and Chrome

Exploring the functionality of the <colgroup> tag in a table with 5 columns and a style attribute. Despite my efforts, I could not get it to function properly on Firefox 3.6/Chrome 5. This led me to search for answers on the w3c website. After exa ...

What is causing the failure in retrieving the smallest number from this array?

The maximum value should be 9.99, and the minimum value should be 6.88 let arr = [["2019","00","01", 9.99], ["2018","00","01", 9.32], ["2017","00","01", 6.88]] let max = Math.max(Number(...arr.map((o) => { return o[3] }))); //9.99 let min = Math.mi ...

Guide on transporting PNG files over the boundary

I am working with two specific css commands. code h1 { background: #000000; border-radius: 6px; color: #fff; display: block; font: 40px/60px "Sans", Inconsolata, "Lucida Console", Terminal, "Courier New", Courier; padding: 40px 40px; text-align: center; ...

How can I use JQuery to sum up the numbers within div elements?

Is there a way to automatically number the generated blocks? For example, the first block would display "1", the second "2" and so on. Below is my current code. Simply input the desired number of blocks in the input field. <!DOCTYPE html> <html ...

Transfer information to a database upon clicking a link, all without the need to refresh the page

Is it possible to send data to a database without needing to refresh the page when clicking on a link? I am currently using PHP and MySQL for my project. ...

The Bootstrap Carousel is failing to respond as expected

Having some trouble incorporating a carousel on my landing page. I can see the first image, but the carousel isn't sliding to the next one. I copied the template from bootstrap-carousel, but even the data-bs-interval attribute isn't responding. M ...

Exploring the Behavior of Row Inside Card in Bootstrap 4 Alpha 6

In my usage of bootstrap 4 alpha 6, I encountered an unexpected issue while incorporating a grid within the body of a card without the card-block class. <div class="container"> <h5> The fundamental component of a card is the .card-bloc ...

Changing the direction of the submenu to the left instead of the right

My Bootstrap 4 menu has a submenu that appears to the right of the main menu. However, since the menu is positioned on the far right of the screen, it gets cut off on the right side. I'm looking for a way to make the submenu appear on the left side o ...