Having trouble arranging the elements when swapping within a pop-up modal

When I drag and drop two divs inside a modal popup, their positions shift down during the animation. I am struggling to fix this issue.

HTML Code:

<title>
  Tile Swapping with Animation</title>

<body>
  <button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>

  <!-- Modal -->
  <div id="myModal" class="modal fade" role="dialog">
    <div class="modal-dialog">

      <!-- Modal content-->
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal">&times;</button>
          <h4 class="modal-title">Modal Header</h4>
        </div>
        <div class="modal-body">
          <p>Some text in the modal.</p>
          <div class='droppable'>
            <div class="draggable">Draggable 1</div>
          </div>
          <div class='droppable'>
            <div class="draggable">Draggable 2</div>
          </div>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        </div>
      </div>

    </div>
  </div>

JavaScript Code:

$(document).ready(function() {
  window.startPos = window.endPos = {};

  makeDraggable();

  $('.droppable').droppable({
    hoverClass: 'hoverClass',
    drop: function(event, ui) {
      var $from = $(ui.draggable),
        $fromParent = $from.parent(),
        $to = $(this).children(),
        $toParent = $(this);

      window.endPos = $to.offset();

      swap($from, $from.offset(), window.endPos, 200);
      swap($to, window.endPos, window.startPos, 1000, function() {
        $toParent.html($from.css({
          position: 'relative',
          left: '',
          top: '',
          'z-index': ''
        }));
        $fromParent.html($to.css({
          position: 'relative',
          left: '',
          top: '',
          'z-index': ''
        }));
        makeDraggable();
      });
    }
  });

  function makeDraggable() {
    $('.draggable').draggable({
      zIndex: 99999,
      revert: 'invalid',
      start: function(event, ui) {
        window.startPos = $(this).offset();
      }
    });
  }

  function swap($el, fromPos, toPos, duration, callback) {
    $el.css('position', 'absolute')
      .css(fromPos)
      .animate(toPos, duration, function() {
        if (callback) callback();
      });
  }
});

View Fiddle Here

Answer №1

It is recommended to utilize the .position() method instead of .offset() when adjusting the positioning of an element set to absolute.

By changing the element's position property to absolute, you are working with a positioned element (i.e., an element with a computed position property of either relative, absolute, fixed, or sticky). When specifying the top css property of a positioned element, you are defining "the distance between the top margin edge of the element and the top edge of its containing block" (not the top edge of the document). The closest ancestor that is also a positioned element is referred to as the offset parent by JQuery.

While .offset() retrieves the coordinates of an element "relative to the document", .position() provides the coordinates "relative to the offset parent".

The offset parent for the element in question is the one with the "modal-body" class. (This is determined as the closest ancestor with a position value of relative.) However, it is not necessary to identify the offset parent manually since the .position() function handles this automatically.

jsfiddle

This jsfiddle mirrors the original content but with each instance of .offset() replaced by .position().

Answer №2

Switch the style from absolute to fixed.

function exchange($element, startPos, endPos, timeFrame, finish) {
  $element.css('position', 'fixed')
  .css(startPos)
  .animate(endPos, timeFrame, function() {
    if (finish) finish();
  });
}

Answer №3

Uncertain if this is the exact solution you seek, but consider this as an alternative (even though it may be a bit unconventional).

I attempted to determine the underlying issue without success, so I devised a creative workaround for the problem. Try replacing your function with this:

 function swap($el, fromPos, toPos, duration, callback) {

$el.css('position', 'fixed')
  .css(fromPos)
  .css('margin-top','-10px')
  .animate(toPos, duration, function() {
    if (callback) callback();       
    $el.css('margin-top','0px');
  });

}

As an additional recommendation, consider increasing the animation duration during the initial phase. For example, try

swap($from, $from.offset(), window.endPos, 1000);

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

Converting an unbroken series of string values into organized key-value pairs for easy reference

I assure you this is not a duplicated question. Despite my attempts with JSON.parse(), it seems to be ineffective. Here's the issue at hand: I recently received assistance from an answer that was both crucial and enlightening. However, the code prov ...

Prevent background from collapsing by considering the context

I am facing an issue with a div that contains a background image and some text. I need the text within the div to not overlap with a specific part of the background image (the ribbon part). Please refer to the images linked below for a clearer understandin ...

Looking to display a visualization using data from a MongoDB database

I am seeking advice on the most effective way to achieve the following goal. I have been storing user activity data in MongoDB as a log, with entries similar to: { "date":"01-01-2002T08:20:30", "task":"contact-lead", "user":"username" } My objective ...

Sending a message through Discord.JS to a designated channel

Recently diving into Discord.JS, I am struggling to understand how to make my bot send a message to the General Chat when a new user joins. Many examples I've come across suggest using the following code: const channel = client.channels.cache.find(ch ...

Resolving negative margin issues in Material UI components through detailed textual guidance

Having an issue with the paragraphs in material-ui components. The problem arises when the text exceeds the dimensions of the component, causing it to spill over as shown in the image below. <Grid container wrap="nowrap" css={[borde,{ ...

Guide on parsing the obj variable into a webix .show() modal?

I have a piece of code that looks like this: $$('TLVab').attachEvent("onAfterEditStop", function(state, editor, ignoreUpdate) { $$('deleteLTMPopup').show();//TODO parse state into the pop up }); UI.deleteLTMPopup= {id:& ...

What is the best way to retrieve data in Nodejs from a different execution context?

My goal is to continuously fetch data from a website that updates frequently using MutateObservable. In order to achieve this, I am utilizing Puppeteer as my scraper since the data changes every second, requiring a browser to remain open constantly. For t ...

Display PDF in Forge Viewer using PDF Extension - warning generated by pdf.worker.js

Whenever we attempt to display a PDF file using our own API, the pdf.worker.js generates a warning message and the PDF always appears completely white. https://i.stack.imgur.com/IqGML.png All I can see is this (it's a wide PDF that renders fine in t ...

Differences in navigation menus on mobile between Chrome and Firefox

I am struggling to understand why the mobile sub menu on my website is displaying differently in Chrome compared to Firefox. If you visit and view it at a resolution below 1200px, you can click on the menu toggle to open up the menu and hover over the Pro ...

Tomickigrzegorz Script Finder Predictive Search

Hey there, I recently tried out the autocomplete script created by tomickigrzegorz. Check it out here! It's been working smoothly for me, but I'm facing an issue with external link tags like https//google.com not functioning properly. Here is ...

Is it possible to dynamically change a form's input value using a JavaScript keyup function based on input from other form elements?

My form utilizes the keyup function to calculate the total value of 3 input fields by multiplying them and displaying the result. Below is a fiddle showcasing this functionality: $(document).ready(function () { $(".txtMult1 input").keyup(multInp ...

Tips for revealing a position: absolute div that is currently hidden with display: none styling

Below is the code for a div element that I want to temporarily hide using JavaScript: <div id="mydiv" style="position: absolute; top: 60px; left:5px; right:25px; bottom:10px;"> </div> After hiding it with display:none in my ...

`Generating Interactive Pie Charts with ASP.NET`

After receiving a helpful suggestion from Gthompson83 about using jqPlot, I am facing a new issue... The current javascript code on my page (the data is just temporary): function CreatePie(div) { var data = [ ['Heavy Indust ...

When trying to pull a component from Svelte, I receive an error message stating "Selection Range

I'm still relatively new to svelte, so I might be handling things incorrectly. Whenever I attempt to separate my button component, regardless of whether I name the component ./Button.svelte, ./Button, Button.svelte, or try variations with capitalizat ...

Identifying Ctrl+V in VueJS: A Guide

Although I found the answers to this question, they were for jQuery and not suitable for my needs with vue.js. Currently, I have successfully implemented code to detect single character presses: export default { name: 'game', data () { ...

Using Node.js: Retrieving a value from a function with an asynchronous call within

Is it possible to create a synchronous function that generates a random string and checks for existing files on Amazon Web Service S3 with the same name? The challenge lies in making this function synchronous, considering the asynchronous nature of calli ...

Concealing div containers and eliminating gaps

Looking for a way to filter div boxes using navigation? Check this out: <ul> <li><a href="javascript:void(0);" data-target="apples">Appels</a></li> <li><a href="javascript:void(0);" data-target="bananas">Ban ...

Transferring a PHP array to JavaScript using AJAX

I have spent time searching for answers to my issue with no success. My PHP file includes the following array: $data = ['logged' => $_SESSION['loggedin'], 'sessName' => $_SESSION['name']]; echo json_encode($dat ...

How can I easily swap between the front and back cameras while using an app?

Trying to create a web-ar experience that allows users to switch between front and back cameras while utilizing SLAM/6dof with the back camera has been a challenging endeavor. While attempting this in PlayCanvas, I faced difficulties getting the front came ...

Troubleshooting a problem with the navigation links on a single-page website with a

https://i.sstatic.net/5xcv9.png My website alampk.com features a single page layout with a fixed navbar at the top. However, when I click on links like exp, portfolio, etc., the section moves to the top but a portion of 50px gets covered by the navbar. I ...