Skip to content

Commit

Permalink
Closes desandro#13.
Browse files Browse the repository at this point in the history
Add `distance` option and make `dragStart` event fire only when the element is moved. Fixes the bug with nested form elements clickability.
  • Loading branch information
mr-mig committed May 21, 2014
1 parent ef8cac3 commit 88406ed
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 41 deletions.
106 changes: 67 additions & 39 deletions draggabilly.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function Draggabilly( element, options ) {
this.element = typeof element === 'string' ?
document.querySelector( element ) : element;

this.options = extend( {}, this.options );
this.options = extend( {distance: 1}, this.options );
extend( this.options, options );

this._create();
Expand Down Expand Up @@ -255,7 +255,7 @@ Draggabilly.prototype.onmousedown = function( event ) {
if ( button && ( button !== 0 && button !== 1 ) ) {
return;
}
this.dragStart( event, event );
this.beforeDragStart( event, event );
};

Draggabilly.prototype.ontouchstart = function( event ) {
Expand All @@ -264,7 +264,7 @@ Draggabilly.prototype.ontouchstart = function( event ) {
return;
}

this.dragStart( event, event.changedTouches[0] );
this.beforeDragStart( event, event.changedTouches[0] );
};

Draggabilly.prototype.onMSPointerDown =
Expand All @@ -274,7 +274,7 @@ Draggabilly.prototype.onpointerdown = function( event ) {
return;
}

this.dragStart( event, event );
this.beforeDragStart( event, event );
};

function setPointerPoint( point, pointer ) {
Expand All @@ -291,19 +291,23 @@ var postStartEvents = {
};

/**
* drag start
* before drag start
* @param {Event} event
* @param {Event or Touch} pointer
*/
Draggabilly.prototype.dragStart = function( event, pointer ) {
Draggabilly.prototype.beforeDragStart = function( event, pointer ) {
if ( !this.isEnabled ) {
return;
}

if ( event.preventDefault ) {
event.preventDefault();
} else {
event.returnValue = false;
// prevent default behaviour only if distance is set to 0
// this denotes that the element is only draggable without side effects
if (this.options.distance === 0){
if ( event.preventDefault ) {
event.preventDefault();
} else {
event.returnValue = false;
}
}

// save pointer identifier to match up touch events
Expand All @@ -317,6 +321,20 @@ Draggabilly.prototype.dragStart = function( event, pointer ) {

// point where drag began
setPointerPoint( this.startPoint, pointer );

// bind move and end events
this._bindEvents({
// get proper events to match start event
events: postStartEvents[ event.type ],
// IE8 needs to be bound to document
node: event.preventDefault ? window : document
});
};

Draggabilly.prototype.dragStart = function(event, pointer){
if (this.isDragging){
return;
}
// position _when_ drag began
this.startPosition.x = this.position.x;
this.startPosition.y = this.position.y;
Expand All @@ -327,14 +345,6 @@ Draggabilly.prototype.dragStart = function( event, pointer ) {
this.dragPoint.x = 0;
this.dragPoint.y = 0;

// bind move and end events
this._bindEvents({
// get proper events to match start event
events: postStartEvents[ event.type ],
// IE8 needs to be bound to document
node: event.preventDefault ? window : document
});

classie.add( this.element, 'is-dragging' );

// reset isDragging flag
Expand Down Expand Up @@ -394,6 +404,14 @@ Draggabilly.prototype.measureContainment = function() {
};
};

Draggabilly.prototype.elementHasMoved = function(){
var start = this.startPoint,
pointer = this.dragPoint,
dx = pointer.x - start.x,
dy = pointer.y - start.y;
return dx * dx + dy * dy > this.options.distance * this.options.distance;
};

// ----- move event ----- //

Draggabilly.prototype.onmousemove = function( event ) {
Expand Down Expand Up @@ -422,30 +440,36 @@ Draggabilly.prototype.ontouchmove = function( event ) {
Draggabilly.prototype.dragMove = function( event, pointer ) {

setPointerPoint( this.dragPoint, pointer );
var dragX = this.dragPoint.x - this.startPoint.x;
var dragY = this.dragPoint.y - this.startPoint.y;
if (!this.isDragging){
if (this.elementHasMoved()){
this.dragStart(event, pointer);
}
} else {
var dragX = this.dragPoint.x - this.startPoint.x;
var dragY = this.dragPoint.y - this.startPoint.y;

var grid = this.options.grid;
var gridX = grid && grid[0];
var gridY = grid && grid[1];
var grid = this.options.grid;
var gridX = grid && grid[0];
var gridY = grid && grid[1];

dragX = applyGrid( dragX, gridX );
dragY = applyGrid( dragY, gridY );
dragX = applyGrid( dragX, gridX );
dragY = applyGrid( dragY, gridY );

dragX = this.containDrag( 'x', dragX, gridX );
dragY = this.containDrag( 'y', dragY, gridY );
dragX = this.containDrag( 'x', dragX, gridX );
dragY = this.containDrag( 'y', dragY, gridY );

// constrain to axis
dragX = this.options.axis === 'y' ? 0 : dragX;
dragY = this.options.axis === 'x' ? 0 : dragY;
// constrain to axis
dragX = this.options.axis === 'y' ? 0 : dragX;
dragY = this.options.axis === 'x' ? 0 : dragY;

this.position.x = this.startPosition.x + dragX;
this.position.y = this.startPosition.y + dragY;
// set dragPoint properties
this.dragPoint.x = dragX;
this.dragPoint.y = dragY;
this.position.x = this.startPosition.x + dragX;
this.position.y = this.startPosition.y + dragY;
// set dragPoint properties
this.dragPoint.x = dragX;
this.dragPoint.y = dragY;

this.emitEvent( 'dragMove', [ this, event, pointer ] );
this.emitEvent( 'dragMove', [ this, event, pointer ] );
}
};

function applyGrid( value, grid, method ) {
Expand Down Expand Up @@ -492,6 +516,13 @@ Draggabilly.prototype.ontouchend = function( event ) {
* @param {Event or Touch} pointer
*/
Draggabilly.prototype.dragEnd = function( event, pointer ) {
// remove events even if drag is not started
// they were binded in beforeDragStart
this._unbindEvents();

if (!this.isDragging){
return false;
}
this.isDragging = false;

delete this.pointerIdentifier;
Expand All @@ -502,9 +533,6 @@ Draggabilly.prototype.dragEnd = function( event, pointer ) {
this.setLeftTop();
}

// remove events
this._unbindEvents();

classie.remove( this.element, 'is-dragging' );

this.emitEvent( 'dragEnd', [ this, event, pointer ] );
Expand Down
19 changes: 17 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@

#axis-y { top: 230px; }

#clickdrag {
position: absolute;
top: 160px;
left: 600px;}

</style>

</head>
Expand Down Expand Up @@ -155,6 +160,15 @@ <h1>Draggabilly</h1>
<div id="axis-x" class="axised">axis: x</div>
<div id="axis-y" class="axised">axis: y</div>

<div id="clickdrag" class="box">
<button>click me</button>
<select>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>

<script src="bower_components/eventEmitter/EventEmitter.js"></script>
<script src="bower_components/eventie/eventie.js"></script>
<script src="bower_components/get-style-property/get-style-property.js"></script>
Expand Down Expand Up @@ -218,12 +232,12 @@ <h1>Draggabilly</h1>

( function() {
var elem = document.querySelector('#kitten');
new Draggabilly( elem );
new Draggabilly( elem , {distance: 0});
})();

( function() {
var elem = document.querySelector('#kitties');
new Draggabilly( elem );
new Draggabilly( elem , {distance: 0});
})();

( function() {
Expand All @@ -236,6 +250,7 @@ <h1>Draggabilly</h1>

new Draggabilly( '#axis-x', { axis: 'x' });
new Draggabilly( '#axis-y', { axis: 'y' });
new Draggabilly( '#clickdrag');

};
</script>
Expand Down

0 comments on commit 88406ed

Please sign in to comment.