Using jScrollPane with jQuery UI Draggable

A work-around to jScrollPane windows not scrolling while dragging list items using jQuery UI draggable, droppable, and sortable utilities.

HTML

<script src="https://raw.github.com/vitch/jScrollPane/master/script/jquery.jscrollpane.min.js"></script>
<h2>Default jQuery UI Sortable</h2>
<div id="window1" class="window">
  <ul id="sortable1" class="sortable">
    <li>Item #1</li>
    <li>Item #2</li>
    <li>Item #3</li>
    <li>Item #4</li>
    <li>Item #5</li>
    <li>Item #6</li>
    <li>Item #7</li>
    <li>Item #8</li>
    <li>Item #9</li>
    <li>Item #10</li>
  </ul>
</div>

<h2>jQuery UI Sortable w/ jScrollPane</h2>
<p>You should be unable to drag items from the top of the list to the bottom</p>
<div id="window2" class="window">
  <ul id="sortable2" class="sortable">
    <li>Item #1</li>
    <li>Item #2</li>
    <li>Item #3</li>
    <li>Item #4</li>
    <li>Item #5</li>
    <li>Item #6</li>
    <li>Item #7</li>
    <li>Item #8</li>
    <li>Item #9</li>
    <li>Item #10</li>
  </ul>
</div>

<h2>jQuery UI Sortable w/ jScrollPane and <code>.scroll-trigger</code></h2>
<p>Now you should be able to drag sortable items in the jScrollPane window</p>
<div id="window3" class="window">
  <ul id="sortable3" class="sortable">
    <li>Item #1</li>
    <li>Item #2</li>
    <li>Item #3</li>
    <li>Item #4</li>
    <li>Item #5</li>
    <li>Item #6</li>
    <li>Item #7</li>
    <li>Item #8</li>
    <li>Item #9</li>
    <li>Item #10</li>
  </ul>
</div>

CSS

.window{position:relative; max-height:300px; max-width:300px; overflow:auto; margin:1em auto 2em; border:1px solid #333;}
.sortable li{display:block; margin:0 0 .5em; padding:1em 2em; background:#efefef;}
h2{font-size:1.4em; font-weight:bold;}

/* Basic jScrollPane styles */
.jspContainer{position:relative; overflow:hidden;}
.jspPane{position:absolute;}
.jspVerticalBar, .jspHorizontalBar{position:absolute; background:#dadada;}
.jspVerticalBar{right:0; top:0; width:8px; height:100%;}
.jspVerticalBar *, .jspHorizontalBar *{margin:0; padding:0;}
.jspCap{display:none;}
.jspHorizontalBar .jspCap{float:left;}
.jspTrack{position:relative;}
.jspDrag{position:relative; top:0; left:0; background:#0069aa; cursor:pointer;}
.jspHorizontalBar .jspTrack, .jspHorizontalBar .jspDrag{float:left; height:100%;}
.jspArrow{display:block; height:10px; text-indent:-20000px; background:#50506d; cursor:pointer;}
.jspArrow.jspDisabled{background: #80808d; cursor:default;}
.jspArrow:focus{outline:none;}
.jspCorner{float:left; height:100%; background:#eeeef4;}

/* .scroll-trigger styles */
.scroll-trigger{position:absolute; left:0; display:block; width:100%; height:28px;}
.scroll-trigger-up{top:0;}
.scroll-trigger-down{bottom:0;}

/* Un-comment this to see a dashed border around .scroll-trigger */
.scroll-trigger{box-sizing:border-box; z-index:100; border:1px dashed red;}

JavaScript

jQuery( function( $ ) {
  var scrollInterval;

  // Make our lists sortable
  $('.sortable').sortable({
    appendTo: 'body'
  });

  // Initialize jScrollPane with the showArrows option
  $('#window2, #window3').jScrollPane({
    showArrows: true
  });

  // Append our .scroll-trigger elements
  $('#window3').prepend( '<div class="scroll-trigger scroll-trigger-up" />' ).append( '<div class="scroll-trigger scroll-trigger-down" />' );
  $('#window3').find( '.scroll-trigger' ).droppable({
    over: function( e, ui ) {
      var self = $(this),
      jspArrow;

      // We're only focused on vertical scrolling in this example
      if ( self.hasClass( 'scroll-trigger-up' ) ) {
        jspArrow = '.jspArrowUp';
      } else if ( self.hasClass( 'scroll-trigger-down' ) ) {
        jspArrow = '.jspArrowDown';
      }

      if ( jspArrow ) {
        scrollInterval = setInterval( function() {
          // Trigger the equivalent of a click event
          $('#window3').find( jspArrow ).trigger( 'mousedown.jsp' ).trigger( 'mouseup.jsp' );
        }, 100 );
      }
    },
    out: function() {
      if ( scrollInterval ) {
        clearInterval( scrollInterval );
      }
    }
  });

});