/* * dnd.js - 要素をマウスで並べ替える * 関連ライブラリ * queryselector.js, event.js geometry.js * 影響を受けるプロパティ * document.body.style.cursor * document.onmousemove * document.onmouseup * document.onselectstart * document.ondragstart */ function(draggable, droppable, callback) { if (typeof callback != 'function') { callback = function(node, prev, next) { if (next) next.parentNode.insertBefore(node, next); else node.parentNode.appendChild(node); }; } /** * initialize draggable */ var $ = @INCLUDE(queryselector.js); var fixEvent = @INCLUDE(event.js); var geometry = new @INCLUDE(geometry.js); var bind = function(obj, fn) { return function() { return fn.apply(obj, arguments); } }; var self = this; $(draggable).each(function(index, node) { node.ondragstart = bind(node, function(evt) { evt = fixEvent(evt); //window.status = window.defaultStatus = "dragstart"; if (evt.type != 'mousemove') return; evt.stop(); this.onmousemove = null; this.droppables = self.prepareDroppable(droppable); var position = geometry.getGeometry(this); var shadow = this.shadow = this.parentNode.appendChild(this.cloneNode(true)); shadow.offX = evt.offsetX; shadow.offY = evt.offsetY; shadow.style.left = (position.left + 16) + 'px'; shadow.style.top = (position.top + 16) + 'px'; shadow.style.position = "absolute"; shadow.onmouseup = null; document.body.style.cursor = 'no-drop'; document.onmousemove = bind(this, function(evt) { evt = fixEvent(evt); //window.status = window.defaultStatus = "drag[" + evt.pageX + "," + evt.pageY + "]"; this.shadow.style.left = (evt.pageX + 16) + "px"; this.shadow.style.top = (evt.pageY + 16) + "px"; }); document.onmouseup = this.ondragend; return false; }); node.ondragend = bind(node, function(evt) { evt = fixEvent(evt); if (evt.type != 'mouseup' || evt.which != 1) return true; evt.stop(); //window.status = window.defaultStatus = "dragend" + this.shadow.nodeName; this.shadow.parentNode.removeChild(this.shadow); for (var i = 0; i < this.droppables.length; i++) { var d = this.droppables[i]; if (d.selected && typeof callback == 'function') { try { callback(this, d.previousSibling, d.nextSibling); } catch (ex){ alert(ex); } } d.parentNode.removeChild(d); } document.body.style.cursor = ''; document.onmousemove = null; document.onmouseup = null; }); node.onmousedown = bind(node, function(evt) { evt = fixEvent(evt); if (evt.type != 'mousedown' || evt.which != 1) return true; evt.stop(); document.onmousemove = this.ondragstart; document.onselectstart = function(evt) { evt = fixEvent(evt); evt.stop(); }; document.ondragstart = function(evt) { evt = fixEvent(evt); evt.stop(); }; }); node.onmouseup = bind(node, function(evt) { document.onmousemove = null; }); }); /** * */ this.finish = function(){}; /** * initialize droppable */ this.prepareDroppable = function(selector) { var $ = @INCLUDE(queryselector.js); var handler = @INCLUDE(event.js); var result = new Array(); var self = this; $(selector).each(function(index, droppable) { var target; for (var i = droppable.childNodes.length - 1; i >= 0; i--) { if (droppable.childNodes.item(i).nodeType != 1) continue; target = self.createDropTarget(droppable, droppable.childNodes.item(i)); result.push(target); } target = self.createDropTarget(droppable); result.push(target); }); return result; }; this.createDropTarget = function(droppable, child) { var target = document.createElement('span'); target.className = target.styleClass = 'droptarget'; target.style.width = '0px'; target.style.height = '0px'; var bar = target.bar = target.appendChild(document.createElement('span')); bar.innerHTML = ' '; if (child) droppable.insertBefore(target, child); else droppable.appendChild(target); target.selected = false; if (document.all) { //IE target.style.backgroundColor = '#FFFFFF'; target.style.filter = 'alpha(opacity=1)'; } target.onmouseover = bind(target, function(evt) { document.body.style.cursor = 'default'; this.style.filter = ''; this.bar.style.display = ''; this.selected = true; }); target.onmouseout = bind(target, function(evt) { document.body.style.cursor = 'no-drop'; this.style.filter = 'alpha(opacity=1)'; this.bar.style.display = 'none'; this.selected = false; }); var prev = target.previousSibling; while (prev && prev.nodeType != 1) prev = prev.previousSibling; var next = target.nextSibling; while (next && next.nodeType != 1) next = next.previousSibling; if ((' ' + (droppable.className || droppable.styleClass) + ' ').match(/ vertical /)) { target.style.width = droppable.offsetWidth + 'px'; target.style.height = '1em'; target.style.marginTop = '-0.5em'; target.style.position = 'absolute'; bar.style.width = droppable.offsetWidth + 'px'; bar.style.height = '0'; bar.style.marginTop = '0.5em'; bar.style.borderTop = '1px dotted black'; bar.style.display = 'none'; bar.style.cssFloat = bar.style.styleFloat = 'left'; bar.style.lineHeight = 0; } else { target.style.width = '1em'; target.style.height = (prev ? prev.offsetHeight : next.offsetHeight) + 'px'; target.style.marginLeft = '-0.5em'; target.style.position = 'absolute'; bar.style.width = '0px'; bar.style.height = '100%'; bar.style.marginLeft = '0.5em'; bar.style.borderLeft = '1px dotted black'; bar.style.display = 'none'; } return target; }; }