|
|
|
|
@@ -1,12 +1,155 @@
|
|
|
|
|
/*!
|
|
|
|
|
* Draggabilly PACKAGED v1.0.5
|
|
|
|
|
* Draggabilly PACKAGED v1.2.4
|
|
|
|
|
* Make that shiz draggable
|
|
|
|
|
* http://draggabilly.desandro.com
|
|
|
|
|
* MIT license
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Bridget makes jQuery widgets
|
|
|
|
|
* v1.1.0
|
|
|
|
|
* MIT license
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
( function( window ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------- utils -------------------------- //
|
|
|
|
|
|
|
|
|
|
var slice = Array.prototype.slice;
|
|
|
|
|
|
|
|
|
|
function noop() {}
|
|
|
|
|
|
|
|
|
|
// -------------------------- definition -------------------------- //
|
|
|
|
|
|
|
|
|
|
function defineBridget( $ ) {
|
|
|
|
|
|
|
|
|
|
// bail if no jQuery
|
|
|
|
|
if ( !$ ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------- addOptionMethod -------------------------- //
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* adds option method -> $().plugin('option', {...})
|
|
|
|
|
* @param {Function} PluginClass - constructor class
|
|
|
|
|
*/
|
|
|
|
|
function addOptionMethod( PluginClass ) {
|
|
|
|
|
// don't overwrite original option method
|
|
|
|
|
if ( PluginClass.prototype.option ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// option setter
|
|
|
|
|
PluginClass.prototype.option = function( opts ) {
|
|
|
|
|
// bail out if not an object
|
|
|
|
|
if ( !$.isPlainObject( opts ) ){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.options = $.extend( true, this.options, opts );
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------- plugin bridge -------------------------- //
|
|
|
|
|
|
|
|
|
|
// helper function for logging errors
|
|
|
|
|
// $.error breaks jQuery chaining
|
|
|
|
|
var logError = typeof console === 'undefined' ? noop :
|
|
|
|
|
function( message ) {
|
|
|
|
|
console.error( message );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* jQuery plugin bridge, access methods like $elem.plugin('method')
|
|
|
|
|
* @param {String} namespace - plugin name
|
|
|
|
|
* @param {Function} PluginClass - constructor class
|
|
|
|
|
*/
|
|
|
|
|
function bridge( namespace, PluginClass ) {
|
|
|
|
|
// add to jQuery fn namespace
|
|
|
|
|
$.fn[ namespace ] = function( options ) {
|
|
|
|
|
if ( typeof options === 'string' ) {
|
|
|
|
|
// call plugin method when first argument is a string
|
|
|
|
|
// get arguments for method
|
|
|
|
|
var args = slice.call( arguments, 1 );
|
|
|
|
|
|
|
|
|
|
for ( var i=0, len = this.length; i < len; i++ ) {
|
|
|
|
|
var elem = this[i];
|
|
|
|
|
var instance = $.data( elem, namespace );
|
|
|
|
|
if ( !instance ) {
|
|
|
|
|
logError( "cannot call methods on " + namespace + " prior to initialization; " +
|
|
|
|
|
"attempted to call '" + options + "'" );
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) {
|
|
|
|
|
logError( "no such method '" + options + "' for " + namespace + " instance" );
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// trigger method with arguments
|
|
|
|
|
var returnValue = instance[ options ].apply( instance, args );
|
|
|
|
|
|
|
|
|
|
// break look and return first value if provided
|
|
|
|
|
if ( returnValue !== undefined ) {
|
|
|
|
|
return returnValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// return this if no return value
|
|
|
|
|
return this;
|
|
|
|
|
} else {
|
|
|
|
|
return this.each( function() {
|
|
|
|
|
var instance = $.data( this, namespace );
|
|
|
|
|
if ( instance ) {
|
|
|
|
|
// apply options & init
|
|
|
|
|
instance.option( options );
|
|
|
|
|
instance._init();
|
|
|
|
|
} else {
|
|
|
|
|
// initialize new instance
|
|
|
|
|
instance = new PluginClass( this, options );
|
|
|
|
|
$.data( this, namespace, instance );
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------- bridget -------------------------- //
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* converts a Prototypical class into a proper jQuery plugin
|
|
|
|
|
* the class must have a ._init method
|
|
|
|
|
* @param {String} namespace - plugin name, used in $().pluginName
|
|
|
|
|
* @param {Function} PluginClass - constructor class
|
|
|
|
|
*/
|
|
|
|
|
$.bridget = function( namespace, PluginClass ) {
|
|
|
|
|
addOptionMethod( PluginClass );
|
|
|
|
|
bridge( namespace, PluginClass );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return $.bridget;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// transport
|
|
|
|
|
if ( typeof define === 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define( 'jquery-bridget/jquery.bridget',[ 'jquery' ], defineBridget );
|
|
|
|
|
} else if ( typeof exports === 'object' ) {
|
|
|
|
|
defineBridget( require('jquery') );
|
|
|
|
|
} else {
|
|
|
|
|
// get jquery from browser global
|
|
|
|
|
defineBridget( window.jQuery );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})( window );
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* classie - class helper functions
|
|
|
|
|
* classie v1.0.1
|
|
|
|
|
* class helper functions
|
|
|
|
|
* from bonzo https://github.com/ded/bonzo
|
|
|
|
|
* MIT license
|
|
|
|
|
*
|
|
|
|
|
* classie.has( elem, 'my-class' ) -> true/false
|
|
|
|
|
* classie.add( elem, 'my-new-class' )
|
|
|
|
|
@@ -14,161 +157,479 @@
|
|
|
|
|
* classie.toggle( elem, 'my-class' )
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*jshint browser: true, strict: true, undef: true */
|
|
|
|
|
/*global define: false */
|
|
|
|
|
/*jshint browser: true, strict: true, undef: true, unused: true */
|
|
|
|
|
/*global define: false, module: false */
|
|
|
|
|
|
|
|
|
|
( function( window ) {
|
|
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// class helper functions from bonzo https://github.com/ded/bonzo
|
|
|
|
|
|
|
|
|
|
function classReg( className ) {
|
|
|
|
|
return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
|
|
|
|
|
}
|
|
|
|
|
function classReg( className ) {
|
|
|
|
|
return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// classList support for class management
|
|
|
|
|
// altho to be fair, the api sucks because it won't accept multiple classes at once
|
|
|
|
|
var hasClass, addClass, removeClass;
|
|
|
|
|
var hasClass, addClass, removeClass;
|
|
|
|
|
|
|
|
|
|
if ( 'classList' in document.documentElement ) {
|
|
|
|
|
hasClass = function( elem, c ) {
|
|
|
|
|
return elem.classList.contains( c );
|
|
|
|
|
};
|
|
|
|
|
addClass = function( elem, c ) {
|
|
|
|
|
elem.classList.add( c );
|
|
|
|
|
};
|
|
|
|
|
removeClass = function( elem, c ) {
|
|
|
|
|
elem.classList.remove( c );
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
hasClass = function( elem, c ) {
|
|
|
|
|
return classReg( c ).test( elem.className );
|
|
|
|
|
};
|
|
|
|
|
addClass = function( elem, c ) {
|
|
|
|
|
if ( !hasClass( elem, c ) ) {
|
|
|
|
|
elem.className = elem.className + ' ' + c;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
removeClass = function( elem, c ) {
|
|
|
|
|
elem.className = elem.className.replace( classReg( c ), ' ' );
|
|
|
|
|
};
|
|
|
|
|
if ( 'classList' in document.documentElement ) {
|
|
|
|
|
hasClass = function( elem, c ) {
|
|
|
|
|
return elem.classList.contains( c );
|
|
|
|
|
};
|
|
|
|
|
addClass = function( elem, c ) {
|
|
|
|
|
elem.classList.add( c );
|
|
|
|
|
};
|
|
|
|
|
removeClass = function( elem, c ) {
|
|
|
|
|
elem.classList.remove( c );
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
hasClass = function( elem, c ) {
|
|
|
|
|
return classReg( c ).test( elem.className );
|
|
|
|
|
};
|
|
|
|
|
addClass = function( elem, c ) {
|
|
|
|
|
if ( !hasClass( elem, c ) ) {
|
|
|
|
|
elem.className = elem.className + ' ' + c;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
removeClass = function( elem, c ) {
|
|
|
|
|
elem.className = elem.className.replace( classReg( c ), ' ' );
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toggleClass( elem, c ) {
|
|
|
|
|
var fn = hasClass( elem, c ) ? removeClass : addClass;
|
|
|
|
|
fn( elem, c );
|
|
|
|
|
}
|
|
|
|
|
function toggleClass( elem, c ) {
|
|
|
|
|
var fn = hasClass( elem, c ) ? removeClass : addClass;
|
|
|
|
|
fn( elem, c );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var classie = {
|
|
|
|
|
// full names
|
|
|
|
|
hasClass: hasClass,
|
|
|
|
|
addClass: addClass,
|
|
|
|
|
removeClass: removeClass,
|
|
|
|
|
toggleClass: toggleClass,
|
|
|
|
|
// short names
|
|
|
|
|
has: hasClass,
|
|
|
|
|
add: addClass,
|
|
|
|
|
remove: removeClass,
|
|
|
|
|
toggle: toggleClass
|
|
|
|
|
};
|
|
|
|
|
var classie = {
|
|
|
|
|
// full names
|
|
|
|
|
hasClass: hasClass,
|
|
|
|
|
addClass: addClass,
|
|
|
|
|
removeClass: removeClass,
|
|
|
|
|
toggleClass: toggleClass,
|
|
|
|
|
// short names
|
|
|
|
|
has: hasClass,
|
|
|
|
|
add: addClass,
|
|
|
|
|
remove: removeClass,
|
|
|
|
|
toggle: toggleClass
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// transport
|
|
|
|
|
if ( typeof define === 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define("classie", classie);
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.classie = classie;
|
|
|
|
|
}
|
|
|
|
|
if ( typeof define === 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define( 'classie/classie',classie );
|
|
|
|
|
} else if ( typeof exports === 'object' ) {
|
|
|
|
|
// CommonJS
|
|
|
|
|
module.exports = classie;
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.classie = classie;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})( window );
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* eventie v1.0.3
|
|
|
|
|
* event binding helper
|
|
|
|
|
* eventie.bind( elem, 'click', myFn )
|
|
|
|
|
* eventie.unbind( elem, 'click', myFn )
|
|
|
|
|
* getStyleProperty v1.0.4
|
|
|
|
|
* original by kangax
|
|
|
|
|
* http://perfectionkills.com/feature-testing-css-properties/
|
|
|
|
|
* MIT license
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*jshint browser: true, undef: true, unused: true */
|
|
|
|
|
/*global define: false */
|
|
|
|
|
/*jshint browser: true, strict: true, undef: true */
|
|
|
|
|
/*global define: false, exports: false, module: false */
|
|
|
|
|
|
|
|
|
|
( function( window ) {
|
|
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
var docElem = document.documentElement;
|
|
|
|
|
|
|
|
|
|
var bind = function() {};
|
|
|
|
|
var prefixes = 'Webkit Moz ms Ms O'.split(' ');
|
|
|
|
|
var docElemStyle = document.documentElement.style;
|
|
|
|
|
|
|
|
|
|
if ( docElem.addEventListener ) {
|
|
|
|
|
bind = function( obj, type, fn ) {
|
|
|
|
|
obj.addEventListener( type, fn, false );
|
|
|
|
|
};
|
|
|
|
|
} else if ( docElem.attachEvent ) {
|
|
|
|
|
bind = function( obj, type, fn ) {
|
|
|
|
|
obj[ type + fn ] = fn.handleEvent ?
|
|
|
|
|
function() {
|
|
|
|
|
var event = window.event;
|
|
|
|
|
// add event.target
|
|
|
|
|
event.target = event.target || event.srcElement;
|
|
|
|
|
fn.handleEvent.call( fn, event );
|
|
|
|
|
} :
|
|
|
|
|
function() {
|
|
|
|
|
var event = window.event;
|
|
|
|
|
// add event.target
|
|
|
|
|
event.target = event.target || event.srcElement;
|
|
|
|
|
fn.call( obj, event );
|
|
|
|
|
};
|
|
|
|
|
obj.attachEvent( "on" + type, obj[ type + fn ] );
|
|
|
|
|
};
|
|
|
|
|
function getStyleProperty( propName ) {
|
|
|
|
|
if ( !propName ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// test standard property first
|
|
|
|
|
if ( typeof docElemStyle[ propName ] === 'string' ) {
|
|
|
|
|
return propName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// capitalize
|
|
|
|
|
propName = propName.charAt(0).toUpperCase() + propName.slice(1);
|
|
|
|
|
|
|
|
|
|
// test vendor specific properties
|
|
|
|
|
var prefixed;
|
|
|
|
|
for ( var i=0, len = prefixes.length; i < len; i++ ) {
|
|
|
|
|
prefixed = prefixes[i] + propName;
|
|
|
|
|
if ( typeof docElemStyle[ prefixed ] === 'string' ) {
|
|
|
|
|
return prefixed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var unbind = function() {};
|
|
|
|
|
|
|
|
|
|
if ( docElem.removeEventListener ) {
|
|
|
|
|
unbind = function( obj, type, fn ) {
|
|
|
|
|
obj.removeEventListener( type, fn, false );
|
|
|
|
|
};
|
|
|
|
|
} else if ( docElem.detachEvent ) {
|
|
|
|
|
unbind = function( obj, type, fn ) {
|
|
|
|
|
obj.detachEvent( "on" + type, obj[ type + fn ] );
|
|
|
|
|
try {
|
|
|
|
|
delete obj[ type + fn ];
|
|
|
|
|
} catch ( err ) {
|
|
|
|
|
// can't delete window object properties
|
|
|
|
|
obj[ type + fn ] = undefined;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var eventie = {
|
|
|
|
|
bind: bind,
|
|
|
|
|
unbind: unbind
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// transport
|
|
|
|
|
if ( typeof define === 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define("eventie", eventie);
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.eventie = eventie;
|
|
|
|
|
}
|
|
|
|
|
if ( typeof define === 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define( 'get-style-property/get-style-property',[],function() {
|
|
|
|
|
return getStyleProperty;
|
|
|
|
|
});
|
|
|
|
|
} else if ( typeof exports === 'object' ) {
|
|
|
|
|
// CommonJS for Component
|
|
|
|
|
module.exports = getStyleProperty;
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.getStyleProperty = getStyleProperty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})( this );
|
|
|
|
|
})( window );
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* EventEmitter v4.2.4 - git.io/ee
|
|
|
|
|
* Oliver Caldwell
|
|
|
|
|
* getSize v1.2.2
|
|
|
|
|
* measure size of elements
|
|
|
|
|
* MIT license
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*jshint browser: true, strict: true, undef: true, unused: true */
|
|
|
|
|
/*global define: false, exports: false, require: false, module: false, console: false */
|
|
|
|
|
|
|
|
|
|
( function( window, undefined ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------- 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'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
function getZeroSize() {
|
|
|
|
|
var size = {
|
|
|
|
|
width: 0,
|
|
|
|
|
height: 0,
|
|
|
|
|
innerWidth: 0,
|
|
|
|
|
innerHeight: 0,
|
|
|
|
|
outerWidth: 0,
|
|
|
|
|
outerHeight: 0
|
|
|
|
|
};
|
|
|
|
|
for ( var i=0, len = measurements.length; i < len; i++ ) {
|
|
|
|
|
var measurement = measurements[i];
|
|
|
|
|
size[ measurement ] = 0;
|
|
|
|
|
}
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function defineGetSize( getStyleProperty ) {
|
|
|
|
|
|
|
|
|
|
// -------------------------- setup -------------------------- //
|
|
|
|
|
|
|
|
|
|
var isSetup = false;
|
|
|
|
|
|
|
|
|
|
var getStyle, boxSizingProp, isBoxSizeOuter;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* setup vars and functions
|
|
|
|
|
* do it on initial getSize(), rather than on script load
|
|
|
|
|
* For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397
|
|
|
|
|
*/
|
|
|
|
|
function setup() {
|
|
|
|
|
// setup once
|
|
|
|
|
if ( isSetup ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
isSetup = true;
|
|
|
|
|
|
|
|
|
|
var getComputedStyle = window.getComputedStyle;
|
|
|
|
|
getStyle = ( function() {
|
|
|
|
|
var getStyleFn = getComputedStyle ?
|
|
|
|
|
function( elem ) {
|
|
|
|
|
return getComputedStyle( elem, null );
|
|
|
|
|
} :
|
|
|
|
|
function( elem ) {
|
|
|
|
|
return elem.currentStyle;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return function getStyle( elem ) {
|
|
|
|
|
var style = getStyleFn( 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;
|
|
|
|
|
};
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
// -------------------------- box sizing -------------------------- //
|
|
|
|
|
|
|
|
|
|
boxSizingProp = getStyleProperty('boxSizing');
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* WebKit measures the outer-width on style.width on border-box elems
|
|
|
|
|
* IE & Firefox measures the inner-width
|
|
|
|
|
*/
|
|
|
|
|
if ( boxSizingProp ) {
|
|
|
|
|
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[ boxSizingProp ] = 'border-box';
|
|
|
|
|
|
|
|
|
|
var body = document.body || document.documentElement;
|
|
|
|
|
body.appendChild( div );
|
|
|
|
|
var style = getStyle( div );
|
|
|
|
|
|
|
|
|
|
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 = !!( boxSizingProp &&
|
|
|
|
|
style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' );
|
|
|
|
|
|
|
|
|
|
// get all measurements
|
|
|
|
|
for ( var i=0, len = measurements.length; i < len; i++ ) {
|
|
|
|
|
var measurement = measurements[i];
|
|
|
|
|
var value = style[ measurement ];
|
|
|
|
|
value = mungeNonPixel( elem, value );
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IE8 returns percent values, not pixels
|
|
|
|
|
// taken from jQuery's curCSS
|
|
|
|
|
function mungeNonPixel( elem, value ) {
|
|
|
|
|
// IE8 and has percent value
|
|
|
|
|
if ( window.getComputedStyle || value.indexOf('%') === -1 ) {
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
var style = elem.style;
|
|
|
|
|
// Remember the original values
|
|
|
|
|
var left = style.left;
|
|
|
|
|
var rs = elem.runtimeStyle;
|
|
|
|
|
var rsLeft = rs && rs.left;
|
|
|
|
|
|
|
|
|
|
// Put in the new values to get a computed value out
|
|
|
|
|
if ( rsLeft ) {
|
|
|
|
|
rs.left = elem.currentStyle.left;
|
|
|
|
|
}
|
|
|
|
|
style.left = value;
|
|
|
|
|
value = style.pixelLeft;
|
|
|
|
|
|
|
|
|
|
// Revert the changed values
|
|
|
|
|
style.left = left;
|
|
|
|
|
if ( rsLeft ) {
|
|
|
|
|
rs.left = rsLeft;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return getSize;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// transport
|
|
|
|
|
if ( typeof define === 'function' && define.amd ) {
|
|
|
|
|
// AMD for RequireJS
|
|
|
|
|
define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize );
|
|
|
|
|
} else if ( typeof exports === 'object' ) {
|
|
|
|
|
// CommonJS for Component
|
|
|
|
|
module.exports = defineGetSize( require('desandro-get-style-property') );
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.getSize = defineGetSize( window.getStyleProperty );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})( window );
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* eventie v1.0.6
|
|
|
|
|
* event binding helper
|
|
|
|
|
* eventie.bind( elem, 'click', myFn )
|
|
|
|
|
* eventie.unbind( elem, 'click', myFn )
|
|
|
|
|
* MIT license
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*jshint browser: true, undef: true, unused: true */
|
|
|
|
|
/*global define: false, module: false */
|
|
|
|
|
|
|
|
|
|
( function( window ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var docElem = document.documentElement;
|
|
|
|
|
|
|
|
|
|
var bind = function() {};
|
|
|
|
|
|
|
|
|
|
function getIEEvent( obj ) {
|
|
|
|
|
var event = window.event;
|
|
|
|
|
// add event.target
|
|
|
|
|
event.target = event.target || event.srcElement || obj;
|
|
|
|
|
return event;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( docElem.addEventListener ) {
|
|
|
|
|
bind = function( obj, type, fn ) {
|
|
|
|
|
obj.addEventListener( type, fn, false );
|
|
|
|
|
};
|
|
|
|
|
} else if ( docElem.attachEvent ) {
|
|
|
|
|
bind = function( obj, type, fn ) {
|
|
|
|
|
obj[ type + fn ] = fn.handleEvent ?
|
|
|
|
|
function() {
|
|
|
|
|
var event = getIEEvent( obj );
|
|
|
|
|
fn.handleEvent.call( fn, event );
|
|
|
|
|
} :
|
|
|
|
|
function() {
|
|
|
|
|
var event = getIEEvent( obj );
|
|
|
|
|
fn.call( obj, event );
|
|
|
|
|
};
|
|
|
|
|
obj.attachEvent( "on" + type, obj[ type + fn ] );
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var unbind = function() {};
|
|
|
|
|
|
|
|
|
|
if ( docElem.removeEventListener ) {
|
|
|
|
|
unbind = function( obj, type, fn ) {
|
|
|
|
|
obj.removeEventListener( type, fn, false );
|
|
|
|
|
};
|
|
|
|
|
} else if ( docElem.detachEvent ) {
|
|
|
|
|
unbind = function( obj, type, fn ) {
|
|
|
|
|
obj.detachEvent( "on" + type, obj[ type + fn ] );
|
|
|
|
|
try {
|
|
|
|
|
delete obj[ type + fn ];
|
|
|
|
|
} catch ( err ) {
|
|
|
|
|
// can't delete window object properties
|
|
|
|
|
obj[ type + fn ] = undefined;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var eventie = {
|
|
|
|
|
bind: bind,
|
|
|
|
|
unbind: unbind
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- module definition ----- //
|
|
|
|
|
|
|
|
|
|
if ( typeof define === 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define( 'eventie/eventie',eventie );
|
|
|
|
|
} else if ( typeof exports === 'object' ) {
|
|
|
|
|
// CommonJS
|
|
|
|
|
module.exports = eventie;
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.eventie = eventie;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})( window );
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* EventEmitter v4.2.11 - git.io/ee
|
|
|
|
|
* Unlicense - http://unlicense.org/
|
|
|
|
|
* Oliver Caldwell - http://oli.me.uk/
|
|
|
|
|
* @preserve
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
(function () {
|
|
|
|
|
'use strict';
|
|
|
|
|
;(function () {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Class for managing events.
|
|
|
|
|
@@ -179,12 +640,12 @@
|
|
|
|
|
function EventEmitter() {}
|
|
|
|
|
|
|
|
|
|
// Shortcuts to improve speed and size
|
|
|
|
|
|
|
|
|
|
// Easy access to the prototype
|
|
|
|
|
var proto = EventEmitter.prototype;
|
|
|
|
|
var exports = this;
|
|
|
|
|
var originalGlobalValue = exports.EventEmitter;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Finds the index of the listener for the event in it's storage array.
|
|
|
|
|
* Finds the index of the listener for the event in its storage array.
|
|
|
|
|
*
|
|
|
|
|
* @param {Function[]} listeners Array of listeners to search through.
|
|
|
|
|
* @param {Function} listener Method to look for.
|
|
|
|
|
@@ -231,7 +692,7 @@
|
|
|
|
|
|
|
|
|
|
// Return a concatenated array of all matching events if
|
|
|
|
|
// the selector is a regular expression.
|
|
|
|
|
if (typeof evt === 'object') {
|
|
|
|
|
if (evt instanceof RegExp) {
|
|
|
|
|
response = {};
|
|
|
|
|
for (key in events) {
|
|
|
|
|
if (events.hasOwnProperty(key) && evt.test(key)) {
|
|
|
|
|
@@ -315,7 +776,7 @@
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Semi-alias of addListener. It will add a listener that will be
|
|
|
|
|
* automatically removed after it's first execution.
|
|
|
|
|
* automatically removed after its first execution.
|
|
|
|
|
*
|
|
|
|
|
* @param {String|RegExp} evt Name of the event to attach the listener to.
|
|
|
|
|
* @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
|
|
|
|
|
@@ -437,7 +898,7 @@
|
|
|
|
|
var single = remove ? this.removeListener : this.addListener;
|
|
|
|
|
var multiple = remove ? this.removeListeners : this.addListeners;
|
|
|
|
|
|
|
|
|
|
// If evt is an object then pass each of it's properties to this method
|
|
|
|
|
// If evt is an object then pass each of its properties to this method
|
|
|
|
|
if (typeof evt === 'object' && !(evt instanceof RegExp)) {
|
|
|
|
|
for (i in evt) {
|
|
|
|
|
if (evt.hasOwnProperty(i) && (value = evt[i])) {
|
|
|
|
|
@@ -484,7 +945,7 @@
|
|
|
|
|
// Remove all listeners for the specified event
|
|
|
|
|
delete events[evt];
|
|
|
|
|
}
|
|
|
|
|
else if (type === 'object') {
|
|
|
|
|
else if (evt instanceof RegExp) {
|
|
|
|
|
// Remove all events matching the regex.
|
|
|
|
|
for (key in events) {
|
|
|
|
|
if (events.hasOwnProperty(key) && evt.test(key)) {
|
|
|
|
|
@@ -609,9 +1070,19 @@
|
|
|
|
|
return this._events || (this._events = {});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
|
|
|
|
|
*
|
|
|
|
|
* @return {Function} Non conflicting EventEmitter class.
|
|
|
|
|
*/
|
|
|
|
|
EventEmitter.noConflict = function noConflict() {
|
|
|
|
|
exports.EventEmitter = originalGlobalValue;
|
|
|
|
|
return EventEmitter;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Expose the class either via AMD, CommonJS or the global object
|
|
|
|
|
if (typeof define === 'function' && define.amd) {
|
|
|
|
|
define("EventEmitter", function () {
|
|
|
|
|
define('eventEmitter/EventEmitter',[],function () {
|
|
|
|
|
return EventEmitter;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
@@ -619,758 +1090,1164 @@
|
|
|
|
|
module.exports = EventEmitter;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
this.EventEmitter = EventEmitter;
|
|
|
|
|
exports.EventEmitter = EventEmitter;
|
|
|
|
|
}
|
|
|
|
|
}.call(this));
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* getStyleProperty by kangax
|
|
|
|
|
* http://perfectionkills.com/feature-testing-css-properties/
|
|
|
|
|
* Unipointer v1.1.0
|
|
|
|
|
* base class for doing one thing with pointer event
|
|
|
|
|
* MIT license
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*jshint browser: true, strict: true, undef: true */
|
|
|
|
|
/*globals define: false */
|
|
|
|
|
/*jshint browser: true, undef: true, unused: true, strict: true */
|
|
|
|
|
/*global define: false, module: false, require: false */
|
|
|
|
|
|
|
|
|
|
( function( window ) {
|
|
|
|
|
( function( window, factory ) {
|
|
|
|
|
|
|
|
|
|
// universal module definition
|
|
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
if ( typeof define == 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define( 'unipointer/unipointer',[
|
|
|
|
|
'eventEmitter/EventEmitter',
|
|
|
|
|
'eventie/eventie'
|
|
|
|
|
], function( EventEmitter, eventie ) {
|
|
|
|
|
return factory( window, EventEmitter, eventie );
|
|
|
|
|
});
|
|
|
|
|
} else if ( typeof exports == 'object' ) {
|
|
|
|
|
// CommonJS
|
|
|
|
|
module.exports = factory(
|
|
|
|
|
window,
|
|
|
|
|
require('wolfy87-eventemitter'),
|
|
|
|
|
require('eventie')
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.Unipointer = factory(
|
|
|
|
|
window,
|
|
|
|
|
window.EventEmitter,
|
|
|
|
|
window.eventie
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var prefixes = 'Webkit Moz ms Ms O'.split(' ');
|
|
|
|
|
var docElemStyle = document.documentElement.style;
|
|
|
|
|
}( window, function factory( window, EventEmitter, eventie ) {
|
|
|
|
|
|
|
|
|
|
function getStyleProperty( propName ) {
|
|
|
|
|
if ( !propName ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// test standard property first
|
|
|
|
|
if ( typeof docElemStyle[ propName ] === 'string' ) {
|
|
|
|
|
return propName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// capitalize
|
|
|
|
|
propName = propName.charAt(0).toUpperCase() + propName.slice(1);
|
|
|
|
|
function noop() {}
|
|
|
|
|
|
|
|
|
|
// test vendor specific properties
|
|
|
|
|
var prefixed;
|
|
|
|
|
for ( var i=0, len = prefixes.length; i < len; i++ ) {
|
|
|
|
|
prefixed = prefixes[i] + propName;
|
|
|
|
|
if ( typeof docElemStyle[ prefixed ] === 'string' ) {
|
|
|
|
|
return prefixed;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
function Unipointer() {}
|
|
|
|
|
|
|
|
|
|
// transport
|
|
|
|
|
if ( typeof define === 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define("getStyleProperty", function() {
|
|
|
|
|
return getStyleProperty;
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.getStyleProperty = getStyleProperty;
|
|
|
|
|
}
|
|
|
|
|
// inherit EventEmitter
|
|
|
|
|
Unipointer.prototype = new EventEmitter();
|
|
|
|
|
|
|
|
|
|
})( window );
|
|
|
|
|
Unipointer.prototype.bindStartEvent = function( elem ) {
|
|
|
|
|
this._bindStartEvent( elem, true );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unipointer.prototype.unbindStartEvent = function( elem ) {
|
|
|
|
|
this._bindStartEvent( elem, false );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* getSize v1.1.4
|
|
|
|
|
* measure size of elements
|
|
|
|
|
* works as unbinder, as you can ._bindStart( false ) to unbind
|
|
|
|
|
* @param {Boolean} isBind - will unbind if falsey
|
|
|
|
|
*/
|
|
|
|
|
Unipointer.prototype._bindStartEvent = function( elem, isBind ) {
|
|
|
|
|
// munge isBind, default to true
|
|
|
|
|
isBind = isBind === undefined ? true : !!isBind;
|
|
|
|
|
var bindMethod = isBind ? 'bind' : 'unbind';
|
|
|
|
|
|
|
|
|
|
/*jshint browser: true, strict: true, undef: true, unused: true */
|
|
|
|
|
/*global define: false */
|
|
|
|
|
if ( window.navigator.pointerEnabled ) {
|
|
|
|
|
// W3C Pointer Events, IE11. See https://coderwall.com/p/mfreca
|
|
|
|
|
eventie[ bindMethod ]( elem, 'pointerdown', this );
|
|
|
|
|
} else if ( window.navigator.msPointerEnabled ) {
|
|
|
|
|
// IE10 Pointer Events
|
|
|
|
|
eventie[ bindMethod ]( elem, 'MSPointerDown', this );
|
|
|
|
|
} else {
|
|
|
|
|
// listen for both, for devices like Chrome Pixel
|
|
|
|
|
eventie[ bindMethod ]( elem, 'mousedown', this );
|
|
|
|
|
eventie[ bindMethod ]( elem, 'touchstart', this );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
( function( window, undefined ) {
|
|
|
|
|
// trigger handler methods for events
|
|
|
|
|
Unipointer.prototype.handleEvent = function( event ) {
|
|
|
|
|
var method = 'on' + event.type;
|
|
|
|
|
if ( this[ method ] ) {
|
|
|
|
|
this[ method ]( event );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
// -------------------------- helpers -------------------------- //
|
|
|
|
|
|
|
|
|
|
var defView = document.defaultView;
|
|
|
|
|
|
|
|
|
|
var getStyle = defView && defView.getComputedStyle ?
|
|
|
|
|
function( elem ) {
|
|
|
|
|
return defView.getComputedStyle( elem, null );
|
|
|
|
|
} :
|
|
|
|
|
function( elem ) {
|
|
|
|
|
return elem.currentStyle;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
// returns the touch that we're keeping track of
|
|
|
|
|
Unipointer.prototype.getTouch = function( touches ) {
|
|
|
|
|
for ( var i=0, len = touches.length; i < len; i++ ) {
|
|
|
|
|
var touch = touches[i];
|
|
|
|
|
if ( touch.identifier == this.pointerIdentifier ) {
|
|
|
|
|
return touch;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// -------------------------- measurements -------------------------- //
|
|
|
|
|
// ----- start event ----- //
|
|
|
|
|
|
|
|
|
|
var measurements = [
|
|
|
|
|
'paddingLeft',
|
|
|
|
|
'paddingRight',
|
|
|
|
|
'paddingTop',
|
|
|
|
|
'paddingBottom',
|
|
|
|
|
'marginLeft',
|
|
|
|
|
'marginRight',
|
|
|
|
|
'marginTop',
|
|
|
|
|
'marginBottom',
|
|
|
|
|
'borderLeftWidth',
|
|
|
|
|
'borderRightWidth',
|
|
|
|
|
'borderTopWidth',
|
|
|
|
|
'borderBottomWidth'
|
|
|
|
|
];
|
|
|
|
|
Unipointer.prototype.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 );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function getZeroSize() {
|
|
|
|
|
var size = {
|
|
|
|
|
width: 0,
|
|
|
|
|
height: 0,
|
|
|
|
|
innerWidth: 0,
|
|
|
|
|
innerHeight: 0,
|
|
|
|
|
outerWidth: 0,
|
|
|
|
|
outerHeight: 0
|
|
|
|
|
};
|
|
|
|
|
for ( var i=0, len = measurements.length; i < len; i++ ) {
|
|
|
|
|
var measurement = measurements[i];
|
|
|
|
|
size[ measurement ] = 0;
|
|
|
|
|
}
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
Unipointer.prototype.ontouchstart = function( event ) {
|
|
|
|
|
this._pointerDown( event, event.changedTouches[0] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unipointer.prototype.onMSPointerDown =
|
|
|
|
|
Unipointer.prototype.onpointerdown = function( event ) {
|
|
|
|
|
this._pointerDown( event, event );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* pointer start
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Unipointer.prototype._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 );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unipointer.prototype.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' ]
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unipointer.prototype._bindPostStartEvents = function( event ) {
|
|
|
|
|
if ( !event ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// get proper events to match start event
|
|
|
|
|
var events = postStartEvents[ event.type ];
|
|
|
|
|
// IE8 needs to be bound to document
|
|
|
|
|
var node = event.preventDefault ? window : document;
|
|
|
|
|
// bind events to node
|
|
|
|
|
for ( var i=0, len = events.length; i < len; i++ ) {
|
|
|
|
|
var evnt = events[i];
|
|
|
|
|
eventie.bind( node, evnt, this );
|
|
|
|
|
}
|
|
|
|
|
// save these arguments
|
|
|
|
|
this._boundPointerEvents = {
|
|
|
|
|
events: events,
|
|
|
|
|
node: node
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unipointer.prototype._unbindPostStartEvents = function() {
|
|
|
|
|
var args = this._boundPointerEvents;
|
|
|
|
|
// IE8 can trigger dragEnd twice, check for _boundEvents
|
|
|
|
|
if ( !args || !args.events ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( var i=0, len = args.events.length; i < len; i++ ) {
|
|
|
|
|
var event = args.events[i];
|
|
|
|
|
eventie.unbind( args.node, event, this );
|
|
|
|
|
}
|
|
|
|
|
delete this._boundPointerEvents;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- move event ----- //
|
|
|
|
|
|
|
|
|
|
Unipointer.prototype.onmousemove = function( event ) {
|
|
|
|
|
this._pointerMove( event, event );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unipointer.prototype.onMSPointerMove =
|
|
|
|
|
Unipointer.prototype.onpointermove = function( event ) {
|
|
|
|
|
if ( event.pointerId == this.pointerIdentifier ) {
|
|
|
|
|
this._pointerMove( event, event );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unipointer.prototype.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
|
|
|
|
|
*/
|
|
|
|
|
Unipointer.prototype._pointerMove = function( event, pointer ) {
|
|
|
|
|
this.pointerMove( event, pointer );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// public
|
|
|
|
|
Unipointer.prototype.pointerMove = function( event, pointer ) {
|
|
|
|
|
this.emitEvent( 'pointerMove', [ event, pointer ] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- end event ----- //
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Unipointer.prototype.onmouseup = function( event ) {
|
|
|
|
|
this._pointerUp( event, event );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function defineGetSize( getStyleProperty ) {
|
|
|
|
|
Unipointer.prototype.onMSPointerUp =
|
|
|
|
|
Unipointer.prototype.onpointerup = function( event ) {
|
|
|
|
|
if ( event.pointerId == this.pointerIdentifier ) {
|
|
|
|
|
this._pointerUp( event, event );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// -------------------------- box sizing -------------------------- //
|
|
|
|
|
Unipointer.prototype.ontouchend = function( event ) {
|
|
|
|
|
var touch = this.getTouch( event.changedTouches );
|
|
|
|
|
if ( touch ) {
|
|
|
|
|
this._pointerUp( event, touch );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var boxSizingProp = getStyleProperty('boxSizing');
|
|
|
|
|
var isBoxSizeOuter;
|
|
|
|
|
/**
|
|
|
|
|
* pointer up
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
* @private
|
|
|
|
|
*/
|
|
|
|
|
Unipointer.prototype._pointerUp = function( event, pointer ) {
|
|
|
|
|
this._pointerDone();
|
|
|
|
|
this.pointerUp( event, pointer );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* WebKit measures the outer-width on style.width on border-box elems
|
|
|
|
|
* IE & Firefox measures the inner-width
|
|
|
|
|
*/
|
|
|
|
|
( function() {
|
|
|
|
|
if ( !boxSizingProp ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// public
|
|
|
|
|
Unipointer.prototype.pointerUp = function( event, pointer ) {
|
|
|
|
|
this.emitEvent( 'pointerUp', [ event, pointer ] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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[ boxSizingProp ] = 'border-box';
|
|
|
|
|
// ----- pointer done ----- //
|
|
|
|
|
|
|
|
|
|
var body = document.body || document.documentElement;
|
|
|
|
|
body.appendChild( div );
|
|
|
|
|
var style = getStyle( div );
|
|
|
|
|
// triggered on pointer up & pointer cancel
|
|
|
|
|
Unipointer.prototype._pointerDone = function() {
|
|
|
|
|
// reset properties
|
|
|
|
|
this.isPointerDown = false;
|
|
|
|
|
delete this.pointerIdentifier;
|
|
|
|
|
// remove events
|
|
|
|
|
this._unbindPostStartEvents();
|
|
|
|
|
this.pointerDone();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
isBoxSizeOuter = getStyleSize( style.width ) === 200;
|
|
|
|
|
body.removeChild( div );
|
|
|
|
|
})();
|
|
|
|
|
Unipointer.prototype.pointerDone = noop;
|
|
|
|
|
|
|
|
|
|
// ----- pointer cancel ----- //
|
|
|
|
|
|
|
|
|
|
// -------------------------- getSize -------------------------- //
|
|
|
|
|
Unipointer.prototype.onMSPointerCancel =
|
|
|
|
|
Unipointer.prototype.onpointercancel = function( event ) {
|
|
|
|
|
if ( event.pointerId == this.pointerIdentifier ) {
|
|
|
|
|
this._pointerCancel( event, event );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function getSize( elem ) {
|
|
|
|
|
// use querySeletor if elem is string
|
|
|
|
|
if ( typeof elem === 'string' ) {
|
|
|
|
|
elem = document.querySelector( elem );
|
|
|
|
|
}
|
|
|
|
|
Unipointer.prototype.ontouchcancel = function( event ) {
|
|
|
|
|
var touch = this.getTouch( event.changedTouches );
|
|
|
|
|
if ( touch ) {
|
|
|
|
|
this._pointerCancel( event, touch );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// do not proceed on non-objects
|
|
|
|
|
if ( !elem || typeof elem !== 'object' || !elem.nodeType ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* pointer cancel
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
* @private
|
|
|
|
|
*/
|
|
|
|
|
Unipointer.prototype._pointerCancel = function( event, pointer ) {
|
|
|
|
|
this._pointerDone();
|
|
|
|
|
this.pointerCancel( event, pointer );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var style = getStyle( elem );
|
|
|
|
|
// public
|
|
|
|
|
Unipointer.prototype.pointerCancel = function( event, pointer ) {
|
|
|
|
|
this.emitEvent( 'pointerCancel', [ event, pointer ] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// if hidden, everything is 0
|
|
|
|
|
if ( style.display === 'none' ) {
|
|
|
|
|
return getZeroSize();
|
|
|
|
|
}
|
|
|
|
|
// ----- ----- //
|
|
|
|
|
|
|
|
|
|
var size = {};
|
|
|
|
|
size.width = elem.offsetWidth;
|
|
|
|
|
size.height = elem.offsetHeight;
|
|
|
|
|
// utility function for getting x/y cooridinates from event, because IE8
|
|
|
|
|
Unipointer.getPointerPoint = function( pointer ) {
|
|
|
|
|
return {
|
|
|
|
|
x: pointer.pageX !== undefined ? pointer.pageX : pointer.clientX,
|
|
|
|
|
y: pointer.pageY !== undefined ? pointer.pageY : pointer.clientY
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var isBorderBox = size.isBorderBox = !!( boxSizingProp &&
|
|
|
|
|
style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' );
|
|
|
|
|
// ----- ----- //
|
|
|
|
|
|
|
|
|
|
// get all measurements
|
|
|
|
|
for ( var i=0, len = measurements.length; i < len; 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;
|
|
|
|
|
}
|
|
|
|
|
return Unipointer;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// transport
|
|
|
|
|
if ( typeof define === 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define("getSize", [ 'getStyleProperty' ], defineGetSize );
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.getSize = defineGetSize( window.getStyleProperty );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})( window );
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* Draggabilly v1.0.5
|
|
|
|
|
* Make that shiz draggable
|
|
|
|
|
* http://draggabilly.desandro.com
|
|
|
|
|
* Unidragger v1.1.0
|
|
|
|
|
* Draggable base class
|
|
|
|
|
* MIT license
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
( function( window ) {
|
|
|
|
|
/*jshint browser: true, unused: true, undef: true, strict: true */
|
|
|
|
|
|
|
|
|
|
( function( window, factory ) {
|
|
|
|
|
/*global define: false, module: false, require: false */
|
|
|
|
|
|
|
|
|
|
// universal module definition
|
|
|
|
|
|
|
|
|
|
if ( typeof define == 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define( 'unidragger/unidragger',[
|
|
|
|
|
'eventie/eventie',
|
|
|
|
|
'unipointer/unipointer'
|
|
|
|
|
], function( eventie, Unipointer ) {
|
|
|
|
|
return factory( window, eventie, Unipointer );
|
|
|
|
|
});
|
|
|
|
|
} else if ( typeof exports == 'object' ) {
|
|
|
|
|
// CommonJS
|
|
|
|
|
module.exports = factory(
|
|
|
|
|
window,
|
|
|
|
|
require('eventie'),
|
|
|
|
|
require('unipointer')
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.Unidragger = factory(
|
|
|
|
|
window,
|
|
|
|
|
window.eventie,
|
|
|
|
|
window.Unipointer
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}( window, function factory( window, eventie, Unipointer ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ----- ----- //
|
|
|
|
|
|
|
|
|
|
function noop() {}
|
|
|
|
|
|
|
|
|
|
// handle IE8 prevent default
|
|
|
|
|
function preventDefaultEvent( event ) {
|
|
|
|
|
if ( event.preventDefault ) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
} else {
|
|
|
|
|
event.returnValue = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getParentLink( elem ) {
|
|
|
|
|
while ( elem != document.body ) {
|
|
|
|
|
elem = elem.parentNode;
|
|
|
|
|
if ( elem.nodeName == 'A' ) {
|
|
|
|
|
return elem;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------- Unidragger -------------------------- //
|
|
|
|
|
|
|
|
|
|
function Unidragger() {}
|
|
|
|
|
|
|
|
|
|
// inherit Unipointer & EventEmitter
|
|
|
|
|
Unidragger.prototype = new Unipointer();
|
|
|
|
|
|
|
|
|
|
// ----- bind start ----- //
|
|
|
|
|
|
|
|
|
|
Unidragger.prototype.bindHandles = function() {
|
|
|
|
|
this._bindHandles( true );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unidragger.prototype.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
|
|
|
|
|
*/
|
|
|
|
|
Unidragger.prototype._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 = function() {
|
|
|
|
|
// TODO re-enable img.ondragstart when unbinding
|
|
|
|
|
if ( isBind ) {
|
|
|
|
|
disableImgOndragstart( handle );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
// bind each handle
|
|
|
|
|
var bindMethod = isBind ? 'bind' : 'unbind';
|
|
|
|
|
for ( var i=0, len = this.handles.length; i < len; i++ ) {
|
|
|
|
|
var handle = this.handles[i];
|
|
|
|
|
this._bindStartEvent( handle, isBind );
|
|
|
|
|
binderExtra( handle );
|
|
|
|
|
eventie[ bindMethod ]( handle, 'click', this );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// remove default dragging interaction on all images in IE8
|
|
|
|
|
// IE8 does its own drag thing on images, which messes stuff up
|
|
|
|
|
|
|
|
|
|
function noDragStart() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO replace this with a IE8 test
|
|
|
|
|
var isIE8 = 'attachEvent' in document.documentElement;
|
|
|
|
|
|
|
|
|
|
// IE8 only
|
|
|
|
|
var disableImgOndragstart = !isIE8 ? noop : function( handle ) {
|
|
|
|
|
|
|
|
|
|
if ( handle.nodeName == 'IMG' ) {
|
|
|
|
|
handle.ondragstart = noDragStart;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var images = handle.querySelectorAll('img');
|
|
|
|
|
for ( var i=0, len = images.length; i < len; i++ ) {
|
|
|
|
|
var img = images[i];
|
|
|
|
|
img.ondragstart = noDragStart;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- start event ----- //
|
|
|
|
|
|
|
|
|
|
var allowTouchstartNodes = Unidragger.allowTouchstartNodes = {
|
|
|
|
|
INPUT: true,
|
|
|
|
|
A: true,
|
|
|
|
|
BUTTON: true,
|
|
|
|
|
SELECT: true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* pointer start
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Unidragger.prototype.pointerDown = function( event, pointer ) {
|
|
|
|
|
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
|
|
|
|
|
Unidragger.prototype._dragPointerDown = function( event, pointer ) {
|
|
|
|
|
// track to see when dragging starts
|
|
|
|
|
this.pointerDownPoint = Unipointer.getPointerPoint( pointer );
|
|
|
|
|
|
|
|
|
|
var targetNodeName = event.target.nodeName;
|
|
|
|
|
// HACK iOS, allow clicks on buttons, inputs, and links, or children of links
|
|
|
|
|
var isTouchstartNode = event.type == 'touchstart' &&
|
|
|
|
|
( allowTouchstartNodes[ targetNodeName ] || getParentLink( event.target ) );
|
|
|
|
|
// do not prevent default on touchstart nodes or <select>
|
|
|
|
|
if ( !isTouchstartNode && targetNodeName != 'SELECT' ) {
|
|
|
|
|
preventDefaultEvent( event );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- move event ----- //
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* drag move
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Unidragger.prototype.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
|
|
|
|
|
Unidragger.prototype._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
|
|
|
|
|
Unidragger.prototype.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
|
|
|
|
|
*/
|
|
|
|
|
Unidragger.prototype.pointerUp = function( event, pointer ) {
|
|
|
|
|
this.emitEvent( 'pointerUp', [ event, pointer ] );
|
|
|
|
|
this._dragPointerUp( event, pointer );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unidragger.prototype._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
|
|
|
|
|
Unidragger.prototype._dragStart = function( event, pointer ) {
|
|
|
|
|
this.isDragging = true;
|
|
|
|
|
this.dragStartPoint = Unidragger.getPointerPoint( pointer );
|
|
|
|
|
// prevent clicks
|
|
|
|
|
this.isPreventingClicks = true;
|
|
|
|
|
|
|
|
|
|
this.dragStart( event, pointer );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unidragger.prototype.dragStart = function( event, pointer ) {
|
|
|
|
|
this.emitEvent( 'dragStart', [ event, pointer ] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// dragMove
|
|
|
|
|
Unidragger.prototype._dragMove = function( event, pointer, moveVector ) {
|
|
|
|
|
// do not drag if not dragging yet
|
|
|
|
|
if ( !this.isDragging ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.dragMove( event, pointer, moveVector );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unidragger.prototype.dragMove = function( event, pointer, moveVector ) {
|
|
|
|
|
this.emitEvent( 'dragMove', [ event, pointer, moveVector ] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// dragEnd
|
|
|
|
|
Unidragger.prototype._dragEnd = function( event, pointer ) {
|
|
|
|
|
// set flags
|
|
|
|
|
this.isDragging = false;
|
|
|
|
|
// re-enable clicking async
|
|
|
|
|
var _this = this;
|
|
|
|
|
setTimeout( function() {
|
|
|
|
|
delete _this.isPreventingClicks;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.dragEnd( event, pointer );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unidragger.prototype.dragEnd = function( event, pointer ) {
|
|
|
|
|
this.emitEvent( 'dragEnd', [ event, pointer ] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- onclick ----- //
|
|
|
|
|
|
|
|
|
|
// handle all clicks and prevent clicks when dragging
|
|
|
|
|
Unidragger.prototype.onclick = function( event ) {
|
|
|
|
|
if ( this.isPreventingClicks ) {
|
|
|
|
|
preventDefaultEvent( event );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- staticClick ----- //
|
|
|
|
|
|
|
|
|
|
// triggered after pointer down & up with no/tiny movement
|
|
|
|
|
Unidragger.prototype._staticClick = function( event, pointer ) {
|
|
|
|
|
// allow click in text input
|
|
|
|
|
if ( event.target.nodeName == 'INPUT' && event.target.type == 'text' ) {
|
|
|
|
|
event.target.focus();
|
|
|
|
|
}
|
|
|
|
|
this.staticClick( event, pointer );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Unidragger.prototype.staticClick = function( event, pointer ) {
|
|
|
|
|
this.emitEvent( 'staticClick', [ event, pointer ] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- ----- //
|
|
|
|
|
|
|
|
|
|
Unidragger.getPointerPoint = function( pointer ) {
|
|
|
|
|
return {
|
|
|
|
|
x: pointer.pageX !== undefined ? pointer.pageX : pointer.clientX,
|
|
|
|
|
y: pointer.pageY !== undefined ? pointer.pageY : pointer.clientY
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- ----- //
|
|
|
|
|
|
|
|
|
|
Unidragger.getPointerPoint = Unipointer.getPointerPoint;
|
|
|
|
|
|
|
|
|
|
return Unidragger;
|
|
|
|
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* Draggabilly v1.2.4
|
|
|
|
|
* Make that shiz draggable
|
|
|
|
|
* http://draggabilly.desandro.com
|
|
|
|
|
* MIT license
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
( function( window, factory ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( typeof define == 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define( [
|
|
|
|
|
'classie/classie',
|
|
|
|
|
'get-style-property/get-style-property',
|
|
|
|
|
'get-size/get-size',
|
|
|
|
|
'unidragger/unidragger'
|
|
|
|
|
],
|
|
|
|
|
function( classie, getStyleProperty, getSize, Unidragger ) {
|
|
|
|
|
return factory( window, classie, getStyleProperty, getSize, Unidragger );
|
|
|
|
|
});
|
|
|
|
|
} else if ( typeof exports == 'object' ) {
|
|
|
|
|
// CommonJS
|
|
|
|
|
module.exports = factory(
|
|
|
|
|
window,
|
|
|
|
|
require('desandro-classie'),
|
|
|
|
|
require('desandro-get-style-property'),
|
|
|
|
|
require('get-size'),
|
|
|
|
|
require('unidragger')
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.Draggabilly = factory(
|
|
|
|
|
window,
|
|
|
|
|
window.classie,
|
|
|
|
|
window.getStyleProperty,
|
|
|
|
|
window.getSize,
|
|
|
|
|
window.Unidragger
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}( window, function factory( window, classie, getStyleProperty, getSize, Unidragger ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
// vars
|
|
|
|
|
var document = window.document;
|
|
|
|
|
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 noop() {}
|
|
|
|
|
function extend( a, b ) {
|
|
|
|
|
for ( var prop in b ) {
|
|
|
|
|
a[ prop ] = b[ prop ];
|
|
|
|
|
}
|
|
|
|
|
return a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- get style ----- //
|
|
|
|
|
|
|
|
|
|
var defView = document.defaultView;
|
|
|
|
|
var defView = document.defaultView;
|
|
|
|
|
|
|
|
|
|
var getStyle = defView && defView.getComputedStyle ?
|
|
|
|
|
function( elem ) {
|
|
|
|
|
return defView.getComputedStyle( elem, null );
|
|
|
|
|
} :
|
|
|
|
|
function( elem ) {
|
|
|
|
|
return elem.currentStyle;
|
|
|
|
|
};
|
|
|
|
|
var getStyle = defView && defView.getComputedStyle ?
|
|
|
|
|
function( elem ) {
|
|
|
|
|
return defView.getComputedStyle( elem, null );
|
|
|
|
|
} :
|
|
|
|
|
function( elem ) {
|
|
|
|
|
return elem.currentStyle;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// http://stackoverflow.com/a/384380/182183
|
|
|
|
|
var isElement = ( typeof HTMLElement === 'object' ) ?
|
|
|
|
|
function isElementDOM2( obj ) {
|
|
|
|
|
return obj instanceof HTMLElement;
|
|
|
|
|
} :
|
|
|
|
|
function isElementQuirky( obj ) {
|
|
|
|
|
return obj && typeof obj === 'object' &&
|
|
|
|
|
obj.nodeType === 1 && typeof obj.nodeName === 'string';
|
|
|
|
|
};
|
|
|
|
|
var isElement = ( typeof HTMLElement == 'object' ) ?
|
|
|
|
|
function isElementDOM2( obj ) {
|
|
|
|
|
return obj instanceof HTMLElement;
|
|
|
|
|
} :
|
|
|
|
|
function isElementQuirky( obj ) {
|
|
|
|
|
return obj && typeof obj == 'object' &&
|
|
|
|
|
obj.nodeType == 1 && typeof obj.nodeName == 'string';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// -------------------------- requestAnimationFrame -------------------------- //
|
|
|
|
|
|
|
|
|
|
// https://gist.github.com/1866474
|
|
|
|
|
|
|
|
|
|
var lastTime = 0;
|
|
|
|
|
var prefixes = 'webkit moz ms o'.split(' ');
|
|
|
|
|
var lastTime = 0;
|
|
|
|
|
var prefixes = 'webkit moz ms o'.split(' ');
|
|
|
|
|
// get unprefixed rAF and cAF, if present
|
|
|
|
|
var requestAnimationFrame = window.requestAnimationFrame;
|
|
|
|
|
var cancelAnimationFrame = window.cancelAnimationFrame;
|
|
|
|
|
var requestAnimationFrame = window.requestAnimationFrame;
|
|
|
|
|
var cancelAnimationFrame = window.cancelAnimationFrame;
|
|
|
|
|
// loop through vendor prefixes and get prefixed rAF and cAF
|
|
|
|
|
var prefix;
|
|
|
|
|
for( var i = 0; i < prefixes.length; i++ ) {
|
|
|
|
|
if ( requestAnimationFrame && cancelAnimationFrame ) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
prefix = prefixes[i];
|
|
|
|
|
requestAnimationFrame = requestAnimationFrame || window[ prefix + 'RequestAnimationFrame' ];
|
|
|
|
|
cancelAnimationFrame = cancelAnimationFrame || window[ prefix + 'CancelAnimationFrame' ] ||
|
|
|
|
|
window[ prefix + 'CancelRequestAnimationFrame' ];
|
|
|
|
|
}
|
|
|
|
|
var prefix;
|
|
|
|
|
for( var i = 0; i < prefixes.length; i++ ) {
|
|
|
|
|
if ( requestAnimationFrame && cancelAnimationFrame ) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
prefix = prefixes[i];
|
|
|
|
|
requestAnimationFrame = requestAnimationFrame || window[ prefix + 'RequestAnimationFrame' ];
|
|
|
|
|
cancelAnimationFrame = cancelAnimationFrame || window[ prefix + 'CancelAnimationFrame' ] ||
|
|
|
|
|
window[ prefix + 'CancelRequestAnimationFrame' ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fallback to setTimeout and clearTimeout if either request/cancel is not supported
|
|
|
|
|
if ( !requestAnimationFrame || !cancelAnimationFrame ) {
|
|
|
|
|
requestAnimationFrame = function( callback ) {
|
|
|
|
|
var currTime = new Date().getTime();
|
|
|
|
|
var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
|
|
|
|
|
var id = window.setTimeout( function() {
|
|
|
|
|
callback( currTime + timeToCall );
|
|
|
|
|
}, timeToCall );
|
|
|
|
|
lastTime = currTime + timeToCall;
|
|
|
|
|
return id;
|
|
|
|
|
};
|
|
|
|
|
if ( !requestAnimationFrame || !cancelAnimationFrame ) {
|
|
|
|
|
requestAnimationFrame = function( callback ) {
|
|
|
|
|
var currTime = new Date().getTime();
|
|
|
|
|
var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
|
|
|
|
|
var id = window.setTimeout( function() {
|
|
|
|
|
callback( currTime + timeToCall );
|
|
|
|
|
}, timeToCall );
|
|
|
|
|
lastTime = currTime + timeToCall;
|
|
|
|
|
return id;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
cancelAnimationFrame = function( id ) {
|
|
|
|
|
window.clearTimeout( id );
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------- definition -------------------------- //
|
|
|
|
|
|
|
|
|
|
function draggabillyDefinition( classie, EventEmitter, eventie, getStyleProperty, getSize ) {
|
|
|
|
|
cancelAnimationFrame = function( id ) {
|
|
|
|
|
window.clearTimeout( id );
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------- support -------------------------- //
|
|
|
|
|
|
|
|
|
|
var transformProperty = getStyleProperty('transform');
|
|
|
|
|
var transformProperty = getStyleProperty('transform');
|
|
|
|
|
// TODO fix quick & dirty check for 3D support
|
|
|
|
|
var is3d = !!getStyleProperty('perspective');
|
|
|
|
|
var is3d = !!getStyleProperty('perspective');
|
|
|
|
|
|
|
|
|
|
var jQuery = window.jQuery;
|
|
|
|
|
|
|
|
|
|
// -------------------------- -------------------------- //
|
|
|
|
|
|
|
|
|
|
function Draggabilly( element, options ) {
|
|
|
|
|
this.element = element;
|
|
|
|
|
function Draggabilly( element, options ) {
|
|
|
|
|
// querySelector if string
|
|
|
|
|
this.element = typeof element == 'string' ?
|
|
|
|
|
document.querySelector( element ) : element;
|
|
|
|
|
|
|
|
|
|
this.options = extend( {}, this.options );
|
|
|
|
|
extend( this.options, options );
|
|
|
|
|
if ( jQuery ) {
|
|
|
|
|
this.$element = jQuery( this.element );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._create();
|
|
|
|
|
// options
|
|
|
|
|
this.options = extend( {}, this.constructor.defaults );
|
|
|
|
|
this.option( options );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
this._create();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// inherit EventEmitter methods
|
|
|
|
|
extend( Draggabilly.prototype, EventEmitter.prototype );
|
|
|
|
|
// inherit Unidragger methods
|
|
|
|
|
extend( Draggabilly.prototype, Unidragger.prototype );
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.options = {
|
|
|
|
|
};
|
|
|
|
|
Draggabilly.defaults = {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype._create = function() {
|
|
|
|
|
/**
|
|
|
|
|
* set options
|
|
|
|
|
* @param {Object} opts
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.option = function( opts ) {
|
|
|
|
|
extend( this.options, opts );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// properties
|
|
|
|
|
this.position = {};
|
|
|
|
|
this._getPosition();
|
|
|
|
|
Draggabilly.prototype._create = function() {
|
|
|
|
|
|
|
|
|
|
this.startPoint = { x: 0, y: 0 };
|
|
|
|
|
this.dragPoint = { x: 0, y: 0 };
|
|
|
|
|
// properties
|
|
|
|
|
this.position = {};
|
|
|
|
|
this._getPosition();
|
|
|
|
|
|
|
|
|
|
this.startPosition = extend( {}, this.position );
|
|
|
|
|
this.startPoint = { x: 0, y: 0 };
|
|
|
|
|
this.dragPoint = { x: 0, y: 0 };
|
|
|
|
|
|
|
|
|
|
// set relative positioning
|
|
|
|
|
var style = getStyle( this.element );
|
|
|
|
|
if ( style.position !== 'relative' && style.position !== 'absolute' ) {
|
|
|
|
|
this.element.style.position = 'relative';
|
|
|
|
|
}
|
|
|
|
|
this.startPosition = extend( {}, this.position );
|
|
|
|
|
|
|
|
|
|
this.enable();
|
|
|
|
|
this.setHandles();
|
|
|
|
|
// set relative positioning
|
|
|
|
|
var style = getStyle( this.element );
|
|
|
|
|
if ( style.position != 'relative' && style.position != 'absolute' ) {
|
|
|
|
|
this.element.style.position = 'relative';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
this.enable();
|
|
|
|
|
this.setHandles();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* set this.handles and bind start events to 'em
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.setHandles = function() {
|
|
|
|
|
this.handles = this.options.handle ?
|
|
|
|
|
this.element.querySelectorAll( this.options.handle ) : [ this.element ];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for ( var i=0, len = this.handles.length; i < len; i++ ) {
|
|
|
|
|
var handle = this.handles[i];
|
|
|
|
|
// bind pointer start event
|
|
|
|
|
// listen for both, for devices like Chrome Pixel
|
|
|
|
|
// which has touch and mouse events
|
|
|
|
|
eventie.bind( handle, 'mousedown', this );
|
|
|
|
|
eventie.bind( handle, 'touchstart', this );
|
|
|
|
|
disableImgOndragstart( handle );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* set this.handles and bind start events to 'em
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.setHandles = function() {
|
|
|
|
|
this.handles = this.options.handle ?
|
|
|
|
|
this.element.querySelectorAll( this.options.handle ) : [ this.element ];
|
|
|
|
|
|
|
|
|
|
// remove default dragging interaction on all images in IE8
|
|
|
|
|
// IE8 does its own drag thing on images, which messes stuff up
|
|
|
|
|
this.bindHandles();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function noDragStart() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO replace this with a IE8 test
|
|
|
|
|
var isIE8 = 'attachEvent' in document.documentElement;
|
|
|
|
|
|
|
|
|
|
// IE8 only
|
|
|
|
|
var disableImgOndragstart = !isIE8 ? noop : function( handle ) {
|
|
|
|
|
|
|
|
|
|
if ( handle.nodeName === 'IMG' ) {
|
|
|
|
|
handle.ondragstart = noDragStart;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var images = handle.querySelectorAll('img');
|
|
|
|
|
for ( var i=0, len = images.length; i < len; i++ ) {
|
|
|
|
|
var img = images[i];
|
|
|
|
|
img.ondragstart = noDragStart;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* emits events via eventEmitter and jQuery events
|
|
|
|
|
* @param {String} type - name of event
|
|
|
|
|
* @param {Event} event - original event
|
|
|
|
|
* @param {Array} args - extra arguments
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.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 left/top position from style
|
|
|
|
|
Draggabilly.prototype._getPosition = function() {
|
|
|
|
|
// properties
|
|
|
|
|
var style = getStyle( this.element );
|
|
|
|
|
Draggabilly.prototype._getPosition = function() {
|
|
|
|
|
// properties
|
|
|
|
|
var style = getStyle( this.element );
|
|
|
|
|
|
|
|
|
|
var x = parseInt( style.left, 10 );
|
|
|
|
|
var y = parseInt( style.top, 10 );
|
|
|
|
|
var x = parseInt( style.left, 10 );
|
|
|
|
|
var y = parseInt( style.top, 10 );
|
|
|
|
|
|
|
|
|
|
// clean up 'auto' or other non-integer values
|
|
|
|
|
this.position.x = isNaN( x ) ? 0 : x;
|
|
|
|
|
this.position.y = isNaN( y ) ? 0 : y;
|
|
|
|
|
// 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 );
|
|
|
|
|
};
|
|
|
|
|
this._addTransformPosition( style );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// add transform: translate( x, y ) to position
|
|
|
|
|
Draggabilly.prototype._addTransformPosition = function( style ) {
|
|
|
|
|
if ( !transformProperty ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
};
|
|
|
|
|
Draggabilly.prototype._addTransformPosition = function( style ) {
|
|
|
|
|
if ( !transformProperty ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
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 -------------------------- //
|
|
|
|
|
|
|
|
|
|
// trigger handler methods for events
|
|
|
|
|
Draggabilly.prototype.handleEvent = function( event ) {
|
|
|
|
|
var method = 'on' + event.type;
|
|
|
|
|
if ( this[ method ] ) {
|
|
|
|
|
this[ method ]( event );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* pointer start
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.pointerDown = function( event, pointer ) {
|
|
|
|
|
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 );
|
|
|
|
|
classie.add( this.element, 'is-pointer-down' );
|
|
|
|
|
this.dispatchEvent( 'pointerDown', event, [ pointer ] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// returns the touch that we're keeping track of
|
|
|
|
|
Draggabilly.prototype.getTouch = function( touches ) {
|
|
|
|
|
for ( var i=0, len = touches.length; i < len; i++ ) {
|
|
|
|
|
var touch = touches[i];
|
|
|
|
|
if ( touch.identifier === this.pointerIdentifier ) {
|
|
|
|
|
return touch;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* drag move
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.pointerMove = function( event, pointer ) {
|
|
|
|
|
var moveVector = this._dragPointerMove( event, pointer );
|
|
|
|
|
this.dispatchEvent( 'pointerMove', event, [ pointer, moveVector ] );
|
|
|
|
|
this._dragMove( event, pointer, moveVector );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- start event ----- //
|
|
|
|
|
/**
|
|
|
|
|
* drag start
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.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();
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.onmousedown = function( event ) {
|
|
|
|
|
this.dragStart( event, event );
|
|
|
|
|
};
|
|
|
|
|
this.dragPoint.x = 0;
|
|
|
|
|
this.dragPoint.y = 0;
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.ontouchstart = function( event ) {
|
|
|
|
|
// disregard additional touches
|
|
|
|
|
if ( this.isDragging ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// reset isDragging flag
|
|
|
|
|
this.isDragging = true;
|
|
|
|
|
classie.add( this.element, 'is-dragging' );
|
|
|
|
|
this.dispatchEvent( 'dragStart', event, [ pointer ] );
|
|
|
|
|
// start animation
|
|
|
|
|
this.animate();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.dragStart( event, event.changedTouches[0] );
|
|
|
|
|
};
|
|
|
|
|
Draggabilly.prototype.measureContainment = function() {
|
|
|
|
|
var containment = this.options.containment;
|
|
|
|
|
if ( !containment ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setPointerPoint( point, pointer ) {
|
|
|
|
|
point.x = pointer.pageX !== undefined ? pointer.pageX : pointer.clientX;
|
|
|
|
|
point.y = pointer.pageY !== undefined ? pointer.pageY : pointer.clientY;
|
|
|
|
|
}
|
|
|
|
|
this.size = getSize( this.element );
|
|
|
|
|
var elemRect = this.element.getBoundingClientRect();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* drag start
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.dragStart = function( event, pointer ) {
|
|
|
|
|
if ( !this.isEnabled ) {
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
if ( event.preventDefault ) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
} else {
|
|
|
|
|
event.returnValue = false;
|
|
|
|
|
}
|
|
|
|
|
this.containerSize = getSize( container );
|
|
|
|
|
var containerRect = container.getBoundingClientRect();
|
|
|
|
|
|
|
|
|
|
var isTouch = event.type === 'touchstart';
|
|
|
|
|
|
|
|
|
|
// save pointer identifier to match up touch events
|
|
|
|
|
this.pointerIdentifier = pointer.identifier;
|
|
|
|
|
|
|
|
|
|
this._getPosition();
|
|
|
|
|
|
|
|
|
|
this.measureContainment();
|
|
|
|
|
|
|
|
|
|
// point where drag began
|
|
|
|
|
setPointerPoint( this.startPoint, pointer );
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
|
|
// bind move and end events
|
|
|
|
|
this._bindEvents({
|
|
|
|
|
events: isTouch ? [ 'touchmove', 'touchend', 'touchcancel' ] :
|
|
|
|
|
[ 'mousemove', 'mouseup' ],
|
|
|
|
|
// IE8 needs to be bound to document
|
|
|
|
|
node: event.preventDefault ? window : document
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
classie.add( this.element, 'is-dragging' );
|
|
|
|
|
|
|
|
|
|
// reset isDragging flag
|
|
|
|
|
this.isDragging = true;
|
|
|
|
|
|
|
|
|
|
this.emitEvent( 'dragStart', [ this, event, pointer ] );
|
|
|
|
|
|
|
|
|
|
// start animation
|
|
|
|
|
this.animate();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype._bindEvents = function( args ) {
|
|
|
|
|
for ( var i=0, len = args.events.length; i < len; i++ ) {
|
|
|
|
|
var event = args.events[i];
|
|
|
|
|
eventie.bind( args.node, event, this );
|
|
|
|
|
}
|
|
|
|
|
// save these arguments
|
|
|
|
|
this._boundEvents = args;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype._unbindEvents = function() {
|
|
|
|
|
var args = this._boundEvents;
|
|
|
|
|
for ( var i=0, len = args.events.length; i < len; i++ ) {
|
|
|
|
|
var event = args.events[i];
|
|
|
|
|
eventie.unbind( args.node, event, this );
|
|
|
|
|
}
|
|
|
|
|
delete this._boundEvents;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.measureContainment = function() {
|
|
|
|
|
var containment = this.options.containment;
|
|
|
|
|
if ( !containment ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.size = getSize( this.element );
|
|
|
|
|
var elemRect = this.element.getBoundingClientRect();
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
|
|
this.containerSize = getSize( container );
|
|
|
|
|
var containerRect = container.getBoundingClientRect();
|
|
|
|
|
|
|
|
|
|
this.relativeStartPosition = {
|
|
|
|
|
x: elemRect.left - containerRect.left,
|
|
|
|
|
y: elemRect.top - containerRect.top
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
this.relativeStartPosition = {
|
|
|
|
|
x: elemRect.left - containerRect.left,
|
|
|
|
|
y: elemRect.top - containerRect.top
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- move event ----- //
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.onmousemove = function( event ) {
|
|
|
|
|
this.dragMove( event, event );
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* drag move
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.dragMove = function( event, pointer, moveVector ) {
|
|
|
|
|
if ( !this.isEnabled ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var dragX = moveVector.x;
|
|
|
|
|
var dragY = moveVector.y;
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.ontouchmove = function( event ) {
|
|
|
|
|
var touch = this.getTouch( event.changedTouches );
|
|
|
|
|
if ( touch ) {
|
|
|
|
|
this.dragMove( event, touch );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
var grid = this.options.grid;
|
|
|
|
|
var gridX = grid && grid[0];
|
|
|
|
|
var gridY = grid && grid[1];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* drag move
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.dragMove = function( event, pointer ) {
|
|
|
|
|
dragX = applyGrid( dragX, gridX );
|
|
|
|
|
dragY = applyGrid( dragY, gridY );
|
|
|
|
|
|
|
|
|
|
setPointerPoint( this.dragPoint, pointer );
|
|
|
|
|
this.dragPoint.x -= this.startPoint.x;
|
|
|
|
|
this.dragPoint.y -= this.startPoint.y;
|
|
|
|
|
dragX = this.containDrag( 'x', dragX, gridX );
|
|
|
|
|
dragY = this.containDrag( 'y', dragY, gridY );
|
|
|
|
|
|
|
|
|
|
if ( this.options.containment ) {
|
|
|
|
|
var relX = this.relativeStartPosition.x;
|
|
|
|
|
var relY = this.relativeStartPosition.y;
|
|
|
|
|
this.dragPoint.x = Math.max( this.dragPoint.x, -relX );
|
|
|
|
|
this.dragPoint.y = Math.max( this.dragPoint.y, -relY );
|
|
|
|
|
this.dragPoint.x = Math.min( this.dragPoint.x, this.containerSize.width - relX - this.size.width );
|
|
|
|
|
this.dragPoint.y = Math.min( this.dragPoint.y, this.containerSize.height - relY - this.size.height );
|
|
|
|
|
}
|
|
|
|
|
// constrain to axis
|
|
|
|
|
dragX = this.options.axis == 'y' ? 0 : dragX;
|
|
|
|
|
dragY = this.options.axis == 'x' ? 0 : dragY;
|
|
|
|
|
|
|
|
|
|
this.position.x = this.startPosition.x + this.dragPoint.x;
|
|
|
|
|
this.position.y = this.startPosition.y + this.dragPoint.y;
|
|
|
|
|
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.dispatchEvent( 'dragMove', event, [ pointer, moveVector ] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function applyGrid( value, grid, method ) {
|
|
|
|
|
method = method || 'round';
|
|
|
|
|
return grid ? Math[ method ]( value / grid ) * grid : value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.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.containerSize[ measure ] - rel - this.size[ measure ];
|
|
|
|
|
max = applyGrid( max, grid, 'floor' );
|
|
|
|
|
return Math.min( max, Math.max( min, drag ) );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- end event ----- //
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.onmouseup = function( event ) {
|
|
|
|
|
this.dragEnd( event, event );
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* pointer up
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.pointerUp = function( event, pointer ) {
|
|
|
|
|
classie.remove( this.element, 'is-pointer-down' );
|
|
|
|
|
this.dispatchEvent( 'pointerUp', event, [ pointer ] );
|
|
|
|
|
this._dragPointerUp( event, pointer );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.ontouchend = function( event ) {
|
|
|
|
|
var touch = this.getTouch( event.changedTouches );
|
|
|
|
|
if ( touch ) {
|
|
|
|
|
this.dragEnd( event, touch );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* drag end
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.dragEnd = function( event, pointer ) {
|
|
|
|
|
this.isDragging = false;
|
|
|
|
|
|
|
|
|
|
delete this.pointerIdentifier;
|
|
|
|
|
|
|
|
|
|
// use top left position when complete
|
|
|
|
|
if ( transformProperty ) {
|
|
|
|
|
this.element.style[ transformProperty ] = '';
|
|
|
|
|
this.setLeftTop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove events
|
|
|
|
|
this._unbindEvents();
|
|
|
|
|
|
|
|
|
|
classie.remove( this.element, 'is-dragging' );
|
|
|
|
|
|
|
|
|
|
this.emitEvent( 'dragEnd', [ this, event, pointer ] );
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- cancel event ----- //
|
|
|
|
|
|
|
|
|
|
// coerce to end event
|
|
|
|
|
Draggabilly.prototype.ontouchcancel = function( event ) {
|
|
|
|
|
var touch = this.getTouch( event.changedTouches );
|
|
|
|
|
this.dragEnd( event, touch );
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* drag end
|
|
|
|
|
* @param {Event} event
|
|
|
|
|
* @param {Event or Touch} pointer
|
|
|
|
|
*/
|
|
|
|
|
Draggabilly.prototype.dragEnd = function( event, pointer ) {
|
|
|
|
|
if ( !this.isEnabled ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.isDragging = false;
|
|
|
|
|
// use top left position when complete
|
|
|
|
|
if ( transformProperty ) {
|
|
|
|
|
this.element.style[ transformProperty ] = '';
|
|
|
|
|
this.setLeftTop();
|
|
|
|
|
}
|
|
|
|
|
classie.remove( this.element, 'is-dragging' );
|
|
|
|
|
this.dispatchEvent( 'dragEnd', event, [ pointer ] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// -------------------------- animation -------------------------- //
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.animate = function() {
|
|
|
|
|
// only render and animate if dragging
|
|
|
|
|
if ( !this.isDragging ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Draggabilly.prototype.animate = function() {
|
|
|
|
|
// only render and animate if dragging
|
|
|
|
|
if ( !this.isDragging ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.positionDrag();
|
|
|
|
|
this.positionDrag();
|
|
|
|
|
|
|
|
|
|
var _this = this;
|
|
|
|
|
requestAnimationFrame( function animateFrame() {
|
|
|
|
|
_this.animate();
|
|
|
|
|
});
|
|
|
|
|
var _this = this;
|
|
|
|
|
requestAnimationFrame( function animateFrame() {
|
|
|
|
|
_this.animate();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// transform translate function
|
|
|
|
|
var translate = is3d ?
|
|
|
|
|
function( x, y ) {
|
|
|
|
|
return 'translate3d( ' + x + 'px, ' + y + 'px, 0)';
|
|
|
|
|
} :
|
|
|
|
|
function( x, y ) {
|
|
|
|
|
return 'translate( ' + x + 'px, ' + y + 'px)';
|
|
|
|
|
};
|
|
|
|
|
var translate = is3d ?
|
|
|
|
|
function( x, y ) {
|
|
|
|
|
return 'translate3d( ' + x + 'px, ' + y + 'px, 0)';
|
|
|
|
|
} :
|
|
|
|
|
function( x, y ) {
|
|
|
|
|
return 'translate( ' + x + 'px, ' + y + 'px)';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// left/top positioning
|
|
|
|
|
Draggabilly.prototype.setLeftTop = function() {
|
|
|
|
|
this.element.style.left = this.position.x + 'px';
|
|
|
|
|
this.element.style.top = this.position.y + 'px';
|
|
|
|
|
};
|
|
|
|
|
Draggabilly.prototype.setLeftTop = function() {
|
|
|
|
|
this.element.style.left = this.position.x + 'px';
|
|
|
|
|
this.element.style.top = this.position.y + 'px';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.positionDrag = transformProperty ?
|
|
|
|
|
function() {
|
|
|
|
|
// position with transform
|
|
|
|
|
this.element.style[ transformProperty ] = translate( this.dragPoint.x, this.dragPoint.y );
|
|
|
|
|
} : Draggabilly.prototype.setLeftTop;
|
|
|
|
|
Draggabilly.prototype.positionDrag = transformProperty ?
|
|
|
|
|
function() {
|
|
|
|
|
// position with transform
|
|
|
|
|
this.element.style[ transformProperty ] = translate( this.dragPoint.x, this.dragPoint.y );
|
|
|
|
|
} : Draggabilly.prototype.setLeftTop;
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.enable = function() {
|
|
|
|
|
this.isEnabled = true;
|
|
|
|
|
};
|
|
|
|
|
// ----- staticClick ----- //
|
|
|
|
|
|
|
|
|
|
Draggabilly.prototype.disable = function() {
|
|
|
|
|
this.isEnabled = false;
|
|
|
|
|
if ( this.isDragging ) {
|
|
|
|
|
this.dragEnd();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
Draggabilly.prototype.staticClick = function( event, pointer ) {
|
|
|
|
|
this.dispatchEvent( 'staticClick', event, [ pointer ] );
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return Draggabilly;
|
|
|
|
|
// ----- methods ----- //
|
|
|
|
|
|
|
|
|
|
} // end definition
|
|
|
|
|
Draggabilly.prototype.enable = function() {
|
|
|
|
|
this.isEnabled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// -------------------------- transport -------------------------- //
|
|
|
|
|
Draggabilly.prototype.disable = function() {
|
|
|
|
|
this.isEnabled = false;
|
|
|
|
|
if ( this.isDragging ) {
|
|
|
|
|
this.dragEnd();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if ( typeof define === 'function' && define.amd ) {
|
|
|
|
|
// AMD
|
|
|
|
|
define('draggabilly', [
|
|
|
|
|
'classie',
|
|
|
|
|
'EventEmitter',
|
|
|
|
|
'eventie',
|
|
|
|
|
'getStyleProperty',
|
|
|
|
|
'getSize'
|
|
|
|
|
],
|
|
|
|
|
draggabillyDefinition );
|
|
|
|
|
} else {
|
|
|
|
|
// browser global
|
|
|
|
|
window.Draggabilly = draggabillyDefinition(
|
|
|
|
|
window.classie,
|
|
|
|
|
window.EventEmitter,
|
|
|
|
|
window.eventie,
|
|
|
|
|
window.getStyleProperty,
|
|
|
|
|
window.getSize
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
Draggabilly.prototype.destroy = function() {
|
|
|
|
|
this.disable();
|
|
|
|
|
// reset styles
|
|
|
|
|
if ( transformProperty ) {
|
|
|
|
|
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
|
|
|
|
|
Draggabilly.prototype._init = noop;
|
|
|
|
|
|
|
|
|
|
if ( jQuery && jQuery.bridget ) {
|
|
|
|
|
jQuery.bridget( 'draggabilly', Draggabilly );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- ----- //
|
|
|
|
|
|
|
|
|
|
return Draggabilly;
|
|
|
|
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
})( window );
|