Skip to content

Instantly share code, notes, and snippets.

@methyl
Created September 5, 2014 23:25
Show Gist options
  • Save methyl/c9cf16594a48dcded033 to your computer and use it in GitHub Desktop.
Save methyl/c9cf16594a48dcded033 to your computer and use it in GitHub Desktop.
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
SquerbWidgets.Utils.DragAndDrop.Draggable = (function() {
_.extend(Draggable.prototype, Backbone.Events);
function Draggable(options) {
this.onMouseLeave = __bind(this.onMouseLeave, this);
this.onMouseUp = __bind(this.onMouseUp, this);
this.onMouseDown = __bind(this.onMouseDown, this);
this.onMouseMove = __bind(this.onMouseMove, this);
this.onTouchEnd = __bind(this.onTouchEnd, this);
this.onTouchMove = __bind(this.onTouchMove, this);
this.onTouchStart = __bind(this.onTouchStart, this);
this.onTouchPress = __bind(this.onTouchPress, this);
var _ref;
this.$el = options.$el;
this.$el.attr('data-id', options.id);
this.dragAndDrop = options.dragAndDrop;
this.mc = new Hammer.Manager(this.$el[0]);
this.mc.add(new Hammer.Press({
time: 100
}));
_ref = this.getTransitionPosition(), this.initialX = _ref[0], this.initialY = _ref[1];
this.bindEvents();
}
Draggable.prototype.getPosition = function() {
if (this.absolutePosition) {
return {
x: this.absolutePosition.x,
y: this.absolutePosition.y
};
} else {
return {
x: 0,
y: 0
};
}
};
Draggable.prototype.getTransitionPosition = function() {
var position;
position = _.last(this.$el.css('transform').split(', ').map(function(i) {
return parseInt(i);
}), 2);
if (position[0]) {
return position;
} else {
return [0, 0];
}
};
Draggable.prototype.bindEvents = function() {
if (Modernizr.touch) {
return this.bindTouchEvents();
} else {
return this.bindNonTouchEvents();
}
};
Draggable.prototype.unbindEvents = function() {
if (Modernizr.touch) {
return this.unbindTouchEvents();
} else {
return this.unbindNonTouchEvents();
}
};
Draggable.prototype.isInDropzone = function() {
return this.dragAndDrop.isInDropzone(this);
};
Draggable.prototype.bindTouchEvents = function() {
this.mc.on('press', this.onTouchPress);
this.$el.on('touchstart', this.onTouchStart);
this.$el.on('touchmove', this.onTouchMove);
return $(window).on('touchend', this.onTouchEnd);
};
Draggable.prototype.unbindTouchEvents = function() {
this.mc.off('press', this.onTouchPress);
this.$el.off('touchstart', this.onTouchStart);
this.$el.off('touchmove', this.onTouchMove);
return $(window).off('touchend', this.onTouchEnd);
};
Draggable.prototype.onTouchPress = function() {
if (this.isDragging) {
return;
}
this.startDragging();
return this.animateInitialPosition();
};
Draggable.prototype.onTouchStart = function(e) {
e = e.originalEvent.changedTouches[0];
if (this.isDragging) {
this.lastX = e.pageX;
return this.lastY = e.pageY;
}
};
Draggable.prototype.onTouchMove = function(e) {
if (!this.isDragging) {
return;
}
this.$el.addClass('disable-transtion');
e.preventDefault();
e = e.originalEvent.changedTouches[0];
this.updatePosition({
x: e.pageX,
y: e.pageY
});
return this.$el.removeClass('disable-transtion');
};
Draggable.prototype.onTouchEnd = function(e) {
var isOnTarget;
e.preventDefault();
e.stopPropagation();
if (!this.isDragging) {
return;
}
e = e.originalEvent.changedTouches[0];
isOnTarget = $(e.target) === this.$el || this.$el.find(e.target).length > 0;
if (!isOnTarget || this.isInDropzone()) {
return this.stopDragging();
}
};
Draggable.prototype.animateInitialPosition = function() {
this.$el.addClass('enable-transition');
this.x = 10;
this.y = 30;
this.redraw();
return setTimeout((function(_this) {
return function() {
return _this.$el.removeClass('enable-transition');
};
})(this), 200);
};
Draggable.prototype.bindNonTouchEvents = function() {
this.$el.on('mousedown', this.onMouseDown);
this.$el.on('click', function(e) {
return e.preventDefault();
});
$(window).on('mouseup', this.onMouseUp);
$(window).on('mousemove', this.onMouseMove);
$(document).on('mouseleave', this.onMouseLeave);
return $(document).on('contextmenu', this.onContextMenu);
};
Draggable.prototype.unbindNonTouchEvents = function() {
this.$el.off('mousedown', this.onMouseDown);
$(window).off('mouseup', this.onMouseUp);
$(window).off('mousemove', this.onMouseMove);
$(document).off('mouseleave', this.onMouseLeave);
return $(document).off('contextmenu', this.onContextMenu);
};
Draggable.prototype.onMouseMove = function(e) {
if (this.isDragging) {
return this.updatePosition({
x: e.pageX,
y: e.pageY
});
}
};
Draggable.prototype.onMouseDown = function(e) {
e.preventDefault();
return this.startDragging();
};
Draggable.prototype.onMouseUp = function(e) {
if (!this.isDragging) {
return;
}
e.preventDefault();
e.stopPropagation();
return this.stopDragging();
};
Draggable.prototype.onMouseLeave = function() {
if (this.isDragging) {
return this.stopDragging();
}
};
Draggable.prototype.onContextMenu = function(e) {
if (e.which === 3) {
if (this.isDragging) {
return e.preventDefault();
}
}
};
Draggable.prototype.updatePosition = function(position) {
this.absolutePosition = position;
if (this.lastX) {
this.x += position.x - this.lastX;
}
if (this.lastY) {
this.y += position.y - this.lastY;
}
this.lastX = position.x;
this.lastY = position.y;
this.trigger('drag', this);
return this.redraw();
};
Draggable.prototype.redraw = function() {
return this.$el.css({
translate: [this.x + this.initialX, this.y + this.initialY]
});
};
Draggable.prototype.startDragging = function(x, y) {
if (x == null) {
x = 0;
}
if (y == null) {
y = 0;
}
this.resetPosition(x, y);
this.isDragging = true;
this.$el.addClass('dragging');
return this.trigger('dragstart', this);
};
Draggable.prototype.resetPosition = function(x, y) {
if (x == null) {
x = 0;
}
if (y == null) {
y = 0;
}
this.x = x;
this.y = y;
this.lastX = 0;
this.lastY = 0;
return this.redraw();
};
Draggable.prototype.stopDragging = function() {
this.isDragging = false;
this.$el.removeClass('dragging');
this.trigger('dragend', this);
this.absolutePosition = null;
return this.resetPosition();
};
return Draggable;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment