jQuery UI Sortable - Eliminate placeholder once item is has been dropped

Trying to implement a nested sortable feature, and while it's mostly working, there's one little issue bothering me.

I'd like the placeholder to only disappear after I release the dragged item (on mouseup), but I'm struggling to achieve this.

The reason for this is that when sorting downwards, the removal of the placeholder affects the parent's height, causing a minor bug. You can see an example of this in action on this JSFiddle.

HTML

<div class="container">     
    <h1>Menu</h1>
    <ul class="list-group striped nest">
        <li class="list-group-item">Home <ul class="list-group striped nest"></ul></li>
        <li class="list-group-item">About <ul class="list-group striped nest></ul></li>
        <li class="list-group-item">
            Services
            <ul class="list-group striped nest">
                <li class="list-group-item">Design <ul class="list-group striped nest></ul>&tl;/li>
                <li class="list-group-item">Programming<ul class="list-group striped nest></ul>&tl;/li>
            </ul>
        </li>
        <li class="list-group-item">Contact <ul class="list-group striped nest></ul>&tl;/li>
        <li class="list-group-item">
            <button class="btn btn-sm btn-default" data-toggle="collapse" data-target="#collapseExample">
                <span class="glyphicon glyphicon-chevron-down" aria-hidden="true"></span>
            </button>

            Empty nestable

            <ul id="collapseExample" class="collapse list-group striped nest" aria-expanded="false"></ul>
        </li>
    </ul>
</div>

CSS

ul.nest {
    min-height: 42px;
    margin: 0;
}

ul.nest:empty {
    border: 1px dashed #ddd;
    border-radius: 3px;
}

ul.nest li:hover {
    cursor: pointer;
}

ul.nest:first-child {
    margin-top: 5px;
}

.bg-info {
    min-height: 42px;
    list-style: none;
}

.striped li:nth-child(even) {
    background-color: #f9f9f9;
}

Script

$(function() {

  $('.nest').sortable({
    connectWith: ".nest",
    items: "> li",
    axis: "y",
    cursor: "row-resize",
    opacity: 0.5,
    placeholder: "bg-info"
  }).disableSelection();

});

Answer №1

When you use the draggable feature on the li.list-group-item(selected tag), the sortable plugin adds another tag li.ui-sortable-placeholder to act as an empty placeholder that moves along with the selected tag as you drag it.

As per your request:

I would like the placeholder to disappear only after I release the currently dragged item (on mouseup), but I am unsure of how to accomplish this.

To achieve this, I have included an additional placeholder named $bgPlaceholder in the code below. This placeholder is added after the selected tag when you move it, and gets removed when you drop the item.

Additionally, a class .selected-tag is assigned to the selected tag.

$(function() {

var $bgPlaceholder = '<li class="bg-placeholder"></li>';
var draggable = false;
var isInMove = false;
$('.nest').sortable({
    connectWith: ".nest",
    items: "> li",
    axis: "y",
    cursor: "row-resize",
    opacity: 0.5
}).disableSelection();

$(".nest").on("mousedown", "li.list-group-item", function() {
    draggable = true;
    var $this = $(this);
    $this.addClass("selected-tag");
});

$(".nest").on("mousemove", "li.list-group-item", function() {
    if (draggable && !isInMove) {
        isInMove = true;
        var $this = $(this);
        $($bgPlaceholder).insertAfter($this);
    }
});

$(".nest").on("mouseup", "li.list-group-item", function() {
    draggable = false;
    isInMove = false;
    var $this = $(this);
    $this.removeClass("selected-tag");
    $(".nest").find(".bg-placeholder").remove();
});

});

Also, there are certain CSS rules:

li.ui-sortable-placeholder will be hidden when placed next to either .selected-tag or .bg-placeholder. This ensures that unnecessary empty placeholders do not appear near the selected tag.

.bg-placeholder {
min-height: 42px;
list-style: none;
background-color: red!important;
}

.bg-placeholder + .ui-sortable-placeholder {
display: none;
}

.selected-tag + .ui-sortable-placeholder {
display: none;
}

Here is an example on JSFiddle : JSFiddle

Answer №2

In order to achieve the desired result, we must enable draggable and sortable functions for both List Items and Header separately.

$('.nest:has(li)').sortable({
   connectWith: ".nest",
   items: "> li",
   axis: "y",
   cursor: "row-resize",
   opacity: 0.5,
   placeholder: "bg-info",
 }).disableSelection();

$('.nest:has(li)>li').draggable({       
    tolerance:"pointer",
    refreshPositions: true ,
    opacity:.4,
});

Additionally, it is necessary to include properties like connectToSortable: '.nest' and helper: 'clone' within the draggable function to implement sorting functionality on the draggable list item and clone the item after dragging. The cloned item will remain in place.

helper : 'clone',
connectToSortable: '.nest',

Once the sortable content has been applied through the draggable function, the clone needs to be removed. This can be achieved by adding the receive functionality in the sortable function.

receive: function (event, ui) {
    ui.item.remove();
}

$(function() {

  $('.nest:has(li)').sortable({
    connectWith: ".nest",
    items: "> li",
    axis: "y",
    cursor: "row-resize",
    opacity: 0.5,
    placeholder: "bg-info",
    receive: function(event, ui) {
      ui.item.remove();
    }
  }).disableSelection();

  $('.nest:has(li)>li').draggable({
    tolerance: "pointer",
    helper: 'clone',
    refreshPositions: true,
    opacity: .4,
    connectToSortable: '.nest',
  });
});
ul.nest {
  min-height: 42px;
  margin: 0;
}
ul.nest:empty {
  border: 1px dashed #ddd;
  border-radius: 3px;
}
ul.nest li:hover {
  cursor: pointer;
}
ul.nest:first-child {
  margin-top: 5px;
}
.bg-info {
  min-height: 42px;
  list-style: none;
}
.striped li:nth-child(even) {
  background-color: #f9f9f9;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
<div class="container">
  <h1>Menu</h1>
  <ul class="list-group striped nest">
    <li class="list-group-item">Home
      <ul class="list-group striped nest"></ul>
    </li>
    <li class="list-group-item">About
      <ul class="list-group striped nest"></ul>
    </li>
    <li class="list-group-item">
      Services
      <ul class="list-group striped nest">
        <li class="list-group-item">Design
          <ul class="list-group striped nest"></ul>
        </li>
        <li class="list-group-item">Programming
          <ul class="list-group striped nest"></ul>
        </li>
      </ul>
    </li>
    <li class="list-group-item">Contact
      <ul class="list-group striped nest"></ul>
    </li>
    <li class="list-group-item">
      <button class="btn btn-sm btn-default" data-toggle="collapse" data-target="#collapseExample">
        <span class="glyphicon glyphicon-chevron-down" aria-hidden="true"></span>
      </button>

      Empty nestable

      <ul id="collapseExample" class="collapse list-group striped nest" aria-expanded="false"></ul>
    </li>
  </ul>
</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

What are the best ways to utilize dynamic CSS on a smartphone browser for optimal performance?

Struggling to optimize my web application for mobile devices, I've encountered challenges with consistent display across different browsers. My idea is to utilize device capability detection to adjust widths and font sizes dynamically based on screen ...

Is it possible to customize the appearance of elements that are disabled using the [disabled] attribute in Angular 8?

I currently have a button on my website that triggers a form: <button (click)="create()" *ngIf="data.new" [disabled]="!dataForm.valid" color="primary" mat-raised-button> Go </button> Under specific conditions, this button disables all fiel ...

``Stylishly Designed CSS Tabs inspired by Google Chrome's Modern

Utilizing Material UI Tabs in React to create curved tabs resembling those seen in Google Chrome. The design requires the parent element to have a bottom border that extends across the entire row, appearing on both the tabs and other content on the right. ...

Why is it that when the form is submitted, the value becomes unclear?

This is a form with HTML and TypeScript code that I am working on. <form> <div class="form-group"> <input class="form-control" ([ngModel])="login" placeholder="Login" required> </div> <div class="form-group"> &l ...

Choosing the right framework for implementing push notifications can be a critical decision. Should

I am currently working on a Java application that requires the server to send push notifications to the client every one second. To achieve this, I am using HTML5 server-sent events for one-way communication from the server to the client. However, my conce ...

What are the steps to effectively incorporate Jquery Ajax in a success function?

Is there a way to successfully implement Jquery Ajax in this scenario? When I click on Getcat it works, but when I click on Cat 1, Cat 2... it fails. Why is that? I'm still learning the basics here, any help would be appreciated. Thanks! This is ca ...

Learn how to implement JavaScript code that allows a video to start playing only upon clicking a specific button

Within the confines of a div lies a <video autoplay> <source src='myvid'> </video>. This div initially has a display ='none' setting in its CSS. Upon receiving a click event, the display property changes from none to b ...

Choosing a row in a table with ASP.NET by utilizing jQuery on click

After setting up a table in ASP.NET with the feature to select individual rows using a link at the end of each row, I have been able to successfully implement it. The process involves setting a value at the top of the view and then dynamically changing the ...

Using an HTML and PHP form to store data in the database, it currently defaults to entering "0000-00-00" for the date instead of the date chosen

Recently, I encountered an issue with inserting date information from an HTML form into a database using a PHP file. The HTML form included a date field with an HTML5 datepicker that was supposed to simplify date selection. However, despite adjusting the P ...

Permanently erasing input values in an HTML textbox with the power of jQuery

I am working with a form field for the user name: <%: Html.TextBoxFor(model=>model.UserName)%>. I need to check if the user name is available or not. If it's unavailable, then I want to clear the TextBox. I tried using the query $("#UserName" ...

Vanilla JavaScript error: Unable to access property

I am working on implementing a header with a logo and navigation that includes a menu toggle link for smaller viewports. My goal is to achieve this using Vanilla JS instead of jQuery. However, when I click on the menu toggle link, I encounter the followin ...

Object is not compliant with HTMLInputElement interface and cannot execute 'stepUp'

Currently, I am facing an issue with passing the selected value from a dropdown list of countries to a PHP file using AJAX. The goal is to take this value and then transfer it to another input field identified by the ID #tele. Here is the gist of my code: ...

On a button click, the div's height will increase and then decrease when the same button is clicked again

I need help with a div that has its height set to 0px initially, and I want it to increase to 300px when a button is clicked. When the button is clicked again, I want the height to go back to 0px. Here's the CSS code: nav{ height:0px; overfl ...

Accessing Facebook through Login with only a button visible

I need help with checking the user's login status on Facebook. I have implemented the code provided by Facebook, but all I see is the login button. How can I determine if the user is already logged in or not? function testAPI() { console.log(&apo ...

Tips on creating a hover-activated drop-down submenu

I'm having trouble getting the submenu to display correctly when hovering over parent list items. It's displaying in a strange way, is there a standard method for doing this? I can't seem to make any code adjustments work with my current set ...

What is the best way to implement an alert box in MVC without triggering a page redirection?

I have a specific requirement to display a custom alert box in order to confirm the user's intention to delete an item. Once the item is deleted, another alert box should appear confirming that the deletion was successful, prompting the user to click ...

When making an Ajax call to an ASP.NET MVC controller, the Access-Control-Allow-Origin error is commonly encountered

Currently, I am facing an issue with my ajax call in the view script. The problem arises when attempting to retrieve data from a controller action within the same website, resulting in a Cross-Origin error message. The JavaScript code snippet is as follow ...

Stop JQuery from executing when an error is caught

Once the document is ready, I have configured: $.ajaxSetup({ "error": function (XMLHttpRequest, textStatus, errorThrown) { if(XMLHttpRequest.status == 403) { display_modal( 'Please login to continue.', &ap ...

How can I give an HTML form input button the appearance of glowing or lighting up like the default OS style?

Is it possible to make the <li><FORM><INPUT class="eButton" type="button" value="Ole"></FORM></li> class glow or light up to notify the user about something, while maintaining the default OS look on Linux, Mac, and Windows? F ...

Alignment of button within bootstrap column is skewed when screen size is reduced

My button is perfectly centered in one of my bootstrap columns, but things start to get messy when the screen size shrinks and the button overlaps with another column containing text. Adjusting the margins only seems to make things weirder. .center-btn- ...