201 lines
5.3 KiB
JavaScript
201 lines
5.3 KiB
JavaScript
/*
|
|
jQuery grab
|
|
https://github.com/jussi-kalliokoski/jQuery.grab
|
|
Ported from Jin.js::gestures
|
|
https://github.com/jussi-kalliokoski/jin.js/
|
|
Created by Jussi Kalliokoski
|
|
Licensed under MIT License.
|
|
|
|
Includes fix for IE
|
|
*/
|
|
|
|
|
|
(function($){
|
|
var extend = $.extend,
|
|
mousedown = 'mousedown',
|
|
mousemove = 'mousemove',
|
|
mouseup = 'mouseup',
|
|
touchstart = 'touchstart',
|
|
touchmove = 'touchmove',
|
|
touchend = 'touchend',
|
|
touchcancel = 'touchcancel';
|
|
|
|
function unbind(elem, type, func){
|
|
if (type.substr(0,5) !== 'touch'){ // A temporary fix for IE8 data passing problem in Jin.
|
|
return $(elem).unbind(type, func);
|
|
}
|
|
var fnc, i;
|
|
for (i=0; i<bind._binds.length; i++){
|
|
if (bind._binds[i].elem === elem && bind._binds[i].type === type && bind._binds[i].func === func){
|
|
if (document.addEventListener){
|
|
elem.removeEventListener(type, bind._binds[i].fnc, false);
|
|
} else {
|
|
elem.detachEvent('on'+type, bind._binds[i].fnc);
|
|
}
|
|
bind._binds.splice(i--, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
function bind(elem, type, func, pass){
|
|
if (type.substr(0,5) !== 'touch'){ // A temporary fix for IE8 data passing problem in Jin.
|
|
return $(elem).bind(type, pass, func);
|
|
}
|
|
var fnc, i;
|
|
if (bind[type]){
|
|
return bind[type].bind(elem, type, func, pass);
|
|
}
|
|
fnc = function(e){
|
|
if (!e){ // Fix some ie bugs...
|
|
e = window.event;
|
|
}
|
|
if (!e.stopPropagation){
|
|
e.stopPropagation = function(){ this.cancelBubble = true; };
|
|
}
|
|
e.data = pass;
|
|
func.call(elem, e);
|
|
};
|
|
if (document.addEventListener){
|
|
elem.addEventListener(type, fnc, false);
|
|
} else {
|
|
elem.attachEvent('on' + type, fnc);
|
|
}
|
|
bind._binds.push({elem: elem, type: type, func: func, fnc: fnc});
|
|
}
|
|
|
|
function grab(elem, options)
|
|
{
|
|
var data = {
|
|
move: {x: 0, y: 0},
|
|
offset: {x: 0, y: 0},
|
|
position: {x: 0, y: 0},
|
|
start: {x: 0, y: 0},
|
|
affects: document.documentElement,
|
|
stopPropagation: false,
|
|
preventDefault: true,
|
|
touch: true // Implementation unfinished, and doesn't support multitouch
|
|
};
|
|
extend(data, options);
|
|
data.element = elem;
|
|
bind(elem, mousedown, mouseDown, data);
|
|
if (data.touch){
|
|
bind(elem, touchstart, touchStart, data);
|
|
}
|
|
}
|
|
function ungrab(elem){
|
|
unbind(elem, mousedown, mousedown);
|
|
}
|
|
function mouseDown(e){
|
|
e.data.position.x = e.pageX;
|
|
e.data.position.y = e.pageY;
|
|
e.data.start.x = e.pageX;
|
|
e.data.start.y = e.pageY;
|
|
e.data.event = e;
|
|
if (e.data.onstart && e.data.onstart.call(e.data.element, e.data)){
|
|
return;
|
|
}
|
|
if (e.preventDefault && e.data.preventDefault){
|
|
e.preventDefault();
|
|
}
|
|
if (e.stopPropagation && e.data.stopPropagation){
|
|
e.stopPropagation();
|
|
}
|
|
bind(e.data.affects, mousemove, mouseMove, e.data);
|
|
bind(e.data.affects, mouseup, mouseUp, e.data);
|
|
}
|
|
function mouseMove(e){
|
|
if (e.preventDefault && e.data.preventDefault){
|
|
e.preventDefault();
|
|
}
|
|
if (e.stopPropagation && e.data.preventDefault){
|
|
e.stopPropagation();
|
|
}
|
|
e.data.move.x = e.pageX - e.data.position.x;
|
|
e.data.move.y = e.pageY - e.data.position.y;
|
|
e.data.position.x = e.pageX;
|
|
e.data.position.y = e.pageY;
|
|
e.data.offset.x = e.pageX - e.data.start.x;
|
|
e.data.offset.y = e.pageY - e.data.start.y;
|
|
e.data.event = e;
|
|
if (e.data.onmove){
|
|
e.data.onmove.call(e.data.element, e.data);
|
|
}
|
|
}
|
|
function mouseUp(e){
|
|
if (e.preventDefault && e.data.preventDefault){
|
|
e.preventDefault();
|
|
}
|
|
if (e.stopPropagation && e.data.stopPropagation){
|
|
e.stopPropagation();
|
|
}
|
|
unbind(e.data.affects, mousemove, mouseMove);
|
|
unbind(e.data.affects, mouseup, mouseUp);
|
|
e.data.event = e;
|
|
if (e.data.onfinish){
|
|
e.data.onfinish.call(e.data.element, e.data);
|
|
}
|
|
}
|
|
function touchStart(e){
|
|
e.data.position.x = e.touches[0].pageX;
|
|
e.data.position.y = e.touches[0].pageY;
|
|
e.data.start.x = e.touches[0].pageX;
|
|
e.data.start.y = e.touches[0].pageY;
|
|
e.data.event = e;
|
|
if (e.data.onstart && e.data.onstart.call(e.data.element, e.data)){
|
|
return;
|
|
}
|
|
if (e.preventDefault && e.data.preventDefault){
|
|
e.preventDefault();
|
|
}
|
|
if (e.stopPropagation && e.data.stopPropagation){
|
|
e.stopPropagation();
|
|
}
|
|
bind(e.data.affects, touchmove, touchMove, e.data);
|
|
bind(e.data.affects, touchend, touchEnd, e.data);
|
|
}
|
|
function touchMove(e){
|
|
if (e.preventDefault && e.data.preventDefault){
|
|
e.preventDefault();
|
|
}
|
|
if (e.stopPropagation && e.data.stopPropagation){
|
|
e.stopPropagation();
|
|
}
|
|
e.data.move.x = e.touches[0].pageX - e.data.position.x;
|
|
e.data.move.y = e.touches[0].pageY - e.data.position.y;
|
|
e.data.position.x = e.touches[0].pageX;
|
|
e.data.position.y = e.touches[0].pageY;
|
|
e.data.offset.x = e.touches[0].pageX - e.data.start.x;
|
|
e.data.offset.y = e.touches[0].pageY - e.data.start.y;
|
|
e.data.event = e;
|
|
if (e.data.onmove){
|
|
e.data.onmove.call(e.data.elem, e.data);
|
|
}
|
|
}
|
|
function touchEnd(e){
|
|
if (e.preventDefault && e.data.preventDefault){
|
|
e.preventDefault();
|
|
}
|
|
if (e.stopPropagation && e.data.stopPropagation){
|
|
e.stopPropagation();
|
|
}
|
|
unbind(e.data.affects, touchmove, touchMove);
|
|
unbind(e.data.affects, touchend, touchEnd);
|
|
e.data.event = e;
|
|
if (e.data.onfinish){
|
|
e.data.onfinish.call(e.data.element, e.data);
|
|
}
|
|
}
|
|
|
|
bind._binds = [];
|
|
|
|
$.fn.grab = function(a, b){
|
|
return this.each(function(){
|
|
return grab(this, a, b);
|
|
});
|
|
};
|
|
$.fn.ungrab = function(a){
|
|
return this.each(function(){
|
|
return ungrab(this, a);
|
|
});
|
|
};
|
|
})(jQuery); |