Created
November 21, 2014 14:46
-
-
Save newbie78/18c1652c249120aafc67 to your computer and use it in GitHub Desktop.
mootools 1.5.1 drag&drop with mobile support
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Drag = new Class({ | |
Implements: [Events, Options], | |
options: {/* | |
onBeforeStart: function(thisElement){}, | |
onStart: function(thisElement, event){}, | |
onSnap: function(thisElement){}, | |
onDrag: function(thisElement, event){}, | |
onCancel: function(thisElement){}, | |
onComplete: function(thisElement, event){},*/ | |
snap: 6, | |
unit: 'px', | |
grid: false, | |
style: true, | |
limit: false, | |
handle: false, | |
invert: false, | |
preventDefault: false, | |
stopPropagation: false, | |
compensateScroll: false, | |
modifiers: {x: 'left', y: 'top'} | |
}, | |
initialize: function(){ | |
var params = Array.link(arguments, { | |
'options': Type.isObject, | |
'element': function(obj){ | |
return obj != null; | |
} | |
}); | |
this.element = document.id(params.element); | |
this.document = this.element.getDocument(); | |
this.setOptions(params.options || {}); | |
var htype = typeOf(this.options.handle); | |
this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element; | |
this.mouse = {'now': {}, 'pos': {}}; | |
this.value = {'start': {}, 'now': {}}; | |
this.offsetParent = (function(el){ | |
var offsetParent = el.getOffsetParent(); | |
var isBody = !offsetParent || (/^(?:body|html)$/i).test(offsetParent.tagName); | |
return isBody ? window : document.id(offsetParent); | |
})(this.element); | |
this.selection = 'selectstart' in document ? 'selectstart' : 'mousedown'; | |
this.compensateScroll = {start: {}, diff: {}, last: {}}; | |
if ('ondragstart' in document && !('FileReader' in window) && !Drag.ondragstartFixed){ | |
document.ondragstart = Function.from(false); | |
Drag.ondragstartFixed = true; | |
} | |
this.bound = { | |
start: this.start.bind(this), | |
check: this.check.bind(this), | |
drag: this.drag.bind(this), | |
stop: this.stop.bind(this), | |
cancel: this.cancel.bind(this), | |
eventStop: Function.from(false), | |
scrollListener: this.scrollListener.bind(this) | |
}; | |
this.attach(); | |
}, | |
attach: function(){ | |
this.handles.addEvent('mousedown', this.bound.start); | |
this.handles.addEvent('touchstart', this.bound.start); | |
if (this.options.compensateScroll) this.offsetParent.addEvent('scroll', this.bound.scrollListener); | |
return this; | |
}, | |
detach: function(){ | |
this.handles.removeEvent('mousedown', this.bound.start); | |
this.handles.removeEvent('touchstart', this.bound.start); | |
if (this.options.compensateScroll) this.offsetParent.removeEvent('scroll', this.bound.scrollListener); | |
return this; | |
}, | |
scrollListener: function(){ | |
if (!this.mouse.start) return; | |
var newScrollValue = this.offsetParent.getScroll(); | |
if (this.element.getStyle('position') == 'absolute'){ | |
var scrollDiff = this.sumValues(newScrollValue, this.compensateScroll.last, -1); | |
this.mouse.now = this.sumValues(this.mouse.now, scrollDiff, 1); | |
} else { | |
this.compensateScroll.diff = this.sumValues(newScrollValue, this.compensateScroll.start, -1); | |
} | |
if (this.offsetParent != window) this.compensateScroll.diff = this.sumValues(this.compensateScroll.start, newScrollValue, -1); | |
this.compensateScroll.last = newScrollValue; | |
this.render(this.options); | |
}, | |
sumValues: function(alpha, beta, op){ | |
var sum = {}, options = this.options; | |
for (z in options.modifiers){ | |
if (!options.modifiers[z]) continue; | |
sum[z] = alpha[z] + beta[z] * op; | |
} | |
return sum; | |
}, | |
start: function(event){ | |
var options = this.options; | |
if (event.rightClick) return; | |
if (options.preventDefault) event.preventDefault(); | |
if (options.stopPropagation) event.stopPropagation(); | |
this.compensateScroll.start = this.compensateScroll.last = this.offsetParent.getScroll(); | |
this.compensateScroll.diff = {x: 0, y: 0}; | |
this.mouse.start = event.page; | |
this.fireEvent('beforeStart', this.element); | |
var limit = options.limit; | |
this.limit = {x: [], y: []}; | |
var z, coordinates, offsetParent = this.offsetParent == window ? null : this.offsetParent; | |
for (z in options.modifiers){ | |
if (!options.modifiers[z]) continue; | |
var style = this.element.getStyle(options.modifiers[z]); | |
// Some browsers (IE and Opera) don't always return pixels. | |
if (style && !style.match(/px$/)){ | |
if (!coordinates) coordinates = this.element.getCoordinates(offsetParent); | |
style = coordinates[options.modifiers[z]]; | |
} | |
if (options.style) this.value.now[z] = (style || 0).toInt(); | |
else this.value.now[z] = this.element[options.modifiers[z]]; | |
if (options.invert) this.value.now[z] *= -1; | |
this.mouse.pos[z] = event.page[z] - this.value.now[z]; | |
if (limit && limit[z]){ | |
var i = 2; | |
while (i--){ | |
var limitZI = limit[z][i]; | |
if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI; | |
} | |
} | |
} | |
if (typeOf(this.options.grid) == 'number') this.options.grid = { | |
x: this.options.grid, | |
y: this.options.grid | |
}; | |
var events = { | |
mousemove: this.bound.check, | |
mouseup: this.bound.cancel, | |
touchmove: this.bound.check, | |
touchend: this.bound.cancel | |
}; | |
events[this.selection] = this.bound.eventStop; | |
this.document.addEvents(events); | |
}, | |
check: function(event){ | |
if (this.options.preventDefault) event.preventDefault(); | |
var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2))); | |
if (distance > this.options.snap){ | |
this.cancel(); | |
this.document.addEvents({ | |
mousemove: this.bound.drag, | |
mouseup: this.bound.stop, | |
touchmove: this.bound.drag, | |
touchend: this.bound.stop | |
}); | |
this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element); | |
} | |
}, | |
drag: function(event){ | |
var options = this.options; | |
if (options.preventDefault) event.preventDefault(); | |
this.mouse.now = this.sumValues(event.page, this.compensateScroll.diff, -1); | |
this.render(options); | |
this.fireEvent('drag', [this.element, event]); | |
}, | |
render: function(options){ | |
for (var z in options.modifiers){ | |
if (!options.modifiers[z]) continue; | |
this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z]; | |
if (options.invert) this.value.now[z] *= -1; | |
if (options.limit && this.limit[z]){ | |
if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){ | |
this.value.now[z] = this.limit[z][1]; | |
} else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){ | |
this.value.now[z] = this.limit[z][0]; | |
} | |
} | |
if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]); | |
if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit); | |
else this.element[options.modifiers[z]] = this.value.now[z]; | |
} | |
}, | |
cancel: function(event){ | |
this.document.removeEvents({ | |
mousemove: this.bound.check, | |
mouseup: this.bound.cancel, | |
touchmove: this.bound.check, | |
touchend: this.bound.cancel | |
}); | |
if (event){ | |
this.document.removeEvent(this.selection, this.bound.eventStop); | |
this.fireEvent('cancel', this.element); | |
} | |
}, | |
stop: function(event){ | |
var events = { | |
mousemove: this.bound.drag, | |
mouseup: this.bound.stop, | |
touchmove: this.bound.drag, | |
touchend: this.bound.stop | |
}; | |
events[this.selection] = this.bound.eventStop; | |
this.document.removeEvents(events); | |
this.mouse.start = null; | |
if (event) this.fireEvent('complete', [this.element, event]); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment