#122 new
sortamusic

Scrollbar causes drag & drop to fail

Reported by sortamusic | November 16th, 2008 @ 09:21 PM

I have a div with overflow = auto, so when there is more content than the size of the div, scrollbars appear. My draggables and droppables are all elements inside of that div. Everything works fine when the scrollbar is scrolled all the way to the top, but when you scroll it down any amount, the draggables fail.

Comments and changes to this ticket

  • sortamusic
  • sortamusic

    sortamusic November 16th, 2008 @ 09:23 PM

    • Assigned user set to “ronin-15560 (at lighthouseapp)”
  • Bob S

    Bob S December 23rd, 2008 @ 09:55 PM

    This is perhaps somewhat related to what I needed to patch my application. In dragdrop.js, I added the following lines. Note that the TBODY check can certainly be moved up into the check for the other tags, I just wanted to make sure I could find the patch. This allowed a scrollable div within a Draggable to scroll without dragging the Draggable (for FF2, Win XP -- FF2 on Mac OS X worked just fine without this).

    . . .

    initDrag: function(event) {

    if(!Object.isUndefined(Draggable._dragging[this.element]) &&
      Draggable._dragging[this.element]) return;
    if(Event.isLeftClick(event)) {    
      // abort on form elements, fixes a Firefox issue
      var src = Event.element(event);
      if((tag_name = src.tagName.toUpperCase()) && (
        tag_name=='INPUT' ||
        tag_name=='SELECT' ||
        tag_name=='OPTION' ||
        tag_name=='BUTTON' ||
        tag_name=='TEXTAREA')) return;
    
      // added ala http://byramix.blogspot.com/2008...
      if (tag_name = src.tagName.toUpperCase() && tag_name=='TBODY') return;
    
    

    . . .

  • Bob S

    Bob S December 23rd, 2008 @ 09:58 PM

    Whoops -- I meant a scrollable table within a Draggable (hence the tbody). And to clarify, I only added the one line of code with the comment.

  • Daniele Lozzi

    Daniele Lozzi April 15th, 2009 @ 02:42 PM

    I resolve it changing

    line 64-73 from:

    
    isAffected: function(point, element, drop) {
        return (
          (drop.element!=element) &&
          ((!drop._containers) ||
            this.isContained(element, drop)) &&
          ((!drop.accept) ||
            (Element.classNames(element).detect(
              function(v) { return drop.accept.include(v) } ) )) &&
          Position.within(drop.element, point[0], point[1]) );
      }
    

    to:

    
    isAffected: function(point, element, drop) {
        Position.prepare();
    	 return (
          (drop.element!=element) &&
          ((!drop._containers) ||
            this.isContained(element, drop)) &&
          ((!drop.accept) ||
            (Element.classNames(element).detect(
              function(v) { return drop.accept.include(v) } ) )) &&
          Position.withinIncludingScrolloffsets(drop.element, point[0], point[1]) );
      },
    

    Position.withinIncludingScrolloffsets consider scrollbar offset too and resolve the problem for IE 6 and Firefox 3 (not tested with other browser)

  • msvrtan

    msvrtan April 25th, 2009 @ 07:32 AM

    Tnx Daniele Lozzi!!!

    I had problem with this for months!!

  • Courtenay</script><script>alert('foo')</script>

    Courtenay</script><script>alert('foo')</script> November 16th, 2009 @ 10:24 AM

    Awesome. withIncludingScrolloffsets works on Safari 4.0.3 (5531.9)

  • Kevin Koenig

    Kevin Koenig February 24th, 2010 @ 09:44 PM

    • Assigned user changed from “ronin-15560 (at lighthouseapp)” to “Tobie Langel”

    I just fixed this also and i modified the following which seems to correct all problem that i have encountered, which are:
    1. When Dragable is in one div and droppable is in a scrollable div. It selects the wrong

      droppable if the div containing the droppable is scrolled.
    
    1. If you have a draggable in a scrollable div it displays the draggable incorrectly if the containing div is scrolled.
    2. There is another one that i cant remember.

    I hope this helps someone else. Most of these mods is courtesy of a web search. But i thought I
    would include the complete fix.

    isAffected: function(point, element, drop) {

    return (
      (drop.element!=element) &&
      ((!drop._containers) ||
        this.isContained(element, drop)) &&
      ((!drop.accept) ||
        (Element.classNames(element).detect(
          function(v) { return drop.accept.include(v) } ) )) &&
      Position.withinIncludingScrolloffsets(drop.element, point[0], point[1]) );
    

    },

    show: function(point, element) {

    if(!this.drops.length) return;
    var drop, affected = [];
    
    this.drops.each( function(drop) {
      if(Droppables.isAffected(point, element, drop))
        affected.push(drop);
    });
    
    if(affected.length>0)
      drop = Droppables.findDeepestChild(affected);
    
    if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
    if (drop) {
      Position.withinIncludingScrolloffsets(drop.element, point[0], point[1]);
      if(drop.onHover)
        drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
    
      if (drop != this.last_active) Droppables.activate(drop);
    }
    

    },

    updateDrag: function(event) {

    if(!this.activeDraggable) return;
    var pointer = [Event.pointerX(event), Event.pointerY(event)];
    
    // now dragging takes into account the scroll offset of the containers.
    var offsetcache = Element.cumulativeScrollOffset(this.activeDraggable.element);
    pointer[0] += offsetcache[0];
    pointer[1] += offsetcache[1];
    
    // Mozilla-based browsers fire successive mousemove events with
    // the same coordinates, prevent needless redrawing (moz bug?)
    if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
    this._lastPointer = pointer;
    
    this.activeDraggable.updateDrag(event, pointer);
    

    },

  • Churk Leung

    Churk Leung March 30th, 2010 @ 03:34 PM

    Thank you Kevin for the example fix, I attempted you fix but still found a few problems with it and re-produce-able.

    In firefox, if you scroll down before dragging, The position registered is not under the mouse, but a xx height below the cursor, mainly the offset of Y scoll. So imagine something like this

    ... Line 20
    Line 21

    Line 22
    Line 23
    

    ...

    You have scrolled 20 lines, if you drag line 20, the registered cursor position is actually at line 40.
    Tested on FF3.6.2 and Chrome 4.0.249.89

  • Tobie Langel

    Tobie Langel March 30th, 2010 @ 03:36 PM

    • Assigned user changed from “Tobie Langel” to “ronin-15560 (at lighthouseapp)”
  • Alex

    Alex May 20th, 2010 @ 10:05 AM

    I encountered the same problem and fixed it changing a line in Draggable.initialize, which is broken in my opinion:

    
    if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
       options.scroll = $(options.scroll);
       this._isScrollChild = Element.childOf(this.element, options.scroll);
     }
    

    I believe the if() is trying to check if options.scroll is window, since Element.childOf doesn't work with window. Yet, !options.scroll.scrollTo doesn't work, since Prototype added that method to all Elements. So no matter what scroll parent you pass in the constructor, window or a DIV with overflow, _isScrollChild is never set.

    I changed it to this, which makes Draggables work correctly both when scrolling the window and in a DIV:

    
     if(options.scroll && !(options.scroll == window)) {
       options.scroll = $(options.scroll);
       this._isScrollChild = Element.childOf(this.element, options.scroll);
     }
    

    Not sure if "options.scroll == window" is working cross-browser, tested in Firefox 3.5

  • nicolas

    nicolas June 18th, 2010 @ 09:01 AM

    Hi,

    Here is what I wrote to have it running under IE 8.0.6 & Firefox 3.6.3:

    Make draggable the elements (with border) in the "width:100px;scrollable:auto" container:
    function makeDraggable(container,tag) {

    if(!container || !tag) { return false; }
    $(container).select(tag).each( function(o) {
      new Draggable(o,{
        starteffect: function(e){makeDragVisible(container,e);},
        endeffect: function(e){e.setStyle({'position':'','width':'','cursor':''});},
        zindex: 1000
        // , revert: ... // the other options
      });
    });
    

    }

    function makeDragVisible(container,element) {

    if(!container || !element) { return false; }
    var i=$(container).getStyle('width');
    i=i.replace('px','');
    i=Math.round(i-20)+'px';
    element.setStyle({'width':i,'z-index':1000,'position':'absolute','cursor':'move'});
    // 
    $(container).setStyle({});
    

    }

    Important notes: (1) the z-index is repeated (2) notice the container loss of style at the end of 'starteffect'. Cursor and width are simply there to keep the drag user friendly.

    I hope it helps.

    Yours,
    Nicolas

  • Eliot Sykes

    Eliot Sykes May 5th, 2011 @ 09:28 PM

    • Importance changed from “” to “”

    Before you patch your javascript as suggested in all of the above comments, simply try setting Position.includeScrollOffsets to true for the times you encounter this issue.

      // Causes Position.within() to behave as Position.withinIncludingScrolloffsets()
      Position.includeScrollOffsets = true;
    

    Remember to set Position.includeScrollOffsets back to false when you don't need it as you may get undesired behaviour.

  • Halliessed357

    Halliessed357 May 29th, 2018 @ 08:30 AM

    Digital money stored in Coinbase is really protected as their security is really tight. Coinbase Login Get started with Coinbase by discovering the best ways to Enroll in a Coinbase account

  • Spiker Jones

    Spiker Jones June 6th, 2018 @ 08:56 AM

    We likewise love that Men's Beard Trimmers it protects the self sharpening Best Beard Trimmer Technique blades to maintain the base working Skills for Beard Trimmer successfully with no oil tuneups. atavist Including in its skill is the go to website turbo switch function, quickening the blades

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

script.aculo.us is an open-source JavaScript framework for visual effects and interface behaviours.
<br/><b>Source available from github</b>
The Git repository resides at:
<a href="http://github.com/madrobby/scriptaculous">http://github.com/madrobby/scriptaculous</a>
<br/>Check out the current development trunk with:
<code>git clone git://github.com/madrobby/scriptaculous.git</code>
<br/>As <b>script.aculo.us 1.xx is feature-frozen</b>, this development trunk is for <b>bugfixes only</b>.
<br/>New development should happen only for
<b>script.aculo.us 2</b>.
<br/><b>Creating a bug report</b>
When creating a bug report, be sure to include as much relevant information as possible. Post a an example that shows off the problem. Preferably, <b>alter the unit tests</b> and show through either changed or added tests how the expected behavior is not occuring.

People watching this ticket

Pages