Search code examples
jqueryjquery-uidraggable

JQuery drag/swip div in all directions


Here is where I am currently at with things:

Number.prototype.roundTo = function(nTo) {
  nTo = nTo || 10;
  return Math.round(this * (1 / nTo)) * nTo;
};

$(function() {
  var slides = $('#slider ul').children().length;
  var slideWidth = $('#slider').width();
  var min = 0;
  var max = -((slides - 1) * slideWidth);
  console.log("Slides: " + slides + ", Width: " + slideWidth + ", min: 0, max: " + max);

  $("#slider ul").width(slides * slideWidth);
  $("#slider ul").draggable({
    axis: 'x',
    drag: function(event, ui) {
      if (ui.position.left > min) ui.position.left = min;
      if (ui.position.left < max) ui.position.left = max;
    },
    stop: function(event, ui) {
      $(this).animate({
        left: (ui.position.left).roundTo(slideWidth)
      });
    }
  });
});
#portfolio {
  background: #3aa756;
  min-height: 100%;
  height: 100%;
}

#portfolio-left {
  background: #ccc;
  display: inline-block;
  min-height: 100vh;
  padding-left: 0;
  padding-right: 0;
}

#portfolio-right {
  background: #ded;
  min-height: 100vh;
  padding-left: 0;
  padding-right: 0;
  float: right;
}

#portfolio #slider {
  width: 400px;
  overflow: hidden;
}

#slider ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

#slider li {
  width: 400px;
  height: 100vh;
  float: left;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.min.js"></script>
<section class="no-padding" id="portfolio">
  <div class="col-lg-6 col-sm-6" id="portfolio-left">
  &nbsp;
  </div>

  <div class="col-lg-6 col-sm-6" id="portfolio-right">
    <div id="slider">
      <ul>
        <li style="background-color: #F00"></li>
        <li style="background-color: #0F0"></li>
        <li style="background-color: #00F"></li>
      </ul>
    </div>
  </div>
</section>

Essentially, the right panel is draggable. So if you drag to the left or right, a new colour panel will appear. At the moment, I am using a li to hold the different panels

<div id="slider">
  <ul>
    <li style="background-color: #F00"></li>
    <li style="background-color: #0F0"></li>
    <li style="background-color: #00F"></li>
  </ul>
</div>

What I am after now is a little more complex. Each li above should essentially act as a parent for more data. So if I was to take the above, it might end up something more like this

<div id="slider">
    <ul>
        <li style="background-color: #F00">
            <ul>
                <li style="background-color: #CCC"></li>
                <li style="background-color: #5CB"></li>
            </ul>
        </li>
        <li style="background-color: #0F0"></li>
        <li style="background-color: #00F"></li>
    </ul>
</div>

So the left to right swipe will control the main li items. I then want an up and down swipe to control the child items for a li parent. So if I get to the first li that has some child data, an up swipe will display the first child li, another up swipe the second etc. But then if I do a right swipe it will then display the second parent li.

Hope I explained it ok. Is something like this possible?

Thanks


Solution

  • I've tweaked your code a little bit.

    Number.prototype.roundTo = function(nTo) {     
        nTo = nTo || 10;
        return Math.round(this * (1 / nTo)) * nTo;
    };
    
    $(function() {
      var slides = $('#slider ul').children('.par').length;
      var slideWidth = $('#slider').width();
      var min = 0;
      var max = -((slides - 1) * slideWidth);
      console.log("Slides: " + slides + ", Width: " + slideWidth + ", min: 0, max: " + max);
    
      $("#slider ul").width(slides * slideWidth);
      $("#slider ul").draggable({
        axis: 'x',
        drag: function(event, ui) {
          if (ui.position.left > min) ui.position.left = min;
          if (ui.position.left < max) ui.position.left = max;
        },
        stop: function(event, ui) {
          $(this).animate({
            left: (ui.position.left).roundTo(slideWidth)
          });
        }
      });
      var slideHeight = $('#ch-data').height();
      var chelms = $('#ch-data').children().length;
      var inmax = -((chelms - 1) * slideHeight);
      var topin = slideHeight-50;
      $("#ch-data").height(chelms * slideHeight);
      $("#ch-data").width($('#ch-data li').width());
      $('#ch-data').css({'top': topin+'px'});
      $('#ch-data').draggable({
       axis: 'y',
       drag: function(event, ui){
       	 /*console.log('ui.position.top = '+ui.position.top);
        console.log('min = '+min);
        console.log('inmax = '+inmax);*/
       },
        stop: function(event, ui) {
        	console.log('slideHeight = '+slideHeight);
        	console.log('min = '+min);
        	console.log('inmax = '+inmax);
        	console.log('ui.position.top = '+ui.position.top);
        	console.log('slideHeight-50 = '+topin);
        	console.log('(ui.position.top).roundTo(topin) = '+(ui.position.top).roundTo(topin));
       		if (ui.position.top > min) {
          	if (ui.position.top > (slideHeight/2)) {
              ui.position.top = topin;
              $(this).animate({
                top: (ui.position.top).roundTo(topin)
              });
              console.log('if of > topin');
            }else{
    					ui.position.top = min;
              $(this).animate({
                top: (ui.position.top).roundTo(slideHeight)
              });
              console.log('if of > min');
            }        
          }else if (ui.position.top < inmax) {
          	ui.position.top = inmax;
          	$(this).animate({
            	top: (ui.position.top).roundTo(slideHeight)
          	});
        		console.log('if of > inmax');
          }else{
          	$(this).animate({
            	top: (ui.position.top).roundTo(slideHeight)
          	});
        		console.log('else');
          }
        }
      });
    });
        #portfolio {
      background: #3aa756;
      min-height: 100%;
      height: 100%;
    }
    
    #portfolio-left {
      background: #ccc;
      display: inline-block;
      min-height: 100vh;
      padding-left: 0;
      padding-right: 0;
    }
    
    #portfolio-right {
      background: #ded;
      min-height: 100vh;
      padding-left: 0;
      padding-right: 0;
      float: right;
    }
    
    #portfolio #slider {
      width: 400px;
      overflow: hidden;
    }
    
    #slider ul {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    #ch-data{
      width: 380px;
      height: 100%;
    }
    #slider li.par {
      width: 390px;
      height: 100vh;
      float: left;
    }
    
    #slider li {
      width: 390px;
      height: 100vh;
      bottom: 0;
    }
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
    <script src="http://code.jquery.com/ui/1.10.3/jquery-ui.min.js"></script>
    <section class="no-padding" id="portfolio">
      <div class="col-lg-6 col-sm-6" id="portfolio-left">
      &nbsp;
      </div>
    
      <div class="col-lg-6 col-sm-6" id="portfolio-right">
        <div id="slider">
          <ul>
            <li class="par" style="background-color: #F00">
              <ul id="ch-data">
                <li style="background-color: #CCC">inner1</li>
                <li style="background-color: #5CB">inner2</li>
                <li style="background-color: #58C">inner3</li>
              </ul>
            </li>
            <li class="par" style="background-color: #0F0"></li>
            <li class="par" style="background-color: #00F"></li>
          </ul>
        </div>
      </div>
    </section>

    I've reduced the width of inner li-s. So that you can see the red colour background of the parent. If we give full width for them, then the right to left drag won't work as we expected. I've followed your same code/method only. So that you can understand well. This is just for illustration. You might need to style accordingly to achieve better UI/UX results. Hope you got the idea.

    I've updated the latest code.

    • Now we can drag right to left and left to right
    • Then we can drag sub panels up and down
    • We can even move it down to hide the sub-panels to show the parent panel