Adding jquery ui

Hello,
i want to make a modal dragable and found a solution that uses jquery ui (Edit fiddle - JSFiddle - Code Playground)

How can i add jquery ui to a project?

thanks

if what you want is to:

add your jsfiddle to bss project:

  1. enable bss jquery (settings->design->booststrap->jquery version)

then there are the most straight forward is just to copy paste your scripts whole html, js(script tag, also wrap it in $( "document" ).ready( your script handler function )) and css(style tag) on custom code (studio → custom code)

the more maintainable way is to separate it in proper bss components and file

  1. html: with proper bss html tag
  2. js: create new js/mjs file put your js code there, make sure its loaded bellow jquery load, or just wrap it with $( "document" ).ready( your script handler function )
  3. css: create new css/scss file and paste it there.

also best practice is you to make sure the scripts are loaded only on the affected *.html document (by using right click js/css file → visibility)

to add jquery ui (the script, as local/cdn) to the project

local

  1. download jquery ui to your local machine
  2. right click javascript → new ->js file → select your downloaded jquery ui file

cdn

  1. right click javascript → link external JS → point to their cdn link

you also need to make sure whether this jquery ui script need jquery to be loaded or not… to whether to enable or disable bss internal jquery…

In addition to @muhammadhakimjazuli 's answer, I would add that if you only need this jQuery script on certain pages of your website, you can link to the jQuery library via CDN, and then use BSS’s visibility feature to enable it only on those pages that need it.

If you enable it via Settings>Design>Bootstrap>jQuery version, it will be loaded on every page of your website by default.

Here is one link to load jQuery via CDN

https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js

The problem you might have is that the example you have given is very old and uses bootstrap 3

You can get the same result by using the following vanilla javascript, therefore no need to use jQuery.

Also you won’t need the css is the JSFiddle.

document.addEventListener('DOMContentLoaded', function() {
    var modal = document.getElementById('myModal');// <--set your modal ID here
    var modalHeader = modal.querySelector('.modal-header');
    var isDragging = false;
    var startX, startY, offsetX, offsetY;
   
    modalHeader.addEventListener('mousedown', function(e) {
       isDragging = true;
       startX = e.clientX;
       startY = e.clientY;
       offsetX = modal.offsetLeft;
       offsetY = modal.offsetTop;
    });
   
    document.addEventListener('mousemove', function(e) {
       if (isDragging) {
         var x = offsetX + e.clientX - startX;
         var y = offsetY + e.clientY - startY;
         modal.style.left = x + 'px';
         modal.style.top = y + 'px';
       }
    });
   
    document.addEventListener('mouseup', function() {
       isDragging = false;
    });
});

Example:

Update: The above js will remember the position of the modal when it is closed. If you want to reset the modal position on close use the following code instead:

document.addEventListener("DOMContentLoaded", function () {
  var modal = document.getElementById("myModal"); // <--set your modal ID here
  var modalHeader = modal.querySelector(".modal-header");
  var isDragging = false;
  var startX, startY, offsetX, offsetY;

  modalHeader.addEventListener("mousedown", function (e) {
    isDragging = true;
    startX = e.clientX;
    startY = e.clientY;
    offsetX = modal.offsetLeft;
    offsetY = modal.offsetTop;
  });

  document.addEventListener("mousemove", function (e) {
    if (isDragging) {
      var x = offsetX + e.clientX - startX;
      var y = offsetY + e.clientY - startY;
      modal.style.left = x + "px";
      modal.style.top = y + "px";
    }
  });

  document.addEventListener("mouseup", function () {
    isDragging = false;
  });

  // Listen for the modal to be hidden
  modal.addEventListener("hidden.bs.modal", function () {
    modal.style.left = "50%"; // Center horizontally
    modal.style.top = "50%"; // Center vertically
    modal.style.transform = "translate(-50%, -50%)"; // Adjust for modal size
  });
});

5 Likes

@richards

You could add this css to give a hint to the user it’s a draggable modal

.modal-header {
  cursor: move;
}

There is a small bug in your script.
Normally if you click outside the modal the modal close
if a user has moved the modal the modal won’t close if you click above the modal

1 Like

@kuligaposten That’s a good idea, I was thinking of adding a move icon before the heading but that would work just as well.

I was thinking of rewriting the script so that it works on touch events so will look at the close issue

Update to code to remove bug pointed out by @kuligaposten (Thanks :slight_smile: ) and add touch support

document.addEventListener('DOMContentLoaded', function() {
  var modal = document.getElementById('myModal');
  var modalContent = modal.querySelector('.modal-content');
  var modalHeader = modal.querySelector('.modal-header');
  var isDragging = false;
  var startX, startY, offsetX, offsetY;
 
  function startDrag(e) {
     isDragging = true;
     startX = e.clientX || e.touches[0].clientX;
     startY = e.clientY || e.touches[0].clientY;
     offsetX = modalContent.offsetLeft;
     offsetY = modalContent.offsetTop;
  }
 
  function drag(e) {
     if (isDragging) {
       var x = offsetX + (e.clientX || e.touches[0].clientX) - startX;
       var y = offsetY + (e.clientY || e.touches[0].clientY) - startY;
       modalContent.style.left = x + 'px';
       modalContent.style.top = y + 'px';
     }
  }
 
  function endDrag() {
     isDragging = false;
  }
 
  modalHeader.addEventListener('mousedown', startDrag);
  modalHeader.addEventListener('touchstart', startDrag);
 
  document.addEventListener('mousemove', drag);
  document.addEventListener('touchmove', drag);
 
  document.addEventListener('mouseup', endDrag);
  document.addEventListener('touchend', endDrag);
 });

CSS:

.modal-header {
  cursor: move;
}

.modal-title::before {
  content: "⠿";
  color: #aaa;
  margin-right:1rem;
  font-size: 1.5rem;;
}

@richards

You could turn your script into a class and have multiple draggable modals on the page
like this

class DraggableModal {
  constructor(modalId) {
    this.modal = document.getElementById(modalId);
    this.modalContent = this.modal.querySelector('.modal-content');
    this.modalHeader = this.modal.querySelector('.modal-header');
    this.isDragging = false;
    this.startX = 0;
    this.startY = 0;
    this.offsetX = 0;
    this.offsetY = 0;

    this.startDrag = this.startDrag.bind(this);
    this.drag = this.drag.bind(this);
    this.endDrag = this.endDrag.bind(this);

    this.modalHeader.addEventListener('mousedown', this.startDrag);
    this.modalHeader.addEventListener('touchstart', this.startDrag);
    document.addEventListener('mousemove', this.drag);
    document.addEventListener('touchmove', this.drag);
    document.addEventListener('mouseup', this.endDrag);
    document.addEventListener('touchend', this.endDrag);
  }

  startDrag(e) {
    this.isDragging = true;
    this.startX = e.clientX || e.touches[0].clientX;
    this.startY = e.clientY || e.touches[0].clientY;
    this.offsetX = this.modalContent.offsetLeft;
    this.offsetY = this.modalContent.offsetTop;
  }

  drag(e) {
    if (this.isDragging) {
      const x = this.offsetX + (e.clientX || e.touches[0].clientX) - this.startX;
      const y = this.offsetY + (e.clientY || e.touches[0].clientY) - this.startY;
      this.modalContent.style.left = x + 'px';
      this.modalContent.style.top = y + 'px';
    }
  }

  endDrag() {
    this.isDragging = false;
  }
}

document.addEventListener('DOMContentLoaded', function() {
  new DraggableModal('myModal');
});
1 Like

Example updated with @kuligaposten suggestion :+1:

1 Like

@richards

2 Likes

@kuligaposten Nice work H.

1 Like

@kuligaposten @richards
You guys are awesome. You amaze me with your skill.

2 Likes

Thanks @printninja I don’t think I will ever get to @kuligaposten level. His code is inspiring and I have learned so much from him. His coding is magical, so well structured and gives me something to aspire to.

1 Like

And from what he’s told me, he does this for RELAXATION. If I recall correctly, he retired from programming years ago.

thanks so much for all this valuable information.