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 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