UNPKG

24.5 kBJavaScriptView Raw
1/*!
2 * The Sutton SignWriting Web Components
3 */
4import { c as createCommonjsModule, a as commonjsGlobal } from './_commonjsHelpers-383fba37.js';
5
6var getSize = createCommonjsModule(function (module) {
7/*!
8 * Infinite Scroll v2.0.4
9 * measure size of elements
10 * MIT license
11 */
12
13( function( window, factory ) {
14 if ( module.exports ) {
15 // CommonJS
16 module.exports = factory();
17 } else {
18 // browser global
19 window.getSize = factory();
20 }
21
22} )( window, function factory() {
23
24// -------------------------- helpers -------------------------- //
25
26// get a number from a string, not a percentage
27function getStyleSize( value ) {
28 let num = parseFloat( value );
29 // not a percent like '100%', and a number
30 let isValid = value.indexOf('%') == -1 && !isNaN( num );
31 return isValid && num;
32}
33
34// -------------------------- measurements -------------------------- //
35
36let measurements = [
37 'paddingLeft',
38 'paddingRight',
39 'paddingTop',
40 'paddingBottom',
41 'marginLeft',
42 'marginRight',
43 'marginTop',
44 'marginBottom',
45 'borderLeftWidth',
46 'borderRightWidth',
47 'borderTopWidth',
48 'borderBottomWidth',
49];
50
51function getZeroSize() {
52 let size = {
53 width: 0,
54 height: 0,
55 innerWidth: 0,
56 innerHeight: 0,
57 outerWidth: 0,
58 outerHeight: 0,
59 };
60 measurements.forEach( ( measurement ) => {
61 size[ measurement ] = 0;
62 } );
63 return size;
64}
65
66// -------------------------- getSize -------------------------- //
67
68function getSize( elem ) {
69 // use querySeletor if elem is string
70 if ( typeof elem == 'string' ) elem = document.querySelector( elem );
71
72 // do not proceed on non-objects
73 let isElement = elem && typeof elem == 'object' && elem.nodeType;
74 if ( !isElement ) return;
75
76 let style = getComputedStyle( elem );
77
78 // if hidden, everything is 0
79 if ( style.display == 'none' ) return getZeroSize();
80
81 let size = {};
82 size.width = elem.offsetWidth;
83 size.height = elem.offsetHeight;
84
85 let isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
86
87 // get all measurements
88 measurements.forEach( ( measurement ) => {
89 let value = style[ measurement ];
90 let num = parseFloat( value );
91 // any 'auto', 'medium' value will be 0
92 size[ measurement ] = !isNaN( num ) ? num : 0;
93 } );
94
95 let paddingWidth = size.paddingLeft + size.paddingRight;
96 let paddingHeight = size.paddingTop + size.paddingBottom;
97 let marginWidth = size.marginLeft + size.marginRight;
98 let marginHeight = size.marginTop + size.marginBottom;
99 let borderWidth = size.borderLeftWidth + size.borderRightWidth;
100 let borderHeight = size.borderTopWidth + size.borderBottomWidth;
101
102 // overwrite width and height if we can get it from style
103 let styleWidth = getStyleSize( style.width );
104 if ( styleWidth !== false ) {
105 size.width = styleWidth +
106 // add padding and border unless it's already including it
107 ( isBorderBox ? 0 : paddingWidth + borderWidth );
108 }
109
110 let styleHeight = getStyleSize( style.height );
111 if ( styleHeight !== false ) {
112 size.height = styleHeight +
113 // add padding and border unless it's already including it
114 ( isBorderBox ? 0 : paddingHeight + borderHeight );
115 }
116
117 size.innerWidth = size.width - ( paddingWidth + borderWidth );
118 size.innerHeight = size.height - ( paddingHeight + borderHeight );
119
120 size.outerWidth = size.width + marginWidth;
121 size.outerHeight = size.height + marginHeight;
122
123 return size;
124}
125
126return getSize;
127
128} );
129});
130
131var evEmitter = createCommonjsModule(function (module) {
132/**
133 * EvEmitter v2.1.1
134 * Lil' event emitter
135 * MIT License
136 */
137
138( function( global, factory ) {
139 // universal module definition
140 if ( module.exports ) {
141 // CommonJS - Browserify, Webpack
142 module.exports = factory();
143 } else {
144 // Browser globals
145 global.EvEmitter = factory();
146 }
147
148}( typeof window != 'undefined' ? window : commonjsGlobal, function() {
149
150function EvEmitter() {}
151
152let proto = EvEmitter.prototype;
153
154proto.on = function( eventName, listener ) {
155 if ( !eventName || !listener ) return this;
156
157 // set events hash
158 let events = this._events = this._events || {};
159 // set listeners array
160 let listeners = events[ eventName ] = events[ eventName ] || [];
161 // only add once
162 if ( !listeners.includes( listener ) ) {
163 listeners.push( listener );
164 }
165
166 return this;
167};
168
169proto.once = function( eventName, listener ) {
170 if ( !eventName || !listener ) return this;
171
172 // add event
173 this.on( eventName, listener );
174 // set once flag
175 // set onceEvents hash
176 let onceEvents = this._onceEvents = this._onceEvents || {};
177 // set onceListeners object
178 let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
179 // set flag
180 onceListeners[ listener ] = true;
181
182 return this;
183};
184
185proto.off = function( eventName, listener ) {
186 let listeners = this._events && this._events[ eventName ];
187 if ( !listeners || !listeners.length ) return this;
188
189 let index = listeners.indexOf( listener );
190 if ( index != -1 ) {
191 listeners.splice( index, 1 );
192 }
193
194 return this;
195};
196
197proto.emitEvent = function( eventName, args ) {
198 let listeners = this._events && this._events[ eventName ];
199 if ( !listeners || !listeners.length ) return this;
200
201 // copy over to avoid interference if .off() in listener
202 listeners = listeners.slice( 0 );
203 args = args || [];
204 // once stuff
205 let onceListeners = this._onceEvents && this._onceEvents[ eventName ];
206
207 for ( let listener of listeners ) {
208 let isOnce = onceListeners && onceListeners[ listener ];
209 if ( isOnce ) {
210 // remove listener
211 // remove before trigger to prevent recursion
212 this.off( eventName, listener );
213 // unset once flag
214 delete onceListeners[ listener ];
215 }
216 // trigger listener
217 listener.apply( this, args );
218 }
219
220 return this;
221};
222
223proto.allOff = function() {
224 delete this._events;
225 delete this._onceEvents;
226 return this;
227};
228
229return EvEmitter;
230
231} ) );
232});
233
234var unidragger = createCommonjsModule(function (module) {
235/*!
236 * Unidragger v3.0.1
237 * Draggable base class
238 * MIT license
239 */
240
241( function( window, factory ) {
242 // universal module definition
243 if ( module.exports ) {
244 // CommonJS
245 module.exports = factory(
246 window,
247 evEmitter,
248 );
249 } else {
250 // browser global
251 window.Unidragger = factory(
252 window,
253 window.EvEmitter,
254 );
255 }
256
257}( typeof window != 'undefined' ? window : commonjsGlobal, function factory( window, EvEmitter ) {
258
259function Unidragger() {}
260
261// inherit EvEmitter
262let proto = Unidragger.prototype = Object.create( EvEmitter.prototype );
263
264// ----- bind start ----- //
265
266// trigger handler methods for events
267proto.handleEvent = function( event ) {
268 let method = 'on' + event.type;
269 if ( this[ method ] ) {
270 this[ method ]( event );
271 }
272};
273
274let startEvent, activeEvents;
275if ( 'ontouchstart' in window ) {
276 // HACK prefer Touch Events as you can preventDefault on touchstart to
277 // disable scroll in iOS & mobile Chrome metafizzy/flickity#1177
278 startEvent = 'touchstart';
279 activeEvents = [ 'touchmove', 'touchend', 'touchcancel' ];
280} else if ( window.PointerEvent ) {
281 // Pointer Events
282 startEvent = 'pointerdown';
283 activeEvents = [ 'pointermove', 'pointerup', 'pointercancel' ];
284} else {
285 // mouse events
286 startEvent = 'mousedown';
287 activeEvents = [ 'mousemove', 'mouseup' ];
288}
289
290// prototype so it can be overwriteable by Flickity
291proto.touchActionValue = 'none';
292
293proto.bindHandles = function() {
294 this._bindHandles( 'addEventListener', this.touchActionValue );
295};
296
297proto.unbindHandles = function() {
298 this._bindHandles( 'removeEventListener', '' );
299};
300
301/**
302 * Add or remove start event
303 * @param {String} bindMethod - addEventListener or removeEventListener
304 * @param {String} touchAction - value for touch-action CSS property
305 */
306proto._bindHandles = function( bindMethod, touchAction ) {
307 this.handles.forEach( ( handle ) => {
308 handle[ bindMethod ]( startEvent, this );
309 handle[ bindMethod ]( 'click', this );
310 // touch-action: none to override browser touch gestures. metafizzy/flickity#540
311 if ( window.PointerEvent ) handle.style.touchAction = touchAction;
312 } );
313};
314
315proto.bindActivePointerEvents = function() {
316 activeEvents.forEach( ( eventName ) => {
317 window.addEventListener( eventName, this );
318 } );
319};
320
321proto.unbindActivePointerEvents = function() {
322 activeEvents.forEach( ( eventName ) => {
323 window.removeEventListener( eventName, this );
324 } );
325};
326
327// ----- event handler helpers ----- //
328
329// trigger method with matching pointer
330proto.withPointer = function( methodName, event ) {
331 if ( event.pointerId === this.pointerIdentifier ) {
332 this[ methodName ]( event, event );
333 }
334};
335
336// trigger method with matching touch
337proto.withTouch = function( methodName, event ) {
338 let touch;
339 for ( let changedTouch of event.changedTouches ) {
340 if ( changedTouch.identifier === this.pointerIdentifier ) {
341 touch = changedTouch;
342 }
343 }
344 if ( touch ) this[ methodName ]( event, touch );
345};
346
347// ----- start event ----- //
348
349proto.onmousedown = function( event ) {
350 this.pointerDown( event, event );
351};
352
353proto.ontouchstart = function( event ) {
354 this.pointerDown( event, event.changedTouches[0] );
355};
356
357proto.onpointerdown = function( event ) {
358 this.pointerDown( event, event );
359};
360
361// nodes that have text fields
362const cursorNodes = [ 'TEXTAREA', 'INPUT', 'SELECT', 'OPTION' ];
363// input types that do not have text fields
364const clickTypes = [ 'radio', 'checkbox', 'button', 'submit', 'image', 'file' ];
365
366/**
367 * any time you set `event, pointer` it refers to:
368 * @param {Event} event
369 * @param {Event | Touch} pointer
370 */
371proto.pointerDown = function( event, pointer ) {
372 // dismiss multi-touch taps, right clicks, and clicks on text fields
373 let isCursorNode = cursorNodes.includes( event.target.nodeName );
374 let isClickType = clickTypes.includes( event.target.type );
375 let isOkayElement = !isCursorNode || isClickType;
376 let isOkay = !this.isPointerDown && !event.button && isOkayElement;
377 if ( !isOkay ) return;
378
379 this.isPointerDown = true;
380 // save pointer identifier to match up touch events
381 this.pointerIdentifier = pointer.pointerId !== undefined ?
382 // pointerId for pointer events, touch.indentifier for touch events
383 pointer.pointerId : pointer.identifier;
384 // track position for move
385 this.pointerDownPointer = {
386 pageX: pointer.pageX,
387 pageY: pointer.pageY,
388 };
389
390 this.bindActivePointerEvents();
391 this.emitEvent( 'pointerDown', [ event, pointer ] );
392};
393
394// ----- move ----- //
395
396proto.onmousemove = function( event ) {
397 this.pointerMove( event, event );
398};
399
400proto.onpointermove = function( event ) {
401 this.withPointer( 'pointerMove', event );
402};
403
404proto.ontouchmove = function( event ) {
405 this.withTouch( 'pointerMove', event );
406};
407
408proto.pointerMove = function( event, pointer ) {
409 let moveVector = {
410 x: pointer.pageX - this.pointerDownPointer.pageX,
411 y: pointer.pageY - this.pointerDownPointer.pageY,
412 };
413 this.emitEvent( 'pointerMove', [ event, pointer, moveVector ] );
414 // start drag if pointer has moved far enough to start drag
415 let isDragStarting = !this.isDragging && this.hasDragStarted( moveVector );
416 if ( isDragStarting ) this.dragStart( event, pointer );
417 if ( this.isDragging ) this.dragMove( event, pointer, moveVector );
418};
419
420// condition if pointer has moved far enough to start drag
421proto.hasDragStarted = function( moveVector ) {
422 return Math.abs( moveVector.x ) > 3 || Math.abs( moveVector.y ) > 3;
423};
424
425// ----- drag ----- //
426
427proto.dragStart = function( event, pointer ) {
428 this.isDragging = true;
429 this.isPreventingClicks = true; // set flag to prevent clicks
430 this.emitEvent( 'dragStart', [ event, pointer ] );
431};
432
433proto.dragMove = function( event, pointer, moveVector ) {
434 this.emitEvent( 'dragMove', [ event, pointer, moveVector ] );
435};
436
437// ----- end ----- //
438
439proto.onmouseup = function( event ) {
440 this.pointerUp( event, event );
441};
442
443proto.onpointerup = function( event ) {
444 this.withPointer( 'pointerUp', event );
445};
446
447proto.ontouchend = function( event ) {
448 this.withTouch( 'pointerUp', event );
449};
450
451proto.pointerUp = function( event, pointer ) {
452 this.pointerDone();
453 this.emitEvent( 'pointerUp', [ event, pointer ] );
454
455 if ( this.isDragging ) {
456 this.dragEnd( event, pointer );
457 } else {
458 // pointer didn't move enough for drag to start
459 this.staticClick( event, pointer );
460 }
461};
462
463proto.dragEnd = function( event, pointer ) {
464 this.isDragging = false; // reset flag
465 // re-enable clicking async
466 setTimeout( () => delete this.isPreventingClicks );
467
468 this.emitEvent( 'dragEnd', [ event, pointer ] );
469};
470
471// triggered on pointer up & pointer cancel
472proto.pointerDone = function() {
473 this.isPointerDown = false;
474 delete this.pointerIdentifier;
475 this.unbindActivePointerEvents();
476 this.emitEvent('pointerDone');
477};
478
479// ----- cancel ----- //
480
481proto.onpointercancel = function( event ) {
482 this.withPointer( 'pointerCancel', event );
483};
484
485proto.ontouchcancel = function( event ) {
486 this.withTouch( 'pointerCancel', event );
487};
488
489proto.pointerCancel = function( event, pointer ) {
490 this.pointerDone();
491 this.emitEvent( 'pointerCancel', [ event, pointer ] );
492};
493
494// ----- click ----- //
495
496// handle all clicks and prevent clicks when dragging
497proto.onclick = function( event ) {
498 if ( this.isPreventingClicks ) event.preventDefault();
499};
500
501// triggered after pointer down & up with no/tiny movement
502proto.staticClick = function( event, pointer ) {
503 // ignore emulated mouse up clicks
504 let isMouseup = event.type === 'mouseup';
505 if ( isMouseup && this.isIgnoringMouseUp ) return;
506
507 this.emitEvent( 'staticClick', [ event, pointer ] );
508
509 // set flag for emulated clicks 300ms after touchend
510 if ( isMouseup ) {
511 this.isIgnoringMouseUp = true;
512 // reset flag after 400ms
513 setTimeout( () => {
514 delete this.isIgnoringMouseUp;
515 }, 400 );
516 }
517};
518
519// ----- ----- //
520
521return Unidragger;
522
523} ) );
524});
525
526var draggabilly = createCommonjsModule(function (module) {
527/*!
528 * Draggabilly v3.0.0
529 * Make that shiz draggable
530 * https://draggabilly.desandro.com
531 * MIT license
532 */
533
534( function( window, factory ) {
535 // universal module definition
536 if ( module.exports ) {
537 // CommonJS
538 module.exports = factory(
539 window,
540 getSize,
541 unidragger,
542 );
543 } else {
544 // browser global
545 window.Draggabilly = factory(
546 window,
547 window.getSize,
548 window.Unidragger,
549 );
550 }
551
552}( typeof window != 'undefined' ? window : commonjsGlobal,
553 function factory( window, getSize, Unidragger ) {
554
555// -------------------------- helpers & variables -------------------------- //
556
557function noop() {}
558
559let jQuery = window.jQuery;
560
561// -------------------------- Draggabilly -------------------------- //
562
563function Draggabilly( element, options ) {
564 // querySelector if string
565 this.element = typeof element == 'string' ?
566 document.querySelector( element ) : element;
567
568 if ( jQuery ) {
569 this.$element = jQuery( this.element );
570 }
571
572 // options
573 this.options = {};
574 this.option( options );
575
576 this._create();
577}
578
579// inherit Unidragger methods
580let proto = Draggabilly.prototype = Object.create( Unidragger.prototype );
581
582/**
583 * set options
584 * @param {Object} opts
585 */
586proto.option = function( opts ) {
587 this.options = {
588 ...this.options,
589 ...opts,
590 };
591};
592
593// css position values that don't need to be set
594const positionValues = [ 'relative', 'absolute', 'fixed' ];
595
596proto._create = function() {
597 // properties
598 this.position = {};
599 this._getPosition();
600
601 this.startPoint = { x: 0, y: 0 };
602 this.dragPoint = { x: 0, y: 0 };
603
604 this.startPosition = { ...this.position };
605
606 // set relative positioning
607 let style = getComputedStyle( this.element );
608 if ( !positionValues.includes( style.position ) ) {
609 this.element.style.position = 'relative';
610 }
611
612 // events
613 this.on( 'pointerDown', this.handlePointerDown );
614 this.on( 'pointerUp', this.handlePointerUp );
615 this.on( 'dragStart', this.handleDragStart );
616 this.on( 'dragMove', this.handleDragMove );
617 this.on( 'dragEnd', this.handleDragEnd );
618
619 this.setHandles();
620 this.enable();
621};
622
623// set this.handles and bind start events to 'em
624proto.setHandles = function() {
625 let { handle } = this.options;
626 if ( typeof handle == 'string' ) {
627 this.handles = this.element.querySelectorAll( handle );
628 } else if ( typeof handle == 'object' && handle.length ) {
629 this.handles = handle;
630 } else if ( handle instanceof HTMLElement ) {
631 this.handles = [ handle ];
632 } else {
633 this.handles = [ this.element ];
634 }
635};
636
637const cancelableEvents = [ 'dragStart', 'dragMove', 'dragEnd' ];
638
639// duck-punch emitEvent to dispatch jQuery events as well
640let emitEvent = proto.emitEvent;
641proto.emitEvent = function( eventName, args ) {
642 // do not emit cancelable events if dragging is disabled
643 let isCanceled = !this.isEnabled && cancelableEvents.includes( eventName );
644 if ( isCanceled ) return;
645
646 emitEvent.call( this, eventName, args );
647
648 // trigger jQuery event
649 let jquery = window.jQuery;
650 if ( !jquery || !this.$element ) return;
651 // create jQuery event
652 let event;
653 let jqArgs = args;
654 let isFirstArgEvent = args && args[0] instanceof Event;
655 if ( isFirstArgEvent ) [ event, ...jqArgs ] = args;
656 /* eslint-disable-next-line new-cap */
657 let $event = jquery.Event( event );
658 $event.type = eventName;
659 this.$element.trigger( $event, jqArgs );
660};
661
662// -------------------------- position -------------------------- //
663
664// get x/y position from style
665proto._getPosition = function() {
666 let style = getComputedStyle( this.element );
667 let x = this._getPositionCoord( style.left, 'width' );
668 let y = this._getPositionCoord( style.top, 'height' );
669 // clean up 'auto' or other non-integer values
670 this.position.x = isNaN( x ) ? 0 : x;
671 this.position.y = isNaN( y ) ? 0 : y;
672
673 this._addTransformPosition( style );
674};
675
676proto._getPositionCoord = function( styleSide, measure ) {
677 if ( styleSide.includes('%') ) {
678 // convert percent into pixel for Safari, #75
679 let parentSize = getSize( this.element.parentNode );
680 // prevent not-in-DOM element throwing bug, #131
681 return !parentSize ? 0 :
682 ( parseFloat( styleSide ) / 100 ) * parentSize[ measure ];
683 }
684 return parseInt( styleSide, 10 );
685};
686
687// add transform: translate( x, y ) to position
688proto._addTransformPosition = function( style ) {
689 let transform = style.transform;
690 // bail out if value is 'none'
691 if ( !transform.startsWith('matrix') ) return;
692
693 // split matrix(1, 0, 0, 1, x, y)
694 let matrixValues = transform.split(',');
695 // translate X value is in 12th or 4th position
696 let xIndex = transform.startsWith('matrix3d') ? 12 : 4;
697 let translateX = parseInt( matrixValues[ xIndex ], 10 );
698 // translate Y value is in 13th or 5th position
699 let translateY = parseInt( matrixValues[ xIndex + 1 ], 10 );
700 this.position.x += translateX;
701 this.position.y += translateY;
702};
703
704// -------------------------- events -------------------------- //
705
706proto.handlePointerDown = function( event, pointer ) {
707 if ( !this.isEnabled ) return;
708 // track start event position
709 // Safari 9 overrides pageX and pageY. These values needs to be copied. flickity#842
710 this.pointerDownPointer = {
711 pageX: pointer.pageX,
712 pageY: pointer.pageY,
713 };
714
715 event.preventDefault();
716 document.activeElement.blur();
717 // bind move and end events
718 this.bindActivePointerEvents( event );
719 this.element.classList.add('is-pointer-down');
720};
721
722proto.handleDragStart = function() {
723 if ( !this.isEnabled ) return;
724
725 this._getPosition();
726 this.measureContainment();
727 // position _when_ drag began
728 this.startPosition.x = this.position.x;
729 this.startPosition.y = this.position.y;
730 // reset left/top style
731 this.setLeftTop();
732
733 this.dragPoint.x = 0;
734 this.dragPoint.y = 0;
735
736 this.element.classList.add('is-dragging');
737 // start animation
738 this.animate();
739};
740
741proto.measureContainment = function() {
742 let container = this.getContainer();
743 if ( !container ) return;
744
745 let elemSize = getSize( this.element );
746 let containerSize = getSize( container );
747 let {
748 borderLeftWidth,
749 borderRightWidth,
750 borderTopWidth,
751 borderBottomWidth,
752 } = containerSize;
753 let elemRect = this.element.getBoundingClientRect();
754 let containerRect = container.getBoundingClientRect();
755
756 let borderSizeX = borderLeftWidth + borderRightWidth;
757 let borderSizeY = borderTopWidth + borderBottomWidth;
758
759 let position = this.relativeStartPosition = {
760 x: elemRect.left - ( containerRect.left + borderLeftWidth ),
761 y: elemRect.top - ( containerRect.top + borderTopWidth ),
762 };
763
764 this.containSize = {
765 width: ( containerSize.width - borderSizeX ) - position.x - elemSize.width,
766 height: ( containerSize.height - borderSizeY ) - position.y - elemSize.height,
767 };
768};
769
770proto.getContainer = function() {
771 let containment = this.options.containment;
772 if ( !containment ) return;
773
774 let isElement = containment instanceof HTMLElement;
775 // use as element
776 if ( isElement ) return containment;
777
778 // querySelector if string
779 if ( typeof containment == 'string' ) {
780 return document.querySelector( containment );
781 }
782 // fallback to parent element
783 return this.element.parentNode;
784};
785
786// ----- move event ----- //
787
788/**
789 * drag move
790 * @param {Event} event
791 * @param {Event | Touch} pointer
792 * @param {Object} moveVector - x and y coordinates
793 */
794proto.handleDragMove = function( event, pointer, moveVector ) {
795 if ( !this.isEnabled ) return;
796
797 let dragX = moveVector.x;
798 let dragY = moveVector.y;
799
800 let grid = this.options.grid;
801 let gridX = grid && grid[0];
802 let gridY = grid && grid[1];
803
804 dragX = applyGrid( dragX, gridX );
805 dragY = applyGrid( dragY, gridY );
806
807 dragX = this.containDrag( 'x', dragX, gridX );
808 dragY = this.containDrag( 'y', dragY, gridY );
809
810 // constrain to axis
811 dragX = this.options.axis == 'y' ? 0 : dragX;
812 dragY = this.options.axis == 'x' ? 0 : dragY;
813
814 this.position.x = this.startPosition.x + dragX;
815 this.position.y = this.startPosition.y + dragY;
816 // set dragPoint properties
817 this.dragPoint.x = dragX;
818 this.dragPoint.y = dragY;
819};
820
821function applyGrid( value, grid, method ) {
822 if ( !grid ) return value;
823
824 method = method || 'round';
825 return Math[ method ]( value/grid ) * grid;
826}
827
828proto.containDrag = function( axis, drag, grid ) {
829 if ( !this.options.containment ) return drag;
830
831 let measure = axis == 'x' ? 'width' : 'height';
832
833 let rel = this.relativeStartPosition[ axis ];
834 let min = applyGrid( -rel, grid, 'ceil' );
835 let max = this.containSize[ measure ];
836 max = applyGrid( max, grid, 'floor' );
837 return Math.max( min, Math.min( max, drag ) );
838};
839
840// ----- end event ----- //
841
842proto.handlePointerUp = function() {
843 this.element.classList.remove('is-pointer-down');
844};
845
846proto.handleDragEnd = function() {
847 if ( !this.isEnabled ) return;
848
849 // use top left position when complete
850 this.element.style.transform = '';
851 this.setLeftTop();
852 this.element.classList.remove('is-dragging');
853};
854
855// -------------------------- animation -------------------------- //
856
857proto.animate = function() {
858 // only render and animate if dragging
859 if ( !this.isDragging ) return;
860
861 this.positionDrag();
862 requestAnimationFrame( () => this.animate() );
863};
864
865// left/top positioning
866proto.setLeftTop = function() {
867 let { x, y } = this.position;
868 this.element.style.left = `${x}px`;
869 this.element.style.top = `${y}px`;
870};
871
872proto.positionDrag = function() {
873 let { x, y } = this.dragPoint;
874 this.element.style.transform = `translate3d(${x}px, ${y}px, 0)`;
875};
876
877// ----- methods ----- //
878
879/**
880 * @param {Number} x
881 * @param {Number} y
882 */
883proto.setPosition = function( x, y ) {
884 this.position.x = x;
885 this.position.y = y;
886 this.setLeftTop();
887};
888
889proto.enable = function() {
890 if ( this.isEnabled ) return;
891 this.isEnabled = true;
892 this.bindHandles();
893};
894
895proto.disable = function() {
896 if ( !this.isEnabled ) return;
897 this.isEnabled = false;
898 if ( this.isDragging ) this.dragEnd();
899 this.unbindHandles();
900};
901
902const resetCssProperties = [ 'transform', 'left', 'top', 'position' ];
903
904proto.destroy = function() {
905 this.disable();
906 // reset styles
907 resetCssProperties.forEach( ( prop ) => {
908 this.element.style[ prop ] = '';
909 } );
910 // unbind handles
911 this.unbindHandles();
912 // remove jQuery data
913 if ( this.$element ) this.$element.removeData('draggabilly');
914};
915
916// ----- jQuery bridget ----- //
917
918// required for jQuery bridget
919proto._init = noop;
920
921if ( jQuery && jQuery.bridget ) {
922 jQuery.bridget( 'draggabilly', Draggabilly );
923}
924
925// ----- ----- //
926
927return Draggabilly;
928
929} ) );
930});
931
932export { draggabilly as d };