|
// addEvent && removeEvent from quirksmode.org function addEvent(obj,evt,fn) { if (obj.addEventListener) obj.addEventListener(evt,fn,false); else if (obj.attachEvent) obj.attachEvent('on'+evt,fn); }
function removeEvent(obj,evt,fn) { if (obj.removeEventListener) obj.removeEventListener(evt,fn,false); else if (obj.detachEvent) obj.detachEvent('on'+evt,fn); }
function addClass(el, klass) { if(!hasClass(el, klass)) { var classes = el.className.split(' '); classes.push(klass); el.className = classes.join(' '); } } function removeClass(el, klass) { var classes = el.className.split(' '); for(var i = 0; i < classes.length; i++) { if(classes == klass) { classes.splice(i, 1); break; } } el.className = classes.join(' '); } function hasClass(el, klass) { var classes = el.className.split(' '); for(var i = 0; i < classes.length; i++) { if(classes == klass) { return true; } } return false; }
function Draggable(el, events, handler) { this.element = el; this.handler = handler || el; addClass(this.handler, 'draggable'); this.handler.dragger = this; this.handler.onmousedown = this.dragStart; this.events = events; this.start, this.mouseStart, this.current; } Draggable.current; Draggable.prototype = { 'getMousePos': function(e) { if(!e) e = window.event; var x = e.clientX; var y = e.clientY; return {'x': x, 'y': y}; }, 'getOffsets': function(el) { el = el || this.element; return {'x': el.offsetLeft, 'y': el.offsetTop}; }, 'getAbsOffsets': function(el) { el = el || this.element; var offs = this.getOffsets(el); if(el.offsetParent) { var par = this.getAbsOffsets(el.offsetParent); offs.x += par.x; offs.y += par.y; } return offs; }, 'setPosition': function(x, y) { this.current = {'x': x, 'y': y}; this.element.style.left = x + this.start.x + 'px'; this.element.style.top = y + this.start.y + 'px'; }, 'setStart': function(x, y) { x = (x)? x : 0; y = (y)? y : 0; this.start = {'x': x, 'y': y}; }, 'dragStart': function(e) { var drg = this.dragger; drg.trigger('preDragStart'); Draggable.current = drg; drg.mouseStart = drg.getMousePos(e); var abs = drg.getAbsOffsets(); drg.setStart(abs.x - drg.mouseStart.x, abs.y - drg.mouseStart.y); document.body.appendChild(drg.element.parentNode.removeChild(drg.element)); drg.setPosition(drg.mouseStart.x, drg.mouseStart.y); drg.element.style.position = 'absolute'; addEvent(document.body, 'mousemove', drg.dragMove); addEvent(document.body, 'mouseup', drg.dragEnd); drg.trigger('postDragStart'); return false; }, 'dragMove': function(e) { var drg = Draggable.current; drg.trigger('preDragMove'); var curMouse = drg.getMousePos(e); drg.setPosition(curMouse.x, curMouse.y) drg.trigger('postDragMove'); }, 'dragEnd': function(e) { var drg = Draggable.current; drg.trigger('preDragEnd'); removeEvent(document.body, 'mousemove', drg.dragMove); removeEvent(document.body, 'mouseup', drg.dragEnd); Draggable.current = null; drg.trigger('postDragEnd'); }, 'trigger': function(event) { if(this.events[event]) { if(this.events[event].constructor == Array) { for(var i = 0; i < this.events[event].length; i++) { this.events[event].call(this); } } else { this.events[event].call(this); } } } }; [/size] I'll pos some pre-built event things later, as that's where most of the functionality in a drag-drop comes from.
Last Edit: Jul 24, 2009 5:41:16 GMT by Eric
|
|
|
|
Looks simple enough. I'm liking the way you set up the pre/post drag stuff. Reminds me of how a plugin system works for, well, most open source PHP apps. Which I guess is the logical way.
|
|
|
|
|
Basic event object that increases functionality by a ton: var dropHolders = { 'preDragStart': function() { this.originalHolder = this.element.parentNode; }, 'postDragEnd': function() { var drops = document.getElementsByTagName('div'); var oH = this.originalHolder; delete this.originalHolder; var offs, ch, c; this.element.style.position = 'relative'; this.element.style.top = '0px'; this.element.style.left = '0px'; for(var d = 0; d < drops.length; d++) { if(hasClass(drops[d], 'droppable')) { offs = this.getAbsOffsets(drops[d]); offs.x2 = offs.x + drops[d].offsetWidth; offs.y2 = offs.y + drops[d].offsetHeight; if(this.current.x > offs.x && this.current.x < offs.x2 && this.current.y > offs.y && this.current.y < offs.y2) { ch = drops[d].childNodes; for(c = 0; c < ch.length; c++) { if(ch[c].nodeName == 'DIV' && this.getAbsOffsets(ch[c]).y > this.current.y) { this.element.parentNode.removeChild(this.element); drops[d].insertBefore(this.element, ch[c]); return; } } this.element.parentNode.removeChild(this.element); drops[d].appendChild(this.element); return; } } } this.element.parentNode.removeChild(this.element); oH.appendChild(this.element); } };
Example behavior: digishout.com/digitalcs/tests/dragndrop.htm
Last Edit: Jul 24, 2009 5:29:29 GMT by Eric
|
|
|
|
Hm ... wonder if I can incorporate this into some drag/drop category sorter!
|
|
|
|
Hm ... wonder if I can incorporate this into some drag/drop category sorter! I've used a more complex event script to manage complex hierarchies of software dependencies and key generation. Every drag and drop had to change several hidden field values so that they could be posted. It definitely can be done.
|
|
|
|
Eric, can I kill the pre there? It's stretching v1 horribly.
|
|
|
|
|
Eric, can I kill the pre there? It's stretching v1 horribly. Negative , then it's not human readable. Is that better? Btw, I'm using V1 and it wasn't that bad for me.
|
|
|
|
It's better now. It was bad if you don't use the post splitter (having a hash in the URL disables it.)
|
|
|
|
|
Not gonna lie... that seems like a shitload of code for something that seems so simple. Granted... I know nothing about coding but still. lol
Fredy Sucks Donkey Ass. Big. Donkey. Ass.
|
|
|
|
Not gonna lie... that seems like a shitload of code for something that seems so simple. Granted... I know nothing about coding but still. lol Fredy Sucks Donkey Ass. Big. Donkey. Ass.Yeah it is fairly lengthy, but that's the price you pay for generic code versus target specific code.
|
|
|
|
Not gonna lie... that seems like a shitload of code for something that seems so simple. Granted... I know nothing about coding but still. lol Fredy Sucks Donkey Ass. Big. Donkey. Ass.Pretty much, Eric's thing above is much more efficient and adaptable. It's like a JS library... I could use an entire library to add a div to the page, or I could add a single line. For reusability purposes, I want the library. If it's very specific, then the single line.
Last Edit: Aug 3, 2009 4:31:31 GMT by Chris
|
|
|
|
|