Skip to content

Instantly share code, notes, and snippets.

@chwkai
Created January 30, 2010 08:18
Show Gist options
  • Select an option

  • Save chwkai/290480 to your computer and use it in GitHub Desktop.

Select an option

Save chwkai/290480 to your computer and use it in GitHub Desktop.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Draggable demo</title>
<style type="text/css">
.item {
background:black;
width:100px;
height:100px;
border:1px solid black;
}
.dropZone{
background:white;
width:400px;
height:200px;
border:1px solid black;
}
.dropZoneHover{
background:#efefef !important;
border:1px dashed black !important;
}
.itemMoving{
opacity:0.5;
z-index:100;
position:fixed;
}
</style>
<script type="text/javascript">
var Samples = {};
/**
* performs the drag&drop action on html element.
* Note: The intent of this code is to demostrate how to realize the drag&drop in javascript.
* It is written without any consideration of cross-browser compatibility, and only tested under firefox 3.5.7,
* please do not pasted into any scripts for IE browsers.
*
* @author chwkai@gmail.com
* @param {Array} zones "ids of the drop zones"
* @param {Array} items "ids of the draggable items"
* @param {Function} callback "function to execute when the drag&drop finsihed"
*/
Samples.draggable = function(zones, items, callback){
var zoneLength = zones.length;
var itemLength = items.length;
/**
* checks whether the given coordinate in the bound of zone
* @param {Object} zone
* @param {Object} left
* @param {Object} top
*/
function _inZone(zone, left, top){
var pos = _getPosition(zone);
if(left > pos.left && left < (pos.left + zone.clientWidth) &&
top > pos.top && top < (pos.top + zone.clientHeight)){
return true;
}
return false;
}
/**
* Returns the absolute position to the browser window
* @param {Object} element
*/
function _getPosition(element){
var pos = {};
pos.left = element.offsetLeft;
pos.top = element.offsetTop;
var parent = element.offsetParent;
while(parent){
pos.left += parent.offsetLeft;
pos.top += parent.offsetTop;
parent = parent.offsetParent;
}
return pos;
}
/**
* handler for the mouse move event of drag items
* @param {Object} evt
*/
function _onMouseMove(evt){
if(this._dragging){
this.style.left =
(this._originalLeft + evt.clientX - this._mouseLeft) + "px";
this.style.top =
(this._originalTop + evt.clientY - this._mouseTop) + "px";
for (var i = 0; i < zoneLength; i++) {
var zone = document.getElementById(zones[i]);
// switch the appearance of the drop zone while mouse enter/leave
if (_inZone(zone, evt.clientX, evt.clientY)) {
if(!zone._css){
zone._css = zone.getAttribute("class") || "";
zone.setAttribute("class", zone._css + " dropZoneHover");
}
}
else{
if(zone._css){
zone.setAttribute("class", zone._css);
delete zone._css;
}
}
}
}
}
/**
* handler for the mouse up event of drag items
* @param {Object} evt
*/
function _onMouseUp(evt){
this.setAttribute("class", this._css);
this.setAttribute("style", this._style);
document.removeEventListener("mousemove", this._mouseMoveHandler, true);
document.removeEventListener("mouseup", this._mouseUpHandler, true);
for(var i = 0; i < zoneLength; i++){
var zone = document.getElementById(zones[i]);
if(_inZone(zone, evt.clientX, evt.clientY)){
this.parentNode.removeChild(this);
zone.appendChild(this);
// notify callback function
if(callback){
callback.apply(window, [zone, this]);
}
}
}
// remove all the temp variables from the drag item
delete this._originalLeft;
delete this._originalTop;
delete this._mouseLeft;
delete this._mouseTop;
delete this._dragging;
delete this._css;
delete this._style;
delete this._mouseUpHandler;
delete this._mouseMoveHandler;
}
// iternates the drop zones to forbid dragging on zones
for(i = 0; i < zoneLength; i++){
var target = document.getElementById(zones[i]);
target.addEventListener("dragstart", function(){return false;}, true);
}
// iterates the drag items to bind the drag events
for(i = 0; i < itemLength; i++){
var target = document.getElementById(items[i]);
target.addEventListener("mousedown",
function(evt){
this._originalLeft = this.offsetLeft;
this._originalTop = this.offsetTop;
this._mouseLeft = evt.clientX;
this._mouseTop = evt.clientY;
this._dragging = true;
// backup the original stylesheet
this._css = this.getAttribute("class") || "";
this._style = this.getAttribute("style") || "";
this.setAttribute("class", this._css + " itemMoving");
// handler for mouse events
// avoid the problem of enclosure
var element = this;
this._mouseMoveHandler = function(evt){
_onMouseMove.apply(element, [evt]);
}
this._mouseUpHandler = function(evt){
_onMouseUp.apply(element, [evt]);
}
document.addEventListener("mousemove", this._mouseMoveHandler, true);
document.addEventListener("mouseup", this._mouseUpHandler, true);
}, true);
target.addEventListener("mouseover",
function(){
this._cssCursor = this.style.cursor;
this.style.cursor = "move";
}, true);
}
};
window.onload = function(){
// register the drop zones and draggable items
Samples.draggable(["zone1", "zone2"],["item1"], onDrag);
};
/**
* callback function for the drag&drop finished
* @param {Object} zone "dom element to the drag zone"
* @param {Object} item "dom element to the draggable item"
*/
function onDrag(zone, item){
var message = "you just place " + item.id + " in " + zone.id;
window.alert(message);
}
</script>
</head>
<body>
<div id="zone1" class="dropZone"></div><BR/>
<div id="zone2" class="dropZone"></div>
<div id="item1" class="item"></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment