views:

1248

answers:

4

It should be a combination of CSS and Javascript,

The main jobs to do should be:

  1. Make it on top of all other elements (which property to specity?)
  2. Catch the event it is clicked (which event to listen to?)
  3. Move the div as mouse moves.

but what are the details?

+2  A: 

Download jQuery and check their source code.

z-boss
I don't want to use any js libs now.
Shore
But you can see how they do what you want to do.
z-boss
Trust me, Shore. You should start using jQuery.
Jonathan Sampson
but the details you ask for is in the source code mentioned by @sneg. The details are too much to be listed here.
Vincent Ramdhanie
why do you say it's an industry standard?what about YUI,dojo and son on?
Shore
Or check this manual: http://www.devarticles.com/c/a/JavaScript/Building-DragandDrop-DIVs-Developing-a-Basic-Script/
z-boss
Vincent++ | This is true. "How do I make drag'n'drop" is a complicated thing. The jQuery team has invested hundreds of hours of development time to make it easy, and you wish to not take advantage of that?
Jonathan Sampson
@Vincent Ramdhanie,I can't dive into the lib,it's too complicated for me now,so I want to make a prototype myself.
Shore
Shore, if looking at jQuery is "too complicated," I wouldn't bother attempting a cross-browser-supported drag'n'drop app on your own.
Jonathan Sampson
I think to make a prototype myself,I'll get a feeling about the principles inside it,otherwise I'll know nothing about what on earth is going on.
Shore
@Shore, then read that source code too and figure out what design decisions were made during the implementations. Then write your own. It's a bit like asking for someone to write a quicksort in java for you. At some point, everyone just points to the reference implementations (whether it's YUI, Dojo, jQuery)
altCognito
@Jonathan Sampson ,I've used YUI before,it supports all browsers quite well,except for its size is not tolerable..
Shore
@Shore, I've updated my answer to give you some ideas on how to do this without a framework. Best of luck to you, man :)
Jonathan Sampson
@altCognito,I think I've listed the main jobs to do to implement a drag-drop div,right?
Shore
It would be nice if we could have one Javascript question that gets at least one answer that does not recommend jQuery. I understand that it is a good library, but IT IS NOT THE SOLUTION FOR EVERYTHING!
Josh Stodola
ditto on the jquery solution that fits everything, +1 josh. its actually a tad annoying how in-your-face jQuqery has become, particularly so since half it's users speak of it and javascript as totally separate entities (maybe not on this site) :/
Dimitar Christoff
+7  A: 

The jQuery Way:

Check out the jQueryUI addons draggable and droppable.

Literally hundreds of hours have been invested into the jQuery framework to make complicated tasks like this almost trivial. Take advantage of the jQuery team's efforts to make programming rich cross-browser applications easier on us all ;)

Chuck Norris' Way:

If you insist on trying this with raw javascript. You'll want to do a few things. One, programmatically set all draggable items to a relative/absolute positioning. If you click a particular item, cause it's top/left values in CSS to reflect the changes made by the x,y axis of the mouse until the click is released. Additionally, you'll want to update the z-index of each draggable when it's clicked to bring it into view.

Tutorial: How to Drag and Drop with Javascript

Jonathan Sampson
+1 for "Chuck Norris' Way," which I'm going to use everywhere from now on. :-)
ajm
Thank you for your update.The reason I want to use raw javascript is that I'm doing this for study purpose.I think I've listed the jobs to do to implement it,but don't know the more detail steps:(
Shore
+3  A: 
  1. make it absolute positioned, with a high z-index.
  2. check for onmousedown of the div.
  3. use the event's mouseX and mouseY attributes to move the div.

Here's an example from a javascript book I was reading recently:

/**
 *  Drag.js: drag absolutely positioned HTML elements.
 *
 *  This module defines a single drag() function that is designed to be called
 *  from an onmousedown event handler. Subsequent mousemove event will
 *  move the specified element. A mouseup event will terminate the drag.
 *  If the element is dragged off the screen, the window does not scroll.
 *  This implementation works with both the DOM Level 2 event model and the
 *  IE event model.
 *
 *  Arguments:
 *
 *   elementToDrag: the element that received the mousedown event or
 *    some containing element. It must be absolutely positioned. Its
 *    style.left and style.top values will be changed based on the user's
 *    drag.
 *
 *   event: ethe Event object for the mousedown event.
 *
 *  Example of how this can be used:
 *   <script src="Drag.js"></script> <!-- Include the Drag.js script -->
 *   <!-- Define the element to be dragged -->
 *   <div style="postion:absolute; left:100px; top:100px; width:250px;
 *      background-color: white; border: solid black;">
 *   <!-- Define the "handler" to drag it with. Note the onmousedown attribute. -->
 *   <div style="background-color: gray; border-bottom: dotted black;
 *      padding: 3px; font-family: sans-serif; font-weight: bold;"
 *    onmousedown="drag(this.parentNode, event);">
 *   Drag Me <!-- The content of the "titlebar" -->
 *   </div>
 *   <!-- Content of the draggable element -->
 *   <p>This is a test. Testing, testing, testing.<p>This is a test.<p>Test.
 *   </div>
 *
 *  Author: David Flanagan; Javascript: The Definitive Guide (O'Reilly)
 *  Page: 422
 **/
 function drag(elementToDrag, event)
 {
     // The mouse position (in window coordinates)
     // at which the drag begins
     var startX = event.clientX, startY = event.clientY;

     // The original position (in document coordinates) of the
     // element that is going to be dragged. Since elementToDrag is
     // absolutely positioned, we assume that its offsetParent is the
     //document bodt.
     var origX = elementToDrag.offsetLeft , origY = elementToDrag.offsetTop;

     // Even though the coordinates are computed in different
     // coordinate systems, we can still compute the difference between them
     // and use it in the moveHandler() function. This works because
     // the scrollbar positoin never changes during the drag.
     var deltaX = startX - origX, deltaY = startY - origY;

     // Register the event handlers that will respond to the mousemove events
     // and the mouseup event that follow this mousedown event.
     if (document.addEventListener) //DOM Level 2 event model
     {
      // Register capturing event handlers
      document.addEventListener("mousemove", moveHandler, true);
      document.addEventListener("mouseup", upHandler, true);
     }
     else if (document.attachEvent) //IE 5+ Event Model
     {
      //In the IE event model, we capture events by calling
      //setCapture() on the element to capture them.
      elementToDrag.setCapture();
      elementToDrag.attachEvent("onmousemove", moveHandler);
      elementToDrag.attachEvent("onmouseup", upHandler);
      // Treat loss of mouse capture as a mouseup event.
      elementToDrag.attachEvent("onclosecapture", upHandler);
     }
     else //IE 4 Event Model
     {
      // In IE 4, we can't use attachEvent() or setCapture(), so we set
      // event handlers directly on the document object and hope that the
      // mouse event we need will bubble up.
      var oldmovehandler = document.onmousemove; //used by upHandler()
      var olduphandler = document.onmouseup;
      document.onmousemove = moveHandler;
      document.onmouseup = upHandler;
     }

     // We've handled this event. Don't let anybody else see it.
     if (event.stopPropagation) event.stopPropagation(); // DOM Level 2
     else event.cancelBubble = true;      // IE

     // Now prevent any default action.
     if (event.preventDefault) event.preventDefault();  // DOM Level 2
     else event.returnValue = false;      // IE

     /**
      * This is the handler that captures mousemove events when an element
      * is being dragged. It is responsible for moving the element.
      **/
      function moveHandler(e)
      {
       if (!e) e = window.event; // IE Event Model

       // Move the element to the current mouse position, adjusted as
       // necessary by the offset of the initial mouse-click.
       elementToDrag.style.left = (e.clientX - deltaX) + "px";
       elementToDrag.style.top = (e.clientY - deltaY) + "px";

       // And don't let anyone else see this event.
       if (e.stopPropagation) e.stopPropagation();  // DOM Level 2
       else e.cancelBubble = true;      // IE
      }

      /**
       * This is the handler that captures the final mouseup event that
       * occurs at the end of a drag.
       **/
       function upHandler(e)
       {
        if (!e) e = window.event; //IE Event Model

        // Unregister the capturing event handlers.
        if (document.removeEventListener) // DOM event model
         {
       document.removeEventListener("mouseup", upHandler, true);
       document.removeEventListener("mousemove", moveHandler, true);
      }
      else if (document.detachEvent)  // IE 5+ Event Model
      {
       elementToDrag.detachEvent("onlosecapture", upHandler);
       elementToDrag.detachEvent("onmouseup", upHandler);
       elementToDrag.detachEvent("onmousemove", moveHandler);
       elementToDrag.releaseCapture();
      }
      else //IE 4 Event Model
      {
       //Restore the original handlers, if any
       document.onmouseup = olduphandler;
       document.onmousemove = oldmovehandler;
      }

      // And don't let the event propagate any further.
      if (e.stopPropagation) e.stopPropagation(); //DOM Level 2
      else e.cancelBubble = true;     //IE
       }
 }

 function closeMe(elementToClose)
 {
     elementToClose.innerHTML = '';
     elementToClose.style.display = 'none';
 }

 function minimizeMe(elementToMin, maxElement)
 {
     elementToMin.style.display = 'none';
 }
Zack
Could you provide a prototype demo?
Shore
@Shore, I thought you wanted to stay away from frameworks? (Assuming you're referring to Prototype, the framework).
Jonathan Sampson
Right,I want to keep away from frameworks.Things are easy at first,but also easy to go unexpectedly later on..
Shore
@Shore so is the above code more what you were looking for?
Zack
@Zack: +1 I don't know if this is the code he was looking for, I was lookign for this great piece of code, thanks for sharing. I didn't understand why you use setCapture, but it sill his great code.
Marco Demajo
A: 

Yeah, you can use jQuery if you want a bloated library with far more functions than you need! Or if you want to be more of an elitist, use Waltern Zorn's drag and drop library, which is one tenth of the size.

Josh Stodola