Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved performance, browser support, bugfixes #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Update draggable.js
Touch support
  • Loading branch information
bcherny committed Sep 24, 2012
commit e7768c80109b630865ef9fb6f00be54196c6cd1e
88 changes: 50 additions & 38 deletions draggable.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
function Drag(element, handle, opts) {
function Draggable(element, handle, opts) {

'use strict';

// options
this.options = {
@@ -21,7 +23,7 @@ function Drag(element, handle, opts) {

// set user-defined options

for (opt in opts) {
for (var opt in opts) {
if (options.hasOwnProperty(opt)) {
options[opt] = opts[opt];
}
@@ -31,43 +33,40 @@ function Drag(element, handle, opts) {
var cursorOffsetX, cursorOffsetY, elementHeight, elementWidth;
var self = this;
var isIE = navigator.appName === 'Microsoft Internet Explorer';
var hasTouch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;

// public vars
this.element = handle || element;
this.X;
this.Y;
this.X = 0;
this.Y = 0;

this.move = function(x ,y) {
var style = this.element.style;
var direction = options.direction;
var limit = options.limit;
var lowIsOk, highIsOk;

if (direction.x) {
if (limit.x !== null) {
var lowIsOk = x > limit.x[0],
highIsOk = x + elementWidth <= limit.x[1];
lowIsOk = x > limit.x[0];
highIsOk = x + elementWidth <= limit.x[1];
}
else var lowIsOk = highIsOk = 1;
else lowIsOk = highIsOk = 1;

self.X = x;
style.left =
lowIsOk && highIsOk
? x + 'px'
: (!lowIsOk ? 0 : (limit.x[1]-elementWidth) + 'px');
lowIsOk && highIsOk ? x + 'px' : (!lowIsOk ? 0 : (limit.x[1]-elementWidth) + 'px');
}

if (direction.y) {
if (limit.y !== null) {
var lowIsOk = y > limit.y[0],
highIsOk = y + elementHeight <= limit.y[1];
lowIsOk = y > limit.y[0],
highIsOk = y + elementHeight <= limit.y[1];
}
else var lowIsOk = highIsOk = 1;
else lowIsOk = highIsOk = 1;

self.Y = y;
style.top =
lowIsOk && highIsOk
? y + 'px'
: (!lowIsOk ? 0 : (limit.y[1]-elementHeight) + 'px');
style.top = lowIsOk && highIsOk ? y + 'px' : (!lowIsOk ? 0 : (limit.y[1]-elementHeight) + 'px');
}
};

@@ -82,8 +81,8 @@ function Drag(element, handle, opts) {
elementWidth = nopx(compStyle.width);

// optional styling
var style = element.style;
if (options.setPosition) {
var style = element.style;
style.left = element.offsetLeft + 'px';
style.top = element.offsetTop + 'px';
style.right = 'auto';
@@ -93,15 +92,15 @@ function Drag(element, handle, opts) {
if (options.setCursor) style.cursor = 'move';

// attach mousedown event
addEvent(element, 'mousedown', start);
addEvent(element, (hasTouch ? 'touchstart' : 'mousedown'), start);
};

var start = function(e) {
// cross-browser event
var e = e || event;
var ev = e || window.event;

// prevent browsers from visually dragging the element's outline
stopEvent(e);
stopEvent(ev);

// set a high z-index, just in case
var element = self.element;
@@ -110,49 +109,61 @@ function Drag(element, handle, opts) {

// set initial position
var initialPosition = getInitialPosition(element);
cursorOffsetX = (self.X=initialPosition.x) - e.clientX;
cursorOffsetY = (self.Y=initialPosition.y) - e.clientY;
cursorOffsetX = (self.X=initialPosition.x) - (hasTouch ? ev.targetTouches[0] : ev).clientX;
cursorOffsetY = (self.Y=initialPosition.y) - (hasTouch ? ev.targetTouches[0] : ev).clientY;

// add event listeners
var doc = document;
addEvent(doc, 'selectstart', stopEvent);
addEvent(doc, 'mousemove', drag);
addEvent(doc, 'mouseup', stop);
if (hasTouch) {
addEvent(doc, 'touchmove', drag);
addEvent(doc, 'touchend', stop);
}
else {
addEvent(doc, 'mousemove', drag);
addEvent(doc, 'mouseup', stop);
}

// trigger start event
if (f=options.onDragStart) f(element, self.X, self.Y, e);
if (options.onDragStart) options.onDragStart(element, self.X, self.Y, ev);
};

var drag = function(e) {
// cross-browser event
var e = e || event;
var ev = e || window.event;

// compute new coordinates
var x = e.clientX + cursorOffsetX;
var y = e.clientY + cursorOffsetY;
var x = (hasTouch ? ev.targetTouches[0] : ev).clientX + cursorOffsetX;
var y = (hasTouch ? ev.targetTouches[0] : ev).clientY + cursorOffsetY;

// move the element
self.move(x, y);

// trigger drag event
if (f=options.onDrag) f(self.element, x, y, e);
if (options.onDrag) options.onDrag(self.element, x, y, ev);
};

var stop = function(e) {
// cross-browser event
var e = e || event;
var ev = e || window.event;

// remove event listeners
var doc = document;
removeEvent(doc, 'mousemove', drag);
removeEvent(doc, 'mouseup', stop);
removeEvent(doc, 'selectstart', stopEvent);
if (hasTouch) {
removeEvent(doc, 'touchmove', drag);
removeEvent(doc, 'touchend', stop);
}
else {
removeEvent(doc, 'mousemove', drag);
removeEvent(doc, 'mouseup', stop);
}

// resent element's z-index
self.element.style.zIndex = self.element.oldZindex;

// trigger dragend event
if (f=options.onDragEnd) f(self.element, self.X, self.Y, e);
if (options.onDragEnd) options.onDragEnd(self.element, self.X, self.Y, ev);
};

var getInitialPosition = function(element) {
@@ -168,9 +179,10 @@ function Drag(element, handle, opts) {
} while (i = i.offsetParent && !getStyle(i.parentNode).position);

// subtract margin and border widths
if (style = getStyle(element)) {
left -= (nopx(style['marginLeft']) || 0) - (nopx(style['borderLeftWidth']) || 0);
top -= (nopx(style['marginTop']) || 0) - (nopx(style['borderTopWidth']) || 0);
var style = getStyle(element);
if (style) {
left -= (nopx(style.marginLeft) || 0) - (nopx(style.borderLeftWidth) || 0);
top -= (nopx(style.marginTop) || 0) - (nopx(style.borderTopWidth) || 0);
}

return {x: left, y: top};
@@ -181,7 +193,7 @@ function Drag(element, handle, opts) {
}

function removeEvent(element, e, func) {
return isIE ? element.detachEvent('on'+e, func) : element.removeEventListener(e, func, false)
return isIE ? element.detachEvent('on'+e, func) : element.removeEventListener(e, func, false);
}

function getStyle(element) {