Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6948961
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T13:53:31+00:00 2026-05-27T13:53:31+00:00

Using a plain JS script from David Flanagan to make my bookmarklet draggable. I

  • 0

Using a plain JS script from David Flanagan to make my bookmarklet draggable.

I have noticed that I can move the pointer off the drag bar during key-down and the pop-up may or may not follow the pointer around or suddenly snap to the pointer.

The total experience in Firefox 8 and 9 is not impressive. IE8 on XP works as designed

It is intended for a bookmarklet, so I canot use a framework like jQuery or YUI.

QUESTION: How do I improve the stickyness of the mousedown / drag so the window stays attached to the mouse onmousedown and onmousemove using plain JS?

Also please help me make the getLeft and getTop work in IE/Chrome and Fx so the popup is restricted to the viewport.

OLD DEMO HERE

NEW AND FIXED DEMO HERE (thanks techfoobar)

function getTop(top) {
//  if (console) console.log('y:'+top+':'+document.body.clientHeight);  
  if (top<0) return 0;
  if (top>=(document.body.clientHeight-40)) return document.body.clientHeight-40;
  return top;
}
function getLeft(left) {
//  if (console) console.log('x:'+left+':'+document.body.clientWidth);  
  if (left<0) return 0;
  if (left>=(document.body.clientWidth-500)) return document.body.clientWidth-500;
  return left;
}
// This code is from the book JavaScript: The Definitive Guide, 6th Edition (ISBN #978-0596805524). Copyright 2011 by David Flanagan.
function getScrollOffsets(w) {
  w = w || window;
  if (w.pageXOffset != null) return {x: w.pageXOffset, y:w.pageYOffset};
  var d = w.document;
  if (document.compatMode == "CSS1Compat") 
    return {x:d.documentElement.scrollLeft, y:d.documentElement.scrollTop};
  return { x: d.body.scrollLeft, y: d.body.scrollTop };
}

function zDrag(elementToDrag, event) { var scroll = getScrollOffsets();
  var startX = event.clientX + scroll.x;
  var startY = event.clientY + scroll.y;
  var origX = elementToDrag.offsetLeft;
  var origY = elementToDrag.offsetTop;
  var deltaX = startX - origX;
  var deltaY = startY - origY;
  if (document.addEventListener) { 
    document.addEventListener("mousemove", moveHandler, true);
    document.addEventListener("mouseup", upHandler, true);
  } 
  else if (document.attachEvent) { 
    elementToDrag.setCapture();
    elementToDrag.attachEvent("onmousemove", moveHandler);
    elementToDrag.attachEvent("onmouseup", upHandler);
    elementToDrag.attachEvent("onlosecapture", upHandler);
  } 
  if (event.stopPropagation) event.stopPropagation();
  else event.cancelBubble = true;
  if (event.preventDefault) event.preventDefault();
  else event.returnValue = false;

  function moveHandler(e) { 
    if (!e) e = window.event;
    var scroll = getScrollOffsets();
    elementToDrag.style.left = getLeft(e.clientX + scroll.x - deltaX,true) + "px";
    elementToDrag.style.top = getTop(e.clientY + scroll.y - deltaY,true) + "px";
    if (e.stopPropagation) e.stopPropagation();
    else e.cancelBubble = true;
  };
  function upHandler(e) { 
    if (!e) e = window.event;
    if (document.removeEventListener) { 
      document.removeEventListener("mouseup", upHandler, true);
      document.removeEventListener("mousemove", moveHandler, true);
    } 
    else if (document.detachEvent) { 
      elementToDrag.detachEvent("onlosecapture", upHandler);
      elementToDrag.detachEvent("onmouseup", upHandler);
      elementToDrag.detachEvent("onmousemove", moveHandler);
      elementToDrag.releaseCapture();
    } 
    if (e.stopPropagation) e.stopPropagation();
    else e.cancelBubble = true;
   };
 } 
  // end drag code
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-27T13:53:31+00:00Added an answer on May 27, 2026 at 1:53 pm

    This should take care of the stickiness issue.

    I could see from your demo site that when the mouse is over the inner iframe, we have an issue with stickiness. This is because the inner iframe does not bubble the event up to the root document element which handles zDrag’s mousemove event.

    I solved that issue by appending an overlay div (invisible but there) that takes the entire area of the root document, thereby effectively preventing the inner iframe from getting the mousemove. And as this overlay div is a direct descendant of our root document element, it bubbles up the mousemove event correctly.

    Changes include an additional method for getting the document height (from http://james.padolsey.com/javascript/get-document-height-cross-browser/), and changes to the zDrag method for adding/showing/hiding the overlay div.

    function getDocHeight() {
      var D = document;
      return Math.max(
        Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
        Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
        Math.max(D.body.clientHeight, D.documentElement.clientHeight)
      );
    }
    
    function zDrag(elementToDrag, event) { 
      var scroll = getScrollOffsets();
    
      // create/show overlay - over the inner iframe and everything else
      var div = document.getElementById('overlay');
      if(div==null) {
        div = document.createElement('div');
        div.id = 'overlay';
        div.style.position = 'absolute';
        div.style.left = '0px';
        div.style.top = '0px';
        div.style.width = '100%';
        div.style.height = getDocHeight()+'px';
        div.style.zIndex = 99999;
        div.style.cursor = 'move';
        var bodyTag = document.getElementsByTagName("body")[0];
        bodyTag.appendChild(div);
      }
      else {
        div.style.display = 'block';
      }
    
      var startX = event.clientX + scroll.x;
      var startY = event.clientY + scroll.y;
      var origX = elementToDrag.offsetLeft;
      var origY = elementToDrag.offsetTop;
      var deltaX = startX - origX;
      var deltaY = startY - origY;
      if (document.addEventListener) { 
        document.addEventListener("mousemove", moveHandler, true);
        document.addEventListener("mouseup", upHandler, true);
      } 
      else if (document.attachEvent) { 
        /*elementToDrag.setCapture();
        elementToDrag.attachEvent("onmousemove", moveHandler);
        elementToDrag.attachEvent("onmouseup", upHandler);
        elementToDrag.attachEvent("onlosecapture", upHandler);*/
    
        // attach the events to the document element, to ensure we dont 'miss' any move events.
        document.setCapture();
        document.attachEvent("onmousemove", moveHandler);
        document.attachEvent("onmouseup", upHandler);
        document.attachEvent("onlosecapture", upHandler);
      } 
    
      if (event.stopPropagation) event.stopPropagation();
      else event.cancelBubble = true;
      if (event.preventDefault) event.preventDefault();
      else event.returnValue = false;
    
      function moveHandler(e) { 
        if (!e) e = window.event;
        var scroll = getScrollOffsets();
        elementToDrag.style.left = getLeft(e.clientX + scroll.x - deltaX,true) + "px";
        elementToDrag.style.top = getTop(e.clientY + scroll.y - deltaY,true) + "px";
        if (e.stopPropagation) e.stopPropagation();
        else e.cancelBubble = true;
      };
    
      function upHandler(e) { 
    
        // dragging is over. hide the overlay.
        document.getElementById('overlay').style.display = 'none';
    
        if (!e) e = window.event;
        if (document.removeEventListener) { 
          document.removeEventListener("mouseup", upHandler, true);
          document.removeEventListener("mousemove", moveHandler, true);
        } 
        else if (document.detachEvent) { 
          /*elementToDrag.detachEvent("onlosecapture", upHandler);
          elementToDrag.detachEvent("onmouseup", upHandler);
          elementToDrag.detachEvent("onmousemove", moveHandler);
          elementToDrag.releaseCapture();*/
          document.detachEvent("onlosecapture", upHandler);
          document.detachEvent("onmouseup", upHandler);
          document.detachEvent("onmousemove", moveHandler);
          document.releaseCapture();
    
        } 
        if (e.stopPropagation) e.stopPropagation();
        else e.cancelBubble = true;
      };
    }
    

    EDIT – For limiting the drag inside the viewport

    Now it will limit the dragging to inside the viewport (i.e browser window inner width and height). Changes include a) an additional cross-browser function to get the window inner width and height (from http://www.javascripter.net/faq/browserw.htm) and b) changes to the moveHandler() method (inside the zDrag method) to check and enforce limits.

    function getWindowSize() {
      var winW = 630, winH = 460;
      if (document.body && document.body.offsetWidth) {
        winW = document.body.offsetWidth;
        winH = document.body.offsetHeight;
      }
      if (document.compatMode=='CSS1Compat' && document.documentElement && document.documentElement.offsetWidth ) {
        winW = document.documentElement.offsetWidth;
        winH = document.documentElement.offsetHeight;
      }
      if (window.innerWidth && window.innerHeight) {
        winW = window.innerWidth;
        winH = window.innerHeight;
      }
      return {width: winW, height: winH};
    }
    

    And inside zDrag(), replace the current moveHandler with:

    function moveHandler(e) { 
      if (!e) e = window.event;
      var scroll = getScrollOffsets();
    
      var newLeft = getLeft(e.clientX + scroll.x - deltaX,true);
      if(newLeft + elementToDrag.offsetWidth > winDim.width) {
        newLeft = winDim.width - elementToDrag.offsetWidth;
      }
      elementToDrag.style.left = newLeft + "px";
    
      var newTop = getTop(e.clientY + scroll.y - deltaY,true);
      if(newTop + elementToDrag.offsetHeight > winDim.height) {
        newTop = winDim.height - elementToDrag.offsetHeight;
      }
      elementToDrag.style.top = newTop + "px";
    
      if (e.stopPropagation) e.stopPropagation();
      else e.cancelBubble = true;
    };
    

    EDIT – the winDim variable

    winDim is the variable that stores the viewport’s dimensions. It is used in the move handler to check if our movable is within the viewport. I kept it outside so as to avoid re-computation of window dimensions on every move event which could degrade performance.

    var winDim = null;
    
    function zDrag(...) {
    
      if(winDim == null) winDim = getWindowSize
    
      // ... rest of the code in zDrag ...
    
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a script that download's files from a server, all works nice. But
I have imported a plain-text version of PDF using a Python script, but it
I have a script that pulls data out of an excel spreadsheet using the
How to strip off HTML tags from a string using plain JavaScript only, not
Is there a way to extract all email addresses from a plain text using
I'm sending a XML content to ActiveMQ from ruby script using stomp I'm explicitly
I'm using nginx with this script as FastCGI wrapper, that I start with: spawn-fcgi
I have a SQL script that inserts data (via INSERT statements currently numbering in
I have a email script that runs every 15 minutes and is supposed to
I have a PHP script called : http://cyber-flick.com/apiMorpho.php?method=getMorphoData&word=kot That displays some data in plain

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.