Paul
Paul

Reputation: 3368

How to add interval to a draggable element

I created a bar which you can select different intervals. I am attempting to make it draggable, which I successfully implemented. The issue I have is that I can drag the green grab bar (where is says "budget"). I am wanting to be able to drag the grab bar and then for it to drop where the range dots are (the intervals) and keep the grab bar within the outer element #sliderBar.

Is there anyway I can change what I have to make this possible?

Here is a fiddle.

 $(function() {
   $("#sliderInterval").draggable();
 });
 $(function() {

   var iSelected = 0;
   var ranges = [{
     lower: 500,
     upper: 1000
   }, {
     lower: 1100,
     upper: 2000
   }, {
     lower: 2100,
     upper: 5000
   }, {
     lower: 5100,
     upper: 10000
   }, {
     lower: 11000,
     upper: 20000
   }, {
     lower: 21000,
     upper: 50000
   }, ];
   var wslider = $("#sliderBar").width() / (ranges.length);
   for (var i = 0; i < ranges.length; i++) {
     var range = $('<div class="rangedot"><div class="intervalCircle"></div></div>');
     var left = (100 / (ranges.length) * i);
     rangeleft = "calc(" + left + "% - 2px)";
     range.css({
       left: rangeleft,
       width: wslider
     });
     range.on("click", function(idx) {
       return function() {
         iSelected = idx;
         var sliderleft = wslider * idx;
         $("#sliderInterval").animate({
           left: sliderleft
         });
         $("#budgetAmount").text("$" + ranges[idx].lower.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " - " + "$" + ranges[idx].upper.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","));
       };
     }(i));
     $("#sliderBar").append(range);
     $("#sliderInterval").css("width", wslider + "px");
   }
   $("#budgetAmount").show().text("$500 - $1,000");

 });
#project-slider-container {
  width: 80%;
  height: auto;
  margin: 40px 0% 30px 0%;
  text-align: center;
}

#project-slider-title {
  text-align: left;
  font-size: 1.2em;
  font-weight: bold;
  margin-bottom: 15px;
}

#project-slider-description {
  text-align: left;
  font-size: 1em;
  line-height: 1.3em;
  color: #2a2a2a;
}

#sliderBar {
  border-radius: 15px;
  width: 100%;
  height: 40px;
  margin: 30px 0;
  background: #454343;
  position: relative;
  overflow: hidden;
}

.intervalCircle {
  border-radius: 50%;
  height: 10px;
  width: 10px;
  background: #CCC;
  z-index: 1;
  display: inline-block;
  margin-top: 18px;
  cursor: pointer;
}

.intervalCircle:hover {
  border-radius: 50%;
  height: 25px;
  width: 25px;
  background: #0085A1;
  z-index: 1;
  display: inline-block;
  margin-top: 11px;
  cursor: pointer;
}

.rangedot {
  height: 40px;
  position: absolute;
  text-align: center;
  left: 0px;
  top: -8px;
  cursor: pointer;
}

#sliderInterval {
  height: 100%;
  border-radius: 15px;
  position: absolute;
  text-align: center;
  z-index: 99;
  color: #FFF;
  font-weight: bold;
  background: #00a16d;
  line-height: 40px;
}

#sliderIntervalBudget {
  padding: 0 5px;
}

#budgetAmount {
  font-size: 1.5em;
  color: #00a16d;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="project-slider-container">
  <div id="project-slider-title">PREFERRED BUDGET</div>
  <div id="sliderBar">
    <div id="sliderInterval"><span id="sliderIntervalBudget">BUDGET</span></div>
  </div>
  <div id="budgetAmount"></div>
</div>

Upvotes: 0

Views: 756

Answers (1)

Twisty
Twisty

Reputation: 30893

Here is a way to do this using Slider.

Working Example: https://jsfiddle.net/Twisty/1846p0nx/3/

HTML

<div id="project-slider-container">
  <div id="project-slider-title">PREFERRED BUDGET</div>
  <div id="project-slider-description">A transparent budget will help set expectations. A higher budget allows for a more complex website project.</div>
  <div class="slide-wrap">
    <div id="slider">
      <div id="custom-handle" class="ui-slider-handle">BUDGET</div>
    </div>
  </div>
  <div id="budgetAmount"></div>
</div>

CSS

.slide-wrap {
  height: 40px;
  padding: 0 60px;
  background: #454343;
  border-radius: 15px;
}

#slider {
  border-radius: 15px;
  height: 40px;
  background: transparent;
  border: 0;
  padding: 0 60px;
}

#custom-handle {
  border-radius: 15px;
  border: 0;
  height: 40px;
  width: 120px;
  text-align: center;
  color: #FFF;
  font-weight: bold;
  background: #00a16d;
  line-height: 40px;
  top: 50%;
  margin-top: -20px;
  margin-left: -60px;
}

JavaScript

$(function(){
   var ranges = [{
     lower: 500,
     upper: 1000
   }, {
     lower: 1100,
     upper: 2000
   }, {
     lower: 2100,
     upper: 5000
   }, {
     lower: 5100,
     upper: 10000
   }, {
     lower: 11000,
     upper: 20000
   }, {
     lower: 21000,
     upper: 50000
   }, ];
   var handle = $("#custom-handle");
   var amount = $("#budgetAmount");
   $("#slider").slider({
     min: 0,
     max: 5,
     step: 1,
     create: function() {
       var i = $(this).slider("value");
       amount.text("$" + ranges[i].lower + " - $" + ranges[i].upper);
       $.each(ranges, function(key, item) {
         var range = $("<div>", {
           class: "rangedot"
         }).data("key", key);
         var dot = $("<div>", {
           class: "intervalCircle"
         }).appendTo(range);
         var l = Math.round(100 / (ranges.length - 1) * key);
         var w = $("#slider").width() / (ranges.length);
         range.css({
           left: "calc(" + l + "% - " + (w / 2) + "px)",
           width: w + "px"
         }).click(function() {
           $("#slider").slider("value", $(this).data("key"));
         }).appendTo("#slider");
       });
     },
     slide: function(event, ui) {
       var i = ui.value;
       amount.text("$" + ranges[i].lower + " - $" + ranges[i].upper);
     }
   });
});

Update

If you want to do this with draggable specifically, I would suggest this.

Example: https://jsfiddle.net/Twisty/1846p0nx/4/

$(function() {
   var iSelected = 0;
   var ranges = [{
     lower: 500,
     upper: 1000
   }, {
     lower: 1100,
     upper: 2000
   }, {
     lower: 2100,
     upper: 5000
   }, {
     lower: 5100,
     upper: 10000
   }, {
     lower: 11000,
     upper: 20000
   }, {
     lower: 21000,
     upper: 50000
   }];
   var wslider = $("#sliderBar").width() / (ranges.length);
   $("#sliderInterval").draggable({
     axis: "x",
     grid: [wslider, 0],
     containment: "#sliderBar",
   });
   for (var i = 0; i < ranges.length; i++) {
     var range = $('<div class="rangedot"><div class="intervalCircle"></div></div>');
     var left = (100 / (ranges.length) * i);
     rangeleft = "calc(" + left + "% - 2px)";
     range.css({
       left: rangeleft,
       width: wslider
     });
     range.on("click", function(idx) {
       return function() {
         iSelected = idx;
         var sliderleft = wslider * idx;
         $("#sliderInterval").animate({
           left: sliderleft
         });
         $("#budgetAmount").text("$" + ranges[idx].lower.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " - " + "$" + ranges[idx].upper.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","));
       };
     }(i));
     $("#sliderBar").append(range);
     $("#sliderInterval").css("width", wslider + "px");
   }
   $("#budgetAmount").show().text("$500 - $1,000");
});

You can then use stop or create a droppable to go along with it to see where it was dropped. I still suggest the slider.

Upvotes: 1

Related Questions