Project

General

Profile

1
/*!
2
 * Draggabilly PACKAGED v1.1.2
3
 * Make that shiz draggable
4
 * http://draggabilly.desandro.com
5
 * MIT license
6
 */
7

    
8
/*!
9
 * classie - class helper functions
10
 * from bonzo https://github.com/ded/bonzo
11
 * 
12
 * classie.has( elem, 'my-class' ) -> true/false
13
 * classie.add( elem, 'my-new-class' )
14
 * classie.remove( elem, 'my-unwanted-class' )
15
 * classie.toggle( elem, 'my-class' )
16
 */
17

    
18
/*jshint browser: true, strict: true, undef: true */
19
/*global define: false */
20

    
21
( function( window ) {
22

    
23
// class helper functions from bonzo https://github.com/ded/bonzo
24

    
25
function classReg( className ) {
26
  return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
27
}
28

    
29
// classList support for class management
30
// altho to be fair, the api sucks because it won't accept multiple classes at once
31
var hasClass, addClass, removeClass;
32

    
33
if ( 'classList' in document.documentElement ) {
34
  hasClass = function( elem, c ) {
35
    return elem.classList.contains( c );
36
  };
37
  addClass = function( elem, c ) {
38
    elem.classList.add( c );
39
  };
40
  removeClass = function( elem, c ) {
41
    elem.classList.remove( c );
42
  };
43
}
44
else {
45
  hasClass = function( elem, c ) {
46
    return classReg( c ).test( elem.className );
47
  };
48
  addClass = function( elem, c ) {
49
    if ( !hasClass( elem, c ) ) {
50
      elem.className = elem.className + ' ' + c;
51
    }
52
  };
53
  removeClass = function( elem, c ) {
54
    elem.className = elem.className.replace( classReg( c ), ' ' );
55
  };
56
}
57

    
58
function toggleClass( elem, c ) {
59
  var fn = hasClass( elem, c ) ? removeClass : addClass;
60
  fn( elem, c );
61
}
62

    
63
var classie = {
64
  // full names
65
  hasClass: hasClass,
66
  addClass: addClass,
67
  removeClass: removeClass,
68
  toggleClass: toggleClass,
69
  // short names
70
  has: hasClass,
71
  add: addClass,
72
  remove: removeClass,
73
  toggle: toggleClass
74
};
75

    
76
// transport
77
if ( typeof define === 'function' && define.amd ) {
78
  // AMD
79
  define( 'classie/classie',classie );
80
} else {
81
  // browser global
82
  window.classie = classie;
83
}
84

    
85
})( window );
86

    
87
/*!
88
 * EventEmitter v4.2.2 - git.io/ee
89
 * Oliver Caldwell
90
 * MIT license
91
 * @preserve
92
 */
93

    
94
(function () {
95
    
96

    
97
    /**
98
     * Class for managing events.
99
     * Can be extended to provide event functionality in other classes.
100
     *
101
     * @class EventEmitter Manages event registering and emitting.
102
     */
103
    function EventEmitter() {}
104

    
105
    // Shortcuts to improve speed and size
106

    
107
    // Easy access to the prototype
108
    var proto = EventEmitter.prototype;
109

    
110
    /**
111
     * Finds the index of the listener for the event in it's storage array.
112
     *
113
     * @param {Function[]} listeners Array of listeners to search through.
114
     * @param {Function} listener Method to look for.
115
     * @return {Number} index of the specified listener, -1 if not found
116
     * @api private
117
     */
118
    function indexOfListener(listeners, listener) {
119
        var i = listeners.length;
120
        while (i--) {
121
            if (listeners[i].listener === listener) {
122
                return i;
123
            }
124
        }
125

    
126
        return -1;
127
    }
128

    
129
    /**
130
     * Alias a method while keeping the context correct, to allow for overwriting of target method.
131
     *
132
     * @param {String} name The name of the target method.
133
     * @return {Function} The aliased method
134
     * @api private
135
     */
136
    function alias(name) {
137
        return function aliasClosure() {
138
            return this[name].apply(this, arguments);
139
        };
140
    }
141

    
142
    /**
143
     * Returns the listener array for the specified event.
144
     * Will initialise the event object and listener arrays if required.
145
     * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
146
     * Each property in the object response is an array of listener functions.
147
     *
148
     * @param {String|RegExp} evt Name of the event to return the listeners from.
149
     * @return {Function[]|Object} All listener functions for the event.
150
     */
151
    proto.getListeners = function getListeners(evt) {
152
        var events = this._getEvents();
153
        var response;
154
        var key;
155

    
156
        // Return a concatenated array of all matching events if
157
        // the selector is a regular expression.
158
        if (typeof evt === 'object') {
159
            response = {};
160
            for (key in events) {
161
                if (events.hasOwnProperty(key) && evt.test(key)) {
162
                    response[key] = events[key];
163
                }
164
            }
165
        }
166
        else {
167
            response = events[evt] || (events[evt] = []);
168
        }
169

    
170
        return response;
171
    };
172

    
173
    /**
174
     * Takes a list of listener objects and flattens it into a list of listener functions.
175
     *
176
     * @param {Object[]} listeners Raw listener objects.
177
     * @return {Function[]} Just the listener functions.
178
     */
179
    proto.flattenListeners = function flattenListeners(listeners) {
180
        var flatListeners = [];
181
        var i;
182

    
183
        for (i = 0; i < listeners.length; i += 1) {
184
            flatListeners.push(listeners[i].listener);
185
        }
186

    
187
        return flatListeners;
188
    };
189

    
190
    /**
191
     * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
192
     *
193
     * @param {String|RegExp} evt Name of the event to return the listeners from.
194
     * @return {Object} All listener functions for an event in an object.
195
     */
196
    proto.getListenersAsObject = function getListenersAsObject(evt) {
197
        var listeners = this.getListeners(evt);
198
        var response;
199

    
200
        if (listeners instanceof Array) {
201
            response = {};
202
            response[evt] = listeners;
203
        }
204

    
205
        return response || listeners;
206
    };
207

    
208
    /**
209
     * Adds a listener function to the specified event.
210
     * The listener will not be added if it is a duplicate.
211
     * If the listener returns true then it will be removed after it is called.
212
     * If you pass a regular expression as the event name then the listener will be added to all events that match it.
213
     *
214
     * @param {String|RegExp} evt Name of the event to attach the listener to.
215
     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
216
     * @return {Object} Current instance of EventEmitter for chaining.
217
     */
218
    proto.addListener = function addListener(evt, listener) {
219
        var listeners = this.getListenersAsObject(evt);
220
        var listenerIsWrapped = typeof listener === 'object';
221
        var key;
222

    
223
        for (key in listeners) {
224
            if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
225
                listeners[key].push(listenerIsWrapped ? listener : {
226
                    listener: listener,
227
                    once: false
228
                });
229
            }
230
        }
231

    
232
        return this;
233
    };
234

    
235
    /**
236
     * Alias of addListener
237
     */
238
    proto.on = alias('addListener');
239

    
240
    /**
241
     * Semi-alias of addListener. It will add a listener that will be
242
     * automatically removed after it's first execution.
243
     *
244
     * @param {String|RegExp} evt Name of the event to attach the listener to.
245
     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
246
     * @return {Object} Current instance of EventEmitter for chaining.
247
     */
248
    proto.addOnceListener = function addOnceListener(evt, listener) {
249
        return this.addListener(evt, {
250
            listener: listener,
251
            once: true
252
        });
253
    };
254

    
255
    /**
256
     * Alias of addOnceListener.
257
     */
258
    proto.once = alias('addOnceListener');
259

    
260
    /**
261
     * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
262
     * You need to tell it what event names should be matched by a regex.
263
     *
264
     * @param {String} evt Name of the event to create.
265
     * @return {Object} Current instance of EventEmitter for chaining.
266
     */
267
    proto.defineEvent = function defineEvent(evt) {
268
        this.getListeners(evt);
269
        return this;
270
    };
271

    
272
    /**
273
     * Uses defineEvent to define multiple events.
274
     *
275
     * @param {String[]} evts An array of event names to define.
276
     * @return {Object} Current instance of EventEmitter for chaining.
277
     */
278
    proto.defineEvents = function defineEvents(evts) {
279
        for (var i = 0; i < evts.length; i += 1) {
280
            this.defineEvent(evts[i]);
281
        }
282
        return this;
283
    };
284

    
285
    /**
286
     * Removes a listener function from the specified event.
287
     * When passed a regular expression as the event name, it will remove the listener from all events that match it.
288
     *
289
     * @param {String|RegExp} evt Name of the event to remove the listener from.
290
     * @param {Function} listener Method to remove from the event.
291
     * @return {Object} Current instance of EventEmitter for chaining.
292
     */
293
    proto.removeListener = function removeListener(evt, listener) {
294
        var listeners = this.getListenersAsObject(evt);
295
        var index;
296
        var key;
297

    
298
        for (key in listeners) {
299
            if (listeners.hasOwnProperty(key)) {
300
                index = indexOfListener(listeners[key], listener);
301

    
302
                if (index !== -1) {
303
                    listeners[key].splice(index, 1);
304
                }
305
            }
306
        }
307

    
308
        return this;
309
    };
310

    
311
    /**
312
     * Alias of removeListener
313
     */
314
    proto.off = alias('removeListener');
315

    
316
    /**
317
     * Adds listeners in bulk using the manipulateListeners method.
318
     * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
319
     * You can also pass it a regular expression to add the array of listeners to all events that match it.
320
     * Yeah, this function does quite a bit. That's probably a bad thing.
321
     *
322
     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
323
     * @param {Function[]} [listeners] An optional array of listener functions to add.
324
     * @return {Object} Current instance of EventEmitter for chaining.
325
     */
326
    proto.addListeners = function addListeners(evt, listeners) {
327
        // Pass through to manipulateListeners
328
        return this.manipulateListeners(false, evt, listeners);
329
    };
330

    
331
    /**
332
     * Removes listeners in bulk using the manipulateListeners method.
333
     * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
334
     * You can also pass it an event name and an array of listeners to be removed.
335
     * You can also pass it a regular expression to remove the listeners from all events that match it.
336
     *
337
     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
338
     * @param {Function[]} [listeners] An optional array of listener functions to remove.
339
     * @return {Object} Current instance of EventEmitter for chaining.
340
     */
341
    proto.removeListeners = function removeListeners(evt, listeners) {
342
        // Pass through to manipulateListeners
343
        return this.manipulateListeners(true, evt, listeners);
344
    };
345

    
346
    /**
347
     * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
348
     * The first argument will determine if the listeners are removed (true) or added (false).
349
     * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
350
     * You can also pass it an event name and an array of listeners to be added/removed.
351
     * You can also pass it a regular expression to manipulate the listeners of all events that match it.
352
     *
353
     * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
354
     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
355
     * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
356
     * @return {Object} Current instance of EventEmitter for chaining.
357
     */
358
    proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
359
        var i;
360
        var value;
361
        var single = remove ? this.removeListener : this.addListener;
362
        var multiple = remove ? this.removeListeners : this.addListeners;
363

    
364
        // If evt is an object then pass each of it's properties to this method
365
        if (typeof evt === 'object' && !(evt instanceof RegExp)) {
366
            for (i in evt) {
367
                if (evt.hasOwnProperty(i) && (value = evt[i])) {
368
                    // Pass the single listener straight through to the singular method
369
                    if (typeof value === 'function') {
370
                        single.call(this, i, value);
371
                    }
372
                    else {
373
                        // Otherwise pass back to the multiple function
374
                        multiple.call(this, i, value);
375
                    }
376
                }
377
            }
378
        }
379
        else {
380
            // So evt must be a string
381
            // And listeners must be an array of listeners
382
            // Loop over it and pass each one to the multiple method
383
            i = listeners.length;
384
            while (i--) {
385
                single.call(this, evt, listeners[i]);
386
            }
387
        }
388

    
389
        return this;
390
    };
391

    
392
    /**
393
     * Removes all listeners from a specified event.
394
     * If you do not specify an event then all listeners will be removed.
395
     * That means every event will be emptied.
396
     * You can also pass a regex to remove all events that match it.
397
     *
398
     * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
399
     * @return {Object} Current instance of EventEmitter for chaining.
400
     */
401
    proto.removeEvent = function removeEvent(evt) {
402
        var type = typeof evt;
403
        var events = this._getEvents();
404
        var key;
405

    
406
        // Remove different things depending on the state of evt
407
        if (type === 'string') {
408
            // Remove all listeners for the specified event
409
            delete events[evt];
410
        }
411
        else if (type === 'object') {
412
            // Remove all events matching the regex.
413
            for (key in events) {
414
                if (events.hasOwnProperty(key) && evt.test(key)) {
415
                    delete events[key];
416
                }
417
            }
418
        }
419
        else {
420
            // Remove all listeners in all events
421
            delete this._events;
422
        }
423

    
424
        return this;
425
    };
426

    
427
    /**
428
     * Emits an event of your choice.
429
     * When emitted, every listener attached to that event will be executed.
430
     * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
431
     * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
432
     * So they will not arrive within the array on the other side, they will be separate.
433
     * You can also pass a regular expression to emit to all events that match it.
434
     *
435
     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
436
     * @param {Array} [args] Optional array of arguments to be passed to each listener.
437
     * @return {Object} Current instance of EventEmitter for chaining.
438
     */
439
    proto.emitEvent = function emitEvent(evt, args) {
440
        var listeners = this.getListenersAsObject(evt);
441
        var listener;
442
        var i;
443
        var key;
444
        var response;
445

    
446
        for (key in listeners) {
447
            if (listeners.hasOwnProperty(key)) {
448
                i = listeners[key].length;
449

    
450
                while (i--) {
451
                    // If the listener returns true then it shall be removed from the event
452
                    // The function is executed either with a basic call or an apply if there is an args array
453
                    listener = listeners[key][i];
454
                    response = listener.listener.apply(this, args || []);
455
                    if (response === this._getOnceReturnValue() || listener.once === true) {
456
                        this.removeListener(evt, listener.listener);
457
                    }
458
                }
459
            }
460
        }
461

    
462
        return this;
463
    };
464

    
465
    /**
466
     * Alias of emitEvent
467
     */
468
    proto.trigger = alias('emitEvent');
469

    
470
    /**
471
     * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
472
     * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
473
     *
474
     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
475
     * @param {...*} Optional additional arguments to be passed to each listener.
476
     * @return {Object} Current instance of EventEmitter for chaining.
477
     */
478
    proto.emit = function emit(evt) {
479
        var args = Array.prototype.slice.call(arguments, 1);
480
        return this.emitEvent(evt, args);
481
    };
482

    
483
    /**
484
     * Sets the current value to check against when executing listeners. If a
485
     * listeners return value matches the one set here then it will be removed
486
     * after execution. This value defaults to true.
487
     *
488
     * @param {*} value The new value to check for when executing listeners.
489
     * @return {Object} Current instance of EventEmitter for chaining.
490
     */
491
    proto.setOnceReturnValue = function setOnceReturnValue(value) {
492
        this._onceReturnValue = value;
493
        return this;
494
    };
495

    
496
    /**
497
     * Fetches the current value to check against when executing listeners. If
498
     * the listeners return value matches this one then it should be removed
499
     * automatically. It will return true by default.
500
     *
501
     * @return {*|Boolean} The current value to check for or the default, true.
502
     * @api private
503
     */
504
    proto._getOnceReturnValue = function _getOnceReturnValue() {
505
        if (this.hasOwnProperty('_onceReturnValue')) {
506
            return this._onceReturnValue;
507
        }
508
        else {
509
            return true;
510
        }
511
    };
512

    
513
    /**
514
     * Fetches the events object and creates one if required.
515
     *
516
     * @return {Object} The events storage object.
517
     * @api private
518
     */
519
    proto._getEvents = function _getEvents() {
520
        return this._events || (this._events = {});
521
    };
522

    
523
    // Expose the class either via AMD, CommonJS or the global object
524
    if (typeof define === 'function' && define.amd) {
525
        define('eventEmitter/EventEmitter',[],function () {
526
            return EventEmitter;
527
        });
528
    }
529
    else if (typeof module === 'object' && module.exports){
530
        module.exports = EventEmitter;
531
    }
532
    else {
533
        this.EventEmitter = EventEmitter;
534
    }
535
}.call(this));
536

    
537
/*!
538
 * eventie v1.0.3
539
 * event binding helper
540
 *   eventie.bind( elem, 'click', myFn )
541
 *   eventie.unbind( elem, 'click', myFn )
542
 */
543

    
544
/*jshint browser: true, undef: true, unused: true */
545
/*global define: false */
546

    
547
( function( window ) {
548

    
549

    
550

    
551
var docElem = document.documentElement;
552

    
553
var bind = function() {};
554

    
555
if ( docElem.addEventListener ) {
556
  bind = function( obj, type, fn ) {
557
    obj.addEventListener( type, fn, false );
558
  };
559
} else if ( docElem.attachEvent ) {
560
  bind = function( obj, type, fn ) {
561
    obj[ type + fn ] = fn.handleEvent ?
562
      function() {
563
        var event = window.event;
564
        // add event.target
565
        event.target = event.target || event.srcElement;
566
        fn.handleEvent.call( fn, event );
567
      } :
568
      function() {
569
        var event = window.event;
570
        // add event.target
571
        event.target = event.target || event.srcElement;
572
        fn.call( obj, event );
573
      };
574
    obj.attachEvent( "on" + type, obj[ type + fn ] );
575
  };
576
}
577

    
578
var unbind = function() {};
579

    
580
if ( docElem.removeEventListener ) {
581
  unbind = function( obj, type, fn ) {
582
    obj.removeEventListener( type, fn, false );
583
  };
584
} else if ( docElem.detachEvent ) {
585
  unbind = function( obj, type, fn ) {
586
    obj.detachEvent( "on" + type, obj[ type + fn ] );
587
    try {
588
      delete obj[ type + fn ];
589
    } catch ( err ) {
590
      // can't delete window object properties
591
      obj[ type + fn ] = undefined;
592
    }
593
  };
594
}
595

    
596
var eventie = {
597
  bind: bind,
598
  unbind: unbind
599
};
600

    
601
// transport
602
if ( typeof define === 'function' && define.amd ) {
603
  // AMD
604
  define( 'eventie/eventie',eventie );
605
} else {
606
  // browser global
607
  window.eventie = eventie;
608
}
609

    
610
})( this );
611

    
612
/*!
613
 * getStyleProperty by kangax
614
 * http://perfectionkills.com/feature-testing-css-properties/
615
 */
616

    
617
/*jshint browser: true, strict: true, undef: true */
618
/*globals define: false */
619

    
620
( function( window ) {
621

    
622

    
623

    
624
var prefixes = 'Webkit Moz ms Ms O'.split(' ');
625
var docElemStyle = document.documentElement.style;
626

    
627
function getStyleProperty( propName ) {
628
  if ( !propName ) {
629
    return;
630
  }
631

    
632
  // test standard property first
633
  if ( typeof docElemStyle[ propName ] === 'string' ) {
634
    return propName;
635
  }
636

    
637
  // capitalize
638
  propName = propName.charAt(0).toUpperCase() + propName.slice(1);
639

    
640
  // test vendor specific properties
641
  var prefixed;
642
  for ( var i=0, len = prefixes.length; i < len; i++ ) {
643
    prefixed = prefixes[i] + propName;
644
    if ( typeof docElemStyle[ prefixed ] === 'string' ) {
645
      return prefixed;
646
    }
647
  }
648
}
649

    
650
// transport
651
if ( typeof define === 'function' && define.amd ) {
652
  // AMD
653
  define( 'get-style-property/get-style-property',[],function() {
654
    return getStyleProperty;
655
  });
656
} else {
657
  // browser global
658
  window.getStyleProperty = getStyleProperty;
659
}
660

    
661
})( window );
662

    
663
/**
664
 * getSize v1.1.4
665
 * measure size of elements
666
 */
667

    
668
/*jshint browser: true, strict: true, undef: true, unused: true */
669
/*global define: false */
670

    
671
( function( window, undefined ) {
672

    
673

    
674

    
675
// -------------------------- helpers -------------------------- //
676

    
677
var defView = document.defaultView;
678

    
679
var getStyle = defView && defView.getComputedStyle ?
680
  function( elem ) {
681
    return defView.getComputedStyle( elem, null );
682
  } :
683
  function( elem ) {
684
    return elem.currentStyle;
685
  };
686

    
687
// get a number from a string, not a percentage
688
function getStyleSize( value ) {
689
  var num = parseFloat( value );
690
  // not a percent like '100%', and a number
691
  var isValid = value.indexOf('%') === -1 && !isNaN( num );
692
  return isValid && num;
693
}
694

    
695
// -------------------------- measurements -------------------------- //
696

    
697
var measurements = [
698
  'paddingLeft',
699
  'paddingRight',
700
  'paddingTop',
701
  'paddingBottom',
702
  'marginLeft',
703
  'marginRight',
704
  'marginTop',
705
  'marginBottom',
706
  'borderLeftWidth',
707
  'borderRightWidth',
708
  'borderTopWidth',
709
  'borderBottomWidth'
710
];
711

    
712
function getZeroSize() {
713
  var size = {
714
    width: 0,
715
    height: 0,
716
    innerWidth: 0,
717
    innerHeight: 0,
718
    outerWidth: 0,
719
    outerHeight: 0
720
  };
721
  for ( var i=0, len = measurements.length; i < len; i++ ) {
722
    var measurement = measurements[i];
723
    size[ measurement ] = 0;
724
  }
725
  return size;
726
}
727

    
728

    
729

    
730
function defineGetSize( getStyleProperty ) {
731

    
732
// -------------------------- box sizing -------------------------- //
733

    
734
var boxSizingProp = getStyleProperty('boxSizing');
735
var isBoxSizeOuter;
736

    
737
/**
738
 * WebKit measures the outer-width on style.width on border-box elems
739
 * IE & Firefox measures the inner-width
740
 */
741
( function() {
742
  if ( !boxSizingProp ) {
743
    return;
744
  }
745

    
746
  var div = document.createElement('div');
747
  div.style.width = '200px';
748
  div.style.padding = '1px 2px 3px 4px';
749
  div.style.borderStyle = 'solid';
750
  div.style.borderWidth = '1px 2px 3px 4px';
751
  div.style[ boxSizingProp ] = 'border-box';
752

    
753
  var body = document.body || document.documentElement;
754
  body.appendChild( div );
755
  var style = getStyle( div );
756

    
757
  isBoxSizeOuter = getStyleSize( style.width ) === 200;
758
  body.removeChild( div );
759
})();
760

    
761

    
762
// -------------------------- getSize -------------------------- //
763

    
764
function getSize( elem ) {
765
  // use querySeletor if elem is string
766
  if ( typeof elem === 'string' ) {
767
    elem = document.querySelector( elem );
768
  }
769

    
770
  // do not proceed on non-objects
771
  if ( !elem || typeof elem !== 'object' || !elem.nodeType ) {
772
    return;
773
  }
774

    
775
  var style = getStyle( elem );
776

    
777
  // if hidden, everything is 0
778
  if ( style.display === 'none' ) {
779
    return getZeroSize();
780
  }
781

    
782
  var size = {};
783
  size.width = elem.offsetWidth;
784
  size.height = elem.offsetHeight;
785

    
786
  var isBorderBox = size.isBorderBox = !!( boxSizingProp &&
787
    style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' );
788

    
789
  // get all measurements
790
  for ( var i=0, len = measurements.length; i < len; i++ ) {
791
    var measurement = measurements[i];
792
    var value = style[ measurement ];
793
    var num = parseFloat( value );
794
    // any 'auto', 'medium' value will be 0
795
    size[ measurement ] = !isNaN( num ) ? num : 0;
796
  }
797

    
798
  var paddingWidth = size.paddingLeft + size.paddingRight;
799
  var paddingHeight = size.paddingTop + size.paddingBottom;
800
  var marginWidth = size.marginLeft + size.marginRight;
801
  var marginHeight = size.marginTop + size.marginBottom;
802
  var borderWidth = size.borderLeftWidth + size.borderRightWidth;
803
  var borderHeight = size.borderTopWidth + size.borderBottomWidth;
804

    
805
  var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
806

    
807
  // overwrite width and height if we can get it from style
808
  var styleWidth = getStyleSize( style.width );
809
  if ( styleWidth !== false ) {
810
    size.width = styleWidth +
811
      // add padding and border unless it's already including it
812
      ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
813
  }
814

    
815
  var styleHeight = getStyleSize( style.height );
816
  if ( styleHeight !== false ) {
817
    size.height = styleHeight +
818
      // add padding and border unless it's already including it
819
      ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
820
  }
821

    
822
  size.innerWidth = size.width - ( paddingWidth + borderWidth );
823
  size.innerHeight = size.height - ( paddingHeight + borderHeight );
824

    
825
  size.outerWidth = size.width + marginWidth;
826
  size.outerHeight = size.height + marginHeight;
827

    
828
  return size;
829
}
830

    
831
return getSize;
832

    
833
}
834

    
835
// transport
836
if ( typeof define === 'function' && define.amd ) {
837
  // AMD
838
  define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize );
839
} else {
840
  // browser global
841
  window.getSize = defineGetSize( window.getStyleProperty );
842
}
843

    
844
})( window );
845

    
846
/*!
847
 * Draggabilly v1.1.2
848
 * Make that shiz draggable
849
 * http://draggabilly.desandro.com
850
 * MIT license
851
 */
852

    
853
( function( window ) {
854

    
855

    
856

    
857
// vars
858
var document = window.document;
859

    
860
// -------------------------- helpers -------------------------- //
861

    
862
// extend objects
863
function extend( a, b ) {
864
  for ( var prop in b ) {
865
    a[ prop ] = b[ prop ];
866
  }
867
  return a;
868
}
869

    
870
function noop() {}
871

    
872
// ----- get style ----- //
873

    
874
var defView = document.defaultView;
875

    
876
var getStyle = defView && defView.getComputedStyle ?
877
  function( elem ) {
878
    return defView.getComputedStyle( elem, null );
879
  } :
880
  function( elem ) {
881
    return elem.currentStyle;
882
  };
883

    
884

    
885
// http://stackoverflow.com/a/384380/182183
886
var isElement = ( typeof HTMLElement === 'object' ) ?
887
  function isElementDOM2( obj ) {
888
    return obj instanceof HTMLElement;
889
  } :
890
  function isElementQuirky( obj ) {
891
    return obj && typeof obj === 'object' &&
892
      obj.nodeType === 1 && typeof obj.nodeName === 'string';
893
  };
894

    
895
// -------------------------- requestAnimationFrame -------------------------- //
896

    
897
// https://gist.github.com/1866474
898

    
899
var lastTime = 0;
900
var prefixes = 'webkit moz ms o'.split(' ');
901
// get unprefixed rAF and cAF, if present
902
var requestAnimationFrame = window.requestAnimationFrame;
903
var cancelAnimationFrame = window.cancelAnimationFrame;
904
// loop through vendor prefixes and get prefixed rAF and cAF
905
var prefix;
906
for( var i = 0; i < prefixes.length; i++ ) {
907
  if ( requestAnimationFrame && cancelAnimationFrame ) {
908
    break;
909
  }
910
  prefix = prefixes[i];
911
  requestAnimationFrame = requestAnimationFrame || window[ prefix + 'RequestAnimationFrame' ];
912
  cancelAnimationFrame  = cancelAnimationFrame  || window[ prefix + 'CancelAnimationFrame' ] ||
913
                            window[ prefix + 'CancelRequestAnimationFrame' ];
914
}
915

    
916
// fallback to setTimeout and clearTimeout if either request/cancel is not supported
917
if ( !requestAnimationFrame || !cancelAnimationFrame )  {
918
  requestAnimationFrame = function( callback ) {
919
    var currTime = new Date().getTime();
920
    var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
921
    var id = window.setTimeout( function() {
922
      callback( currTime + timeToCall );
923
    }, timeToCall );
924
    lastTime = currTime + timeToCall;
925
    return id;
926
  };
927

    
928
  cancelAnimationFrame = function( id ) {
929
    window.clearTimeout( id );
930
  };
931
}
932

    
933
// -------------------------- definition -------------------------- //
934

    
935
function draggabillyDefinition( classie, EventEmitter, eventie, getStyleProperty, getSize ) {
936

    
937
// -------------------------- support -------------------------- //
938

    
939
var transformProperty = getStyleProperty('transform');
940
// TODO fix quick & dirty check for 3D support
941
var is3d = !!getStyleProperty('perspective');
942

    
943
// --------------------------  -------------------------- //
944

    
945
function Draggabilly( element, options ) {
946
  // querySelector if string
947
  this.element = typeof element === 'string' ?
948
    document.querySelector( element ) : element;
949

    
950
  this.options = extend( {}, this.options );
951
  extend( this.options, options );
952

    
953
  this._create();
954
}
955

    
956
// inherit EventEmitter methods
957
extend( Draggabilly.prototype, EventEmitter.prototype );
958

    
959
Draggabilly.prototype.options = {
960
};
961

    
962
Draggabilly.prototype._create = function() {
963

    
964
  // properties
965
  this.position = {};
966
  this._getPosition();
967

    
968
  this.startPoint = { x: 0, y: 0 };
969
  this.dragPoint = { x: 0, y: 0 };
970

    
971
  this.startPosition = extend( {}, this.position );
972

    
973
  // set relative positioning
974
  var style = getStyle( this.element );
975
  if ( style.position !== 'relative' && style.position !== 'absolute' ) {
976
    this.element.style.position = 'relative';
977
  }
978

    
979
  this.enable();
980
  this.setHandles();
981

    
982
};
983

    
984
/**
985
 * set this.handles and bind start events to 'em
986
 */
987
Draggabilly.prototype.setHandles = function() {
988
  this.handles = this.options.handle ?
989
    this.element.querySelectorAll( this.options.handle ) : [ this.element ];
990

    
991
  this.bindHandles( true );
992
};
993

    
994
// -------------------------- bind -------------------------- //
995

    
996
/**
997
 * @param {Boolean} isBind - will unbind if falsey
998
 */
999
Draggabilly.prototype.bindHandles = function( isBind ) {
1000
  var binder;
1001
  if ( window.navigator.pointerEnabled ) {
1002
    binder = this.bindPointer;
1003
  } else if ( window.navigator.msPointerEnabled ) {
1004
    binder = this.bindMSPointer;
1005
  } else {
1006
    binder = this.bindMouseTouch;
1007
  }
1008
  // munge isBind, default to true
1009
  isBind = isBind === undefined ? true : !!isBind;
1010
  for ( var i=0, len = this.handles.length; i < len; i++ ) {
1011
    var handle = this.handles[i];
1012
    binder.call( this, handle, isBind );
1013
  }
1014
};
1015

    
1016
Draggabilly.prototype.bindPointer = function( handle, isBind ) {
1017
  // W3C Pointer Events, IE11. See https://coderwall.com/p/mfreca
1018
  var bindMethod = isBind ? 'bind' : 'unbind';
1019
  eventie[ bindMethod ]( handle, 'pointerdown', this );
1020
  // disable scrolling on the element
1021
  handle.style.touchAction = isBind ? 'none' : '';
1022
};
1023

    
1024
Draggabilly.prototype.bindMSPointer = function( handle, isBind ) {
1025
  // IE10 Pointer Events
1026
  var bindMethod = isBind ? 'bind' : 'unbind';
1027
  eventie[ bindMethod ]( handle, 'MSPointerDown', this );
1028
  // disable scrolling on the element
1029
  handle.style.msTouchAction = isBind ? 'none' : '';
1030
};
1031

    
1032
Draggabilly.prototype.bindMouseTouch = function( handle, isBind ) {
1033
  // listen for both, for devices like Chrome Pixel
1034
  //   which has touch and mouse events
1035
  var bindMethod = isBind ? 'bind' : 'unbind';
1036
  eventie[ bindMethod ]( handle, 'mousedown', this );
1037
  eventie[ bindMethod ]( handle, 'touchstart', this );
1038
  // TODO re-enable img.ondragstart when unbinding
1039
  if ( isBind ) {
1040
    disableImgOndragstart( handle );
1041
  }
1042
};
1043

    
1044
// remove default dragging interaction on all images in IE8
1045
// IE8 does its own drag thing on images, which messes stuff up
1046

    
1047
function noDragStart() {
1048
  return false;
1049
}
1050

    
1051
// TODO replace this with a IE8 test
1052
var isIE8 = 'attachEvent' in document.documentElement;
1053

    
1054
// IE8 only
1055
var disableImgOndragstart = !isIE8 ? noop : function( handle ) {
1056

    
1057
  if ( handle.nodeName === 'IMG' ) {
1058
    handle.ondragstart = noDragStart;
1059
  }
1060

    
1061
  var images = handle.querySelectorAll('img');
1062
  for ( var i=0, len = images.length; i < len; i++ ) {
1063
    var img = images[i];
1064
    img.ondragstart = noDragStart;
1065
  }
1066
};
1067

    
1068
// -------------------------- position -------------------------- //
1069

    
1070
// get left/top position from style
1071
Draggabilly.prototype._getPosition = function() {
1072
  // properties
1073
  var style = getStyle( this.element );
1074

    
1075
  var x = parseInt( style.left, 10 );
1076
  var y = parseInt( style.top, 10 );
1077

    
1078
  // clean up 'auto' or other non-integer values
1079
  this.position.x = isNaN( x ) ? 0 : x;
1080
  this.position.y = isNaN( y ) ? 0 : y;
1081

    
1082
  this._addTransformPosition( style );
1083
};
1084

    
1085
// add transform: translate( x, y ) to position
1086
Draggabilly.prototype._addTransformPosition = function( style ) {
1087
  if ( !transformProperty ) {
1088
    return;
1089
  }
1090
  var transform = style[ transformProperty ];
1091
  // bail out if value is 'none'
1092
  if ( transform.indexOf('matrix') !== 0 ) {
1093
    return;
1094
  }
1095
  // split matrix(1, 0, 0, 1, x, y)
1096
  var matrixValues = transform.split(',');
1097
  // translate X value is in 12th or 4th position
1098
  var xIndex = transform.indexOf('matrix3d') === 0 ? 12 : 4;
1099
  var translateX = parseInt( matrixValues[ xIndex ], 10 );
1100
  // translate Y value is in 13th or 5th position
1101
  var translateY = parseInt( matrixValues[ xIndex + 1 ], 10 );
1102
  this.position.x += translateX;
1103
  this.position.y += translateY;
1104
};
1105

    
1106
// -------------------------- events -------------------------- //
1107

    
1108
// trigger handler methods for events
1109
Draggabilly.prototype.handleEvent = function( event ) {
1110
  var method = 'on' + event.type;
1111
  if ( this[ method ] ) {
1112
    this[ method ]( event );
1113
  }
1114
};
1115

    
1116
// returns the touch that we're keeping track of
1117
Draggabilly.prototype.getTouch = function( touches ) {
1118
  for ( var i=0, len = touches.length; i < len; i++ ) {
1119
    var touch = touches[i];
1120
    if ( touch.identifier === this.pointerIdentifier ) {
1121
      return touch;
1122
    }
1123
  }
1124
};
1125

    
1126
// ----- start event ----- //
1127

    
1128
Draggabilly.prototype.onmousedown = function( event ) {
1129
  // dismiss clicks from right or middle buttons
1130
  var button = event.button;
1131
  if ( button && ( button !== 0 && button !== 1 ) ) {
1132
    return;
1133
  }
1134
  this.dragStart( event, event );
1135
};
1136

    
1137
Draggabilly.prototype.ontouchstart = function( event ) {
1138
  // disregard additional touches
1139
  if ( this.isDragging ) {
1140
    return;
1141
  }
1142

    
1143
  this.dragStart( event, event.changedTouches[0] );
1144
};
1145

    
1146
Draggabilly.prototype.onMSPointerDown =
1147
Draggabilly.prototype.onpointerdown = function( event ) {
1148
  // disregard additional touches
1149
  if ( this.isDragging ) {
1150
    return;
1151
  }
1152

    
1153
  this.dragStart( event, event );
1154
};
1155

    
1156
function setPointerPoint( point, pointer ) {
1157
  point.x = pointer.pageX !== undefined ? pointer.pageX : pointer.clientX;
1158
  point.y = pointer.pageY !== undefined ? pointer.pageY : pointer.clientY;
1159
}
1160

    
1161
// hash of events to be bound after start event
1162
var postStartEvents = {
1163
  mousedown: [ 'mousemove', 'mouseup' ],
1164
  touchstart: [ 'touchmove', 'touchend', 'touchcancel' ],
1165
  pointerdown: [ 'pointermove', 'pointerup', 'pointercancel' ],
1166
  MSPointerDown: [ 'MSPointerMove', 'MSPointerUp', 'MSPointerCancel' ]
1167
};
1168

    
1169
/**
1170
 * drag start
1171
 * @param {Event} event
1172
 * @param {Event or Touch} pointer
1173
 */
1174
Draggabilly.prototype.dragStart = function( event, pointer ) {
1175
  if ( !this.isEnabled ) {
1176
    return;
1177
  }
1178

    
1179
  if ( event.preventDefault ) {
1180
    event.preventDefault();
1181
  } else {
1182
    event.returnValue = false;
1183
  }
1184

    
1185
  // save pointer identifier to match up touch events
1186
  this.pointerIdentifier = pointer.pointerId !== undefined ?
1187
    // pointerId for pointer events, touch.indentifier for touch events
1188
    pointer.pointerId : pointer.identifier;
1189

    
1190
  this._getPosition();
1191

    
1192
  this.measureContainment();
1193

    
1194
  // point where drag began
1195
  setPointerPoint( this.startPoint, pointer );
1196
  // position _when_ drag began
1197
  this.startPosition.x = this.position.x;
1198
  this.startPosition.y = this.position.y;
1199

    
1200
  // reset left/top style
1201
  this.setLeftTop();
1202

    
1203
  this.dragPoint.x = 0;
1204
  this.dragPoint.y = 0;
1205

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

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

    
1216
  // reset isDragging flag
1217
  this.isDragging = true;
1218

    
1219
  this.emitEvent( 'dragStart', [ this, event, pointer ] );
1220

    
1221
  // start animation
1222
  this.animate();
1223
};
1224

    
1225
Draggabilly.prototype._bindEvents = function( args ) {
1226
  for ( var i=0, len = args.events.length; i < len; i++ ) {
1227
    var event = args.events[i];
1228
    eventie.bind( args.node, event, this );
1229
  }
1230
  // save these arguments
1231
  this._boundEvents = args;
1232
};
1233

    
1234
Draggabilly.prototype._unbindEvents = function() {
1235
  var args = this._boundEvents;
1236
  // IE8 can trigger dragEnd twice, check for _boundEvents
1237
  if ( !args || !args.events ) {
1238
    return;
1239
  }
1240

    
1241
  for ( var i=0, len = args.events.length; i < len; i++ ) {
1242
    var event = args.events[i];
1243
    eventie.unbind( args.node, event, this );
1244
  }
1245
  delete this._boundEvents;
1246
};
1247

    
1248
Draggabilly.prototype.measureContainment = function() {
1249
  var containment = this.options.containment;
1250
  if ( !containment ) {
1251
    return;
1252
  }
1253

    
1254
  this.size = getSize( this.element );
1255
  var elemRect = this.element.getBoundingClientRect();
1256

    
1257
  // use element if element
1258
  var container = isElement( containment ) ? containment :
1259
    // fallback to querySelector if string
1260
    typeof containment === 'string' ? document.querySelector( containment ) :
1261
    // otherwise just `true`, use the parent
1262
    this.element.parentNode;
1263

    
1264
  this.containerSize = getSize( container );
1265
  var containerRect = container.getBoundingClientRect();
1266

    
1267
  this.relativeStartPosition = {
1268
    x: elemRect.left - containerRect.left,
1269
    y: elemRect.top  - containerRect.top
1270
  };
1271
};
1272

    
1273
// ----- move event ----- //
1274

    
1275
Draggabilly.prototype.onmousemove = function( event ) {
1276
  this.dragMove( event, event );
1277
};
1278

    
1279
Draggabilly.prototype.onMSPointerMove =
1280
Draggabilly.prototype.onpointermove = function( event ) {
1281
  if ( event.pointerId === this.pointerIdentifier ) {
1282
    this.dragMove( event, event );
1283
  }
1284
};
1285

    
1286
Draggabilly.prototype.ontouchmove = function( event ) {
1287
  var touch = this.getTouch( event.changedTouches );
1288
  if ( touch ) {
1289
    this.dragMove( event, touch );
1290
  }
1291
};
1292

    
1293
/**
1294
 * drag move
1295
 * @param {Event} event
1296
 * @param {Event or Touch} pointer
1297
 */
1298
Draggabilly.prototype.dragMove = function( event, pointer ) {
1299

    
1300
  setPointerPoint( this.dragPoint, pointer );
1301
  var dragX = this.dragPoint.x - this.startPoint.x;
1302
  var dragY = this.dragPoint.y - this.startPoint.y;
1303

    
1304
  var grid = this.options.grid;
1305
  var gridX = grid && grid[0];
1306
  var gridY = grid && grid[1];
1307

    
1308
  dragX = applyGrid( dragX, gridX );
1309
  dragY = applyGrid( dragY, gridY );
1310

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

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

    
1318
  this.position.x = this.startPosition.x + dragX;
1319
  this.position.y = this.startPosition.y + dragY;
1320
  // set dragPoint properties
1321
  this.dragPoint.x = dragX;
1322
  this.dragPoint.y = dragY;
1323

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

    
1327
function applyGrid( value, grid, method ) {
1328
  method = method || 'round';
1329
  return grid ? Math[ method ]( value / grid ) * grid : value;
1330
}
1331

    
1332
Draggabilly.prototype.containDrag = function( axis, drag, grid ) {
1333
  if ( !this.options.containment ) {
1334
    return drag;
1335
  }
1336
  var measure = axis === 'x' ? 'width' : 'height';
1337

    
1338
  var rel = this.relativeStartPosition[ axis ];
1339
  var min = applyGrid( -rel, grid, 'ceil' );
1340
  var max = this.containerSize[ measure ] - rel - this.size[ measure ];
1341
  max = applyGrid( max, grid, 'floor' );
1342
  return  Math.min( max, Math.max( min, drag ) );
1343
};
1344

    
1345
// ----- end event ----- //
1346

    
1347
Draggabilly.prototype.onmouseup = function( event ) {
1348
  this.dragEnd( event, event );
1349
};
1350

    
1351
Draggabilly.prototype.onMSPointerUp =
1352
Draggabilly.prototype.onpointerup = function( event ) {
1353
  if ( event.pointerId === this.pointerIdentifier ) {
1354
    this.dragEnd( event, event );
1355
  }
1356
};
1357

    
1358
Draggabilly.prototype.ontouchend = function( event ) {
1359
  var touch = this.getTouch( event.changedTouches );
1360
  if ( touch ) {
1361
    this.dragEnd( event, touch );
1362
  }
1363
};
1364

    
1365
/**
1366
 * drag end
1367
 * @param {Event} event
1368
 * @param {Event or Touch} pointer
1369
 */
1370
Draggabilly.prototype.dragEnd = function( event, pointer ) {
1371
  this.isDragging = false;
1372

    
1373
  delete this.pointerIdentifier;
1374

    
1375
  // use top left position when complete
1376
  if ( transformProperty ) {
1377
    this.element.style[ transformProperty ] = '';
1378
    this.setLeftTop();
1379
  }
1380

    
1381
  // remove events
1382
  this._unbindEvents();
1383

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

    
1386
  this.emitEvent( 'dragEnd', [ this, event, pointer ] );
1387

    
1388
};
1389

    
1390
// ----- cancel event ----- //
1391

    
1392
// coerce to end event
1393

    
1394
Draggabilly.prototype.onMSPointerCancel =
1395
Draggabilly.prototype.onpointercancel = function( event ) {
1396
  if ( event.pointerId === this.pointerIdentifier ) {
1397
    this.dragEnd( event, event );
1398
  }
1399
};
1400

    
1401
Draggabilly.prototype.ontouchcancel = function( event ) {
1402
  var touch = this.getTouch( event.changedTouches );
1403
  this.dragEnd( event, touch );
1404
};
1405

    
1406
// -------------------------- animation -------------------------- //
1407

    
1408
Draggabilly.prototype.animate = function() {
1409
  // only render and animate if dragging
1410
  if ( !this.isDragging ) {
1411
    return;
1412
  }
1413

    
1414
  this.positionDrag();
1415

    
1416
  var _this = this;
1417
  requestAnimationFrame( function animateFrame() {
1418
    _this.animate();
1419
  });
1420

    
1421
};
1422

    
1423
// transform translate function
1424
var translate = is3d ?
1425
  function( x, y ) {
1426
    return 'translate3d( ' + x + 'px, ' + y + 'px, 0)';
1427
  } :
1428
  function( x, y ) {
1429
    return 'translate( ' + x + 'px, ' + y + 'px)';
1430
  };
1431

    
1432
// left/top positioning
1433
Draggabilly.prototype.setLeftTop = function() {
1434
  this.element.style.left = this.position.x + 'px';
1435
  this.element.style.top  = this.position.y + 'px';
1436
};
1437

    
1438
Draggabilly.prototype.positionDrag = transformProperty ?
1439
  function() {
1440
    // position with transform
1441
    this.element.style[ transformProperty ] = translate( this.dragPoint.x, this.dragPoint.y );
1442
  } : Draggabilly.prototype.setLeftTop;
1443

    
1444
// -----  ----- //
1445

    
1446
Draggabilly.prototype.enable = function() {
1447
  this.isEnabled = true;
1448
};
1449

    
1450
Draggabilly.prototype.disable = function() {
1451
  this.isEnabled = false;
1452
  if ( this.isDragging ) {
1453
    this.dragEnd();
1454
  }
1455
};
1456

    
1457
Draggabilly.prototype.destroy = function() {
1458
  this.disable();
1459
  // reset styles
1460
  if ( transformProperty ) {
1461
    this.element.style[ transformProperty ] = '';
1462
  }
1463
  this.element.style.left = '';
1464
  this.element.style.top = '';
1465
  this.element.style.position = '';
1466
  // unbind handles
1467
  this.bindHandles( false );
1468
};
1469

    
1470
// -----  ----- //
1471

    
1472
return Draggabilly;
1473

    
1474
} // end definition
1475

    
1476
// -------------------------- transport -------------------------- //
1477

    
1478
if ( typeof define === 'function' && define.amd ) {
1479
  // AMD
1480
  define( [
1481
      'classie/classie',
1482
      'eventEmitter/EventEmitter',
1483
      'eventie/eventie',
1484
      'get-style-property/get-style-property',
1485
      'get-size/get-size'
1486
    ],
1487
    draggabillyDefinition );
1488
} else if ( typeof exports === 'object' ) {
1489
  // CommonJS
1490
  module.exports = draggabillyDefinition(
1491
    require('desandro-classie'),
1492
    require('wolfy87-eventemitter'),
1493
    require('eventie'),
1494
    require('desandro-get-style-property'),
1495
    require('get-size')
1496
  );
1497
} else {
1498
  // browser global
1499
  window.Draggabilly = draggabillyDefinition(
1500
    window.classie,
1501
    window.EventEmitter,
1502
    window.eventie,
1503
    window.getStyleProperty,
1504
    window.getSize
1505
  );
1506
}
1507

    
1508
})( window );
1509

    
(4-4/13)