Loading ...
Sorry, an error occurred while loading the content.

Re: Checking location on mousedown for drag/drop objects

Expand Messages
  • randomjuju
    I fixed this by overriding a few of the drag/drop functions (and adding one of my own). It works just fine, but the trouble is that it needs position caching
    Message 1 of 3 , Jul 5, 2006
    • 0 Attachment
      I fixed this by overriding a few of the drag/drop functions (and adding one of my own).  It works just fine, but the trouble is that it needs position caching turned off in the DragDropMgr, which slows everything to glacial speeds.  I think the Right Thing To Do(tm) is to only cache positions for non-fixed elements.  I'll add that functionality later, but for now, I have to get back to the project I wrote this for in the first place ;)

      I know this works for DDProxy objects; I haven't tested it for straight-up DD objects, but I wouldn't be surprised if it worked there, too.

      -Jon

      My changes are in bold below:

      -- BEGIN dd_proxy_fix.js --
      YAHOO.util.DragDropMgr.fixedAncestryCache = [];

      YAHOO.util.DragDropMgr.hasFixedAncestry = function(el)
      {
          var nodeType = (el.tagName ? el.tagName.toLowerCase() : el.nodeName.toLowerCase());
         
          if(el.id && this.fixedAncestryCache[el.id] != undefined)
          {
              return this.fixedAncestryCache[el.id];
          }
         
          if(nodeType == 'body' || nodeType == 'html')
          {
              if(el.id)
              {
                  this.fixedAncestryCache[el.id] = false;
              }
             
              return false;
          }
          else if(YAHOO.util.Dom.getStyle(el, 'position').toLowerCase() == 'fixed')
          {
              if(el.id)
              {
                  this.fixedAncestryCache[el.id] = true;
              }
             
              return true;
          }
          else
          {
              return this.hasFixedAncestry(el.parentNode, true);
          }
      }

      YAHOO.util.DragDropMgr.isOverTarget = function(pt, oDDTarget, intersect) {
          // use cache if available
          var loc = this.locationCache[oDDTarget.id];
          if (!loc || !this.useCache) {
          loc = this.getLocation(oDDTarget);
          this.locationCache[oDDTarget.id] = loc;

          }

          if(this.hasFixedAncestry(oDDTarget.getEl()))
          {
              var scrollTop = 0;
              var scrollLeft = 0;
             
              if(document.documentElement && typeof(document.documentElement.scrollTop) == 'number')
              {
                  this.scrollTop = document.documentElement.scrollTop;
                  this.scrollLeft = document.documentElement.scrollLeft;
              }
              else
              {
                  this.scrollTop = document.body.scrollTop;
                  this.scrollLeft = document.body.scrollLeft;
              }

              loc.left += this.scrollLeft;
              loc.right += this.scrollLeft;
              loc.top += this.scrollTop;
              loc.bottom += this.scrollTop;
          }
         
          // var cursorIsOver =  (x >= loc[3] && x <= loc[1] && y >= loc[0] && y <= loc[2]);
          //oDDTarget.cursorIsOver = loc.contains( new YAHOO.util.Point(x, y) );
          oDDTarget.cursorIsOver = loc.contains( pt );
          oDDTarget.overlap = null;

          // if (this.INTERSECT == this.mode) {
          if (intersect) {

          // var curRegion =
            //   YAHOO.util.Region.getRegion(
            //   this.dragCurrent.getDragEl());
          var el = this.dragCurrent.getDragEl();
          var x = pt.x - this.dragCurrent.deltaX;
          var y = pt.y - this.dragCurrent.deltaY;
          var curRegion = new YAHOO.util.Region( y, x + el.offsetWidth,
                                 y + el.offsetHeight, x );

          var overlap = curRegion.intersect(loc);

          if (overlap) {
              oDDTarget.overlap = overlap;
              return true;
          } else {
              return false;
          }

          } else {
          return oDDTarget.cursorIsOver;
          }
      }

      YAHOO.util.DD.prototype.autoOffset = function(iPageX, iPageY) {
          var el = this.getEl();
          var aCoord = YAHOO.util.Dom.getXY(el);

          if(YAHOO.util.DragDropMgr.hasFixedAncestry(el))
          {
              var scrollTop = 0;
              var scrollLeft = 0;
             
              if(document.documentElement && typeof(document.documentElement.scrollTop) == 'number')
              {
                  this.scrollTop = document.documentElement.scrollTop;
                  this.scrollLeft = document.documentElement.scrollLeft;
              }
              else
              {
                  this.scrollTop = document.body.scrollTop;
                  this.scrollLeft = document.body.scrollLeft;
              }
             
              aCoord[0] += this.DDM.scrollLeft;
              aCoord[1] += this.DDM.scrollTop;
          }

          var x = iPageX - aCoord[0];
          var y = iPageY - aCoord[1];
          this.setDelta(x, y);
      };
      -- END dd_proxy_fix.js --

      --- In ydn-javascript@yahoogroups.com, "randomjuju" <jon.chambers@...> wrote:
      >
      > The 'handleMouseDown' function of a YAHOO.util.DD object checks to see
      > if the mousedown event was over the registered target (the line is "if
      > ( this.DDM.isOverTarget(pt,this)..."). According to the source:
      >
      > // Only process the event if we really clicked within the linked
      > // element. The reason we make this check is that in the case that
      > // another element was moved between the clicked element and the
      > // cursor in the time between the mousedown and mouseup events. When
      > // this happens, the element gets the next mousedown event
      > // regardless of where on the screen it happened.
      >
      > This causes drag/drop events to abort if the target element is
      > contained in a fixed element and the page is scrolled.
      >
      > Here's an example:
      >
      > Imagine a div containing a set of draggable images at the bottom of a
      > page. It's fixed to the bottom of the page, so it moves as the user
      > scrolls the page. There are two ways to calculate the position of the
      > images once the page has been scrolled. The first is to get the
      > absolute position of the image on the screen, which will remain
      > constant as the page scrolls. The second is to take into account how
      > much the page has scrolled which is variable.
      >
      > It seems that when the click is reported in the mousedown event, it
      > takes into account the scrolled distance of the page (which makes
      > perfect sense). The calculation of the target position, does not
      > (which also makes sense, given that the target is fixed to the page).
      > The unfortunate net result is that isOverTarget returns false if the
      > page has been scrolled enough.
      >
      > I'm not sure what the best way to fix this is, but I did want to call
      > it to everybody's attention. To the Yahoo folks, I'd suggest that it
      > might be possible to crawl up the DOM tree to see if the target
      > element or one of its ancestors has a fixed position and to compensate
      > if it does.
      >
      > Thanks!
      >
      > -Jon
      >
    Your message has been successfully submitted and would be delivered to recipients shortly.