ドラッグ&ドロップで入れ替え可能なリスト
縦並び型
- ほげほげ
- ふがふが
- はらほれ
- ひれはれ
- はなもげら
head要素内
var draggable_list = new DraggableList("DRAGGABLE_LIST");
var callback = function()
{
draggable_list.create();
};
Event.observe(window, "load", callback);
スクリプト
DraggableList = function(_str)
{
this.id = _str;
this.container;
this.items = [];
this.drop_targets = [];
this.target;
this.direction = "";
}
DraggableList.prototype = {
create: function()
{
this.container = document.getElementById(this.id);
var nodelist = this.container.getElementsByTagName("li");
for(var i=0; i<nodelist.length; i++)
{
var elm = nodelist[i];
this.direction = (function()
{
if(document.defaultView)
return document.defaultView.getComputedStyle(elm,"").getPropertyValue("float")
else if(elm.currentStyle)
return elm.currentStyle.styleFloat;
})();
var dli = new DraggableList.ListItem(elm, i);
dli.addEventListener("onDrag", this);
dli.addEventListener("startDrag", this);
dli.addEventListener("stopDrag", this);
this.items.push(dli);
}
for(i=0; i<this.items.length; i++)
{
var drop_target = document.createElement("li");
drop_target.display = "none";
drop_target.style.padding = 0+"px";
if(this.direction=="none")
{
drop_target.style.width = getBounds(nodelist[0]).width+"px";
drop_target.style.height = 0+"px";
} else {
drop_target.style.width = 0+"px";
drop_target.style.height = getBounds(nodelist[0]).height+"px";
}
drop_target.style.border = 0+"px";
drop_target.style.background = "none";
drop_target.style.fontSize = 0;
this.drop_targets.push(drop_target);
}
},
startDrag: function(e)
{
var temporaries = [];
for(var i=0; i<this.items.length+1; i++)
{
var item_ = this.items[i];
if(e.target!=item_)
{
temporaries.push(item_);
}
}
for(i=0; i<temporaries.length; i++)
{
var drop_target = this.drop_targets[i];
if(i<temporaries.length-1)
{
this.container.insertBefore(drop_target, temporaries[i].elm);
} else {
this.container.appendChild(drop_target);
}
}
},
stopDrag: function(e)
{
this.container.insertBefore(e.target.elm, this.target);
for(var i=0; i<this.drop_targets.length; i++)
{
this.container.removeChild(this.drop_targets[i]);
}
},
onDrag: function(e)
{
var _dir = this.direction
var current = e.target;
var showTarget = function()
{
drop_target.display = "block";
if(_dir=="none")
drop_target.style.borderTop = "5px solid #06c";
else
drop_target.style.borderLeft = "5px solid #06c";
}
var hideTarget = function()
{
drop_target.display = "none";
drop_target.style.border = "0";
}
for(var i=0; i<this.drop_targets.length; i++)
{
var drop_target = this.drop_targets[i];
var width = getBounds(current.dummy).width + getBounds(drop_target).width;
var left = getBounds(drop_target).right - getBounds(current.dummy).left;
var height = getBounds(current.dummy).height + getBounds(drop_target).height;
var top = getBounds(drop_target).bottom - getBounds(current.dummy).top;
if((0<left&&left<width)&&(0<top&&top<height))
{
showTarget();
this.target = drop_target;
} else {
hideTarget();
}
}
}
}
DraggableList.ListItem = function(_elm, _id)
{
EventDispatcher.initialize(this);
this.item_id = _id;
this.elm = _elm;
this.dummy = document.createElement("div");
this.dummy.style.width = _elm.offsetWidth+"px";
this.dummy.style.height = _elm.offsetHeight+"px";
this.dummy.style.border = "2px dotted #06c";
this.dummy.style.position = "absolute";
this.dummy.style.cursor = "pointer";
this.dummy.style.fontSize = "0";
_elm.style.cursor = "pointer";
var _scope = this;
var _supplementX = 0;
var _supplementY = 0;
var _pos = getBounds(_elm);
var _dummy = this.dummy
var mouseMoveHandler = function(e)
{
if(document.all) event.returnValue = false;
_scope.dispatchEvent({ type:"onDrag", target:_scope });
_dummy.style.left = (e.clientX - _supplementX) + "px";
_dummy.style.top = (e.clientY - _supplementY) + "px";
}
var startDrag = function(e)
{
_pos = getBounds(_elm);
_supplementX = e.clientX - _pos.left;
_supplementY = e.clientY - _pos.top;
document.body.appendChild(_dummy);
_elm.style.display = "none";
_scope.dispatchEvent({ type:"startDrag", target:_scope });
if(window.addEventListener)
window.addEventListener("mousemove", mouseMoveHandler, false);
else if(document.attachEvent)
document.attachEvent("onmousemove", mouseMoveHandler);
}
var stopDrag = function(e)
{
document.body.removeChild(_dummy);
_elm.style.display = "block";
_scope.dispatchEvent({ type:"stopDrag", target:_scope });
if(window.removeEventListener)
window.removeEventListener("mousemove", mouseMoveHandler, false);
else if(document.detachEvent)
document.detachEvent("onmousemove", mouseMoveHandler);
}
if(_elm.addEventListener)
{
_elm.addEventListener("mousedown", function(e)
{
e.preventDefault();
window.addEventListener("mouseup", function(e)
{
stopDrag(e);
window.removeEventListener("mouseup", arguments.callee, false);
}, false);
startDrag(e);
}, false);
} else if(_elm.attachEvent) {
_elm.attachEvent("onmousedown", function(e)
{
event.returnValue = false;
document.attachEvent("onmouseup", function(e)
{
stopDrag(e);
document.detachEvent("onmouseup", arguments.callee);
});
startDrag(e);
});
}
}
function getBounds(_elm)
{
var width = _elm.offsetWidth;
var height = _elm.offsetHeight;
var left = _elm.offsetLeft;
var top = _elm.offsetTop;
while(_elm.offsetParent)
{
_elm = _elm.offsetParent;
left += _elm.offsetLeft;
top += _elm.offsetTop;
}
var right = left + width;
var bottom = top + height;
return {left:left, top:top, right:right, bottom:bottom, width:width, height:height};
}