PageSourceSearch

https://etablissement.site/wp-content/themes/etablissement/js/lib/jquery.pep.js

js etablissement.site collected 2026-10-02 15:07:21 UTC 42,455 bytes, 1,205 lines download raw bytes

1/*
2 *         ________                                                            ________
3 *         ______(_)_____ ____  __________________  __ _____________________   ______(_)_______
4 *         _____  /_  __ `/  / / /  _ \_  ___/_  / / / ___  __ \  _ \__  __ \  _____  /__  ___/
5 *         ____  / / /_/ // /_/ //  __/  /   _  /_/ /____  /_/ /  __/_  /_/ /______  / _(__  )
6 *         ___  /  \__, / \__,_/ \___//_/    _\__, /_(_)  .___/\___/_  .___/_(_)__  /  /____/
7 *         /___/     /_/                     /____/    /_/          /_/        /___/
8 *
9 *        http://pep.briangonzalez.org
10 *        Kinetic drag for mobile/desktop.
11 *
12 *        Copyright (c) 2014 Brian Gonzalez
13 *        Licensed under the MIT license.
14 *
15 *        Title generated using "Speed" @
16 *        http://patorjk.com/software/taag/#p=display&f=Speed&t=jquery.pep.js
17 */
18
19;(function ( $, window, undefined ) {
20
21  "use strict";
22
23  //  create the defaults once
24  var pluginName = 'pep';
25  var defaults   = {
26
27    // Options
28    // ----------------------------------------------------------------------------------------------
29    // See ** https://github.com/briangonzalez/jquery.pep.js ** for fully documented options.
30    // It was too hard to manage options here and in the readme.
31    // ----------------------------------------------------------------------------------------------
32    initiate:                       function(){},
33    start:                          function(){},
34    drag:                           function(){},
35    stop:                           function(){},
36    easing:                         null,
37    rest:                           function(){},
38    moveTo:                         false,
39    callIfNotStarted:               ['stop', 'rest'],
40    startThreshold:                 [0,0],
41    grid:                           [1,1],
42    debug:                          false,
43    activeClass:                    'pep-active',
44    startClass:                     'pep-start',
45    easeClass:                      'pep-ease',
46    multiplier:                     1,
47    velocityMultiplier:             2.5,
48    shouldPreventDefault:           true,
49    allowDragEventPropagation:      true,
50    stopEvents:                     '',
51    hardwareAccelerate:             true,
52    useCSSTranslation:              true,
53    disableSelect:                  true,
54    cssEaseString:                  "cubic-bezier(0.190, 1.000, 0.220, 1.000)",
55    cssEaseDuration:                1000,
56    shouldEase:                     true,
57    droppable:                      false,
58    droppableActiveClass:           'pep-dpa',
59    overlapFunction:                false,
60    constrainTo:                    false,
61    removeMargins:                  true,
62    place:                          true,
63    deferPlacement:                 false,
64    axis:                           null,
65    forceNonCSS3Movement:           false,
66    elementsWithInteraction:        'input',
67    revert:                         false,
68    revertAfter:                    'stop',
69    revertIf:                       function(){ return true; },
70    ignoreRightClick:               true,
71    startPos:                       {
72        left:                           null,
73        top:                            null
74    },
75    useBoundingClientRect:          false
76  };
77
78  //  ---------------------------------
79  //  -----  Our main Pep object  -----
80  //  ---------------------------------
81  function Pep( el, options ) {
82
83    this.name = pluginName;
84
85    // reference to our DOM object
86    // and it's jQuery equivalent.
87    this.el  = el;
88    this.$el = $(el);
89
90    //  merge in defaults
91    this.options    = $.extend( {}, defaults, options) ;
92
93    // store document/body so we don't need to keep grabbing them
94    // throughout the code
95    this.$document  = $(this.$el[0].ownerDocument);
96    this.$body      = this.$document.find('body');
97
98    //  Create our triggers based on touch/click device
99    this.moveTrigger        = "MSPointerMove pointermove touchmove mousemove";
100    this.startTrigger       = "MSPointerDown pointerdown touchstart mousedown";
101    this.stopTrigger        = "MSPointerUp pointerup touchend mouseup";
102    this.startTriggerArray  = this.startTrigger.split(' ');
103    this.moveTriggerArray   = this.moveTrigger.split(' ');
104    this.stopTriggerArray   = this.stopTrigger.split(' ');
105    this.stopEvents         = [ this.stopTrigger, this.options.stopEvents ].join(' ');
106
107    if ( this.options.constrainTo === 'window' )
108      this.$container = this.$document;
109    else if ( this.options.constrainTo && (this.options.constrainTo !== 'parent') )
110      this.$container = $(this.options.constrainTo);
111    else
112      this.$container = this.$el.parent();
113
114    // IE need this
115    if ( this.isPointerEventCompatible() )
116      this.applyMSDefaults();
117
118    this.CSSEaseHash    = this.getCSSEaseHash();
119    this.scale          = 1;
120    this.started        = false;
121    this.disabled       = false;
122    this.autoAxis       = false;
123    this.activeDropRegions = [];
124    this.resetVelocityQueue();
125
126    this.init();
127    return this;
128  }
129
130  //  init();
131  //    initialization logic
132  //    you already have access to the DOM el and the options via the instance,
133  //    e.g., this.el and this.options
134  Pep.prototype.init = function () {
135
136    if ( this.options.debug )
137      this.buildDebugDiv();
138
139    if ( this.options.disableSelect )
140      this.disableSelect();
141
142    // position the parent & place the object, if necessary.
143    if ( this.options.place && !this.options.deferPlacement ) {
144      this.positionParent();
145      this.placeObject();
146    }
147
148    this.ev = {};       // to store our event movements
149    this.pos = {};      // to store positions
150    this.subscribe();
151  };
152
153  //  subscribe();
154  //    useful in the event we want to programmatically
155  //    interact with our Pep object.
156  //      e.g.:     $('#pep').trigger('stop')
157  Pep.prototype.subscribe = function () {
158    var self = this;
159
160    // Subscribe to our start event
161    this.onStartEvent = function(ev){ self.handleStart(ev); };
162    this.$el.on(this.startTrigger, this.onStartEvent);
163
164    // Add a flag to events that start on elements that should allow interaction
165    // so handleStart() can ignore them but allow them to bubble up through the DOM
166    this.onStartEventOnElementsWithInteraction = function(ev){ ev.ignorePropagation = true; };
167    this.$el.on(
168      this.startTrigger,
169      this.options.elementsWithInteraction,
170      this.onStartEventOnElementsWithInteraction
171    );
172
173    // Subscribe to our stop event
174    this.onStopEvents = function(ev) { self.handleStop(ev); };
175    this.$document.on(this.stopEvents, this.onStopEvents);
176
177    // Subscribe to our move event
178    this.onMoveEvents = function(ev){ self.moveEvent = ev; };
179    this.$document.on(this.moveTrigger, this.onMoveEvents);
180  };
181
182  Pep.prototype.unsubscribe = function() {
183    this.$el.off(this.startTrigger, this.onStartEvent);
184    this.$el.off(
185      this.startTrigger,
186      this.options.elementsWithInteraction,
187      this.onStartEventOnElementsWithInteraction
188    );
189    this.$document.off(this.stopEvents, this.onStopEvents);
190    this.$document.off(this.moveTrigger, this.onMoveEvents);
191  };
192
193  //  handleStart();
194  //    once this.startTrigger occurs, handle all of the logic
195  //    that must go on. This is where Pep's heavy lifting is done.
196  Pep.prototype.handleStart = function(ev) {
197
198    // ignorePropagation is set to true if the event originates from an element
199    // listed in this.options.elementsWithInteraction
200    if (ev.ignorePropagation) return;
201
202    var self = this;
203
204            // only continue chugging if our start event is a valid move event.
205            if ( this.isValidMoveEvent(ev) && !this.disabled ){
206
207              if( !(this.options.ignoreRightClick && ev.which === 3) ) {
208
209                    // IE10 Hack. Me not happy.
210                    if ( this.isPointerEventCompatible() && ev.preventManipulation )
211                      ev.preventManipulation();
212
213                    // normalize event
214                    ev = this.normalizeEvent(ev);
215
216                    // position the parent & place the object, if necessary.
217                    if ( this.options.place && this.options.deferPlacement ) {
218                      this.positionParent();
219                      this.placeObject();
220                    }
221
222                    // log it
223                    this.log({ type: 'event', event: ev.type });
224
225                    // hardware accelerate, if necessary.
226                    if ( this.options.hardwareAccelerate && !this.hardwareAccelerated ) {
227                      this.hardwareAccelerate();
228                      this.hardwareAccelerated = true;
229                    }
230
231                    // fire user's initiate event.
232                    var shouldContinue = this.options.initiate.call(this, ev, this);
233                    if ( shouldContinue === false )
234                      return;
235
236
237                    // cancel the rest timeout
238                    clearTimeout( this.restTimeout );
239
240                    // add active class and reset css animation, if necessary
241                    this.$el.addClass( this.options.activeClass );
242                    this.removeCSSEasing();
243
244                    // store event's x & y values for later use
245                    this.startX = this.ev.x = ev.pep.x;
246                    this.startY = this.ev.y = ev.pep.y;
247
248                    // store initial offset.
249                    this.initialPosition = this.initialPosition || this.$el.position();
250
251                    // store the initial touch/click event, used to calculate the inital delta values.
252                    this.startEvent = this.moveEvent = ev;
253
254                    // make object active, so watchMoveLoop starts looping.
255                    this.active     = true;
256
257                    // preventDefault(), is necessary
258                    if ( this.options.shouldPreventDefault )
259                      ev.preventDefault();
260
261                    // allow / disallow event bubbling
262                    if ( !this.options.allowDragEventPropagation )
263                      ev.stopPropagation();
264
265                    // animation loop to ensure we don't fire
266                    // too many unneccessary repaints
267                    (function watchMoveLoop(){
268                        if ( !self.active ) return;
269                        self.handleMove();
270                        self.requestAnimationFrame( watchMoveLoop );
271                    })();
272
273                    (function watchEasingLoop(){
274                        if ( !self.options.easing ) return;
275                        if ( self.easing ) self.options.easing.call(self, null, self);
276                        self.requestAnimationFrame( watchEasingLoop );
277                    })();
278              }
279            }
280  };
281
282  //  handleMove();
283  //    the logic for when the move events occur
284  Pep.prototype.handleMove = function() {
285
286            // setup our event object
287            if ( typeof(this.moveEvent) === 'undefined' )
288              return;
289
290            // get our move event's x & y
291            var ev      = this.normalizeEvent( this.moveEvent );
292            var curX    = window.parseInt(ev.pep.x / this.options.grid[0]) * this.options.grid[0];
293            var curY    = window.parseInt(ev.pep.y / this.options.grid[1]) * this.options.grid[1];
294
295            // last in, first out (LIFO) queue to help us manage velocity
296            this.addToLIFO( { time: ev.timeStamp, x: curX, y: curY } );
297
298            // calculate values necessary to moving
299            var dx, dy;
300
301            if ( $.inArray( ev.type, this.startTriggerArray ) > -1  ){
302              dx = 0;
303              dy = 0;
304            } else{
305              dx = curX - this.ev.x;
306              dy = curY - this.ev.y;
307            }
308
309            this.dx   = dx;
310            this.dy   = dy;
311            this.ev.x = curX;
312            this.ev.y = curY;
313
314            // no movement in either direction -- so return
315            if (dx === 0 && dy === 0){
316              this.log({ type: 'event', event: '** stopped **' });
317              return;
318            }
319
320            // check if object has moved past X/Y thresholds
321            // if so, fire users start event
322            var initialDx  = Math.abs(this.startX - curX);
323            var initialDy  = Math.abs(this.startY - curY);
324            if ( !this.started && ( initialDx > this.options.startThreshold[0] || initialDy > this.options.startThreshold[1] ) ){
325              this.started = true;
326              this.$el.addClass(this.options.startClass);
327              this.options.start.call(this, this.startEvent, this);
328            }
329
330            // Move before calculate position and fire events
331            this.doMoveTo(dx, dy);
332
333            // Calculate our drop regions
334            if ( this.options.droppable ) {
335              this.calculateActiveDropRegions();
336            }
337
338            // fire user's drag event.
339            var continueDrag = this.options.drag.call(this, ev, this);
340
341            if ( continueDrag === false ) {
342              this.resetVelocityQueue();
343              return;
344            }
345
346            // log the move trigger & event position
347            this.log({ type: 'event', event: ev.type });
348            this.log({ type: 'event-coords', x: this.ev.x, y: this.ev.y });
349            this.log({ type: 'velocity' });
350  };
351
352  Pep.prototype.doMoveTo = function(dx, dy) {
353            var hash = this.handleConstraint(dx, dy);
354            var xOp, yOp;
355
356            // if using the "auto" axis, determine which axis to use based on
357            // whether the user has dragged more along the x or the y axis
358            if ( this.options.axis === 'auto' && !this.autoAxis) {
359              if ( Math.abs(dx) > Math.abs(dy) ) this.autoAxis = 'x';
360              else
361              if ( Math.abs(dx) < Math.abs(dy) ) this.autoAxis = 'y';
362              // don't move at all if the axis can't be determined
363              else {
364                dy = 0;
365                dx = 0;
366              }
367            }
368
369            // if using not using CSS transforms, move object via absolute position
370            if ( typeof this.options.moveTo === 'function') {
371              xOp     = ( dx >= 0 ) ? "+=" + Math.abs(dx/this.scale)*this.options.multiplier : "-=" + Math.abs(dx/this.scale)*this.options.multiplier;
372              yOp     = ( dy >= 0 ) ? "+=" + Math.abs(dy/this.scale)*this.options.multiplier : "-=" + Math.abs(dy/this.scale)*this.options.multiplier;
373
374              if ( this.options.constrainTo ) {
375                xOp = (hash.x !== false) ? hash.x : xOp;
376                yOp = (hash.y !== false) ? hash.y : yOp;
377              }
378
379              // only move along single axis, if necessary
380              if ( this.options.axis === 'x' || this.autoAxis === 'x' ) yOp = hash.y;
381              if ( this.options.axis === 'y' || this.autoAxis === 'y' ) xOp = hash.x;
382
383              this.options.moveTo.call(this, xOp, yOp);
384            } else if ( !this.shouldUseCSSTranslation() ){
385              xOp     = ( dx >= 0 ) ? "+=" + Math.abs(dx/this.scale)*this.options.multiplier : "-=" + Math.abs(dx/this.scale)*this.options.multiplier;
386              yOp     = ( dy >= 0 ) ? "+=" + Math.abs(dy/this.scale)*this.options.multiplier : "-=" + Math.abs(dy/this.scale)*this.options.multiplier;
387
388              if ( this.options.constrainTo ) {
389                xOp = (hash.x !== false) ? hash.x : xOp;
390                yOp = (hash.y !== false) ? hash.y : yOp;
391              }
392
393              // only move along single axis, if necessary
394              if ( this.options.axis === 'x' || this.autoAxis === 'x' ) yOp = hash.y;
395              if ( this.options.axis === 'y' || this.autoAxis === 'y' ) xOp = hash.x;
396
397              this.moveTo(xOp, yOp);
398            }
399            else {
400
401              dx = (dx/this.scale)*this.options.multiplier;
402              dy = (dy/this.scale)*this.options.multiplier;
403
404              if ( this.options.constrainTo ) {
405                dx = (hash.x === false) ? dx : 0 ;
406                dy = (hash.y === false) ? dy : 0 ;
407              }
408
409              // only move along single axis, if necessary
410              if ( this.options.axis === 'x' || this.autoAxis === 'x' ) dy = 0;
411              if ( this.options.axis === 'y' || this.autoAxis === 'y' ) dx = 0;
412
413              this.moveToUsingTransforms( dx, dy );
414            }
415  };
416
417  //  handleStop();
418  //    the logic for when the stop events occur
419  Pep.prototype.handleStop = function(ev) {
420
421            // no need to handle stop event if we're not active
422            if (!this.active)
423              return;
424
425            // log it
426            this.log({ type: 'event', event: ev.type });
427
428            // make object inactive, so watchMoveLoop returns
429            this.active = false;
430
431            // make object easing.
432            this.easing = true;
433
434            // remove our start class
435            this.$el.removeClass(this.options.startClass)
436                    .addClass(this.options.easeClass);
437
438            // Calculate our drop regions
439            if ( this.options.droppable ) {
440              this.calculateActiveDropRegions();
441            }
442
443            // fire user's stop event.
444            if ( this.started || (!this.started &&  $.inArray('stop', this.options.callIfNotStarted) > -1 ) ) {
445              this.options.stop.call(this, ev, this);
446            }
447
448            // ease the object, if necessary.
449            if (this.options.shouldEase) {
450              this.ease(ev, this.started);
451            } else {
452              this.removeActiveClass();
453            }
454
455            if ( this.options.revert && (this.options.revertAfter === 'stop' || !this.options.shouldEase) && ( this.options.revertIf && this.options.revertIf.call(this) ) ) {
456              this.revert();
457            }
458
459            // this must be set to false after
460            // the user's stop event is called, so the dev
461            // has access to it.
462            this.started = false;
463
464            // reset the auto-axis
465            if ( this.autoAxis ) this.autoAxis = false;
466
467            // reset the velocity queue
468            this.resetVelocityQueue();
469
470  };
471
472  //  ease();
473  //    used in conjunction with the LIFO queue
474  //    to ease the object after stop
475  Pep.prototype.ease = function(ev, started){
476
477            var pos       = this.$el.position();
478            var vel       = this.velocity();
479            var dt        = this.dt;
480            var x         = (vel.x/this.scale) * this.options.multiplier;
481            var y         = (vel.y/this.scale) * this.options.multiplier;
482
483            var hash      = this.handleConstraint(x, y, true);
484
485            // ✪  Apply the CSS3 animation easing magic  ✪
486            if ( this.cssAnimationsSupported() )
487              this.$el.css( this.getCSSEaseHash() );
488
489            var xOp = ( vel.x >
489 0 ) ? "+=" + x : "-=" + Math.abs(x);
490            var yOp = ( vel.y > 0 ) ? "+=" + y : "-=" + Math.abs(y);
491
492            if ( this.options.constrainTo ) {
493              xOp = (hash.x !== false) ? hash.x : xOp;
494              yOp = (hash.y !== false) ? hash.y : yOp;
495            }
496
497            if ( this.options.axis === 'x' || this.autoAxis === 'x' ) yOp = "+=0";
498            if ( this.options.axis === 'y' || this.autoAxis === 'y' ) xOp = "+=0";
499
500            // ease it via JS, the last true tells it to animate.
501            var jsAnimateFallback = !this.cssAnimationsSupported() || this.options.forceNonCSS3Movement;
502            if (typeof this.options.moveTo === 'function') {
503              this.options.moveTo.call(this, xOp, yOp);
504            } else {
505              this.moveTo(xOp, yOp, jsAnimateFallback);
506            }
507
508            // when the rest occurs, remove active class and call
509            // user's rest event.
510            var self = this;
511            this.restTimeout = setTimeout( function(){
512
513              // Calculate our drop regions
514              if ( self.options.droppable ) {
515                self.calculateActiveDropRegions();
516              }
517
518              self.easing = false;
519
520              // call users rest event.
521              if ( started || ( !started && $.inArray('rest', self.options.callIfNotStarted) > -1 ) ) {
522                self.options.rest.call(self, ev, self);
523              }
524
525              // revert thy self!
526              if ( self.options.revert && (self.options.revertAfter === 'ease' && self.options.shouldEase) && ( self.options.revertIf && self.options.revertIf.call(self) ) ) {
527                self.revert();
528              }
529
530              // remove active class
531              self.removeActiveClass();
532
533            }, this.options.cssEaseDuration );
534
535  };
536
537  // normalizeEvent()
538  Pep.prototype.normalizeEvent = function(ev) {
539      ev.pep        = {};
540
541      if ( this.isTouch(ev) ) {
542
543        ev.pep.x      = ev.originalEvent.touches[0].pageX;
544        ev.pep.y      = ev.originalEvent.touches[0].pageY;
545        ev.pep.type   = ev.type;
546
547      }
548      else if ( this.isPointerEventCompatible() || !this.isTouch(ev) ) {
549
550        if ( ev.pageX  ) {
551          ev.pep.x      = ev.pageX;
552          ev.pep.y      = ev.pageY;
553        } else {
554          ev.pep.x      = ev.originalEvent.pageX;
555          ev.pep.y      = ev.originalEvent.pageY;
556        }
557
558        ev.pep.type   = ev.type;
559
560      }
561
562      return ev;
563   };
564
565  // resetVelocityQueue()
566  //
567  Pep.prototype.resetVelocityQueue = function() {
568    this.velocityQueue = new Array(5);
569  };
570
571  //  moveTo();
572  //    move the object to an x and/or y value
573  //    using jQuery's .css function -- this fxn uses the
574  //    .css({top: "+=20", left: "-=30"}) syntax
575  Pep.prototype.moveTo = function(x,y, animate) {
576
577    this.log({ type: 'delta', x: x, y: y });
578    if ( animate ) {
579      this.$el.animate({ top: y, left: x }, 0, 'easeOutQuad', {queue: false});
580    } else{
581      this.$el.stop(true, false).css({ top: y , left: x });
582    }
583
584  };
585
586  //  moveToUsingTransforms();
587  //    move the object to an x and/or y value
588  Pep.prototype.moveToUsingTransforms = function(x,y) {
589
590    // Check for our initial values if we don't have them.
591    var matrixArray  = this.matrixToArray( this.matrixString() );
592    if ( !this.cssX )
593      this.cssX = this.xTranslation( matrixArray );
594
595    if ( !this.cssY )
596      this.cssY = this.yTranslation( matrixArray );
597
598    // CSS3 transforms are additive from current position
599    this.cssX = this.cssX + x;
600    this.cssY = this.cssY + y;
601
602    this.log({ type: 'delta', x: x, y: y });
603
604    matrixArray[4]    = this.cssX;
605    matrixArray[5]    = this.cssY;
606
607    this.translation  = this.arrayToMatrix( matrixArray );
608    this.transform( this.translation );
609  };
610
611  Pep.prototype.transform = function(value) {
612    this.$el.css({
613        '-webkit-transform': value,
614           '-moz-transform': value,
615            '-ms-transform': value,
616             '-o-transform': value,
617                'transform': value  });
618  };
619
620  Pep.prototype.xTranslation = function(matrixArray) {
621    matrixArray  = matrixArray || this.matrixToArray( this.matrixString() );
622    return parseInt(matrixArray[4], 10);
623  };
624
625  Pep.prototype.yTranslation = function(matrixArray) {
626    matrixArray  = matrixArray || this.matrixToArray( this.matrixString() );
627    return parseInt(matrixArray[5], 10);
628  };
629
630
631  // 3 helper functions for working with the
632  // objects CSS3 transforms
633  // matrixString
634  // matrixToArray
635  // arrayToMatrix
636  Pep.prototype.matrixString = function() {
637
638    var validMatrix = function(o){
639      return !( !o || o === 'none' || o.indexOf('matrix') < 0  );
640    };
641
642    var matrix = "matrix(1, 0, 0, 1, 0, 0)";
643
644    if ( validMatrix( this.$el.css('-webkit-transform') ) )
645      matrix = this.$el.css('-webkit-transform');
646
647    if ( validMatrix( this.$el.css('-moz-transform') ) )
648      matrix = this.$el.css('-moz-transform');
649
650    if ( validMatrix( this.$el.css('-ms-transform') ) )
651      matrix = this.$el.css('-ms-transform');
652
653    if ( validMatrix( this.$el.css('-o-transform') ) )
654      matrix = this.$el.css('-o-transform');
655
656    if ( validMatrix( this.$el.css('transform') ) )
657      matrix = this.$el.css('transform');
658
659    return matrix;
660  };
661
662  Pep.prototype.matrixToArray = function(str) {
663      return str.split('(')[1].split(')')[0].split(',');
664  };
665
666  Pep.prototype.arrayToMatrix = function(array) {
667      return "matrix(" +  array.join(',')  + ")";
668  };
669
670  //  addToLIFO();
671  //    a Last-In/First-Out array of the 5 most recent
672  //    velocity points, which is used for easing
673  Pep.prototype.addToLIFO = function(val){
674    // last in, first out
675    var arr = this.velocityQueue;
676    arr = arr.slice(1, arr.length);
677    arr.push(val);
678    this.velocityQueue = arr;
679  };
680
681  //  velocity();
682  //    using the LIFO, calculate velocity and return
683  //    velocity in each direction (x & y)
684  Pep.prototype.velocity = function(){
685    var sumX = 0;
686    var sumY = 0;
687
688    for ( var i = 0; i < this.velocityQueue.length -1; i++  ){
689      if ( this.velocityQueue[i] ){
690        sumX        += (this.velocityQueue[i+1].x - this.velocityQueue[i].x);
691        sumY        += (this.velocityQueue[i+1].y - this.velocityQueue[i].y);
692        this.dt     = ( this.velocityQueue[i+1].time - this.velocityQueue[i].time );
693      }
694    }
695
696    // return velocity in each direction.
697    return { x: sumX*this.options.velocityMultiplier, y: sumY*this.options.velocityMultiplier};
698  };
699
700  Pep.prototype.revert = function() {
701    if ( this.shouldUseCSSTranslation() ){
702      this.moveToUsingTransforms(-this.xTranslation(),-this.yTranslation());
703    }
704
705    if (this.options.place) {
706      this.moveTo(this.initialPosition.left, this.initialPosition.top);
707    }
708  };
709
710  //  requestAnimationFrame();
711  //    requestAnimationFrame Polyfill
712  //    More info:
713  //    http://paulirish.com/2011/requestanimationframe-for-smart-animating/
714  Pep.prototype.requestAnimationFrame = function(callback) {
715    return  window.requestAnimationFrame        && window.requestAnimationFrame(callback)         ||
716            window.webkitRequestAnimationFrame  && window.webkitRequestAnimationFrame(callback)   ||
717            window.mozRequestAnimationFrame     && window.mozRequestAnimationFrame(callback)      ||
718            window.oRequestAnimationFrame       && window.mozRequestAnimationFrame(callback)      ||
719            window.msRequestAnimationFrame      && window.msRequestAnimationFrame(callback)       ||
720            window.setTimeout(callback, 1000 / 60);
721  };
722
723  //  positionParent();
724  //    add the right positioning to the parent object
725  Pep.prototype.positionParent = function() {
726
727    if ( !this.options.constrainTo || this.parentPositioned )
728      return;
729
730    this.parentPositioned = true;
731
732    // make `relative` parent if necessary
733    if ( this.options.constrainTo === 'parent' ) {
734      this.$container.css({ position: 'relative' });
735    } else if ( this.options.constrainTo === 'window'             &&
736                this.$container.get(0).nodeName !== "#document"   &&
737                this.$container.css('position') !== 'static' )
738    {
739      this.$container.css({ position: 'static' });
740    }
741
742  };
743
744  //  placeObject();
745  //    add the right positioning to the object
746  Pep.prototype.placeObject = function() {
747
748    if ( this.objectPlaced )
749      return;
750
751    this.objectPlaced = true;
752
753    this.offset = (this.options.constrainTo === 'parent' || this.hasNonBodyRelative() ) ?
754                    this.$el.position() : this.$el.offset();
755
756    // better to leave absolute position alone if
757    // it already has one.
758    if ( parseInt( this.$el.css('left'), 10 ) )
759      this.offset.left = this.$el.css('left');
760
761    if (typeof this.options.startPos.left === "number")
762        this.offset.left = this.options.startPos.left;
763
764    if ( parseInt( this.$el.css('top'), 10 ) )
765      this.offset.top = this.$el.css('top');
766
767    if (typeof this.options.startPos.top === "number")
768        this.offset.top = this.options.startPos.top;
769
770    if ( this.options.removeMargins )
771      this.$el.css({margin: 0});
772
773    this.$el.css({
774      position:   'absolute',
775      top:        this.offset.top,
776      left:       this.offset.left
777    });
778
779  };
780
781  //  hasNonBodyRelative()
782  //    returns true if any parent other than the body
783  //    has relative positioning
784  Pep.prototype.hasNonBodyRelative = function() {
785    return this.$el.parents().filter(function() {
786        var $this = $(this);
787        return $this.is('body') || $this.css('position') === 'relative';
788    }).length > 1;
789  };
790
791  //  setScale()
792  //    set the scale of the object being moved.
793  Pep.prototype.setScale = function(val) {
794    this.scale = val;
795  };
796
797  //  setMultiplier()
798  //    set the multiplier of the object being moved.
799  Pep.prototype.setMultiplier = function(val) {
800    this.options.multiplier = val;
801  };
802
803  //  removeCSSEasing();
804  //    remove CSS easing properties, if necessary
805  Pep.prototype.removeCSSEasing = function() {
806    if ( this.cssAnimationsSupported() )
807      this.$el.css( this.getCSSEaseHash(true) );
808  };
809
810  //  disableSelect();
811  //    add the property which causes the object
812  //    to not be selected user drags over text areas
813  Pep.prototype.disableSelect = function() {
814
815    this.$el.css({
816      '-webkit-touch-callout' : 'none',
817        '-webkit-user-select' : 'none',
818         '-khtml-user-select' : 'none',
819           '-moz-user-select' : 'none',
820            '-ms-user-select' : 'none',
821                'user-select' : 'none'
822    });
823
824  };
825
826  // removeActiveClass()
827  //  Removes the active class.
828  Pep.prototype.removeActiveClass = function() {
829    this.$el.removeClass( [this.options.activeClass, this.options.easeClass].join(' ') );
830  };
831
832  //  handleConstraint();
833  //    returns a hash of where to move to
834  //    when we constrain to parent/window
835  Pep.prototype.handleConstraint = function(dx, dy, accountForTranslation) {
836    var pos               = this.$el.position();
837    this.pos.x            = pos.left;
838    this.pos.y            = pos.top;
839
840    var hash              = { x: false, y: false };
841
842    var upperYLimit, upperXLimit, lowerXLimit, lowerYLimit;
843
844    // log our positions
845    this.log({ type: "pos-coords", x: this.pos.x, y: this.pos.y});
846
847    if ( $.isArray( this.options.constrainTo ) ) {
848
849      if ( this.options.constrainTo[3] !== undefined && this.options.constrainTo[1] !== undefined ) {
850        upperXLimit     = this.options.constrainTo[1] === false ?  Infinity : this.options.constrainTo[1];
851        lowerXLimit     = this.options.constrainTo[3] === false ? -Infinity : this.options.constrainTo[3];
852      }
853      if ( this.options.constrainTo[0] !== false && this.options.constrainTo[2] !== false ) {
854        upperYLimit       = this.options.constrainTo[2] === false ?  Infinity : this.options.constrainTo[2];
855        lowerYLimit       = this.options.constrainTo[0] === false ? -Infinity : this.options.constrainTo[0];
856      }
857
858      // is our object trying to move outside lower X & Y limits?
859      if ( this.pos.x + dx < lowerXLimit)     hash.x = lowerXLimit;
860      if ( this.pos.y + dy < lowerYLimit)     hash.y = lowerYLimit;
861
862    } else if ( typeof this.options.constrainTo === 'string' ) {
863      lowerXLimit       = 0;
864      lowerYLimit       = 0;
865      upperXLimit       = this.$container.width()  - (this.options.useBoundingClientRect ? this.$el[0].getBoundingClientRect().width : this.$el.outerWidth());
866      upperYLimit       = this.$container.height() - (this.options.useBoundingClientRect ? this.$el[0].getBoundingClientRect().height : this.$el.outerHeight());
867
868      // is our object trying to move outside lower X & Y limits?
869      if ( this.pos.x + dx < 0 )              hash.x = 0;
870      if ( this.pos.y + dy < 0 )              hash.y = 0;
871    }
872
873    // is our object trying to move outside upper X & Y limits?
874    if ( this.pos.x + dx > upperXLimit )    hash.x = upperXLimit;
875    if ( this.pos.y + dy > upperYLimit )    hash.y = upperYLimit;
876
877    // Account for translation, which makes movement a little tricky.
878    if ( this.shouldUseCSSTranslation() && accountForTranslation ){
879      if (hash.x === lowerXLimit && this.xTranslation() ) hash.x = lowerXLimit - this.xTranslation();
880      if (hash.x === upperXLimit && this.xTranslation() ) hash.x = upperXLimit - this.xTranslation();
881
882      if (hash.y === lowerYLimit && this.yTranslation() ) hash.y = lowerYLimit - this.yTranslation();
883      if (hash.y === upperYLimit && this.yTranslation() ) hash.y = upperYLimit - this.yTranslation();
884    }
885
886    return hash;
887  };
888
889  //  getCSSEaseHash();
890  //    returns a hash of params used in conjunction
891  //    with this.options.cssEaseString
892  Pep.prototype.getCSSEaseHash = function(reset){
893    if ( typeof(reset) === 'undefined' ) reset = false;
894
895    var cssEaseString;
896    if (reset){
897      cssEaseString = '';
898    } else if ( this.CSSEaseHash ) {
899      return this.CSSEaseHash;
900    } else {
901      cssEaseString = ['all', this.options.cssEaseDuration + 'ms', this.options.cssEaseString].join(' ');
902    }
903
904    return {
905                  '-webkit-transition'   : cssEaseString,   // chrome, safari, etc.
906                     '-moz-transition'   : cssEaseString,   // firefox
907                      '-ms-transition'   : cssEaseString,   // microsoft
908                       '-o-transition'   : cssEaseString,   // opera
909                          'transition'   : cssEaseString    // future
910          };
911  };
912
913  // calculateActiveDropRegions()
914  //    sets parent droppables of this.
915  Pep.prototype.calculateActiveDropRegions = function() {
916    var self = this;
917    this.activeDropRegions.length = 0;
918
919    $.each( $(this.options.droppable), function(idx, el){
920      var $el = $(el);
921      if ( self.isOverlapping($el, self.$el) ){
922        $el.addClass(self.options.droppableActiveClass);
923        self.activeDropRegions.push($el);
924      } else {
925        $el.removeClass(self.options.droppableActiveClass);
926      }
927    });
928
929  };
930
931  //  isOverlapping();
932  //    returns true if element a over
933  Pep.prototype.isOverlapping = function($a,$b) {
934
935    if ( this.options.overlapFunction ) {
936      return this.options.overlapFunction($a,$b);
937    }
938
939    var rect1 = $a[0].getBoundingClientRect();
940    var rect2 = $b[0].getBoundingClientRect();
941
942    return !( rect1.right   < rect2.left  ||
943              rect1.left    > rect2.right ||
944              rect1.bottom  < rect2.top   ||
945              rect1.top     > rect2.bottom  );
946  };
947
948  //  isTouch();
949  //    returns whether or not event is a touch event
950  Pep.prototype.isTouch = function(ev){
951    return ev.type.search('touch') > -1;
952  };
953
954  // isPointerEventCompatible();
955  //    return whether or note our device is pointer
956  //    event compatible; typically means where on a
957  //    touch Win8 device
958  Pep.prototype.isPointerEventCompatible = function() {
959    return ("MSPointerEvent" in window);
960  };
961
962  // applyMSDefaults();
963  Pep.prototype.applyMSDefaults = function(first_argument) {
964    this.$el.css({
965        '-ms-touch-action' :    'none',
966        'touch-action' :        'none',
967        '-ms-scroll-chaining':  'none',
968        '-ms-scroll-limit':     '0 0 0 0'
969    });
970  };
971
972  //  isValidMoveEvent();
973  //    returns true if we're on a non-touch device -- or --
974  //    if the event is **single** touch event on a touch device
975  Pep.prototype.isValidMoveEvent = function(ev){
976    return ( !this.isTouch(ev) || ( this.isTouch(ev) && ev.originalEvent && ev.originalEvent.touches && ev.originalEvent.touches.length === 1 ) );
977  };
978
979  //  shouldUseCSSTranslation();
980  //    return true if we should use CSS transforms for move the object
981  Pep.prototype.shouldUseCSSTranslation = function() {
982
983    if ( this.options.forceNonCSS3Movement )
984      return false;
985
986    if ( typeof(this.useCSSTranslation) !== "undefined" )
987      return this.useCSSTranslation;
988
989    var useCSSTranslation = false;
990
991    if ( !this.options.useCSSTranslation || ( typeof(Modernizr) !== "undefined" && !Modernizr.csstransforms)){
992      useCSSTranslation = false;
993    }
994    else{
995      useCSSTranslation = true;
996    }
997
998    this.useCSSTranslation =  useCSSTranslation;
999    return useCSSTranslation;
1000  };
1001
1002  //  cssAnimationsSupported():
1003  //    returns true if the browser supports CSS animations
1004  //    which are used for easing..
1005  Pep.prototype.cssAnimationsSupported = function() {
1006
1007    if ( typeof(this.cssAnimationsSupport) !== "undefined" ){
1008      return this.cssAnimationsSupport;
1009    }
1010
1011    // If the page has Modernizr, let them do the heavy lifting.
1012    if ( ( typeof(Modernizr) !== "undefined" && Modernizr.cssanimations) ){
1013      this.cssAnimationsSupport = true;
1014      return true;
1015    }
1016
1017    var animation = false,
1018        elm = document.createElement('div'),
1019        animationstring = 'animation',
1020        keyframeprefix = '',
1021        domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
1022        pfx  = '';
1023
1024    if( elm.style.animationName ) { animation = true; }
1025
1026    if( animation === false ) {
1027      for( var i = 0; i < domPrefixes.length; i++ ) {
1028        if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
1029          pfx = domPrefixes[ i ];
1030          animationstring = pfx + 'Animation';
1031          keyframeprefix = '-' + pfx.toLowerCase() + '-';
1032          animation = true;
1033          break;
1034        }
1035      }
1036    }
1037
1038    this.cssAnimationsSupport = animation;
1039    return animation;
1040  };
1041
1042  //  hardwareAccelerate();
1043  //    add fool-proof CSS3 hardware acceleration.
1044  Pep.prototype.hardwareAccelerate = function() {
1045    this.$el.css({
1046      '-webkit-perspective':          1000,
1047      'perspective':                  1000,
1048      '-webkit-backface-visibility':  'hidden',
1049      'backface-visibility':          'hidden'
1050    });
1051   };
1052
1053  //  getMovementValues();
1054  //    returns object pos, event position, and velocity in each direction.
1055  Pep.prototype.getMovementValues = function() {
1056    return { ev: this.ev, pos: this.pos, velocity: this.velocity() };
1057   };
1058
1059  //  buildDebugDiv();
1060  //    Create a little div in the lower right corner of the window
1061  //    for extra info about the object currently moving
1062  Pep.prototype.buildDebugDiv = function() {
1063
1064    // Build the debugDiv and it's inner HTML -- if necessary
1065    var $debugDiv;
1066    if ( $('#pep-debug').length === 0 ){
1067      $debugDiv = $('<div></div>');
1068      $debugDiv
1069        .attr('id', 'pep-debug')
1070        .append("<div style='font-weight:bold; background: red; color: white;'>DEBUG MODE</div>")
1071        .append("<div id='pep-debug-event'>no event</div>")
1072        .append("<div id='pep-debug-ev-coords'>event coords: <span class='pep-x'>-</span>, <span class='pep-y'>-</span></div>")
1073        .append("<div id='pep-debug-pos-coords'>position coords: <span class='pep-x'>-</span>, <span class='pep-y'>-</span></div>")
1074        .append("<div id='pep-debug-velocity'>velocity: <span class='pep-x'>-</span>, <span class='pep-y'>-</span></div>")
1075        .append("<div id='pep-debug-delta'>&Delta; movement: <span class='pep-x'>-</span>, <span class='pep-y'>-</span></div>")
1076        .css({
1077          position:   'fixed',
1078          bottom:     5,
1079          right:      5,
1080          zIndex:     99999,
1081          textAlign:  'right',
1082          fontFamily: 'Arial, sans',
1083          fontSize:   10,
1084          border:     '1px solid #DDD',
1085          padding:    '3px',
1086          background: 'white',
1087          color:      '#333'
1088        });
1089    }
1090
1091    var self = this;
1092    setTimeout(function(){
1093      self.debugElements = {
1094        $event:      $("#pep-debug-event"),
1095        $velocityX:  $("#pep-debug-velocity .pep-x"),
1096        $velocityY:  $("#pep-debug-velocity .pep-y"),
1097        $dX:         $("#pep-debug-delta .pep-x"),
1098        $dY:         $("#pep-debug-delta .pep-y"),
1099        $evCoordsX:  $("#pep-debug-ev-coords .pep-x"),
1100        $evCoordsY:  $("#pep-debug-ev-coords .pep-y"),
1101        $posCoordsX: $("#pep-debug-pos-coords .pep-x"),
1102        $posCoordsY: $("#pep-debug-pos-coords .pep-y")
1103      };
1104    }, 0);
1105
1106    $('body').append( $debugDiv );
1107  };
1108
1109  // log()
1110  Pep.prototype.log = function(opts) {
1111    if ( !this.options.debug ) return;
1112
1113    switch (opts.type){
1114    case "event":
1115      this.debugElements.$event.text(opts.event);
1116      break;
1117    case "pos-coords":
1118      this.debugElements.$posCoordsX.text(opts.x);
1119      this.debugElements.$posCoordsY.text(opts.y);
1120      break;
1121    case "event-coords":
1122      this.debugElements.$evCoordsX.text(opts.x);
1123      this.debugElements.$evCoordsY.text(opts.y);
1124      break;
1125    case "delta":
1126      this.debugElements.$dX.text(opts.x);
1127      this.debugElements.$dY.text(opts.y);
1128      break;
1129    case "velocity":
1130      var vel = this.velocity();
1131      this.debugElements.$velocityX.text( Math.round(vel.x) );
1132      this.debugElements.$velocityY.text( Math.round(vel.y) );
1133      break;
1134    }
1135  };
1136
1137  // toggle()
1138  //  toggle the pep object
1139  Pep.prototype.toggle = function(on) {
1140    if ( typeof(on) === "undefined"){
1141      this.disabled = !this.disabled;
1142    }
1143    else {
1144      this.disabled = !on;
1145    }
1146  };
1147
1148  //  *** Special Easings functions ***
1149  //    Used for JS easing fallback
1150  //    We can use any of these for a
1151  //    good intertia ease
1152  $.extend($.easing,
1153  {
1154    easeOutQuad: function (x, t, b, c, d) {
1155      return -c *(t/=d)*(t-2) + b;
1156    },
1157    easeOutCirc: function (x, t, b, c, d) {
1158      return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
1159    },
1160    easeOutExpo: function (x, t, b, c, d) {
1161      return (t===d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
1162    }
1163  });
1164
1165  //  wrap it
1166  //    A really lightweight plugin wrapper around the constructor,
1167  //    preventing against multiple instantiations.
1168  $.fn[pluginName] = function ( options ) {
1169    return this.each(function () {
1170      if (!$.data(this, 'plugin_' + pluginName)) {
1171        var pepObj = new Pep( this, options );
1172        $.data(this, 'plugin_' + pluginName, pepObj);
1173        $.pep.peps.push(pepObj);
1174      }
1175    });
1176  };
1177
1178  //  The   _   ___ ___
1179  //       /_\ | _ \_ _|
1180  //      / _ \|  _/| |
1181  //     /_/ \_\_| |___|
1182  //
1183  $.pep = {};
1184  $.pep.peps = [];
1185  $.pep.toggleAll = function(on){
1186    $.each(this.peps, function(index, pepObj){
1187      pepObj.toggle(on);
1188    });
1189  };
1190
1191  $.pep.unbind = function($obj){
1192    $.each($obj, function(index, pepObj) {
1193      pepObj = $(pepObj);
1194      var pep = pepObj.data('plugin_' + pluginName);
1195
1196      if ( typeof pep === 'undefined' )
1197        return;
1198
1199      pep.toggle(false);
1200      pep.unsubscribe();
1201      pepObj.removeData('plugin_' + pluginName);
1202    });
1203  };
1204
1205}(jQuery, window));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.