Files
dbois/public/css/vendor/plugins/draggabilly/draggabilly.pkgd.js
T
2017-12-14 10:17:13 +01:00

1539 lines
37 KiB
JavaScript
Executable File

/*!
* Draggabilly PACKAGED v2.1.1
* Make that shiz draggable
* http://draggabilly.desandro.com
* MIT license
*/
/**
* Bridget makes jQuery widgets
* v2.0.0
* MIT license
*/
/* jshint browser: true, strict: true, undef: true, unused: true */
( function( window, factory ) {
/* globals define: false, module: false, require: false */
if ( typeof define == 'function' && define.amd ) {
// AMD
define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {
factory( window, jQuery );
});
} else if ( typeof module == 'object' && module.exports ) {
// CommonJS
module.exports = factory(
window,
require('jquery')
);
} else {
// browser global
window.jQueryBridget = factory(
window,
window.jQuery
);
}
}( window, function factory( window, jQuery ) {
// ----- utils ----- //
var arraySlice = Array.prototype.slice;
// helper function for logging errors
// $.error breaks jQuery chaining
var console = window.console;
var logError = typeof console == 'undefined' ? function() {} :
function( message ) {
console.error( message );
};
// ----- jQueryBridget ----- //
function jQueryBridget( namespace, PluginClass, $ ) {
$ = $ || jQuery || window.jQuery;
if ( !$ ) {
return;
}
// add option method -> $().plugin('option', {...})
if ( !PluginClass.prototype.option ) {
// option setter
PluginClass.prototype.option = function( opts ) {
// bail out if not an object
if ( !$.isPlainObject( opts ) ){
return;
}
this.options = $.extend( true, this.options, opts );
};
}
// make jQuery plugin
$.fn[ namespace ] = function( arg0 /*, arg1 */ ) {
if ( typeof arg0 == 'string' ) {
// method call $().plugin( 'methodName', { options } )
// shift arguments by 1
var args = arraySlice.call( arguments, 1 );
return methodCall( this, arg0, args );
}
// just $().plugin({ options })
plainCall( this, arg0 );
return this;
};
// $().plugin('methodName')
function methodCall( $elems, methodName, args ) {
var returnValue;
var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';
$elems.each( function( i, elem ) {
// get instance
var instance = $.data( elem, namespace );
if ( !instance ) {
logError( namespace + ' not initialized. Cannot call methods, i.e. ' +
pluginMethodStr );
return;
}
var method = instance[ methodName ];
if ( !method || methodName.charAt(0) == '_' ) {
logError( pluginMethodStr + ' is not a valid method' );
return;
}
// apply method, get return value
var value = method.apply( instance, args );
// set return value if value is returned, use only first value
returnValue = returnValue === undefined ? value : returnValue;
});
return returnValue !== undefined ? returnValue : $elems;
}
function plainCall( $elems, options ) {
$elems.each( function( i, elem ) {
var instance = $.data( elem, namespace );
if ( instance ) {
// set options & init
instance.option( options );
instance._init();
} else {
// initialize new instance
instance = new PluginClass( elem, options );
$.data( elem, namespace, instance );
}
});
}
updateJQuery( $ );
}
// ----- updateJQuery ----- //
// set $.bridget for v1 backwards compatibility
function updateJQuery( $ ) {
if ( !$ || ( $ && $.bridget ) ) {
return;
}
$.bridget = jQueryBridget;
}
updateJQuery( jQuery || window.jQuery );
// ----- ----- //
return jQueryBridget;
}));
/*!
* getSize v2.0.2
* measure size of elements
* MIT license
*/
/*jshint browser: true, strict: true, undef: true, unused: true */
/*global define: false, module: false, console: false */
( function( window, factory ) {
if ( typeof define == 'function' && define.amd ) {
// AMD
define( 'get-size/get-size',[],function() {
return factory();
});
} else if ( typeof module == 'object' && module.exports ) {
// CommonJS
module.exports = factory();
} else {
// browser global
window.getSize = factory();
}
})( window, function factory() {
// -------------------------- helpers -------------------------- //
// get a number from a string, not a percentage
function getStyleSize( value ) {
var num = parseFloat( value );
// not a percent like '100%', and a number
var isValid = value.indexOf('%') == -1 && !isNaN( num );
return isValid && num;
}
function noop() {}
var logError = typeof console == 'undefined' ? noop :
function( message ) {
console.error( message );
};
// -------------------------- measurements -------------------------- //
var measurements = [
'paddingLeft',
'paddingRight',
'paddingTop',
'paddingBottom',
'marginLeft',
'marginRight',
'marginTop',
'marginBottom',
'borderLeftWidth',
'borderRightWidth',
'borderTopWidth',
'borderBottomWidth'
];
var measurementsLength = measurements.length;
function getZeroSize() {
var size = {
width: 0,
height: 0,
innerWidth: 0,
innerHeight: 0,
outerWidth: 0,
outerHeight: 0
};
for ( var i=0; i < measurementsLength; i++ ) {
var measurement = measurements[i];
size[ measurement ] = 0;
}
return size;
}
// -------------------------- getStyle -------------------------- //
/**
* getStyle, get style of element, check for Firefox bug
* https://bugzilla.mozilla.org/show_bug.cgi?id=548397
*/
function getStyle( elem ) {
var style = getComputedStyle( elem );
if ( !style ) {
logError( 'Style returned ' + style +
'. Are you running this code in a hidden iframe on Firefox? ' +
'See http://bit.ly/getsizebug1' );
}
return style;
}
// -------------------------- setup -------------------------- //
var isSetup = false;
var isBoxSizeOuter;
/**
* setup
* check isBoxSizerOuter
* do on first getSize() rather than on page load for Firefox bug
*/
function setup() {
// setup once
if ( isSetup ) {
return;
}
isSetup = true;
// -------------------------- box sizing -------------------------- //
/**
* WebKit measures the outer-width on style.width on border-box elems
* IE & Firefox<29 measures the inner-width
*/
var div = document.createElement('div');
div.style.width = '200px';
div.style.padding = '1px 2px 3px 4px';
div.style.borderStyle = 'solid';
div.style.borderWidth = '1px 2px 3px 4px';
div.style.boxSizing = 'border-box';
var body = document.body || document.documentElement;
body.appendChild( div );
var style = getStyle( div );
getSize.isBoxSizeOuter = isBoxSizeOuter = getStyleSize( style.width ) == 200;
body.removeChild( div );
}
// -------------------------- getSize -------------------------- //
function getSize( elem ) {
setup();
// use querySeletor if elem is string
if ( typeof elem == 'string' ) {
elem = document.querySelector( elem );
}
// do not proceed on non-objects
if ( !elem || typeof elem != 'object' || !elem.nodeType ) {
return;
}
var style = getStyle( elem );
// if hidden, everything is 0
if ( style.display == 'none' ) {
return getZeroSize();
}
var size = {};
size.width = elem.offsetWidth;
size.height = elem.offsetHeight;
var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
// get all measurements
for ( var i=0; i < measurementsLength; i++ ) {
var measurement = measurements[i];
var value = style[ measurement ];
var num = parseFloat( value );
// any 'auto', 'medium' value will be 0
size[ measurement ] = !isNaN( num ) ? num : 0;
}
var paddingWidth = size.paddingLeft + size.paddingRight;
var paddingHeight = size.paddingTop + size.paddingBottom;
var marginWidth = size.marginLeft + size.marginRight;
var marginHeight = size.marginTop + size.marginBottom;
var borderWidth = size.borderLeftWidth + size.borderRightWidth;
var borderHeight = size.borderTopWidth + size.borderBottomWidth;
var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
// overwrite width and height if we can get it from style
var styleWidth = getStyleSize( style.width );
if ( styleWidth !== false ) {
size.width = styleWidth +
// add padding and border unless it's already including it
( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
}
var styleHeight = getStyleSize( style.height );
if ( styleHeight !== false ) {
size.height = styleHeight +
// add padding and border unless it's already including it
( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
}
size.innerWidth = size.width - ( paddingWidth + borderWidth );
size.innerHeight = size.height - ( paddingHeight + borderHeight );
size.outerWidth = size.width + marginWidth;
size.outerHeight = size.height + marginHeight;
return size;
}
return getSize;
});
/**
* EvEmitter v1.0.3
* Lil' event emitter
* MIT License
*/
/* jshint unused: true, undef: true, strict: true */
( function( global, factory ) {
// universal module definition
/* jshint strict: false */ /* globals define, module, window */
if ( typeof define == 'function' && define.amd ) {
// AMD - RequireJS
define( 'ev-emitter/ev-emitter',factory );
} else if ( typeof module == 'object' && module.exports ) {
// CommonJS - Browserify, Webpack
module.exports = factory();
} else {
// Browser globals
global.EvEmitter = factory();
}
}( typeof window != 'undefined' ? window : this, function() {
function EvEmitter() {}
var proto = EvEmitter.prototype;
proto.on = function( eventName, listener ) {
if ( !eventName || !listener ) {
return;
}
// set events hash
var events = this._events = this._events || {};
// set listeners array
var listeners = events[ eventName ] = events[ eventName ] || [];
// only add once
if ( listeners.indexOf( listener ) == -1 ) {
listeners.push( listener );
}
return this;
};
proto.once = function( eventName, listener ) {
if ( !eventName || !listener ) {
return;
}
// add event
this.on( eventName, listener );
// set once flag
// set onceEvents hash
var onceEvents = this._onceEvents = this._onceEvents || {};
// set onceListeners object
var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
// set flag
onceListeners[ listener ] = true;
return this;
};
proto.off = function( eventName, listener ) {
var listeners = this._events && this._events[ eventName ];
if ( !listeners || !listeners.length ) {
return;
}
var index = listeners.indexOf( listener );
if ( index != -1 ) {
listeners.splice( index, 1 );
}
return this;
};
proto.emitEvent = function( eventName, args ) {
var listeners = this._events && this._events[ eventName ];
if ( !listeners || !listeners.length ) {
return;
}
var i = 0;
var listener = listeners[i];
args = args || [];
// once stuff
var onceListeners = this._onceEvents && this._onceEvents[ eventName ];
while ( listener ) {
var isOnce = onceListeners && onceListeners[ listener ];
if ( isOnce ) {
// remove listener
// remove before trigger to prevent recursion
this.off( eventName, listener );
// unset once flag
delete onceListeners[ listener ];
}
// trigger listener
listener.apply( this, args );
// get next listener
i += isOnce ? 0 : 1;
listener = listeners[i];
}
return this;
};
return EvEmitter;
}));
/*!
* Unipointer v2.1.0
* base class for doing one thing with pointer event
* MIT license
*/
/*jshint browser: true, undef: true, unused: true, strict: true */
( function( window, factory ) {
// universal module definition
/* jshint strict: false */ /*global define, module, require */
if ( typeof define == 'function' && define.amd ) {
// AMD
define( 'unipointer/unipointer',[
'ev-emitter/ev-emitter'
], function( EvEmitter ) {
return factory( window, EvEmitter );
});
} else if ( typeof module == 'object' && module.exports ) {
// CommonJS
module.exports = factory(
window,
require('ev-emitter')
);
} else {
// browser global
window.Unipointer = factory(
window,
window.EvEmitter
);
}
}( window, function factory( window, EvEmitter ) {
function noop() {}
function Unipointer() {}
// inherit EvEmitter
var proto = Unipointer.prototype = Object.create( EvEmitter.prototype );
proto.bindStartEvent = function( elem ) {
this._bindStartEvent( elem, true );
};
proto.unbindStartEvent = function( elem ) {
this._bindStartEvent( elem, false );
};
/**
* works as unbinder, as you can ._bindStart( false ) to unbind
* @param {Boolean} isBind - will unbind if falsey
*/
proto._bindStartEvent = function( elem, isBind ) {
// munge isBind, default to true
isBind = isBind === undefined ? true : !!isBind;
var bindMethod = isBind ? 'addEventListener' : 'removeEventListener';
if ( window.navigator.pointerEnabled ) {
// W3C Pointer Events, IE11. See https://coderwall.com/p/mfreca
elem[ bindMethod ]( 'pointerdown', this );
} else if ( window.navigator.msPointerEnabled ) {
// IE10 Pointer Events
elem[ bindMethod ]( 'MSPointerDown', this );
} else {
// listen for both, for devices like Chrome Pixel
elem[ bindMethod ]( 'mousedown', this );
elem[ bindMethod ]( 'touchstart', this );
}
};
// trigger handler methods for events
proto.handleEvent = function( event ) {
var method = 'on' + event.type;
if ( this[ method ] ) {
this[ method ]( event );
}
};
// returns the touch that we're keeping track of
proto.getTouch = function( touches ) {
for ( var i=0; i < touches.length; i++ ) {
var touch = touches[i];
if ( touch.identifier == this.pointerIdentifier ) {
return touch;
}
}
};
// ----- start event ----- //
proto.onmousedown = function( event ) {
// dismiss clicks from right or middle buttons
var button = event.button;
if ( button && ( button !== 0 && button !== 1 ) ) {
return;
}
this._pointerDown( event, event );
};
proto.ontouchstart = function( event ) {
this._pointerDown( event, event.changedTouches[0] );
};
proto.onMSPointerDown =
proto.onpointerdown = function( event ) {
this._pointerDown( event, event );
};
/**
* pointer start
* @param {Event} event
* @param {Event or Touch} pointer
*/
proto._pointerDown = function( event, pointer ) {
// dismiss other pointers
if ( this.isPointerDown ) {
return;
}
this.isPointerDown = true;
// save pointer identifier to match up touch events
this.pointerIdentifier = pointer.pointerId !== undefined ?
// pointerId for pointer events, touch.indentifier for touch events
pointer.pointerId : pointer.identifier;
this.pointerDown( event, pointer );
};
proto.pointerDown = function( event, pointer ) {
this._bindPostStartEvents( event );
this.emitEvent( 'pointerDown', [ event, pointer ] );
};
// hash of events to be bound after start event
var postStartEvents = {
mousedown: [ 'mousemove', 'mouseup' ],
touchstart: [ 'touchmove', 'touchend', 'touchcancel' ],
pointerdown: [ 'pointermove', 'pointerup', 'pointercancel' ],
MSPointerDown: [ 'MSPointerMove', 'MSPointerUp', 'MSPointerCancel' ]
};
proto._bindPostStartEvents = function( event ) {
if ( !event ) {
return;
}
// get proper events to match start event
var events = postStartEvents[ event.type ];
// bind events to node
events.forEach( function( eventName ) {
window.addEventListener( eventName, this );
}, this );
// save these arguments
this._boundPointerEvents = events;
};
proto._unbindPostStartEvents = function() {
// check for _boundEvents, in case dragEnd triggered twice (old IE8 bug)
if ( !this._boundPointerEvents ) {
return;
}
this._boundPointerEvents.forEach( function( eventName ) {
window.removeEventListener( eventName, this );
}, this );
delete this._boundPointerEvents;
};
// ----- move event ----- //
proto.onmousemove = function( event ) {
this._pointerMove( event, event );
};
proto.onMSPointerMove =
proto.onpointermove = function( event ) {
if ( event.pointerId == this.pointerIdentifier ) {
this._pointerMove( event, event );
}
};
proto.ontouchmove = function( event ) {
var touch = this.getTouch( event.changedTouches );
if ( touch ) {
this._pointerMove( event, touch );
}
};
/**
* pointer move
* @param {Event} event
* @param {Event or Touch} pointer
* @private
*/
proto._pointerMove = function( event, pointer ) {
this.pointerMove( event, pointer );
};
// public
proto.pointerMove = function( event, pointer ) {
this.emitEvent( 'pointerMove', [ event, pointer ] );
};
// ----- end event ----- //
proto.onmouseup = function( event ) {
this._pointerUp( event, event );
};
proto.onMSPointerUp =
proto.onpointerup = function( event ) {
if ( event.pointerId == this.pointerIdentifier ) {
this._pointerUp( event, event );
}
};
proto.ontouchend = function( event ) {
var touch = this.getTouch( event.changedTouches );
if ( touch ) {
this._pointerUp( event, touch );
}
};
/**
* pointer up
* @param {Event} event
* @param {Event or Touch} pointer
* @private
*/
proto._pointerUp = function( event, pointer ) {
this._pointerDone();
this.pointerUp( event, pointer );
};
// public
proto.pointerUp = function( event, pointer ) {
this.emitEvent( 'pointerUp', [ event, pointer ] );
};
// ----- pointer done ----- //
// triggered on pointer up & pointer cancel
proto._pointerDone = function() {
// reset properties
this.isPointerDown = false;
delete this.pointerIdentifier;
// remove events
this._unbindPostStartEvents();
this.pointerDone();
};
proto.pointerDone = noop;
// ----- pointer cancel ----- //
proto.onMSPointerCancel =
proto.onpointercancel = function( event ) {
if ( event.pointerId == this.pointerIdentifier ) {
this._pointerCancel( event, event );
}
};
proto.ontouchcancel = function( event ) {
var touch = this.getTouch( event.changedTouches );
if ( touch ) {
this._pointerCancel( event, touch );
}
};
/**
* pointer cancel
* @param {Event} event
* @param {Event or Touch} pointer
* @private
*/
proto._pointerCancel = function( event, pointer ) {
this._pointerDone();
this.pointerCancel( event, pointer );
};
// public
proto.pointerCancel = function( event, pointer ) {
this.emitEvent( 'pointerCancel', [ event, pointer ] );
};
// ----- ----- //
// utility function for getting x/y coords from event
Unipointer.getPointerPoint = function( pointer ) {
return {
x: pointer.pageX,
y: pointer.pageY
};
};
// ----- ----- //
return Unipointer;
}));
/*!
* Unidragger v2.1.0
* Draggable base class
* MIT license
*/
/*jshint browser: true, unused: true, undef: true, strict: true */
( function( window, factory ) {
// universal module definition
/*jshint strict: false */ /*globals define, module, require */
if ( typeof define == 'function' && define.amd ) {
// AMD
define( 'unidragger/unidragger',[
'unipointer/unipointer'
], function( Unipointer ) {
return factory( window, Unipointer );
});
} else if ( typeof module == 'object' && module.exports ) {
// CommonJS
module.exports = factory(
window,
require('unipointer')
);
} else {
// browser global
window.Unidragger = factory(
window,
window.Unipointer
);
}
}( window, function factory( window, Unipointer ) {
// ----- ----- //
function noop() {}
// -------------------------- Unidragger -------------------------- //
function Unidragger() {}
// inherit Unipointer & EvEmitter
var proto = Unidragger.prototype = Object.create( Unipointer.prototype );
// ----- bind start ----- //
proto.bindHandles = function() {
this._bindHandles( true );
};
proto.unbindHandles = function() {
this._bindHandles( false );
};
var navigator = window.navigator;
/**
* works as unbinder, as you can .bindHandles( false ) to unbind
* @param {Boolean} isBind - will unbind if falsey
*/
proto._bindHandles = function( isBind ) {
// munge isBind, default to true
isBind = isBind === undefined ? true : !!isBind;
// extra bind logic
var binderExtra;
if ( navigator.pointerEnabled ) {
binderExtra = function( handle ) {
// disable scrolling on the element
handle.style.touchAction = isBind ? 'none' : '';
};
} else if ( navigator.msPointerEnabled ) {
binderExtra = function( handle ) {
// disable scrolling on the element
handle.style.msTouchAction = isBind ? 'none' : '';
};
} else {
binderExtra = noop;
}
// bind each handle
var bindMethod = isBind ? 'addEventListener' : 'removeEventListener';
for ( var i=0; i < this.handles.length; i++ ) {
var handle = this.handles[i];
this._bindStartEvent( handle, isBind );
binderExtra( handle );
handle[ bindMethod ]( 'click', this );
}
};
// ----- start event ----- //
/**
* pointer start
* @param {Event} event
* @param {Event or Touch} pointer
*/
proto.pointerDown = function( event, pointer ) {
// dismiss range sliders
if ( event.target.nodeName == 'INPUT' && event.target.type == 'range' ) {
// reset pointerDown logic
this.isPointerDown = false;
delete this.pointerIdentifier;
return;
}
this._dragPointerDown( event, pointer );
// kludge to blur focused inputs in dragger
var focused = document.activeElement;
if ( focused && focused.blur ) {
focused.blur();
}
// bind move and end events
this._bindPostStartEvents( event );
this.emitEvent( 'pointerDown', [ event, pointer ] );
};
// base pointer down logic
proto._dragPointerDown = function( event, pointer ) {
// track to see when dragging starts
this.pointerDownPoint = Unipointer.getPointerPoint( pointer );
var canPreventDefault = this.canPreventDefaultOnPointerDown( event, pointer );
if ( canPreventDefault ) {
event.preventDefault();
}
};
// overwriteable method so Flickity can prevent for scrolling
proto.canPreventDefaultOnPointerDown = function( event ) {
// prevent default, unless touchstart or <select>
return event.target.nodeName != 'SELECT';
};
// ----- move event ----- //
/**
* drag move
* @param {Event} event
* @param {Event or Touch} pointer
*/
proto.pointerMove = function( event, pointer ) {
var moveVector = this._dragPointerMove( event, pointer );
this.emitEvent( 'pointerMove', [ event, pointer, moveVector ] );
this._dragMove( event, pointer, moveVector );
};
// base pointer move logic
proto._dragPointerMove = function( event, pointer ) {
var movePoint = Unipointer.getPointerPoint( pointer );
var moveVector = {
x: movePoint.x - this.pointerDownPoint.x,
y: movePoint.y - this.pointerDownPoint.y
};
// start drag if pointer has moved far enough to start drag
if ( !this.isDragging && this.hasDragStarted( moveVector ) ) {
this._dragStart( event, pointer );
}
return moveVector;
};
// condition if pointer has moved far enough to start drag
proto.hasDragStarted = function( moveVector ) {
return Math.abs( moveVector.x ) > 3 || Math.abs( moveVector.y ) > 3;
};
// ----- end event ----- //
/**
* pointer up
* @param {Event} event
* @param {Event or Touch} pointer
*/
proto.pointerUp = function( event, pointer ) {
this.emitEvent( 'pointerUp', [ event, pointer ] );
this._dragPointerUp( event, pointer );
};
proto._dragPointerUp = function( event, pointer ) {
if ( this.isDragging ) {
this._dragEnd( event, pointer );
} else {
// pointer didn't move enough for drag to start
this._staticClick( event, pointer );
}
};
// -------------------------- drag -------------------------- //
// dragStart
proto._dragStart = function( event, pointer ) {
this.isDragging = true;
this.dragStartPoint = Unipointer.getPointerPoint( pointer );
// prevent clicks
this.isPreventingClicks = true;
this.dragStart( event, pointer );
};
proto.dragStart = function( event, pointer ) {
this.emitEvent( 'dragStart', [ event, pointer ] );
};
// dragMove
proto._dragMove = function( event, pointer, moveVector ) {
// do not drag if not dragging yet
if ( !this.isDragging ) {
return;
}
this.dragMove( event, pointer, moveVector );
};
proto.dragMove = function( event, pointer, moveVector ) {
event.preventDefault();
this.emitEvent( 'dragMove', [ event, pointer, moveVector ] );
};
// dragEnd
proto._dragEnd = function( event, pointer ) {
// set flags
this.isDragging = false;
// re-enable clicking async
setTimeout( function() {
delete this.isPreventingClicks;
}.bind( this ) );
this.dragEnd( event, pointer );
};
proto.dragEnd = function( event, pointer ) {
this.emitEvent( 'dragEnd', [ event, pointer ] );
};
// ----- onclick ----- //
// handle all clicks and prevent clicks when dragging
proto.onclick = function( event ) {
if ( this.isPreventingClicks ) {
event.preventDefault();
}
};
// ----- staticClick ----- //
// triggered after pointer down & up with no/tiny movement
proto._staticClick = function( event, pointer ) {
// ignore emulated mouse up clicks
if ( this.isIgnoringMouseUp && event.type == 'mouseup' ) {
return;
}
// allow click in <input>s and <textarea>s
var nodeName = event.target.nodeName;
if ( nodeName == 'INPUT' || nodeName == 'TEXTAREA' ) {
event.target.focus();
}
this.staticClick( event, pointer );
// set flag for emulated clicks 300ms after touchend
if ( event.type != 'mouseup' ) {
this.isIgnoringMouseUp = true;
// reset flag after 300ms
setTimeout( function() {
delete this.isIgnoringMouseUp;
}.bind( this ), 400 );
}
};
proto.staticClick = function( event, pointer ) {
this.emitEvent( 'staticClick', [ event, pointer ] );
};
// ----- utils ----- //
Unidragger.getPointerPoint = Unipointer.getPointerPoint;
// ----- ----- //
return Unidragger;
}));
/*!
* Draggabilly v2.1.1
* Make that shiz draggable
* http://draggabilly.desandro.com
* MIT license
*/
/*jshint browser: true, strict: true, undef: true, unused: true */
( function( window, factory ) {
// universal module definition
/* jshint strict: false */ /*globals define, module, require */
if ( typeof define == 'function' && define.amd ) {
// AMD
define( [
'get-size/get-size',
'unidragger/unidragger'
],
function( getSize, Unidragger ) {
return factory( window, getSize, Unidragger );
});
} else if ( typeof module == 'object' && module.exports ) {
// CommonJS
module.exports = factory(
window,
require('get-size'),
require('unidragger')
);
} else {
// browser global
window.Draggabilly = factory(
window,
window.getSize,
window.Unidragger
);
}
}( window, function factory( window, getSize, Unidragger ) {
// vars
var document = window.document;
function noop() {}
// -------------------------- helpers -------------------------- //
// extend objects
function extend( a, b ) {
for ( var prop in b ) {
a[ prop ] = b[ prop ];
}
return a;
}
function isElement( obj ) {
return obj instanceof HTMLElement;
}
// -------------------------- requestAnimationFrame -------------------------- //
// get rAF, prefixed, if present
var requestAnimationFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
// fallback to setTimeout
var lastTime = 0;
if ( !requestAnimationFrame ) {
requestAnimationFrame = function( callback ) {
var currTime = new Date().getTime();
var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
var id = setTimeout( callback, timeToCall );
lastTime = currTime + timeToCall;
return id;
};
}
// -------------------------- support -------------------------- //
var docElem = document.documentElement;
var transformProperty = typeof docElem.style.transform == 'string' ?
'transform' : 'WebkitTransform';
var jQuery = window.jQuery;
// -------------------------- -------------------------- //
function Draggabilly( element, options ) {
// querySelector if string
this.element = typeof element == 'string' ?
document.querySelector( element ) : element;
if ( jQuery ) {
this.$element = jQuery( this.element );
}
// options
this.options = extend( {}, this.constructor.defaults );
this.option( options );
this._create();
}
// inherit Unidragger methods
var proto = Draggabilly.prototype = Object.create( Unidragger.prototype );
Draggabilly.defaults = {
};
/**
* set options
* @param {Object} opts
*/
proto.option = function( opts ) {
extend( this.options, opts );
};
// css position values that don't need to be set
var positionValues = {
relative: true,
absolute: true,
fixed: true
};
proto._create = function() {
// properties
this.position = {};
this._getPosition();
this.startPoint = { x: 0, y: 0 };
this.dragPoint = { x: 0, y: 0 };
this.startPosition = extend( {}, this.position );
// set relative positioning
var style = getComputedStyle( this.element );
if ( !positionValues[ style.position ] ) {
this.element.style.position = 'relative';
}
this.enable();
this.setHandles();
};
/**
* set this.handles and bind start events to 'em
*/
proto.setHandles = function() {
this.handles = this.options.handle ?
this.element.querySelectorAll( this.options.handle ) : [ this.element ];
this.bindHandles();
};
/**
* emits events via EvEmitter and jQuery events
* @param {String} type - name of event
* @param {Event} event - original event
* @param {Array} args - extra arguments
*/
proto.dispatchEvent = function( type, event, args ) {
var emitArgs = [ event ].concat( args );
this.emitEvent( type, emitArgs );
var jQuery = window.jQuery;
// trigger jQuery event
if ( jQuery && this.$element ) {
if ( event ) {
// create jQuery event
var $event = jQuery.Event( event );
$event.type = type;
this.$element.trigger( $event, args );
} else {
// just trigger with type if no event available
this.$element.trigger( type, args );
}
}
};
// -------------------------- position -------------------------- //
// get x/y position from style
proto._getPosition = function() {
var style = getComputedStyle( this.element );
var x = this._getPositionCoord( style.left, 'width' );
var y = this._getPositionCoord( style.top, 'height' );
// clean up 'auto' or other non-integer values
this.position.x = isNaN( x ) ? 0 : x;
this.position.y = isNaN( y ) ? 0 : y;
this._addTransformPosition( style );
};
proto._getPositionCoord = function( styleSide, measure ) {
if ( styleSide.indexOf('%') != -1 ) {
// convert percent into pixel for Safari, #75
var parentSize = getSize( this.element.parentNode );
// prevent not-in-DOM element throwing bug, #131
return !parentSize ? 0 :
( parseFloat( styleSide ) / 100 ) * parentSize[ measure ];
}
return parseInt( styleSide, 10 );
};
// add transform: translate( x, y ) to position
proto._addTransformPosition = function( style ) {
var transform = style[ transformProperty ];
// bail out if value is 'none'
if ( transform.indexOf('matrix') !== 0 ) {
return;
}
// split matrix(1, 0, 0, 1, x, y)
var matrixValues = transform.split(',');
// translate X value is in 12th or 4th position
var xIndex = transform.indexOf('matrix3d') === 0 ? 12 : 4;
var translateX = parseInt( matrixValues[ xIndex ], 10 );
// translate Y value is in 13th or 5th position
var translateY = parseInt( matrixValues[ xIndex + 1 ], 10 );
this.position.x += translateX;
this.position.y += translateY;
};
// -------------------------- events -------------------------- //
/**
* pointer start
* @param {Event} event
* @param {Event or Touch} pointer
*/
proto.pointerDown = function( event, pointer ) {
this._dragPointerDown( event, pointer );
// kludge to blur focused inputs in dragger
var focused = document.activeElement;
// do not blur body for IE10, metafizzy/flickity#117
if ( focused && focused.blur && focused != document.body ) {
focused.blur();
}
// bind move and end events
this._bindPostStartEvents( event );
this.element.classList.add('is-pointer-down');
this.dispatchEvent( 'pointerDown', event, [ pointer ] );
};
/**
* drag move
* @param {Event} event
* @param {Event or Touch} pointer
*/
proto.pointerMove = function( event, pointer ) {
var moveVector = this._dragPointerMove( event, pointer );
this.dispatchEvent( 'pointerMove', event, [ pointer, moveVector ] );
this._dragMove( event, pointer, moveVector );
};
/**
* drag start
* @param {Event} event
* @param {Event or Touch} pointer
*/
proto.dragStart = function( event, pointer ) {
if ( !this.isEnabled ) {
return;
}
this._getPosition();
this.measureContainment();
// position _when_ drag began
this.startPosition.x = this.position.x;
this.startPosition.y = this.position.y;
// reset left/top style
this.setLeftTop();
this.dragPoint.x = 0;
this.dragPoint.y = 0;
this.element.classList.add('is-dragging');
this.dispatchEvent( 'dragStart', event, [ pointer ] );
// start animation
this.animate();
};
proto.measureContainment = function() {
var containment = this.options.containment;
if ( !containment ) {
return;
}
// use element if element
var container = isElement( containment ) ? containment :
// fallback to querySelector if string
typeof containment == 'string' ? document.querySelector( containment ) :
// otherwise just `true`, use the parent
this.element.parentNode;
var elemSize = getSize( this.element );
var containerSize = getSize( container );
var elemRect = this.element.getBoundingClientRect();
var containerRect = container.getBoundingClientRect();
var borderSizeX = containerSize.borderLeftWidth + containerSize.borderRightWidth;
var borderSizeY = containerSize.borderTopWidth + containerSize.borderBottomWidth;
var position = this.relativeStartPosition = {
x: elemRect.left - ( containerRect.left + containerSize.borderLeftWidth ),
y: elemRect.top - ( containerRect.top + containerSize.borderTopWidth )
};
this.containSize = {
width: ( containerSize.width - borderSizeX ) - position.x - elemSize.width,
height: ( containerSize.height - borderSizeY ) - position.y - elemSize.height
};
};
// ----- move event ----- //
/**
* drag move
* @param {Event} event
* @param {Event or Touch} pointer
*/
proto.dragMove = function( event, pointer, moveVector ) {
if ( !this.isEnabled ) {
return;
}
var dragX = moveVector.x;
var dragY = moveVector.y;
var grid = this.options.grid;
var gridX = grid && grid[0];
var gridY = grid && grid[1];
dragX = applyGrid( dragX, gridX );
dragY = applyGrid( 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;
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.dispatchEvent( 'dragMove', event, [ pointer, moveVector ] );
};
function applyGrid( value, grid, method ) {
method = method || 'round';
return grid ? Math[ method ]( value / grid ) * grid : value;
}
proto.containDrag = function( axis, drag, grid ) {
if ( !this.options.containment ) {
return drag;
}
var measure = axis == 'x' ? 'width' : 'height';
var rel = this.relativeStartPosition[ axis ];
var min = applyGrid( -rel, grid, 'ceil' );
var max = this.containSize[ measure ];
max = applyGrid( max, grid, 'floor' );
return Math.min( max, Math.max( min, drag ) );
};
// ----- end event ----- //
/**
* pointer up
* @param {Event} event
* @param {Event or Touch} pointer
*/
proto.pointerUp = function( event, pointer ) {
this.element.classList.remove('is-pointer-down');
this.dispatchEvent( 'pointerUp', event, [ pointer ] );
this._dragPointerUp( event, pointer );
};
/**
* drag end
* @param {Event} event
* @param {Event or Touch} pointer
*/
proto.dragEnd = function( event, pointer ) {
if ( !this.isEnabled ) {
return;
}
// use top left position when complete
if ( transformProperty ) {
this.element.style[ transformProperty ] = '';
this.setLeftTop();
}
this.element.classList.remove('is-dragging');
this.dispatchEvent( 'dragEnd', event, [ pointer ] );
};
// -------------------------- animation -------------------------- //
proto.animate = function() {
// only render and animate if dragging
if ( !this.isDragging ) {
return;
}
this.positionDrag();
var _this = this;
requestAnimationFrame( function animateFrame() {
_this.animate();
});
};
// left/top positioning
proto.setLeftTop = function() {
this.element.style.left = this.position.x + 'px';
this.element.style.top = this.position.y + 'px';
};
proto.positionDrag = function() {
this.element.style[ transformProperty ] = 'translate3d( ' + this.dragPoint.x +
'px, ' + this.dragPoint.y + 'px, 0)';
};
// ----- staticClick ----- //
proto.staticClick = function( event, pointer ) {
this.dispatchEvent( 'staticClick', event, [ pointer ] );
};
// ----- methods ----- //
proto.enable = function() {
this.isEnabled = true;
};
proto.disable = function() {
this.isEnabled = false;
if ( this.isDragging ) {
this.dragEnd();
}
};
proto.destroy = function() {
this.disable();
// reset styles
this.element.style[ transformProperty ] = '';
this.element.style.left = '';
this.element.style.top = '';
this.element.style.position = '';
// unbind handles
this.unbindHandles();
// remove jQuery data
if ( this.$element ) {
this.$element.removeData('draggabilly');
}
};
// ----- jQuery bridget ----- //
// required for jQuery bridget
proto._init = noop;
if ( jQuery && jQuery.bridget ) {
jQuery.bridget( 'draggabilly', Draggabilly );
}
// ----- ----- //
return Draggabilly;
}));